#ifndef __BLOP_AXIS_H__
#define __BLOP_AXIS_H__
#include "label.h"
#include "var.h"
#include "constants.h"
#include "color.h"
#include "tic.h"
#include "function.h"
#include "units.h"
#include <utility>
namespace blop
{
class axis : public grob
{
private:
axis *transformed_axis_;
function transform_, transform_inverse_;
bool own_tic_calculation_;
vector<pair<double,double> > cuts_;
length cut_x1_,cut_x2_,cut_x3_,cut_x4_,cut_y1_,cut_y2_,cut_y3_,cut_y4_;
length cut_gap_;
static length &default_cut_gap_();
void print_cuts(terminal *);
color axiscolor_;
static color default_axiscolor_;
double unit_value_;
string unit_symbol_;
string unit_format_;
#ifndef __CINT__
friend class frame;
friend class mframe;
#endif
double scale_;
label scalelabel_;
length bl1_,bl2_,bl3_,bl4_;
int id_;
bool logscale_;
label title_;
bool title_autoset_;
std::vector<blop::tic> tics_,minor_tics_;
string tics_format_,minor_tics_format_;
length ticlength_,minor_ticlength_;
static length &default_ticlength_();
static length &default_minor_ticlength_();
bool draw_tics_,draw_minor_tics_;
static bool default_draw_tics_;
int n_minor_tics_;
double min_, max_;
bool min_fixed_,max_fixed_;
double tic_start_,tic_incr_,tic_end_;
bool tic_start_fixed_, tic_incr_fixed_, tic_end_fixed_;
std::vector<blop::tic> user_tics_;
length labelsep_,titlesep_,label_maxsize_,label_maxdist_,
title_axis_sep_,script_size_;
length beg_,end_,pos_;
bool pos_changed_;
int autoextend_min_, autoextend_max_;
void operator= (const axis &);
void pos(const length &pos,
const length &,const length &);
bool symmetric_range_;
static bool default_symmetric_range_;
public:
class tic_setter
{
private:
axis *axis_;
public:
tic_setter(axis *a) : axis_(a) {}
blop::axis::tic_setter &operator()();
blop::axis::tic_setter &operator()(var);
blop::axis::tic_setter &operator()(var,var);
blop::axis::tic_setter &operator()(var,var,var);
};
tic_setter tics;
axis &axiscolor(const color &);
const color &axiscolor() const;
static void default_axiscolor(const color &);
axis &ticlength(const length &l) {ticlength_ = l; return *this;}
const length &ticlength() const {return ticlength_;}
static void default_ticlength(const length &);
static void default_minor_ticlength(const length &);
axis &minor_ticlength(const length &l) {minor_ticlength_ = l; return *this;}
const length &minor_ticlength() const {return minor_ticlength_;}
axis &ticformat(const var &f) {tics_format_ = f.str();return *this;}
var ticformat() const { return tics_format_; }
axis &minor_ticformat(const var &f) {minor_tics_format_ = f.str(); return *this;}
var minor_ticformat() const { return minor_tics_format_; }
axis &draw_tics(bool i = true) {draw_tics_ = i; return *this;}
axis &draw_minor_tics(bool i=true) {draw_minor_tics_ = i; return *this;}
static void default_draw_tics(bool f);
axis &n_minor_tics(int n) { n_minor_tics_ = n; return *this; }
axis &symmetric_range(bool s) { symmetric_range_ = s; return *this; }
static void default_symmetric_range(bool s);
const length &titlesep() const {return titlesep_;}
axis &titlesep(const length &l) {titlesep_ = l; return *this;}
const length &titleaxissep() const {return title_axis_sep_;}
axis &titleaxissep(const length &l);
const length &labelsep() const {return labelsep_;}
axis &labelsep(const length &l) {labelsep_ = l; return *this;}
const length &scriptsize() const {return script_size_;}
axis &logscale(bool l);
bool logscale() const {return logscale_;}
axis &unit(const var &u, const var &format=unit::default_format());
axis &scale(double s);
double scale() const;
double min() {return min_;}
double max() {return max_;}
axis &range(double a,double b);
axis &min(double d);
axis &max(double d);
bool min_fixed() const {return min_fixed_;}
bool max_fixed() const {return max_fixed_;}
axis &autoextend_min(bool f = true);
axis &autoextend_max(bool f = true);
axis &autoextend (bool f = true);
axis &autoextend_min_soft(bool f = true);
axis &autoextend_max_soft(bool f = true);
axis &clear_autosettings();
axis &clear();
axis &extend_range(double a);
label *titlebox();
axis &title(const var &s, bool autoset = false);
var title() const;
bool title_autoset() const { return title_autoset_; }
axis &cut(double low, double high);
axis &cut();
axis &cut_gap(length l);
const length &cut_gap() const;
static void default_cut_gap(length l);
axis &transform(axis *orig,
const function &f=_1, const function &finverse=_1,
bool own_tic_calculation = false);
length &begin() {return beg_;}
length &end() {return end_;}
void print(terminal *t);
void print(terminal *t, bool print_line);
void print_tics(terminal *t,const length &p1, const length &p2,
const length &p,bool mirror = false);
void print_line(terminal *);
void print_ticlabels(terminal *);
void print_title(terminal *);
double map_point(double);
axis &calculate_tics();
void calculate_lengths();
void prepare_for_draw();
void pos(const length &);
bool pos_changed() const { return pos_changed_; }
enum {x1=1,x2=2,y1=4,y2=8};
axis(int id);
axis(const axis &o);
virtual ~axis();
int id() const {return id_;}
friend class axis::tic_setter;
axis &layer(const var & l) { grob::layer(l); return *this; }
};
class tic_setter
{
private:
int axis_;
axis *get_axis();
public:
tic_setter(int i);
tic_setter &operator()();
tic_setter &operator()(var);
tic_setter &operator()(var,var);
tic_setter &operator()(var,var,var);
};
}
#endif