Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights 2 // See the file tools.license for terms. 3 4 #ifndef tools_sg_infos_box 5 #define tools_sg_infos_box 6 7 // 8 // In z the scene is within [0,0.5] 9 // 10 11 #include "back_area" 12 #include "matrix" 13 #include "text_hershey" 14 #include "base_freetype" 15 #include "enums" 16 17 #include "../colorf" 18 19 namespace tools { 20 namespace sg { 21 22 class infos_box : public back_area { 23 TOOLS_NODE(infos_box,tools::sg::infos_box,ba 24 public: 25 mf_string lstrings; 26 mf_string rstrings; 27 sf<unsigned int> num_spaces; //in "number of 28 29 sf_vec<colorf,float> color; 30 sf_string font; 31 sf_enum<sg::font_modeling> font_modeling; 32 sf_string encoding; 33 sf<float> line_width; // for text_hershey. 34 sf_enum<winding_type> front_face; //no more 35 36 sf<bool> back_visible; 37 sf<float> wmargin_factor; 38 sf<float> hmargin_factor; 39 sf_enum<hjust> lhjust; 40 sf_enum<hjust> rhjust; 41 sf<bool> confine; 42 public: 43 virtual const desc_fields& node_desc_fields( 44 TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::inf 45 static const desc_fields s_v(parent::node_ 46 TOOLS_ARG_FIELD_DESC(lstrings), 47 TOOLS_ARG_FIELD_DESC(rstrings), 48 TOOLS_ARG_FIELD_DESC(num_spaces), 49 TOOLS_ARG_FIELD_DESC(color), 50 51 TOOLS_ARG_FIELD_DESC_OPTS_BEG(font,10) 52 font_hershey().c_str(), 53 font_lato_regular_ttf().c_str(), 54 font_roboto_bold_ttf().c_str(), 55 font_arial_ttf().c_str(), 56 font_arialbd_ttf().c_str(), 57 font_timesbd_ttf().c_str(), 58 font_symbol_ttf().c_str(), 59 font_stixgeneral_otf().c_str(), 60 font_helvetica_ttf().c_str(), 61 font_times_roman_ttf().c_str() 62 TOOLS_ARG_FIELD_DESC_OPTS_END, 63 64 TOOLS_ARG_FIELD_DESC_ENUMS_BEG(font_mode 65 TOOLS_ARG_ENUM(font_outline), 66 TOOLS_ARG_ENUM(font_filled), 67 TOOLS_ARG_ENUM(font_pixmap) 68 TOOLS_ARG_FIELD_DESC_ENUMS_END, 69 70 TOOLS_ARG_FIELD_DESC(encoding), 71 TOOLS_ARG_FIELD_DESC(line_width), 72 TOOLS_ARG_FIELD_DESC(front_face), 73 74 TOOLS_ARG_FIELD_DESC(back_visible), //10 75 TOOLS_ARG_FIELD_DESC(wmargin_factor), 76 TOOLS_ARG_FIELD_DESC(hmargin_factor), 77 TOOLS_ARG_FIELD_DESC(lhjust), 78 TOOLS_ARG_FIELD_DESC(rhjust), 79 TOOLS_ARG_FIELD_DESC(confine) 80 ); 81 return s_v; 82 } 83 private: 84 void add_fields(){ 85 add_field(&lstrings); 86 add_field(&rstrings); 87 add_field(&num_spaces); 88 89 add_field(&color); 90 add_field(&font); 91 add_field(&font_modeling); 92 add_field(&encoding); 93 add_field(&line_width); 94 add_field(&front_face); 95 96 add_field(&back_visible); 97 add_field(&wmargin_factor); 98 add_field(&hmargin_factor); 99 add_field(&lhjust); 100 add_field(&rhjust); 101 add_field(&confine); 102 } 103 public: 104 virtual void render(render_action& a_action) 105 if(touched()) { 106 update_sg(); 107 reset_touched(); 108 } 109 if(back_visible.value()) m_back_sep.render 110 m_sep.render(a_action); 111 } 112 virtual void pick(pick_action& a_action) { 113 if(touched()) { 114 update_sg(); 115 reset_touched(); 116 } 117 if(back_visible.value()) { 118 m_back_sep.pick(a_action); 119 if(a_action.done()) return; 120 } 121 } 122 virtual void search(search_action& a_action) 123 if(touched()) { 124 update_sg(); 125 reset_touched(); 126 } 127 node::search(a_action); 128 if(a_action.done()) return; 129 if(back_visible.value()) { 130 m_back_sep.search(a_action); 131 if(a_action.done()) return; 132 } 133 m_sep.search(a_action); 134 if(a_action.done()) return; 135 } 136 virtual bool write(write_action& a_action) { 137 if(touched()) { 138 update_sg(); 139 reset_touched(); 140 } 141 if(back_visible.value()) if(!m_back_sep.wr 142 return m_sep.write(a_action); 143 } 144 virtual void bbox(bbox_action& a_action) { 145 if(touched()) { 146 update_sg(); 147 reset_touched(); 148 } 149 if(back_visible.value()) m_back_sep.bbox(a 150 m_sep.bbox(a_action); 151 } 152 public: 153 infos_box(const base_freetype& a_ttf) 154 :parent() 155 ,lstrings() 156 ,rstrings() 157 ,num_spaces(4) 158 159 ,color(colorf_black()) 160 ,font(font_hershey()) 161 ,font_modeling(font_filled) 162 ,encoding(encoding_PAW()) 163 ,line_width(1) 164 ,front_face(winding_ccw) 165 166 ,back_visible(true) 167 ,wmargin_factor(0.9f) 168 ,hmargin_factor(0.9f) 169 ,lhjust(left) 170 ,rhjust(right) 171 172 ,confine(false) 173 174 ,m_ttf(a_ttf) 175 { 176 add_fields(); 177 } 178 virtual ~infos_box(){} 179 public: 180 infos_box(const infos_box& a_from) 181 :parent(a_from) 182 ,lstrings(a_from.lstrings) 183 ,rstrings(a_from.rstrings) 184 ,num_spaces(a_from.num_spaces) 185 186 ,color(a_from.color) 187 ,font(a_from.font) 188 ,font_modeling(a_from.font_modeling) 189 ,encoding(a_from.encoding) 190 ,line_width(a_from.line_width) 191 ,front_face(a_from.front_face) 192 193 ,back_visible(a_from.back_visible) 194 ,wmargin_factor(a_from.wmargin_factor) 195 ,hmargin_factor(a_from.hmargin_factor) 196 ,lhjust(a_from.lhjust) 197 ,rhjust(a_from.rhjust) 198 199 ,confine(a_from.confine) 200 201 ,m_ttf(a_from.m_ttf) 202 { 203 add_fields(); 204 } 205 infos_box& operator=(const infos_box& a_from 206 parent::operator=(a_from); 207 lstrings = a_from.lstrings; 208 rstrings = a_from.rstrings; 209 num_spaces = a_from.num_spaces; 210 211 color = a_from.color; 212 font = a_from.font; 213 font_modeling = a_from.font_modeling; 214 encoding = a_from.encoding; 215 line_width = a_from.line_width; 216 front_face = a_from.front_face; 217 218 back_visible = a_from.back_visible; 219 wmargin_factor = a_from.wmargin_factor; 220 hmargin_factor = a_from.hmargin_factor; 221 lhjust = a_from.lhjust; 222 rhjust = a_from.rhjust; 223 224 confine = a_from.confine; 225 226 return *this; 227 } 228 public: 229 void update_sg() { 230 // have this method public in order to use 231 // This is so because infos_box::height is 232 // needed in plotter to place the box. 233 234 m_back_sep.clear(); //back_area::update_sg 235 236 m_sep.clear(); 237 238 if(width.value()<=0) return; 239 if(confine) { 240 if(height.value()<=0) return; 241 } 242 243 {bool empty = true; 244 std::vector<std::string>::const_iterator i 245 for(it=lstrings.values().begin();it!=lstri 246 if((*it).size()) {empty = false;break;} 247 } 248 if(empty){ 249 for(it=rstrings.values().begin();it!=rst 250 if((*it).size()) {empty = false;break; 251 } 252 } 253 if(empty) { 254 //parent::update_sg(); 255 return; 256 }} 257 258 rgba* mat = new rgba(); 259 mat->color = color; 260 m_sep.add(mat); 261 262 if(font==font_hershey()) { 263 draw_style* ds = new draw_style; 264 ds->style.value(draw_lines); 265 //ds->line_pattern = line_pattern; 266 ds->line_width = line_width; 267 m_sep.add(ds); 268 } 269 270 ////////////////////////////////////////// 271 /// left text //////////////////////////// 272 ////////////////////////////////////////// 273 base_text* ltext = 0; 274 matrix* ltsf = 0; 275 276 {separator* sep = new separator; 277 m_sep.add(sep); 278 ltsf = new matrix; 279 sep->add(ltsf); 280 if(font==font_hershey()) { 281 text_hershey* text = new text_hershey; 282 ltext = text; 283 text->encoding = encoding; 284 sep->add(text); 285 } else { 286 base_freetype* text = base_freetype::cre 287 //TTNODE* text = new TTNODE; 288 ltext = text; 289 text->font = font; 290 text->modeling = font_modeling; 291 sep->add(text); 292 } 293 ltext->strings = lstrings; 294 ltext->hjust = lhjust;} 295 296 ////////////////////////////////////////// 297 /// right text /////////////////////////// 298 ////////////////////////////////////////// 299 base_text* rtext = 0; 300 matrix* rtsf = 0; 301 302 {separator* sep = new separator; 303 m_sep.add(sep); 304 rtsf = new matrix; 305 sep->add(rtsf); 306 if(font==font_hershey()) { 307 text_hershey* text = new text_hershey; 308 rtext = text; 309 text->encoding = encoding; 310 sep->add(text); 311 } else { 312 base_freetype* text = base_freetype::cre 313 //TTNODE* text = new TTNODE; 314 rtext = text; 315 text->font = font; 316 text->modeling = font_modeling; 317 sep->add(text); 318 } 319 rtext->strings = rstrings; 320 rtext->hjust = rhjust;} 321 322 ////////////////////////////////////////// 323 /// middle spaces //////////////////////// 324 ////////////////////////////////////////// 325 base_text* mtext = 0; 326 {std::string _s(num_spaces,' '); 327 if(font==font_hershey()) { 328 text_hershey* text = new text_hershey; 329 mtext = text; 330 text->strings.add(_s); 331 text->hjust = left; 332 } else { 333 base_freetype* text = base_freetype::cre 334 //TTNODE* text = new TTNODE; 335 mtext = text; 336 text->strings.add(_s); 337 text->hjust = left; 338 text->font = font; 339 text->modeling = font_modeling; 340 }} 341 342 //sf<float> zfront ? 343 float zz = back_visible.value()?0.01f:0; 344 345 float fw = width * wmargin_factor; 346 347 if(confine) { 348 // left right texts may overlap. 349 350 // adjust height : 351 float fh = height * hmargin_factor; 352 float th = fh; 353 {float mn_x,mn_y,mn_z; 354 float mx_x,mx_y,mx_z; 355 ltext->get_bounds(th,mn_x,mn_y,mn_z,mx_x 356 float bxh = mx_y-mn_y; 357 // adjust box height : 358 // fh -> bxh then to have fh : 359 if(!bxh) { 360 m_sep.clear(); 361 parent::update_sg(); 362 delete mtext; 363 return; 364 } 365 th = fh*fh/bxh;} 366 367 ltext->height = th; 368 rtext->height = th; 369 370 {float mn_x,mn_y,mn_z; 371 float mx_x,mx_y,mx_z; 372 ltext->get_bounds(th,mn_x,mn_y,mn_z,mx_x 373 float lw = mx_x-mn_x; 374 float xtrans = (fw-lw)*0.5f; //left just 375 float xx = -(mn_x+mx_x)*0.5F-xtrans; 376 float yy = -(mn_y+mx_y)*0.5F; 377 ltsf->set_translate(xx,yy,zz);} 378 379 {float mn_x,mn_y,mn_z; 380 float mx_x,mx_y,mx_z; 381 rtext->get_bounds(th,mn_x,mn_y,mn_z,mx_x 382 rtext->hjust = right; 383 float xx = fw*0.5f; 384 float yy = -(mn_y+mx_y)*0.5F; 385 rtsf->set_translate(xx,yy,zz);} 386 387 parent::update_sg(); 388 389 } else { 390 // height of the info box is an output o 391 // The input to compute the geometry is 392 // box, the left/right texts and the spa 393 // left/right texts. 394 395 // from a text height of th=1, and a lef 396 // of num_spaces*th, get width of the bo 397 398 float th = 1; 399 400 float lmn_x,lmn_y,lmn_z; 401 float lmx_x,lmx_y,lmx_z; 402 ltext->get_bounds(th,lmn_x,lmn_y,lmn_z,l 403 float lw = (lmx_x<lmn_x)?0:lmx_x-lmn_x; 404 405 float rmn_x,rmn_y,rmn_z; 406 float rmx_x,rmx_y,rmx_z; 407 rtext->get_bounds(th,rmn_x,rmn_y,rmn_z,r 408 float rw = (rmx_x<rmn_x)?0:rmx_x-rmn_x; 409 410 float mmn_x,mmn_y,mmn_z; 411 float mmx_x,mmx_y,mmx_z; 412 mtext->get_bounds(th,mmn_x,mmn_y,mmn_z,m 413 float mw = (mmx_x<mmn_x)?0:mmx_x-mmn_x; 414 415 float winfos = lw+mw+rw; 416 if(!winfos) { 417 m_sep.clear(); 418 height = 1; 419 parent::update_sg(); 420 delete mtext; 421 return; 422 } 423 424 // assuming that text size is linear rel 425 // to th, we get the th needed to match 426 // th -> winfos then to have fw : 427 th = fw*th/winfos; 428 429 // place the left/right texts by rescali 430 // the new th : 431 ltext->height = th; 432 ltext->get_bounds(th,lmn_x,lmn_y,lmn_z,l 433 float hinfos = (lmx_x<lmn_x)?0:lmx_y-lmn 434 435 float xx = -fw*0.5F; //left justified. 436 float ty = -ltext->ascent(th)+hinfos*0.5 437 ltsf->set_translate(xx,ty,zz); 438 439 rtext->height = th; 440 if(rtext->hjust==right) { 441 xx = fw*0.5F; 442 } else if(rtext->hjust==left) { 443 rtext->get_bounds(th,rmn_x,rmn_y,rmn_z 444 rw = (rmx_x<rmn_x)?0:rmx_x-rmn_x; 445 xx = fw*0.5F-rw; 446 } else { //center 447 rtext->get_bounds(th,rmn_x,rmn_y,rmn_z 448 rw = (rmx_x<rmn_x)?0:rmx_x-rmn_x; 449 xx = fw*0.5F-rw*0.5F; 450 } 451 rtsf->set_translate(xx,ty,zz); 452 453 // set infos_box.height : 454 height = hinfos/hmargin_factor; 455 456 //done last because of the upper height 457 parent::update_sg(); 458 459 } 460 461 delete mtext; 462 463 } 464 protected: 465 const base_freetype& m_ttf; 466 467 separator m_sep; 468 }; 469 470 }} 471 472 #endif