Warning, /include/Geant4/tools/sg/infos_box is written in an unsupported language. File is not indexed.
0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003
0004 #ifndef tools_sg_infos_box
0005 #define tools_sg_infos_box
0006
0007 //
0008 // In z the scene is within [0,0.5]
0009 //
0010
0011 #include "back_area"
0012 #include "matrix"
0013 #include "text_hershey"
0014 #include "base_freetype"
0015 #include "enums"
0016
0017 #include "../colorf"
0018
0019 namespace tools {
0020 namespace sg {
0021
0022 class infos_box : public back_area {
0023 TOOLS_NODE(infos_box,tools::sg::infos_box,back_area)
0024 public:
0025 mf_string lstrings;
0026 mf_string rstrings;
0027 sf<unsigned int> num_spaces; //in "number of one line height" unit.
0028
0029 sf_vec<colorf,float> color;
0030 sf_string font;
0031 sf_enum<sg::font_modeling> font_modeling;
0032 sf_string encoding;
0033 sf<float> line_width; // for text_hershey.
0034 sf_enum<winding_type> front_face; //no more used.
0035
0036 sf<bool> back_visible;
0037 sf<float> wmargin_factor;
0038 sf<float> hmargin_factor;
0039 sf_enum<hjust> lhjust;
0040 sf_enum<hjust> rhjust;
0041 sf<bool> confine;
0042 public:
0043 virtual const desc_fields& node_desc_fields() const {
0044 TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::infos_box)
0045 static const desc_fields s_v(parent::node_desc_fields(),15, //WARNING : take care of count.
0046 TOOLS_ARG_FIELD_DESC(lstrings),
0047 TOOLS_ARG_FIELD_DESC(rstrings),
0048 TOOLS_ARG_FIELD_DESC(num_spaces),
0049 TOOLS_ARG_FIELD_DESC(color),
0050
0051 TOOLS_ARG_FIELD_DESC_OPTS_BEG(font,10)
0052 font_hershey().c_str(),
0053 font_lato_regular_ttf().c_str(),
0054 font_roboto_bold_ttf().c_str(),
0055 font_arial_ttf().c_str(),
0056 font_arialbd_ttf().c_str(),
0057 font_timesbd_ttf().c_str(),
0058 font_symbol_ttf().c_str(),
0059 font_stixgeneral_otf().c_str(),
0060 font_helvetica_ttf().c_str(),
0061 font_times_roman_ttf().c_str()
0062 TOOLS_ARG_FIELD_DESC_OPTS_END,
0063
0064 TOOLS_ARG_FIELD_DESC_ENUMS_BEG(font_modeling,3)
0065 TOOLS_ARG_ENUM(font_outline),
0066 TOOLS_ARG_ENUM(font_filled),
0067 TOOLS_ARG_ENUM(font_pixmap)
0068 TOOLS_ARG_FIELD_DESC_ENUMS_END,
0069
0070 TOOLS_ARG_FIELD_DESC(encoding),
0071 TOOLS_ARG_FIELD_DESC(line_width),
0072 TOOLS_ARG_FIELD_DESC(front_face),
0073
0074 TOOLS_ARG_FIELD_DESC(back_visible), //10
0075 TOOLS_ARG_FIELD_DESC(wmargin_factor),
0076 TOOLS_ARG_FIELD_DESC(hmargin_factor),
0077 TOOLS_ARG_FIELD_DESC(lhjust),
0078 TOOLS_ARG_FIELD_DESC(rhjust),
0079 TOOLS_ARG_FIELD_DESC(confine)
0080 );
0081 return s_v;
0082 }
0083 private:
0084 void add_fields(){
0085 add_field(&lstrings);
0086 add_field(&rstrings);
0087 add_field(&num_spaces);
0088
0089 add_field(&color);
0090 add_field(&font);
0091 add_field(&font_modeling);
0092 add_field(&encoding);
0093 add_field(&line_width);
0094 add_field(&front_face);
0095
0096 add_field(&back_visible);
0097 add_field(&wmargin_factor);
0098 add_field(&hmargin_factor);
0099 add_field(&lhjust);
0100 add_field(&rhjust);
0101 add_field(&confine);
0102 }
0103 public:
0104 virtual void render(render_action& a_action) {
0105 if(touched()) {
0106 update_sg();
0107 reset_touched();
0108 }
0109 if(back_visible.value()) m_back_sep.render(a_action);
0110 m_sep.render(a_action);
0111 }
0112 virtual void pick(pick_action& a_action) {
0113 if(touched()) {
0114 update_sg();
0115 reset_touched();
0116 }
0117 if(back_visible.value()) {
0118 m_back_sep.pick(a_action);
0119 if(a_action.done()) return;
0120 }
0121 }
0122 virtual void search(search_action& a_action) {
0123 if(touched()) {
0124 update_sg();
0125 reset_touched();
0126 }
0127 node::search(a_action);
0128 if(a_action.done()) return;
0129 if(back_visible.value()) {
0130 m_back_sep.search(a_action);
0131 if(a_action.done()) return;
0132 }
0133 m_sep.search(a_action);
0134 if(a_action.done()) return;
0135 }
0136 virtual bool write(write_action& a_action) {
0137 if(touched()) {
0138 update_sg();
0139 reset_touched();
0140 }
0141 if(back_visible.value()) if(!m_back_sep.write(a_action)) return false;
0142 return m_sep.write(a_action);
0143 }
0144 virtual void bbox(bbox_action& a_action) {
0145 if(touched()) {
0146 update_sg();
0147 reset_touched();
0148 }
0149 if(back_visible.value()) m_back_sep.bbox(a_action);
0150 m_sep.bbox(a_action);
0151 }
0152 public:
0153 infos_box(const base_freetype& a_ttf)
0154 :parent()
0155 ,lstrings()
0156 ,rstrings()
0157 ,num_spaces(4)
0158
0159 ,color(colorf_black())
0160 ,font(font_hershey())
0161 ,font_modeling(font_filled)
0162 ,encoding(encoding_PAW())
0163 ,line_width(1)
0164 ,front_face(winding_ccw)
0165
0166 ,back_visible(true)
0167 ,wmargin_factor(0.9f)
0168 ,hmargin_factor(0.9f)
0169 ,lhjust(left)
0170 ,rhjust(right)
0171
0172 ,confine(false)
0173
0174 ,m_ttf(a_ttf)
0175 {
0176 add_fields();
0177 }
0178 virtual ~infos_box(){}
0179 public:
0180 infos_box(const infos_box& a_from)
0181 :parent(a_from)
0182 ,lstrings(a_from.lstrings)
0183 ,rstrings(a_from.rstrings)
0184 ,num_spaces(a_from.num_spaces)
0185
0186 ,color(a_from.color)
0187 ,font(a_from.font)
0188 ,font_modeling(a_from.font_modeling)
0189 ,encoding(a_from.encoding)
0190 ,line_width(a_from.line_width)
0191 ,front_face(a_from.front_face)
0192
0193 ,back_visible(a_from.back_visible)
0194 ,wmargin_factor(a_from.wmargin_factor)
0195 ,hmargin_factor(a_from.hmargin_factor)
0196 ,lhjust(a_from.lhjust)
0197 ,rhjust(a_from.rhjust)
0198
0199 ,confine(a_from.confine)
0200
0201 ,m_ttf(a_from.m_ttf)
0202 {
0203 add_fields();
0204 }
0205 infos_box& operator=(const infos_box& a_from){
0206 parent::operator=(a_from);
0207 lstrings = a_from.lstrings;
0208 rstrings = a_from.rstrings;
0209 num_spaces = a_from.num_spaces;
0210
0211 color = a_from.color;
0212 font = a_from.font;
0213 font_modeling = a_from.font_modeling;
0214 encoding = a_from.encoding;
0215 line_width = a_from.line_width;
0216 front_face = a_from.front_face;
0217
0218 back_visible = a_from.back_visible;
0219 wmargin_factor = a_from.wmargin_factor;
0220 hmargin_factor = a_from.hmargin_factor;
0221 lhjust = a_from.lhjust;
0222 rhjust = a_from.rhjust;
0223
0224 confine = a_from.confine;
0225
0226 return *this;
0227 }
0228 public:
0229 void update_sg() {
0230 // have this method public in order to use it in plotter.
0231 // This is so because infos_box::height is an output field
0232 // needed in plotter to place the box.
0233
0234 m_back_sep.clear(); //back_area::update_sg done last.
0235
0236 m_sep.clear();
0237
0238 if(width.value()<=0) return;
0239 if(confine) {
0240 if(height.value()<=0) return;
0241 }
0242
0243 {bool empty = true;
0244 std::vector<std::string>::const_iterator it;
0245 for(it=lstrings.values().begin();it!=lstrings.values().end();++it) {
0246 if((*it).size()) {empty = false;break;}
0247 }
0248 if(empty){
0249 for(it=rstrings.values().begin();it!=rstrings.values().end();++it) {
0250 if((*it).size()) {empty = false;break;}
0251 }
0252 }
0253 if(empty) {
0254 //parent::update_sg();
0255 return;
0256 }}
0257
0258 rgba* mat = new rgba();
0259 mat->color = color;
0260 m_sep.add(mat);
0261
0262 if(font==font_hershey()) {
0263 draw_style* ds = new draw_style;
0264 ds->style.value(draw_lines);
0265 //ds->line_pattern = line_pattern;
0266 ds->line_width = line_width;
0267 m_sep.add(ds);
0268 }
0269
0270 ////////////////////////////////////////////////////////////
0271 /// left text //////////////////////////////////////////////
0272 ////////////////////////////////////////////////////////////
0273 base_text* ltext = 0;
0274 matrix* ltsf = 0;
0275
0276 {separator* sep = new separator;
0277 m_sep.add(sep);
0278 ltsf = new matrix;
0279 sep->add(ltsf);
0280 if(font==font_hershey()) {
0281 text_hershey* text = new text_hershey;
0282 ltext = text;
0283 text->encoding = encoding;
0284 sep->add(text);
0285 } else {
0286 base_freetype* text = base_freetype::create(m_ttf);
0287 //TTNODE* text = new TTNODE;
0288 ltext = text;
0289 text->font = font;
0290 text->modeling = font_modeling;
0291 sep->add(text);
0292 }
0293 ltext->strings = lstrings;
0294 ltext->hjust = lhjust;}
0295
0296 ////////////////////////////////////////////////////////////
0297 /// right text /////////////////////////////////////////////
0298 ////////////////////////////////////////////////////////////
0299 base_text* rtext = 0;
0300 matrix* rtsf = 0;
0301
0302 {separator* sep = new separator;
0303 m_sep.add(sep);
0304 rtsf = new matrix;
0305 sep->add(rtsf);
0306 if(font==font_hershey()) {
0307 text_hershey* text = new text_hershey;
0308 rtext = text;
0309 text->encoding = encoding;
0310 sep->add(text);
0311 } else {
0312 base_freetype* text = base_freetype::create(m_ttf);
0313 //TTNODE* text = new TTNODE;
0314 rtext = text;
0315 text->font = font;
0316 text->modeling = font_modeling;
0317 sep->add(text);
0318 }
0319 rtext->strings = rstrings;
0320 rtext->hjust = rhjust;}
0321
0322 ////////////////////////////////////////////////////////////
0323 /// middle spaces //////////////////////////////////////////
0324 ////////////////////////////////////////////////////////////
0325 base_text* mtext = 0;
0326 {std::string _s(num_spaces,' ');
0327 if(font==font_hershey()) {
0328 text_hershey* text = new text_hershey;
0329 mtext = text;
0330 text->strings.add(_s);
0331 text->hjust = left;
0332 } else {
0333 base_freetype* text = base_freetype::create(m_ttf);
0334 //TTNODE* text = new TTNODE;
0335 mtext = text;
0336 text->strings.add(_s);
0337 text->hjust = left;
0338 text->font = font;
0339 text->modeling = font_modeling;
0340 }}
0341
0342 //sf<float> zfront ?
0343 float zz = back_visible.value()?0.01f:0;
0344
0345 float fw = width * wmargin_factor;
0346
0347 if(confine) {
0348 // left right texts may overlap.
0349
0350 // adjust height :
0351 float fh = height * hmargin_factor;
0352 float th = fh;
0353 {float mn_x,mn_y,mn_z;
0354 float mx_x,mx_y,mx_z;
0355 ltext->get_bounds(th,mn_x,mn_y,mn_z,mx_x,mx_y,mx_z);
0356 float bxh = mx_y-mn_y;
0357 // adjust box height :
0358 // fh -> bxh then to have fh :
0359 if(!bxh) {
0360 m_sep.clear();
0361 parent::update_sg();
0362 delete mtext;
0363 return;
0364 }
0365 th = fh*fh/bxh;}
0366
0367 ltext->height = th;
0368 rtext->height = th;
0369
0370 {float mn_x,mn_y,mn_z;
0371 float mx_x,mx_y,mx_z;
0372 ltext->get_bounds(th,mn_x,mn_y,mn_z,mx_x,mx_y,mx_z);
0373 float lw = mx_x-mn_x;
0374 float xtrans = (fw-lw)*0.5f; //left justified
0375 float xx = -(mn_x+mx_x)*0.5F-xtrans;
0376 float yy = -(mn_y+mx_y)*0.5F;
0377 ltsf->set_translate(xx,yy,zz);}
0378
0379 {float mn_x,mn_y,mn_z;
0380 float mx_x,mx_y,mx_z;
0381 rtext->get_bounds(th,mn_x,mn_y,mn_z,mx_x,mx_y,mx_z);
0382 rtext->hjust = right;
0383 float xx = fw*0.5f;
0384 float yy = -(mn_y+mx_y)*0.5F;
0385 rtsf->set_translate(xx,yy,zz);}
0386
0387 parent::update_sg();
0388
0389 } else {
0390 // height of the info box is an output of the below.
0391 // The input to compute the geometry is the width of the infos
0392 // box, the left/right texts and the space between
0393 // left/right texts.
0394
0395 // from a text height of th=1, and a left/right sep
0396 // of num_spaces*th, get width of the box :
0397
0398 float th = 1;
0399
0400 float lmn_x,lmn_y,lmn_z;
0401 float lmx_x,lmx_y,lmx_z;
0402 ltext->get_bounds(th,lmn_x,lmn_y,lmn_z,lmx_x,lmx_y,lmx_z);
0403 float lw = (lmx_x<lmn_x)?0:lmx_x-lmn_x;
0404
0405 float rmn_x,rmn_y,rmn_z;
0406 float rmx_x,rmx_y,rmx_z;
0407 rtext->get_bounds(th,rmn_x,rmn_y,rmn_z,rmx_x,rmx_y,rmx_z);
0408 float rw = (rmx_x<rmn_x)?0:rmx_x-rmn_x;
0409
0410 float mmn_x,mmn_y,mmn_z;
0411 float mmx_x,mmx_y,mmx_z;
0412 mtext->get_bounds(th,mmn_x,mmn_y,mmn_z,mmx_x,mmx_y,mmx_z);
0413 float mw = (mmx_x<mmn_x)?0:mmx_x-mmn_x;
0414
0415 float winfos = lw+mw+rw;
0416 if(!winfos) {
0417 m_sep.clear();
0418 height = 1;
0419 parent::update_sg();
0420 delete mtext;
0421 return;
0422 }
0423
0424 // assuming that text size is linear relative
0425 // to th, we get the th needed to match infos_box.width :
0426 // th -> winfos then to have fw :
0427 th = fw*th/winfos;
0428
0429 // place the left/right texts by rescaling them to
0430 // the new th :
0431 ltext->height = th;
0432 ltext->get_bounds(th,lmn_x,lmn_y,lmn_z,lmx_x,lmx_y,lmx_z);
0433 float hinfos = (lmx_x<lmn_x)?0:lmx_y-lmn_y;
0434
0435 float xx = -fw*0.5F; //left justified.
0436 float ty = -ltext->ascent(th)+hinfos*0.5f;
0437 ltsf->set_translate(xx,ty,zz);
0438
0439 rtext->height = th;
0440 if(rtext->hjust==right) {
0441 xx = fw*0.5F;
0442 } else if(rtext->hjust==left) {
0443 rtext->get_bounds(th,rmn_x,rmn_y,rmn_z,rmx_x,rmx_y,rmx_z);
0444 rw = (rmx_x<rmn_x)?0:rmx_x-rmn_x;
0445 xx = fw*0.5F-rw;
0446 } else { //center
0447 rtext->get_bounds(th,rmn_x,rmn_y,rmn_z,rmx_x,rmx_y,rmx_z);
0448 rw = (rmx_x<rmn_x)?0:rmx_x-rmn_x;
0449 xx = fw*0.5F-rw*0.5F;
0450 }
0451 rtsf->set_translate(xx,ty,zz);
0452
0453 // set infos_box.height :
0454 height = hinfos/hmargin_factor;
0455
0456 //done last because of the upper height setup.
0457 parent::update_sg();
0458
0459 }
0460
0461 delete mtext;
0462
0463 }
0464 protected:
0465 const base_freetype& m_ttf;
0466
0467 separator m_sep;
0468 };
0469
0470 }}
0471
0472 #endif