#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_; // the numerical value of the unit used for the axis
string unit_symbol_; // the symbol (LaTeX) of the unit (the user-supplied string like Ohm*A parsed, transformed)
string unit_format_; // the format, how the symbol should be appended to the title
#ifndef __CINT__
friend class frame;
friend class mframe;
#endif
double scale_;
label scalelabel_;
// band limits of the decorations
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;
// This is a function-like class, which defines the parenthesis
// operators. These operators return a reference to the same
// class, so they can be called subsequently, providing a very
// user-friendly interface. Every axis contains one instance
// of this class as a member (called 'tics').
// ---------- color of the axis ---------------------------------------------------
axis &axiscolor(const color &);
const color &axiscolor() const;
static void default_axiscolor(const color &);
// ---------- ticlength ----------------------------------------------------------
// set or get the length of the major tics of this axis
axis &ticlength(const length &l) {ticlength_ = l; return *this;}
const length &ticlength() const {return ticlength_;}
// Set the default values (for all axes created after this point)
static void default_ticlength(const length &);
static void default_minor_ticlength(const length &);
// set or get the length of the minor tics of this axis
axis &minor_ticlength(const length &l) {minor_ticlength_ = l; return *this;}
const length &minor_ticlength() const {return minor_ticlength_;}
// ---------- ticformat -----------------------------------------------------------
// set or get the format of the major ticlabels (this is the
// format string of a printf command)
axis &ticformat(const var &f) {tics_format_ = f.str();return *this;}
var ticformat() const { return tics_format_; }
// set or get the format of the minor ticlabels (this is the
// format string of a printf command)
axis &minor_ticformat(const var &f) {minor_tics_format_ = f.str(); return *this;}
var minor_ticformat() const { return minor_tics_format_; }
// --------------------------------------------------------------------------------
// these functions control if the major and minor
// tics are printed
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);
// --------------------------------------------------------------------------------
// these functions control the number of minor tic intervals between major ones
axis &n_minor_tics(int n) { n_minor_tics_ = n; return *this; }
// --------------------------------------------------------------------------------
// Force the axis range to be symmetric around 0
axis &symmetric_range(bool s) { symmetric_range_ = s; return *this; }
static void default_symmetric_range(bool s);
// --------------------------------------------------------------------------------
// set or get the separating gap between the title
// and the ticlabels (if ticlabels exist), or between
// the title and the axis itself, if no ticlabels
// are shown
const length &titlesep() const {return titlesep_;}
axis &titlesep(const length &l) {titlesep_ = l; return *this;}
// --------------------------------------------------------------------------------
// Set or get the distance between the axis and
// the axis title. By default this is a derived
// length calculated from the tic labels' sizes,
// and from the 'labelsep' (distance between the
// axis and the tic labels) and 'titlesep' (see
// above
const length &titleaxissep() const {return title_axis_sep_;}
axis &titleaxissep(const length &l);
// --------------------------------------------------------------------------------
// set or get the distance between the axis and
// the tic labels
const length &labelsep() const {return labelsep_;}
axis &labelsep(const length &l) {labelsep_ = l; return *this;}
// --------------------------------------------------------------------------------
// get the size (width, if y1 or y2 axis, or height,
// if x1 or x2 axis) of all the scripts decorating
// this axis (ticlabels, title and the separating
// gaps between them)
const length &scriptsize() const {return script_size_;}
// ---------- set/get logscale ----------------------------------------------------
// If the user changes to logscale, and a previously set
// minimum is negative or 0, then this minimum is released
// in order to avoid the warning message appearing with
// negative values on a logscale
axis &logscale(bool l);
bool logscale() const {return logscale_;}
// ---------- set the unit --------------------------------------------------------
axis &unit(const var &u, const var &format=unit::default_format());
// ---------- set/get scale factor ------------------------------------------------
// set or get the scaling factor of this axis (a scaling
// factor of 100 for example means, that every ticlabel
// shown on this axis is divided by 100, and x10^2 is
// shown at the end of the axis
axis &scale(double s);
double scale() const;
// ---------- set/release range ---------------------------------------------------
// set the ranges of the axis. 'unset' is also a valid
// value, which releases the range
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);
// ---------- clear_autosettings --------------------------------------------------
// clear all settings, which were not set directly by the user.
// the range is for example not cleared by this function, if it
// has been set via the min(double a), max(double b) or range(double a,double b)
// function, where 'a' or 'b' are not 'unset'
axis &clear_autosettings();
// ---------- clear ---------------------------------------------------------------
// This could also be called 'reset'. Sets the axis
// to its default status, every user settings are
// cleared as well
axis &clear();
// ---------- extend_range --------------------------------------------------------
// extend the range of the axis such that it
// includes the provided value, 'a'
axis &extend_range(double a);
// ---------- titlebox ------------------------------------------------------------
// return a pointer to the title of this axis as a titlebox
// (see label.h for more details). You can call the member
// functions of 'label' on the returned pointer to set
// any properties of the title
label *titlebox();
// ---------- get/set axis title --------------------------------------------------
// set or get the title (the text which appears) of this axis
// The 'auto' flag can be used to indicate whether this is an
// automatically set title (by some automatic mechanism, like
// reading in column titles from the datafile)
axis &title(const var &s, bool autoset = false);
var title() const;
bool title_autoset() const { return title_autoset_; }
// ---------- Cut out regions from the axis --------------------------------------
axis &cut(double low, double high);
axis &cut(); // reset: clear cut-out regions
axis &cut_gap(length l);
const length &cut_gap() const;
static void default_cut_gap(length l);
// ---------- Show transformed values of another axis -----------------------------
axis &transform(axis *orig,
const function &f=_1, const function &finverse=_1,
bool own_tic_calculation = false);
// --- and finally some undocumented functions, which will probably
// --- not be called by the user
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