Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/tools/sg/plots 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_plots
0005 #define tools_sg_plots
0006 
0007 #include "_switch"
0008 #include "matrix"
0009 
0010 #include "plotter"
0011 
0012 namespace tools {
0013 namespace sg {
0014 
0015 class plots : public node {
0016   TOOLS_NODE(plots,tools::sg::plots,node)
0017 public:
0018   sf<float> width;
0019   sf<float> height;
0020   sf<unsigned int> cols; //must never be 0.
0021   sf<unsigned int> rows; //must never be 0.
0022   sf<bool> view_border; //current plotter border
0023   sf<float> plotter_scale; //scale factor applied to each plotter.
0024 
0025   sf<bool> border_visible;
0026   sf<float> border_width;
0027   sf<float> border_height;
0028   sf<float> border_z;
0029   sf<float> border_scale;
0030   sf_vec<colorf,float> border_color;
0031 
0032   // for gopaw :
0033   sf<float> left_margin;
0034   sf<float> right_margin;
0035   sf<float> top_margin;
0036   sf<float> bottom_margin;
0037   sf<float> horizontal_spacing;
0038   sf<float> vertical_spacing;
0039 public:
0040   virtual const desc_fields& node_desc_fields() const {
0041     TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::plots)
0042     static const desc_fields s_v(parent::node_desc_fields(),18, //WARNING : take care of count.
0043       TOOLS_ARG_FIELD_DESC(width),  //1
0044       TOOLS_ARG_FIELD_DESC(height),
0045       TOOLS_ARG_FIELD_DESC(cols),
0046       TOOLS_ARG_FIELD_DESC(rows),
0047       TOOLS_ARG_FIELD_DESC(view_border),
0048       TOOLS_ARG_FIELD_DESC(plotter_scale),
0049       TOOLS_ARG_FIELD_DESC(border_visible),
0050       TOOLS_ARG_FIELD_DESC(border_width),
0051       TOOLS_ARG_FIELD_DESC(border_height),
0052       TOOLS_ARG_FIELD_DESC(border_z),  //10
0053       TOOLS_ARG_FIELD_DESC(border_scale),
0054       TOOLS_ARG_FIELD_DESC(border_color),
0055       TOOLS_ARG_FIELD_DESC(left_margin),
0056       TOOLS_ARG_FIELD_DESC(right_margin),
0057       TOOLS_ARG_FIELD_DESC(top_margin),
0058       TOOLS_ARG_FIELD_DESC(bottom_margin),
0059       TOOLS_ARG_FIELD_DESC(horizontal_spacing),
0060       TOOLS_ARG_FIELD_DESC(vertical_spacing)
0061     );
0062     return s_v;
0063   }
0064   virtual bool touched() {
0065     if(parent::touched()) return true;
0066 
0067      if(m_sep.empty()) return true;
0068      if(m_extras.size()!=m_extras_sep.size()) return true;
0069 
0070      return false;
0071    }
0072 private:
0073   void add_fields(){
0074     add_field(&width);
0075     add_field(&height);
0076     add_field(&cols);
0077     add_field(&rows);
0078     add_field(&view_border);
0079     add_field(&plotter_scale);
0080     add_field(&border_visible);
0081     add_field(&border_width);
0082     add_field(&border_height);
0083     add_field(&border_z);
0084     add_field(&border_scale);
0085     add_field(&border_color);
0086     add_field(&left_margin);
0087     add_field(&right_margin);
0088     add_field(&top_margin);
0089     add_field(&bottom_margin);
0090     add_field(&horizontal_spacing);
0091     add_field(&vertical_spacing);
0092   }
0093 private:
0094   static unsigned int MATRIX()  {return 0;}
0095   static unsigned int BORDER()  {return 1;}
0096   static unsigned int PLOTTER() {return 2;}
0097 
0098   typedef std::vector<plottable*> ptbs_t;
0099   typedef std::vector<node*> todels_t;
0100   typedef std::vector<plotprim*> prims_t;
0101 public:
0102   virtual void render(render_action& a_action) {
0103     update_if_touched();
0104     m_group.render(a_action);
0105   }
0106   virtual void pick(pick_action& a_action) {
0107     update_if_touched();
0108     nodekit_pick(a_action,m_group,this);
0109   }
0110   virtual void search(search_action& a_action) {
0111     update_if_touched();
0112     parent::search(a_action);
0113     if(a_action.done()) return;
0114     if(a_action.do_path()) a_action.path_push(this);
0115     m_group.search(a_action);
0116     if(a_action.done()) return;
0117     if(a_action.do_path()) a_action.path_pop();
0118   }
0119   virtual void bbox(bbox_action& a_action) {
0120     update_if_touched();
0121     m_group.bbox(a_action);
0122   }
0123 
0124   virtual void event(event_action& a_action) {
0125     update_if_touched();
0126     m_group.event(a_action);
0127     if(a_action.done()) return;
0128   }
0129   virtual bool write(write_action& a_action) {
0130     update_if_touched();
0131     return m_group.write(a_action);
0132   }
0133 public:
0134   plots(const base_freetype& a_ttf)
0135   :parent()
0136   ,width(1)
0137   ,height(1)
0138   ,cols(1)
0139   ,rows(1)
0140   ,view_border(true)
0141   ,plotter_scale(1)
0142   ,border_visible(false)
0143   ,border_width(0)
0144   ,border_height(0)
0145   ,border_z(0)
0146   ,border_scale(1)
0147   ,border_color(colorf_grey())
0148   ,left_margin(0)
0149   ,right_margin(0)
0150   ,top_margin(0)
0151   ,bottom_margin(0)
0152   ,horizontal_spacing(0)
0153   ,vertical_spacing(0)
0154 
0155   ,m_ttf(a_ttf)
0156   ,m_current(0)
0157   ,m_extras()
0158   ,m_old_cols(0)
0159   ,m_old_rows(0)
0160   {
0161     add_fields();
0162     init_sg();
0163   }
0164   virtual ~plots() {
0165   }
0166 public:
0167   plots(const plots& a_from)
0168   :parent(a_from)
0169   ,width(a_from.width)
0170   ,height(a_from.height)
0171   ,cols(a_from.cols)
0172   ,rows(a_from.rows)
0173   ,view_border(a_from.view_border)
0174   ,plotter_scale(a_from.plotter_scale)
0175   ,border_visible(a_from.border_visible)
0176   ,border_width(a_from.border_width)
0177   ,border_height(a_from.border_height)
0178   ,border_z(a_from.border_z)
0179   ,border_scale(a_from.border_scale)
0180   ,border_color(a_from.border_color)
0181   ,left_margin(a_from.left_margin)
0182   ,right_margin(a_from.right_margin)
0183   ,top_margin(a_from.top_margin)
0184   ,bottom_margin(a_from.bottom_margin)
0185   ,horizontal_spacing(a_from.horizontal_spacing)
0186   ,vertical_spacing(a_from.vertical_spacing)
0187 
0188   ,m_ttf(a_from.m_ttf)
0189   ,m_current(a_from.m_current)
0190   ,m_extras(a_from.m_extras)
0191   ,m_old_cols(0)
0192   ,m_old_rows(0)
0193   ,m_origins(a_from.m_origins)
0194   ,m_sizes(a_from.m_sizes)
0195   ,m_extras_origins(a_from.m_extras_origins)
0196   ,m_extras_sizes(a_from.m_extras_sizes)
0197   {
0198     add_fields();
0199     init_sg();
0200     if(!copy_plotters(a_from)) {}
0201   }
0202   plots& operator=(const plots& a_from){
0203     parent::operator=(a_from);
0204     if(&a_from==this) return *this;
0205 
0206     width = a_from.width;
0207     height = a_from.height;
0208 
0209     cols = a_from.cols;
0210     rows = a_from.rows;
0211     view_border = a_from.view_border;
0212     plotter_scale = a_from.plotter_scale;
0213 
0214     border_visible = a_from.border_visible;
0215     border_width = a_from.border_width;
0216     border_height = a_from.border_height;
0217     border_z = a_from.border_z;
0218     border_scale = a_from.border_scale;
0219     border_color = a_from.border_color;
0220 
0221     left_margin = a_from.left_margin;
0222     right_margin = a_from.right_margin;
0223     top_margin = a_from.top_margin;
0224     bottom_margin = a_from.bottom_margin;
0225     horizontal_spacing = a_from.horizontal_spacing;
0226     vertical_spacing = a_from.vertical_spacing;
0227 
0228     m_old_cols = 0;
0229     m_old_rows = 0;
0230     m_origins = a_from.m_origins;
0231     m_sizes = a_from.m_sizes;
0232     m_extras_origins = a_from.m_extras_origins;
0233     m_extras_sizes = a_from.m_extras_sizes;
0234 
0235     m_current = a_from.m_current;
0236     m_extras = a_from.m_extras;
0237 
0238     if(!copy_plotters(a_from)) {}
0239 
0240     return *this;
0241   }
0242 public:
0243   unsigned int number() const {return cols*rows;}
0244   unsigned int current_index() const {return m_current;}
0245 
0246   void adjust_size(unsigned int a_ww,unsigned int a_wh) {
0247     if(!a_ww||!a_wh) return;
0248     float aspect = float(a_ww)/float(a_wh);
0249     width = height * aspect;
0250   }
0251 
0252   const base_freetype& ttf() const {return m_ttf;}
0253 public:
0254   void clear() {
0255     update_if_touched();
0256    {size_t _number = m_sep.size();
0257     for(size_t index=0;index<_number;index++) {
0258       separator* sep = (separator*)m_sep[index];
0259       plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0260       _plotter->clear();
0261     }}
0262     tools_vforit(extra,m_extras,it) {
0263       separator* sep = (*it).m_sep;
0264       plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0265       _plotter->clear();
0266     }
0267   }
0268 
0269   bool has_data() {
0270     update_if_touched();
0271    {size_t _number = m_sep.size();
0272     for(size_t index=0;index<_number;index++) {
0273       separator* sep = (separator*)m_sep[index];
0274       plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0275       if(_plotter->plottables().size()) return true;
0276     }}
0277     tools_vforit(extra,m_extras,it) {
0278       separator* sep = (*it).m_sep;
0279       plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0280       if(_plotter->plottables().size()) return true;
0281     }
0282     return false;
0283   }
0284 
0285   void touch_plotters() { //used in exlib/geant4/session.
0286     update_if_touched();
0287    {size_t _number = m_sep.size();
0288     for(size_t index=0;index<_number;index++) {
0289       separator* sep = (separator*)m_sep[index];
0290       plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0291       _plotter->touch();
0292     }}
0293     tools_vforit(extra,m_extras,it) {
0294       separator* sep = (*it).m_sep;
0295       plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0296       _plotter->touch();
0297     }
0298   }
0299 
0300   void next() {
0301     update_if_touched();
0302     size_t _number = m_sep.size();
0303     if(m_current>=(uint32(_number)-1)) {
0304       m_current = 0;
0305     } else {
0306       m_current++;
0307     }
0308     update_current_border();
0309   }
0310 
0311   bool set_current_plotter(unsigned int a_index) {
0312     update_if_touched();
0313     if(a_index>=m_sep.size()) return false;
0314     m_current = a_index;
0315     update_current_border();
0316     return true;
0317   }
0318 
0319   bool set_current(plotter* a_plotter) { //for popup.
0320     update_if_touched();
0321     size_t _number = m_sep.size();
0322     for(size_t index=0;index<_number;index++) {
0323       separator* sep = (separator*)m_sep[index];
0324       plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0325       if(_plotter==a_plotter) {
0326         m_current = uint32(index);
0327         update_current_border();
0328         return true;
0329       }
0330     }
0331     return false;
0332   }
0333 
0334   plotter& current_plotter() {
0335     update_if_touched();
0336     separator* sep = (separator*)m_sep[m_current];
0337     return *((plotter*)(*sep)[PLOTTER()]);
0338   }
0339   plotter* find_plotter(unsigned int a_index) {
0340     update_if_touched();
0341     if(a_index>=m_sep.size()) return 0;
0342     separator* sep = (separator*)m_sep[a_index];
0343     return (plotter*)(*sep)[PLOTTER()];
0344   }
0345 
0346   void set_regions(unsigned int a_cols = 1,unsigned int a_rows = 1,bool a_transfer = false) {
0347     unsigned int oldn = cols*rows;
0348 
0349     std::vector<ptbs_t> ptbss;
0350     std::vector<prims_t> primss;
0351     std::vector<todels_t> tdlss;
0352     std::vector<plotter> pls;
0353 
0354     if(a_transfer) {
0355       ptbss.resize(oldn);
0356       primss.resize(oldn);
0357       tdlss.resize(oldn);
0358       pls.resize(oldn,plotter(m_ttf));
0359       for(unsigned int index=0;index<oldn;index++) {
0360         plotter* p = find_plotter(index);
0361         p->transfer_plottables(ptbss[index]);
0362         p->transfer_primitives(primss[index]);
0363         p->transfer_todels(tdlss[index]);
0364         pls[index] = *p; //to copy styles.
0365       }
0366     }
0367 
0368     cols = a_cols?a_cols:1;
0369     rows = a_rows?a_rows:1;
0370     if(view_border.value()) {view_border = (number()==1?false:true);}
0371     update_sg();
0372     set_current_plotter(0);
0373     clear();
0374     if(a_transfer) {
0375       //fill new plotters with old data :
0376       unsigned int num = min_of(oldn,cols*rows);
0377       for(unsigned int index=0;index<num;index++) {
0378         plotter* p = find_plotter(index);
0379         p->copy_style(pls[index]);  //it must not touch p width, height, depth.
0380 
0381        {const ptbs_t& ptbs = ptbss[index];
0382         tools_vforcit(plottable*,ptbs,it) p->add_plottable(*it);}
0383        {const prims_t& prims = primss[index];
0384         tools_vforcit(plotprim*,prims,it) p->add_primitive(*it);}
0385        {const todels_t& todels = tdlss[index];
0386         tools_vforcit(node*,todels,it) p->add_node_todel(*it);}
0387       }
0388     }
0389     reset_touched();
0390   }
0391 
0392   void current_to_one() {
0393     ptbs_t ptbs;current_plotter().transfer_plottables(ptbs);
0394     prims_t prims;current_plotter().transfer_primitives(prims);
0395     todels_t tdls;current_plotter().transfer_todels(tdls);
0396     plotter pl = current_plotter(); //to copy styles.
0397 
0398     set_regions(1,1,false);
0399 
0400     plotter& p = current_plotter();
0401     p.copy_style(pl); //copy styles.
0402 
0403    {tools_vforcit(plottable*,ptbs,it) p.add_plottable(*it);}
0404    {tools_vforcit(plotprim*,prims,it) p.add_primitive(*it);}
0405    {tools_vforcit(node*,tdls,it) p.add_node_todel(*it);}
0406 
0407   }
0408 
0409   void plotters(std::vector<plotter*>& a_vec) { //a_vec do NOT get ownership of sg::plotter objects. Use in G4Analysis.
0410     a_vec.clear();
0411     update_if_touched();
0412     size_t _number = m_sep.size();
0413     for(size_t index=0;index<_number;index++) {
0414       separator* sep = (separator*)m_sep[index];
0415       plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0416       a_vec.push_back(_plotter);
0417     }
0418   }
0419 
0420   //////////////////////////////////////////////////////////////////////
0421   //// styling methods : ///////////////////////////////////////////////
0422   //////////////////////////////////////////////////////////////////////
0423   void set_line_width(float a_line_width) {
0424     update_if_touched();
0425     size_t _number = m_sep.size();
0426     for(size_t index=0;index<_number;index++) {
0427       separator* sep = (separator*)m_sep[index];
0428       plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0429 
0430       _plotter->bins_style(0).line_width = a_line_width;
0431       _plotter->inner_frame_style().line_width = a_line_width;
0432       _plotter->grid_style().line_width = a_line_width;
0433       _plotter->x_axis().line_style().width = a_line_width;
0434       _plotter->x_axis().ticks_style().width = a_line_width;
0435       _plotter->y_axis().line_style().width = a_line_width;
0436       _plotter->y_axis().ticks_style().width = a_line_width;
0437       _plotter->z_axis().line_style().width = a_line_width;
0438       _plotter->z_axis().ticks_style().width = a_line_width;
0439       _plotter->colormap_axis().line_style().width = a_line_width;
0440       _plotter->colormap_axis().ticks_style().width = a_line_width;
0441 
0442       // needed if font is hershey :
0443       _plotter->title_style().line_width = a_line_width;
0444       _plotter->infos_style().line_width = a_line_width;
0445       _plotter->title_box_style().line_width = a_line_width;
0446 
0447       _plotter->x_axis().labels_style().line_width = a_line_width;
0448       _plotter->x_axis().mag_style().line_width = a_line_width;
0449       _plotter->x_axis().title_style().line_width = a_line_width;
0450 
0451       _plotter->y_axis().labels_style().line_width = a_line_width;
0452       _plotter->y_axis().mag_style().line_width = a_line_width;
0453       _plotter->y_axis().title_style().line_width = a_line_width;
0454 
0455       _plotter->z_axis().labels_style().line_width = a_line_width;
0456       _plotter->z_axis().mag_style().line_width = a_line_width;
0457       _plotter->z_axis().title_style().line_width = a_line_width;
0458 
0459       _plotter->colormap_axis().labels_style().line_width = a_line_width;
0460       _plotter->colormap_axis().mag_style().line_width = a_line_width;
0461       _plotter->colormap_axis().title_style().line_width = a_line_width;
0462     }
0463   }
0464 
0465   void set_grids_visibility(bool a_visible = false) {
0466     update_if_touched();
0467     size_t _number = m_sep.size();
0468     for(size_t index=0;index<_number;index++) {
0469       separator* sep = (separator*)m_sep[index];
0470       plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0471       _plotter->grid_style().visible = a_visible;
0472     }
0473     border_visible = true;
0474   }
0475 
0476   void adjust_scales(float a_plotter_scale = 1) {
0477     // Rescale some plotter parameters (for example margins) according to the number of plots.
0478     // We assume that these parameters had been set previously according to one plot per page.
0479     // Then this function must be applied after all the styles had been applied (because
0480     // a plotting style may set these parameters).
0481 
0482     float ww_wc = width.value();
0483     float wh_wc = height.value();
0484     float rw_wc = ww_wc/cols.value();
0485     float rh_wc = wh_wc/rows.value();
0486 
0487     float cooking = 1.2f; //if increased the data area is diminished.
0488 
0489     float wfac = (rw_wc/ww_wc)*cooking;
0490     float hfac = (rh_wc/wh_wc)*cooking;
0491 
0492     float label_cooking = 1.6f; //if increased the labels are bigger.
0493 
0494     if((cols.value()>=4)&&(cols.value()>rows.value())) label_cooking = 0.9f;
0495 
0496     float title_cooking = 1.1f; //extra title cooking.
0497 
0498     plotter_scale = a_plotter_scale;
0499 
0500     update_if_touched();
0501    {size_t _number = m_sep.size();
0502     for(size_t index=0;index<_number;index++) {
0503       separator* sep = (separator*)m_sep[index];
0504       plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0505 
0506       _plotter->left_margin = _plotter->left_margin * wfac;
0507       _plotter->right_margin = _plotter->right_margin * wfac;
0508       _plotter->bottom_margin = _plotter->bottom_margin * hfac;
0509       _plotter->top_margin = _plotter->top_margin * hfac;
0510 
0511       _plotter->x_axis().tick_length = _plotter->x_axis().tick_length * wfac;
0512       _plotter->y_axis().tick_length = _plotter->y_axis().tick_length * hfac;
0513 
0514       _plotter->title_to_axis = _plotter->title_to_axis * hfac;
0515       _plotter->title_height = _plotter->title_height * hfac * title_cooking;
0516 
0517       _plotter->x_axis().label_height = _plotter->x_axis().label_height * hfac * label_cooking;
0518       _plotter->y_axis().label_height = _plotter->y_axis().label_height * hfac * label_cooking;
0519     }}
0520   }
0521 
0522   //gopaw:
0523   void configure_grid_PAW(unsigned int a_ww,unsigned int a_wh) {
0524 
0525     m_origins.clear();
0526     m_sizes.clear();
0527 
0528     float wvp = float(a_ww); //pixels.
0529     float hvp = float(a_wh); //pixels.
0530     if( (wvp<=0)||(hvp<=0)||(width.value()<=0)||(height.value()<=0) ) return;
0531 
0532     unsigned int _cols = cols.value();
0533     unsigned int _rows = rows.value();
0534     if((!_cols)||(!_rows)) return;
0535 
0536     float wdata = (width.value()-left_margin.value()-right_margin.value()-(_cols-1)*horizontal_spacing.value())/_cols;
0537     float hdata = (height.value()-bottom_margin.value()-top_margin.value()-(_rows-1)*vertical_spacing.value())/_rows;
0538 
0539     if((wdata<=0)||(hdata<=0)) return;
0540 
0541 
0542     unsigned int _num = number();
0543     for(unsigned int iregion=0;iregion<_num;iregion++) {
0544       //iregion = col + row * cols
0545       unsigned int row = iregion/_cols;
0546       unsigned int col = iregion - row * _cols;
0547 
0548       float wr,hr,x,y,lm,rm,bm,tm;
0549       wr = hr = x = y = 0;
0550       lm = rm = bm = tm = 0;
0551 
0552       if(_cols==1) {
0553         wr = width.value();
0554         x = 0;
0555         lm = left_margin.value();
0556         rm = right_margin.value();
0557       } else {
0558         float wrl = left_margin.value()+wdata+horizontal_spacing.value()/2;
0559         float wrr = right_margin.value()+wdata+horizontal_spacing.value()/2;
0560         float wri = wdata+horizontal_spacing.value();
0561         if(col==0) {
0562           wr = wrl;
0563           x = 0;
0564           lm = left_margin.value();
0565           rm = horizontal_spacing.value()/2;
0566         } else if(col==(_cols-1)) {
0567           wr = wrr;
0568           x = width.value() - wrr;
0569           lm = horizontal_spacing.value()/2;
0570           rm = right_margin.value();
0571         } else {
0572           wr = wri;
0573           x = wrl + (col-1) * wri;
0574           lm = horizontal_spacing.value()/2;
0575           rm = horizontal_spacing.value()/2;
0576         }
0577       }
0578 
0579       if(_rows==1) {
0580         hr = height.value();
0581         y = 0;
0582         tm = top_margin.value();
0583         bm = bottom_margin.value();
0584       } else {
0585         float hrt = top_margin.value()+hdata+vertical_spacing.value()/2; //top
0586         float hrb = bottom_margin.value()+hdata+vertical_spacing.value()/2;     //bottom
0587         float hri = hdata+vertical_spacing.value();
0588         if(row==0) { //top row.
0589           hr = hrt;
0590           y = height.value()-hrt;
0591           tm = top_margin.value();
0592           bm = vertical_spacing.value()/2;
0593         } else if(row==(_rows-1)) {
0594           hr = hrb;
0595           y = 0;
0596           tm = vertical_spacing.value()/2;
0597           bm = bottom_margin.value();
0598         } else {
0599           hr = hri;
0600           y = height.value()- (hrt + row * hri);
0601           tm = vertical_spacing.value()/2;
0602           bm = vertical_spacing.value()/2;
0603         }
0604       }
0605 
0606       m_origins.push_back(vec2f(x,y));
0607       m_sizes.push_back(vec2f(wr,hr));
0608 
0609       separator* sep = (separator*)m_sep[iregion];
0610       plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0611 
0612       _plotter->left_margin = lm;
0613       _plotter->right_margin = rm;
0614 
0615       _plotter->top_margin = tm;
0616       _plotter->bottom_margin = bm; 
0617     }
0618   }
0619 
0620   void configure_extras_PAW(unsigned int a_ww,unsigned int a_wh) {
0621 
0622     m_extras_origins.clear();
0623     m_extras_sizes.clear();
0624 
0625     float wvp = float(a_ww); //pixels.
0626     float hvp = float(a_wh); //pixels.
0627     if( (wvp<=0)||(hvp<=0)||(width.value()<=0)||(height.value()<=0) ) return;
0628 
0629     tools_vforcit(extra,m_extras,it) {
0630       const extra& _extra = *it;
0631 
0632       unsigned int _cols = _extra.m_cols;
0633       unsigned int _rows = _extra.m_rows;
0634       if((!_cols)||(!_rows)) continue;
0635 
0636       float wdata = (width.value()-left_margin.value()-right_margin.value()-(_cols-1)*horizontal_spacing.value())/_cols;
0637       float hdata = (height.value()-bottom_margin.value()-top_margin.value()-(_rows-1)*vertical_spacing.value())/_rows;
0638 
0639       if((wdata<=0)||(hdata<=0)) continue;
0640 
0641       unsigned int iregion = _extra.m_index;
0642       unsigned int row = iregion/_cols;
0643       unsigned int col = iregion - row * _cols;
0644 
0645       float wr,hr,x,y,lm,rm,bm,tm;
0646       wr = hr = x = y = 0;
0647       lm = rm = bm = tm = 0;
0648 
0649       if(_cols==1) {
0650         wr = width.value();
0651         x = 0;
0652         lm = left_margin.value();
0653         rm = right_margin.value();
0654       } else {
0655         float wrl = left_margin.value()+wdata+horizontal_spacing.value()/2;
0656         float wrr = right_margin.value()+wdata+horizontal_spacing.value()/2;
0657         float wri = wdata+horizontal_spacing.value();
0658         if(col==0) {
0659           wr = wrl;
0660           x = 0;
0661           lm = left_margin.value();
0662           rm = horizontal_spacing.value()/2;
0663         } else if(col==(_cols-1)) {
0664           wr = wrr;
0665           x = width.value() - wrr;
0666           lm = horizontal_spacing.value()/2;
0667           rm = right_margin.value();
0668         } else {
0669           wr = wri;
0670           x = wrl + (col-1) * wri;
0671           lm = horizontal_spacing.value()/2;
0672           rm = horizontal_spacing.value()/2;
0673         }
0674       }
0675 
0676       if(_rows==1) {
0677         hr = height.value();
0678         y = 0;
0679         tm = top_margin.value();
0680         bm = bottom_margin.value();
0681       } else {
0682         float hrt = top_margin.value()+hdata+vertical_spacing.value()/2; //top
0683         float hrb = bottom_margin.value()+hdata+vertical_spacing.value()/2;     //bottom
0684         float hri = hdata+vertical_spacing.value();
0685         if(row==0) { //top row.
0686           hr = hrt;
0687           y = height.value()-hrt;
0688           tm = top_margin.value();
0689           bm = vertical_spacing.value()/2;
0690         } else if(row==(_rows-1)) {
0691           hr = hrb;
0692           y = 0;
0693           tm = vertical_spacing.value()/2;
0694           bm = bottom_margin.value();
0695         } else {
0696           hr = hri;
0697           y = height.value()- (hrt + row * hri);
0698           tm = vertical_spacing.value()/2;
0699           bm = vertical_spacing.value()/2;
0700         }
0701       }
0702 
0703       m_extras_origins.push_back(vec2f(x,y));
0704       m_extras_sizes.push_back(vec2f(wr,hr));
0705 
0706       separator* sep = _extra.m_sep;
0707       plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0708 
0709       _plotter->left_margin = lm;
0710       _plotter->right_margin = rm;
0711 
0712       _plotter->top_margin = tm;
0713       _plotter->bottom_margin = bm;
0714     } //tools_vforcit
0715   }
0716   void configure_PAW(unsigned int a_ww,unsigned int a_wh) {
0717     configure_grid_PAW(a_ww,a_wh);
0718     configure_extras_PAW(a_ww,a_wh);
0719     touch();
0720     update_if_touched();
0721   }
0722   //////////////////////////////////////////////////////////////////////
0723   //////////////////////////////////////////////////////////////////////
0724   //////////////////////////////////////////////////////////////////////
0725 
0726   //gopaw:
0727   void delete_extras() {
0728     m_extras_sep.clear();
0729     m_extras.clear();
0730   }
0731 
0732   plotter* create_extra_plotter(unsigned int a_cols,unsigned int a_rows,unsigned int a_index) {
0733     // Create a plotter with size and position as if in a grid of a_colsxa_rows and at position a_index.
0734     // The index numbering being for example for a grid of 3x2 :
0735     //  0 1 2
0736     //  3 4 5
0737     m_extras.push_back(extra(a_cols,a_rows,a_index));
0738     update_if_touched();
0739     separator* sep = m_extras.back().m_sep;
0740     return (plotter*)(*sep)[PLOTTER()];
0741   }
0742   plotter* last_extra_plotter() const {
0743     if(m_extras.empty()) return 0;
0744     separator* sep = m_extras.back().m_sep;
0745     return (plotter*)(*sep)[PLOTTER()];
0746   }
0747 public:
0748   void init_sg() {  // used also in gopaw::base_viewer::clean_gstos().
0749     m_group.clear();
0750     m_sep.clear();
0751     m_border_sep.clear();
0752     m_extras_sep.clear();
0753     m_group.add(new noderef(m_sep));
0754     m_group.add(new noderef(m_border_sep));
0755     m_group.add(new noderef(m_extras_sep));
0756   }
0757   void clear_sg() { //used in GL_plots_viewer.
0758     m_group.clear();
0759     m_sep.clear();
0760     m_border_sep.clear();
0761     m_extras_sep.clear();
0762   }
0763 protected:
0764   void update_if_touched() {
0765     if(touched()) {
0766       update_sg();
0767       reset_touched();
0768     }
0769   }
0770   void update_sg(){
0771 
0772     if(m_sep.empty()||(cols.value()!=m_old_cols)||(rows.value()!=m_old_rows)){
0773 
0774       m_old_cols = cols;
0775       m_old_rows = rows;
0776 
0777       m_sep.clear();
0778 
0779       for(unsigned int irow=0;irow<rows;irow++) {
0780         for(unsigned int icol=0;icol<cols;icol++) {
0781           separator* sep = new separator;
0782           m_sep.add(sep);
0783 
0784           sep->add(new sg::matrix); //MATRIX()
0785 
0786           _switch* border = new _switch;
0787           sep->add(border); //BORDER()
0788 
0789           sep->add(new plotter(m_ttf)); //PLOTTER()
0790         }
0791       }
0792 
0793       if(m_current>=m_sep.size()) m_current = 0;
0794     }
0795 
0796     update_current_border();
0797     update_border();
0798 
0799     if((width.value()>0)&&(height.value()>0)) {
0800       size_t _number = m_sep.size();
0801 
0802       bool configure = (m_origins.size()==_number)&&(m_sizes.size()==_number)?true:false;
0803 
0804       // all window wc :
0805       float ww_wc = width;
0806       float wh_wc = height;
0807 
0808       for(size_t index=0;index<_number;index++) {
0809         separator* sep = (separator*)m_sep[index];
0810         set_plotter_layout(*sep,index,configure,cols.value(),rows.value(),
0811                            ww_wc,wh_wc,m_origins,m_sizes,plotter_scale.value());
0812       }
0813     }
0814 
0815     update_extras();
0816   }
0817 
0818   bool copy_plotters(const plots& a_from) {
0819     update_if_touched();
0820     if(m_sep.size()==a_from.m_sep.size()) {
0821       size_t _number = m_sep.size();
0822       for(size_t index=0;index<_number;index++) {
0823         separator* _from_sep = (separator*)a_from.m_sep[index];
0824         matrix* _from_matrix = (matrix*)(*_from_sep)[MATRIX()];
0825         plotter* _from_plotter = (plotter*)(*_from_sep)[PLOTTER()];
0826 
0827         separator* _sep = (separator*)m_sep[index];
0828         matrix* _matrix = (matrix*)(*_sep)[MATRIX()];
0829         plotter* _plotter = (plotter*)(*_sep)[PLOTTER()];
0830 
0831         _matrix->operator=(*_from_matrix);
0832         _plotter->operator=(*_from_plotter);
0833       }
0834     }
0835     if(m_extras_sep.size()==a_from.m_extras_sep.size()) {
0836       size_t _number = m_extras_sep.size();
0837       for(size_t index=0;index<_number;index++) {
0838         separator* _from_sep = (separator*)a_from.m_extras_sep[index];
0839         matrix* _from_matrix = (matrix*)(*_from_sep)[MATRIX()];
0840         plotter* _from_plotter = (plotter*)(*_from_sep)[PLOTTER()];
0841 
0842         separator* _sep = (separator*)m_extras_sep[index];
0843         matrix* _matrix = (matrix*)(*_sep)[MATRIX()];
0844         plotter* _plotter = (plotter*)(*_sep)[PLOTTER()];
0845 
0846         _matrix->operator=(*_from_matrix);
0847         _plotter->operator=(*_from_plotter);
0848       }
0849     }
0850     return true;
0851   }
0852 
0853   static void create_plotter_border(_switch& a_parent,float a_w,float a_h) {
0854     a_parent.clear();
0855 
0856     group* sep = new group;
0857     a_parent.add(sep);
0858 
0859     a_parent.add(new group()); //empty
0860 
0861     rgba* mat = new rgba();
0862     mat->color = colorf_red();
0863     sep->add(mat);
0864 
0865     draw_style* ds = new draw_style;
0866     ds->style = draw_lines;
0867     ds->line_width = 4;
0868     sep->add(ds);
0869 
0870     vertices* vtxs = new vertices;
0871     vtxs->mode = gl::line_strip();
0872     sep->add(vtxs);
0873 
0874     float dw = a_w*0.5f;
0875     float dh = a_h*0.5f;
0876     vtxs->add(-dw,-dh,0);
0877     vtxs->add( dw,-dh,0);
0878     vtxs->add( dw, dh,0);
0879     vtxs->add(-dw, dh,0);
0880     vtxs->add(-dw,-dh,0);
0881   }
0882 
0883   void update_current_border() {
0884     size_t _number = m_sep.size();
0885     for(size_t index=0;index<_number;index++) {
0886       separator* sep = (separator*)m_sep[index];
0887       _switch* _border = (_switch*)(*sep)[BORDER()];
0888       if(index==m_current) {
0889         _border->which = view_border.value()?0:1;
0890       } else {
0891         _border->which = 1;
0892       }
0893     }
0894   }
0895 
0896   void update_border() {
0897     m_border_sep.clear();
0898 
0899     if(!border_visible.value()) return;
0900 
0901     if(width.value()<=0) return;
0902     if(height.value()<=0) return;
0903     if(border_width.value()<=0) return;
0904     if(border_height.value()<=0) return;
0905 
0906     // border_scale could be used as an offscreen (inzb_[ps,png,jpeg], gl2s_pdf)
0907     // cooking to avoid seeing a one pixel line at some side (in general left)
0908     // coming from the border.
0909     if(border_scale.value()!=1) {
0910       matrix* _m = new matrix;
0911       _m->set_scale(border_scale.value(),border_scale.value(),1);
0912       m_border_sep.add(_m);
0913     }
0914 
0915     float bw = border_width;
0916     float bh = border_height;
0917 
0918     // do it with four externals back_area.
0919 
0920     float zz = border_z.value();
0921 
0922     // top :
0923    {separator* sep = new separator;
0924     m_border_sep.add(sep);
0925 
0926     float wba = width+2*bw;
0927     float hba = bh;
0928     float x = 0;
0929     float y = height*0.5f+bh*0.5f;
0930 
0931     matrix* _m = new matrix;
0932     _m->set_translate(x,y,zz);
0933     sep->add(_m);
0934 
0935     back_area* b = new back_area;
0936     b->border_visible = false;
0937     b->color = border_color;
0938     b->width = wba;
0939     b->height = hba;
0940     sep->add(b);}
0941 
0942     // bottom :
0943    {separator* sep = new separator;
0944     m_border_sep.add(sep);
0945 
0946     float wba = width+2*bw;
0947     float hba = bh;
0948     float x = 0;
0949     float y = -height*0.5f-bh*0.5f;
0950 
0951     matrix* _m = new matrix;
0952     _m->set_translate(x,y,zz);
0953     sep->add(_m);
0954 
0955     back_area* b = new back_area;
0956     b->border_visible = false;
0957     b->color = border_color;
0958     b->width = wba;
0959     b->height = hba;
0960     sep->add(b);}
0961 
0962     // left :
0963    {separator* sep = new separator;
0964     m_border_sep.add(sep);
0965 
0966     float wba = bw;
0967     float hba = height+2*bh;
0968     float x = -width*0.5f-bw*0.5f;
0969     float y = 0;
0970 
0971     matrix* _m = new matrix;
0972     _m->set_translate(x,y,zz);
0973     sep->add(_m);
0974 
0975     back_area* b = new back_area;
0976     b->border_visible = false;
0977     b->color = border_color;
0978     b->width = wba;
0979     b->height = hba;
0980     sep->add(b);}
0981 
0982     // right :
0983    {separator* sep = new separator;
0984     m_border_sep.add(sep);
0985 
0986     float wba = bw;
0987     float hba = height+2*bh;
0988     float x = width*0.5f+bw*0.5f;
0989     float y = 0;
0990 
0991     matrix* _m = new matrix;
0992     _m->set_translate(x,y,zz);
0993     sep->add(_m);
0994 
0995     back_area* b = new back_area;
0996     b->border_visible = false;
0997     b->color = border_color;
0998     b->width = wba;
0999     b->height = hba;
1000     sep->add(b);}
1001 
1002   }
1003 protected:
1004   class extra {
1005   public:
1006     extra(unsigned int a_cols,unsigned int a_rows,unsigned int a_index)
1007     :m_cols(a_cols),m_rows(a_rows),m_index(a_index),m_sep(0){}
1008     virtual ~extra(){}
1009   public:
1010     extra(const extra& a_from):m_cols(a_from.m_cols),m_rows(a_from.m_rows),m_index(a_from.m_index),m_sep(0){}
1011     extra& operator=(const extra& a_from) {
1012       m_cols = a_from.m_cols;
1013       m_rows = a_from.m_rows;
1014       m_index = a_from.m_index;
1015       m_sep = a_from.m_sep;
1016       return *this;
1017     }
1018   public:
1019     unsigned int m_cols;
1020     unsigned int m_rows;
1021     unsigned int m_index;
1022     separator* m_sep;
1023   };
1024 
1025   void update_extras() {
1026     if(m_extras.size()!=m_extras_sep.size()) {
1027       m_extras_sep.clear();
1028       tools_vforit(extra,m_extras,it) { // same sg layout than grid plotters.
1029         separator* sep = new separator;
1030         m_extras_sep.add(sep);
1031         (*it).m_sep = sep; //*it does not get ownership.
1032 
1033         sep->add(new sg::matrix); //MATRIX()
1034 
1035         _switch* border = new _switch;
1036         sep->add(border); //BORDER()
1037         sep->add(new plotter(m_ttf)); //PLOTTER()
1038       }
1039     }
1040 
1041     if(width.value()<=0) return;
1042     if(height.value()<=0) return;
1043 
1044     // all window wc :
1045     float ww_wc = width;
1046     float wh_wc = height;
1047 
1048     size_t _number = m_extras.size();
1049 
1050     bool configure = (m_extras_origins.size()==_number)&&(m_extras_sizes.size()==_number)?true:false;
1051 
1052     tools_vforcit(extra,m_extras,it) {
1053       const extra& _extra = *it;
1054       unsigned int index = _extra.m_index;
1055       if(index>=(m_extras_sep.size())) index = 0;
1056 
1057       separator* sep = _extra.m_sep;
1058       set_plotter_layout(*sep,index,configure,_extra.m_cols,_extra.m_rows,
1059                          ww_wc,wh_wc,m_extras_origins,m_extras_sizes,plotter_scale.value());
1060     }
1061 
1062   }
1063 protected:
1064   static void set_plotter_layout(separator& a_sep,size_t a_index,bool a_configure,
1065                           unsigned int a_cols,unsigned int a_rows,
1066                           float a_ww_wc,float a_wh_wc,
1067                           const std::vector<vec2f>& a_origins,const std::vector<vec2f>& a_sizes,float a_scale) {
1068     size_t row = a_index/a_cols;
1069     size_t col = a_index-a_cols*row;
1070 
1071     float rw_wc = a_ww_wc/a_cols;
1072     float rh_wc = a_wh_wc/a_rows;
1073 
1074     matrix* _matrix = (matrix*)(a_sep)[MATRIX()];
1075     plotter* _plotter = (plotter*)(a_sep)[PLOTTER()];
1076 
1077     if(a_configure) {
1078       _plotter->width = a_sizes[a_index].x();
1079       _plotter->height = a_sizes[a_index].y();
1080       float x = -a_ww_wc*0.5f + a_origins[a_index].x() + _plotter->width*0.5f;
1081       float y = -a_wh_wc*0.5f + a_origins[a_index].y() + _plotter->height*0.5f;
1082       _matrix->set_translate(x,y,0);
1083     } else {
1084       float x = -a_ww_wc*0.5f + col * rw_wc + rw_wc * 0.5f;
1085       float y =  a_wh_wc*0.5f - row * rh_wc - rh_wc * 0.5f;
1086       _matrix->set_translate(x,y,0);
1087     }
1088     _matrix->mul_scale(a_scale,a_scale,1); //applied first.
1089 
1090    {_switch* _border = (_switch*)(a_sep)[BORDER()];
1091     create_plotter_border(*_border,rw_wc,rh_wc);
1092     _border->which = 1;
1093     }
1094 
1095     if(_plotter->shape.value()==plotter::xy) {
1096       _plotter->depth = min_of(rw_wc,rh_wc);
1097     } else {
1098       _plotter->depth = rh_wc;
1099     }
1100 
1101     if(a_configure) {
1102     } else {
1103       if(_plotter->shape.value()==plotter::xy) {
1104         _plotter->width = rw_wc;
1105         _plotter->height = rh_wc;
1106       } else {
1107         if((rw_wc/rh_wc)>=1.0f) {
1108           _plotter->width = rh_wc;
1109           _plotter->height = rh_wc;
1110         } else {
1111           _plotter->width = rw_wc;
1112           _plotter->height = rw_wc;
1113         }
1114       }
1115     }
1116   }
1117 protected:
1118   const base_freetype& m_ttf;
1119 
1120   group m_group;
1121   separator m_sep;
1122   separator m_border_sep;
1123   separator m_extras_sep;
1124   unsigned int m_current;
1125 
1126   std::vector<extra> m_extras;
1127 
1128   //updater* m_updater;
1129   unsigned int m_old_cols;
1130   unsigned int m_old_rows;
1131 
1132   std::vector<vec2f> m_origins;
1133   std::vector<vec2f> m_sizes;
1134   std::vector<vec2f> m_extras_origins;
1135   std::vector<vec2f> m_extras_sizes;
1136 
1137 };
1138 
1139 }}
1140 
1141 #endif