Files
geant4/source/analysis/g4tools/include/tools/sg/legend
T
2017-12-08 12:52:30 +01:00

405 lines
9.6 KiB
Plaintext

// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef tools_sg_legend
#define tools_sg_legend
// To handle a colored "rep" (line or marker) with a text at right.
#include "back_area"
#include "matrix"
#include "text_hershey"
#include "base_freetype"
#include "markers"
#include "enums"
#include "../colorf"
//#include "../paw2stix"
#include "text_valop"
namespace tools {
namespace sg {
class legend : public back_area {
TOOLS_NODE(legend,tools::sg::legend,back_area)
public:
mf_string strings;
sf_vec<colorf,float> color; //color of the "rep"
// text atbs :
//sf<float> transparency;
sf_string font;
sf_string encoding;
//sf<float> line_width; // for text_hershey.
sf<bool> back_visible;
sf<float> wmargin_factor;
sf<float> hmargin_factor;
sf_enum<hjust> lhjust;
sf_enum<hjust> rhjust;
//sf<bool> confine;
sf_enum<sg::marker_style> marker_style;
sf<float> marker_size;
public:
virtual const std::vector<field_desc>& node_fields() const {
TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::legend)
static std::vector<field_desc> s_v;
if(s_v.empty()) {
s_v = parent::node_fields();
TOOLS_ADD_FIELD_DESC(strings)
TOOLS_ADD_FIELD_DESC(color)
TOOLS_ADD_FIELD_DESC(font)
TOOLS_ADD_FIELD_DESC(encoding);
TOOLS_ADD_FIELD_DESC(back_visible)
TOOLS_ADD_FIELD_DESC(wmargin_factor)
TOOLS_ADD_FIELD_DESC(hmargin_factor)
TOOLS_ADD_FIELD_DESC(lhjust)
TOOLS_ADD_FIELD_DESC(rhjust)
TOOLS_ADD_FIELD_DESC(marker_style)
TOOLS_ADD_FIELD_DESC(marker_size)
}
return s_v;
}
private:
void add_fields(){
add_field(&strings);
add_field(&color);
add_field(&font);
add_field(&encoding);
add_field(&back_visible);
add_field(&wmargin_factor);
add_field(&hmargin_factor);
add_field(&lhjust);
add_field(&rhjust);
add_field(&marker_style);
add_field(&marker_size);
}
public:
virtual void render(render_action& a_action) {
if(touched()) {
update_sg();
reset_touched();
}
if(back_visible.value()) m_back_sep.render(a_action);
m_sep.render(a_action);
}
virtual void pick(pick_action& a_action) {
if(touched()) {
update_sg();
reset_touched();
}
if(back_visible.value()) {
m_back_sep.pick(a_action);
if(a_action.done()) return;
}
}
virtual void search(search_action& a_action) {
node::search(a_action);
if(a_action.done()) return;
if(touched()) {
update_sg();
reset_touched();
}
if(back_visible.value()) {
m_back_sep.search(a_action);
if(a_action.done()) return;
}
m_sep.search(a_action);
if(a_action.done()) return;
}
virtual void bbox(bbox_action& a_action) {
if(touched()) {
update_sg();
reset_touched();
}
if(back_visible.value()) m_back_sep.bbox(a_action);
m_sep.bbox(a_action);
}
public:
legend(const base_freetype& a_ttf)
:parent()
,strings()
,color(colorf_black())
//,transparency(0)
,font(font_hershey())
,encoding(encoding_PAW())
//,line_width(1)
,back_visible(true)
,wmargin_factor(0.9f)
,hmargin_factor(0.9f)
,lhjust(left)
,rhjust(right)
,marker_style(marker_dot)
,marker_size(10)
//,confine(false)
,m_ttf(a_ttf)
{
add_fields();
}
virtual ~legend(){}
public:
legend(const legend& a_from)
:parent(a_from)
,strings(a_from.strings)
,color(a_from.color)
//,transparency(a_from.transparency)
,font(a_from.font)
,encoding(a_from.encoding)
//,line_width(a_from.line_width)
,back_visible(a_from.back_visible)
,wmargin_factor(a_from.wmargin_factor)
,hmargin_factor(a_from.hmargin_factor)
,lhjust(a_from.lhjust)
,rhjust(a_from.rhjust)
,marker_style(a_from.marker_style)
,marker_size(a_from.marker_size)
//,confine(a_from.confine)
,m_ttf(a_from.m_ttf)
{
add_fields();
}
legend& operator=(const legend& a_from){
parent::operator=(a_from);
strings = a_from.strings;
color = a_from.color;
//transparency = a_from.transparency;
font = a_from.font;
encoding = a_from.encoding;
//line_width = a_from.line_width;
back_visible = a_from.back_visible;
wmargin_factor = a_from.wmargin_factor;
hmargin_factor = a_from.hmargin_factor;
lhjust = a_from.lhjust;
rhjust = a_from.rhjust;
marker_style = a_from.marker_style;
marker_size = a_from.marker_size;
//confine = a_from.confine;
return *this;
}
public:
void update_sg() {
// have this method public in order to use it in plotter.
// This is so because legend::height is an output field
// needed in plotter to place the box.
m_back_sep.clear(); //back_area::update_sg done last.
m_sep.clear();
if(width.value()<=0) return;
//if(confine) {
// if(height.value()<=0) return;
//}
{bool empty = true;
std::vector<std::string>::const_iterator it;
for(it=strings.values().begin();it!=strings.values().end();++it) {
if((*it).size()) {empty = false;break;}
}
if(empty) return;}
//sf<float> zfront ?
float zz = back_visible.value()?0.01f:0;
//bool rep_line = false;
//rep_line = true;
/*
float fw = 0;
float fh = 0;
float lw = 0;
float rw = 0;
if(rep_line) {
fw = width * wmargin_factor;
fh = height * hmargin_factor;
lw = fw*0.5f*0.95f;
rw = fw*0.5f;
}*/
////////////////////////////////////////////////////////////
/// rep at left ////////////////////////////////////////////
////////////////////////////////////////////////////////////
{separator* _sep = new separator;
m_sep.add(_sep);
rgba* mat = new rgba();
mat->color = color;
_sep->add(mat);
/* if(rep_line) {
matrix* ltsf = new matrix;
float xx = -fw*0.5F; //left justified.
ltsf->set_translate(xx,0,zz);
_sep->add(ltsf);
draw_style* ds = new draw_style;
ds->style = draw_style::lines;
_sep->add(ds);
vertices* vtxs = new vertices;
vtxs->mode = gl::line_strip();
vtxs->add( 0,0,zz);
vtxs->add(lw,0,zz);
_sep->add(vtxs);
} else*/ { // rep marker :
if(marker_style.value()==marker_dot) {
draw_style* ds = new draw_style;
ds->style = draw_style::points;
ds->point_size = marker_size;
_sep->add(ds);
vertices* vtxs = new vertices;
vtxs->mode = gl::points();
vtxs->add(-width*0.5f+height*0.5f,0,zz);
_sep->add(vtxs);
} else {
markers* vtxs = new markers;
vtxs->size = marker_size;
vtxs->style = marker_style;
vtxs->add(-width*0.5f+height*0.5f,0,zz);
_sep->add(vtxs);
}
}
}
////////////////////////////////////////////////////////////
/// right text /////////////////////////////////////////////
////////////////////////////////////////////////////////////
base_text* rtext = 0;
matrix* rtsf = 0;
{separator* _sep = new separator;
m_sep.add(_sep);
rgba* mat = new rgba();
mat->color = colorf_black();
_sep->add(mat);
if(font==font_hershey()) {
draw_style* ds = new draw_style;
ds->style.value(draw_style::lines);
_sep->add(ds);
}
rtsf = new matrix;
_sep->add(rtsf);
if(font==font_hershey()) {
text_hershey* text = new text_hershey;
text->encoding = encoding;
text->strings = strings;
_sep->add(text);
rtext = text;
} else {
if(encoding==encoding_PAW()) {
text_valop* text = new text_valop(m_ttf);
text->font = font;
text->strings = strings;
_sep->add(text);
rtext = text;
} else {
base_freetype* text = base_freetype::create(m_ttf);
text->font = font;
text->strings = strings;
_sep->add(text);
rtext = text;
}
}
rtext->hjust = rhjust;}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
/* if(rep_line) {
// adjust width :
float th = fh;
{float mn_x,mn_y,mn_z;
float mx_x,mx_y,mx_z;
rtext->get_bounds(th,mn_x,mn_y,mn_z,mx_x,mx_y,mx_z);
float bxw = mx_x-mn_x;
if(!bxw) {
m_sep.clear();
parent::update_sg();
return;
}
// adjust box width :
// fh -> bxw then to have rw :
float max_width = rw;
if(bxw>max_width) th = max_width*fh/bxw;}
rtext->height = th;
{float mn_x,mn_y,mn_z;
float mx_x,mx_y,mx_z;
rtext->get_bounds(th,mn_x,mn_y,mn_z,mx_x,mx_y,mx_z);
rtext->hjust = right;
float xx = fw*0.5f;
float yy = -(mn_y+mx_y)*0.5F;
rtsf->set_translate(xx,yy,zz);}
} else*/ { //rep mark :
// adjust width :
float th = height;
{float mn_x,mn_y,mn_z;
float mx_x,mx_y,mx_z;
rtext->get_bounds(th,mn_x,mn_y,mn_z,mx_x,mx_y,mx_z);
float bxw = mx_x-mn_x;
if(!bxw) {
m_sep.clear();
parent::update_sg();
return;
}
// adjust box width :
// height -> bxw then to have a wanted width :
float max_width = (width-height)*wmargin_factor;
if(bxw>max_width) th = max_width*height/bxw;
if(th<0) {
m_sep.clear();
parent::update_sg();
return;
}}
rtext->height = th;
{float mn_x,mn_y,mn_z;
float mx_x,mx_y,mx_z;
rtext->get_bounds(th,mn_x,mn_y,mn_z,mx_x,mx_y,mx_z);
rtext->hjust = left;
float yy = -(mn_y+mx_y)*0.5F;
rtsf->set_translate(-width*0.5f+height,yy,zz);}
}
parent::update_sg();
}
protected:
separator m_sep;
const base_freetype& m_ttf;
};
}}
#endif