#include "box.h"
#include "exc.H"
#include "warning.h"
#include <cstdio>
namespace blop
{
using namespace std;
box &box::fix_width(bool f)
{
if(f && (width_.depends_on(left_) || width_.depends_on(right_) || width_.depends_on(xcenter_)))
{
warning::print("Please set the width of the box to an independent value before fixing it","box::fix_width(true)");
return *this;
}
width_fixed_ = f;
return *this;
}
box &box::fix_height(bool f)
{
if(f && (height_.depends_on(bottom_) || height_.depends_on(top_) || height_.depends_on(ycenter_)))
{
warning::print("Please set the height of the box to an independent value before fixing it","box::fix_height(true)");
return *this;
}
height_fixed_ = f;
return *this;
}
void box::set_(const length &l,
length &left,
length &right,
length &width,
length ¢er,
bool width_fixed,
history_values history[2],
history_values todo,
bool &left_modified,
bool &right_modified)
{
left_modified = false;
right_modified = false;
switch(todo)
{
case LeftBottom: left = l; left_modified = true; break;
case RightTop: right = l; right_modified = true; break;
case WidthHeight:
if(width_fixed)
{
warning::print("This should never happen: trying to set width/height of box although it's fixed");
return;
}
width = l; break;
case Center: center = l; break;
default: err("This should not happen...");
}
if(history[1] == todo)
{
return;
}
if(history[0] == todo)
{
history[0] = history[1];
history[1] = todo;
return;
}
if(width_fixed)
{
if(width.depends_on(left) || width.depends_on(right) || width.depends_on(center))
{
warning::print("Width/height depends on other values, although it is fixed. This should never happen...");
return;
}
switch(todo)
{
case LeftBottom: right = !left + !width; center=0.5*(!left+!right); right_modified=true; break;
case RightTop: left = !right - !width; center=0.5*(!left+!right); left_modified =true; break;
case Center: left = !center - 0.5*!width; right = !center + 0.5*!width; right_modified=true; left_modified=true; break;
default: warning::print("This should never happen","box::set_"); break;
}
}
else
{
history_values h1=history[1], h2=todo;
if(h1>h2) swap(h1,h2);
if(h1 == LeftBottom && h2 == RightTop)
{
width = !right - !left;
center = 0.5*(!left + !right);
}
else if(h1 == LeftBottom && h2 == WidthHeight)
{
right = !left + !width;
center = !left + 0.5*!width;
right_modified = true;
}
else if(h1 == LeftBottom && h2 == Center)
{
width = 2*(!center - !left);
right = 2*!center - !left;
right_modified = true;
}
else if(h1 == RightTop && h2 == WidthHeight)
{
left = !right - !width;
center = !right - 0.5*!width;
left_modified = true;
}
else if(h1 == RightTop && h2 == Center)
{
width = 2*(!right - !center);
left = 2*!center - !right;
left_modified = true;
}
else if(h1 == WidthHeight && h2 == Center)
{
left = !center - 0.5*!width;
right = !center + 0.5*!width;
left_modified = right_modified = true;
}
else
{
err("h1 and h2 has impossible values");
}
}
history[0] = history[1];
history[1] = todo;
}
void box::prepare_for_draw()
{
left_.register_me();
right_.register_me();
bottom_.register_me();
top_.register_me();
}
box::box() : left_(0.0), right_(CM), bottom_(0.0), top_(1.0)
{
name("box");
width_fixed_ = false;
height_fixed_ = false;
width_ = !right_ - !left_;
xcenter_ = 0.5*(!left_ + !right_);
height_ = !top_ - !bottom_;
ycenter_ = 0.5*(!bottom_ + !top_);
xhistory_[0] = RightTop;
xhistory_[1] = LeftBottom;
yhistory_[0] = RightTop;
yhistory_[1] = LeftBottom;
left_.set_scale(x_unit());
right_.set_scale(x_unit());
width_.set_scale(x_unit());
xcenter_.set_scale(x_unit());
bottom_.set_scale(y_unit());
top_.set_scale(y_unit());
height_.set_scale(y_unit());
ycenter_.set_scale(y_unit());
}
void box::set_left_(const length &l, bool &left_modified, bool &right_modified)
{
modified_ = true;
set_(l,left_,right_,width_,xcenter_,width_fixed_,xhistory_,LeftBottom,
left_modified,right_modified);
left_.set_scale(x_unit());
}
box &box::left(const length &l)
{
bool b;
set_left_(l,b,b);
return *this;
}
void box::set_right_(const length &l, bool &left_modified, bool &right_modified)
{
modified_ = true;
set_(l,left_,right_,width_,xcenter_,width_fixed_,xhistory_,RightTop,
left_modified,right_modified);
right_.set_scale(x_unit());
}
box &box::right(const length &l)
{
bool b;
set_right_(l,b,b);
return *this;
}
void box::set_width_(const length &l, bool &left_modified, bool &right_modified)
{
modified_ = true;
set_(l,left_,right_,width_,xcenter_,width_fixed_,xhistory_,WidthHeight,
left_modified,right_modified);
width_.set_scale(x_unit());
}
box &box::width(const length &l)
{
if(width_fixed_)
{
warning::print("The width of this box is fixed","box::width(const length &)");
return *this;
}
bool b;
set_width_(l,b,b);
return *this;
}
void box::set_xcenter_(const length &l, bool &left_modified, bool &right_modified)
{
modified_ = true;
set_(l,left_,right_,width_,xcenter_,width_fixed_,xhistory_,Center,
left_modified,right_modified);
xcenter_.set_scale(x_unit());
}
box &box::xcenter(const length &l)
{
bool b;
set_xcenter_(l,b,b);
return *this;
}
void box::set_bottom_(const length &l, bool &bottom_modified, bool &top_modified)
{
modified_ = true;
set_(l,bottom_,top_,height_,ycenter_,height_fixed_,yhistory_,LeftBottom,
bottom_modified,top_modified);
bottom_.set_scale(y_unit());
}
box &box::bottom(const length &l)
{
bool b;
set_bottom_(l,b,b);
return *this;
}
void box::set_top_(const length &l, bool &bottom_modified, bool &top_modified)
{
modified_ = true;
set_(l,bottom_,top_,height_,ycenter_,height_fixed_,yhistory_,RightTop,
bottom_modified,top_modified);
top_.set_scale(y_unit());
}
box &box::top(const length &l)
{
bool b;
set_top_(l,b,b);
return *this;
}
void box::set_height_(const length &l, bool &bottom_modified, bool &top_modified)
{
modified_ = true;
set_(l,bottom_,top_,height_,ycenter_,height_fixed_,yhistory_,WidthHeight,
bottom_modified,top_modified);
height_.set_scale(y_unit());
}
box &box::height(const length &l)
{
if(height_fixed_)
{
warning::print("The height of this box is fixed","box::height(const length &)");
return *this;
}
bool b;
set_height_(l,b,b);
return *this;
}
void box::set_ycenter_(const length &l, bool &bottom_modified, bool &top_modified)
{
modified_ = true;
set_(l,bottom_,top_,height_,ycenter_,height_fixed_,yhistory_,Center,
bottom_modified,top_modified);
ycenter_.set_scale(y_unit());
}
box &box::ycenter(const length &l)
{
bool b;
set_ycenter_(l,b,b);
return *this;
}
const length &box::left() const {return left_;}
const length &box::right() const {return right_;}
const length &box::width() const {return width_;}
const length &box::xcenter() const {return xcenter_;}
const length &box::bottom() const {return bottom_;}
const length &box::top() const {return top_;}
const length &box::height() const {return height_;}
const length &box::ycenter() const {return ycenter_;}
}