00001
00002 #include "vgui_selector_tableau.h"
00003
00004
00005
00006
00007
00008
00009 #include <vcl_iostream.h>
00010 #include <vcl_sstream.h>
00011 #include <vcl_vector.h>
00012 #include <vcl_algorithm.h>
00013 #include <vcl_string.h>
00014
00015 #include <vgui/vgui.h>
00016 #include <vgui/vgui_gl.h>
00017 #include <vgui/vgui_event.h>
00018 #include <vgui/vgui_command.h>
00019 #include <vgui/vgui_menu.h>
00020 #include <vgui/vgui_popup_params.h>
00021 #include <vgui/vgui_matrix_state.h>
00022
00023
00024
00025
00026 vgui_selector_tableau::vgui_selector_tableau()
00027 {
00028 }
00029
00030
00031
00032
00033
00034 vgui_selector_tableau::vgui_selector_tableau(vcl_vector<vgui_tableau_sptr> const& the_children)
00035 {
00036 for (unsigned int i = 0; i < the_children.size(); ++i)
00037 add(the_children[i]);
00038 active_child_ = render_order_.front();
00039 }
00040
00041
00042
00043 vgui_selector_tableau::~vgui_selector_tableau()
00044 {
00045 }
00046
00047
00048
00049 vcl_string vgui_selector_tableau::file_name() const
00050 {
00051 vcl_map<vcl_string, vgui_parent_child_link>::const_iterator itr = child_map_.find(active_child_);
00052 if (itr != child_map_.end())
00053 return itr->second->file_name();
00054
00055 return type_name();
00056 }
00057
00058
00059
00060
00061 vcl_string vgui_selector_tableau::pretty_name() const
00062 {
00063 vcl_stringstream s; s << type_name() << "[#kids=" << child_map_.size() << ']';
00064 return s.str();
00065 }
00066
00067
00068
00069 bool vgui_selector_tableau::handle(const vgui_event& event)
00070 {
00071
00072
00073 vgui_matrix_state PM;
00074
00075
00076 if (event.type==vgui_DRAW || event.type==vgui_DRAW_OVERLAY) {
00077 bool retv = true;
00078
00079 vcl_vector<vcl_string>::iterator itr = render_order_.begin();
00080 for (; itr != render_order_.end(); ++itr){
00081 if (visible_[*itr] && child_map_[*itr]) {
00082 PM.restore();
00083 if ( !child_map_[*itr]->handle(event) )
00084 retv=false;
00085 }
00086 }
00087
00088 return retv;
00089 }
00090
00091
00092
00093 vcl_map<vcl_string, vgui_parent_child_link>::iterator itr = child_map_.find(active_child_);
00094 if (itr == child_map_.end() || !itr->second)
00095 return false;
00096
00097 return itr->second->handle(event);
00098 }
00099
00100
00101
00102 bool vgui_selector_tableau::get_bounding_box(float lo[3], float hi[3]) const
00103 {
00104
00105 if (child_map_.empty())
00106 return false;
00107
00108
00109 vcl_vector<vcl_string>::const_iterator o_itr = render_order_.begin();
00110 for (; o_itr!=render_order_.end(); ++o_itr ){
00111 vcl_map<vcl_string, bool>::const_iterator v_itr = visible_.find(*o_itr);
00112 if ((v_itr != visible_.end()) && v_itr->second){
00113 vcl_map<vcl_string, vgui_parent_child_link>::const_iterator t_itr = child_map_.find(*o_itr);
00114 if (!t_itr->second->get_bounding_box(lo, hi))
00115 return false;
00116 break;
00117 }
00118 }
00119
00120 if (o_itr == render_order_.end())
00121 return false;
00122
00123 for (; o_itr!=render_order_.end(); ++o_itr ){
00124 vcl_map<vcl_string, bool>::const_iterator v_itr = visible_.find(*o_itr);
00125 if ((v_itr != visible_.end()) && v_itr->second){
00126
00127 vcl_map<vcl_string, vgui_parent_child_link>::const_iterator t_itr = child_map_.find(*o_itr);
00128 float l[3], h[3];
00129 if (!t_itr->second->get_bounding_box(l, h))
00130 return false;
00131
00132
00133 for (unsigned j=0; j<3; ++j) {
00134 if (l[j] < lo[j]) lo[j] = l[j];
00135 if (h[j] > hi[j]) hi[j] = h[j];
00136 }
00137 }
00138 }
00139 return true;
00140 }
00141
00142
00143 void vgui_selector_tableau::add(vgui_tableau_sptr const& tab, vcl_string name)
00144 {
00145 if (name == "") name = tab->file_name();
00146
00147 vcl_map<vcl_string, vgui_parent_child_link>::iterator itr = child_map_.find(name);
00148 bool exists = (itr != child_map_.end());
00149
00150 child_map_[name] = vgui_parent_child_link(this,tab);
00151 if (!exists){
00152 render_order_.push_back(name);
00153 visible_[name] = true;
00154 }
00155 if (active_child_ == "") active_child_ = name;
00156 }
00157
00158
00159
00160
00161 bool vgui_selector_tableau::add_child(vgui_tableau_sptr const& t)
00162 {
00163 this->add(t);
00164 return true;
00165 }
00166
00167
00168
00169 void vgui_selector_tableau::remove(vgui_tableau_sptr const& t)
00170 {
00171 if (!remove_child(t))
00172 vcl_cerr << __FILE__ " : no such child tableau\n";
00173 }
00174
00175
00176
00177 bool vgui_selector_tableau::remove(const vcl_string name)
00178 {
00179 vcl_map<vcl_string, vgui_parent_child_link>::iterator itr = child_map_.find(name);
00180 if (itr != child_map_.end())
00181 child_map_.erase(itr);
00182 else
00183 return false;
00184
00185 vcl_map<vcl_string, bool>::iterator v_itr = visible_.find(name);
00186 if (v_itr != visible_.end())
00187 visible_.erase(v_itr);
00188
00189 vcl_vector<vcl_string>::iterator o_itr = vcl_find(render_order_.begin(),
00190 render_order_.end(),
00191 name);
00192 if (o_itr != render_order_.end())
00193 render_order_.erase(o_itr);
00194
00195 if (active_child_ == name){
00196 active_child_ = "";
00197 for (o_itr = render_order_.begin(); o_itr!=render_order_.end(); ++o_itr ){
00198 if (visible_[*o_itr]){
00199 active_child_ = *o_itr;
00200 break;
00201 }
00202 }
00203 }
00204 return true;
00205 }
00206
00207
00208 void vgui_selector_tableau::clear()
00209 {
00210 child_map_.clear();
00211 visible_.clear();
00212 render_order_.clear();
00213 active_child_ = "";
00214 }
00215
00216
00217
00218 vgui_tableau_sptr vgui_selector_tableau::active_tableau() const
00219 {
00220 vcl_map<vcl_string, vgui_parent_child_link>::const_iterator itr = child_map_.find(active_child_);
00221 if (itr == child_map_.end()) return NULL;
00222 return itr->second;
00223 }
00224
00225
00226
00227 vgui_tableau_sptr vgui_selector_tableau::get_tableau(const vcl_string& name) const
00228 {
00229 vcl_map<vcl_string, vgui_parent_child_link>::const_iterator itr = child_map_.find(name);
00230 if (itr == child_map_.end()) return NULL;
00231 return itr->second;
00232 }
00233
00234
00235
00236 bool vgui_selector_tableau::remove_child(vgui_tableau_sptr const &t)
00237 {
00238 bool retval = false;
00239
00240 for (vcl_map<vcl_string, vgui_parent_child_link>::iterator itr=child_map_.begin();
00241 itr!=child_map_.end(); ++itr )
00242 if ( (itr->second.child()) == t )
00243 retval = this->remove(itr->first) || retval;
00244
00245 return retval;
00246 }
00247
00248
00249
00250 bool vgui_selector_tableau::toggle(const vcl_string& name)
00251 {
00252 vcl_map<vcl_string, bool>::iterator itr = visible_.find(name);
00253 if (itr == visible_.end()) return false;
00254 bool state = itr->second;
00255 itr->second = !state;
00256
00257 return true;
00258 }
00259
00260
00261 bool vgui_selector_tableau::is_visible(const vcl_string& name) const
00262 {
00263 vcl_map<vcl_string, bool>::const_iterator itr = visible_.find(name);
00264 if (itr == visible_.end()) return false;
00265 return itr->second;
00266 }
00267
00268
00269
00270 void vgui_selector_tableau::set_active(const vcl_string& name)
00271 {
00272 vcl_map<vcl_string, vgui_parent_child_link>::iterator itr = child_map_.find(name);
00273 if (itr != child_map_.end()) active_child_ = name;
00274 }
00275
00276
00277
00278 void vgui_selector_tableau::active_raise()
00279 {
00280 vcl_vector<vcl_string>::iterator itr;
00281 itr = vcl_find(render_order_.begin(), render_order_.end(), active_child_);
00282 if (itr != render_order_.end() && itr+1 != render_order_.end()) {
00283 *itr = *(itr+1);
00284 *(itr+1) = active_child_;
00285 }
00286 }
00287
00288
00289
00290 void vgui_selector_tableau::active_lower()
00291 {
00292 vcl_vector<vcl_string>::iterator itr;
00293 itr = vcl_find(render_order_.begin(), render_order_.end(), active_child_);
00294 if (itr != render_order_.end() && itr != render_order_.begin()) {
00295 *itr = *(itr-1);
00296 *(itr-1) = active_child_;
00297 }
00298 }
00299
00300
00301
00302 void vgui_selector_tableau::active_to_top()
00303 {
00304 vcl_vector<vcl_string>::iterator itr;
00305 itr = vcl_find(render_order_.begin(), render_order_.end(), active_child_);
00306 while (itr != render_order_.end() && itr+1 != render_order_.end()) {
00307 *itr = *(itr+1);
00308 ++itr;
00309 }
00310 *(itr) = active_child_;
00311 }
00312
00313
00314
00315 void vgui_selector_tableau::active_to_bottom()
00316 {
00317 vcl_vector<vcl_string>::iterator itr;
00318 itr = vcl_find(render_order_.begin(), render_order_.end(), active_child_);
00319 while (itr != render_order_.end() && itr != render_order_.begin()) {
00320 *itr = *(itr-1);
00321 --itr;
00322 }
00323 *(itr) = active_child_;
00324 }
00325
00326
00327 class vgui_selector_switch_command : public vgui_command
00328 {
00329 public:
00330 vgui_selector_switch_command(vgui_selector_tableau* s, const vcl_string& n) : selector(s), name(n) {}
00331 void execute() { selector->set_active(name); selector->post_redraw(); }
00332
00333 vgui_selector_tableau *selector;
00334 vcl_string name;
00335 };
00336
00337
00338 class vgui_selector_toggle_command : public vgui_command
00339 {
00340 public:
00341 vgui_selector_toggle_command(vgui_selector_tableau* s, const vcl_string& n) : selector(s), name(n) {}
00342 void execute() { selector->toggle(name); selector->post_redraw(); }
00343
00344 vgui_selector_tableau *selector;
00345 vcl_string name;
00346 };
00347
00348
00349 class vgui_selector_position_command : public vgui_command
00350 {
00351 public:
00352 enum motion { TO_TOP, RAISE, LOWER, TO_BOTTOM };
00353 vgui_selector_position_command(vgui_selector_tableau* s, motion m) : selector(s), m_type(m) {}
00354 void execute()
00355 {
00356 switch (m_type)
00357 {
00358 case TO_TOP:
00359 selector->active_to_top();
00360 break;
00361 case RAISE:
00362 selector->active_raise();
00363 break;
00364 case LOWER:
00365 selector->active_lower();
00366 break;
00367 case TO_BOTTOM:
00368 selector->active_to_bottom();
00369 break;
00370 default:
00371 break;
00372 };
00373 selector->post_redraw();
00374 }
00375
00376 vgui_selector_tableau *selector;
00377 motion m_type;
00378 };
00379
00380
00381
00382
00383 void vgui_selector_tableau::get_popup(const vgui_popup_params& params,
00384 vgui_menu &menu)
00385 {
00386 vgui_menu submenu;
00387
00388
00389 vgui_menu active_menu;
00390 vgui_menu visible_menu;
00391 vgui_menu position_menu;
00392
00393 vcl_string check;
00394 vcl_vector<vcl_string>::reverse_iterator itr = render_order_.rbegin();
00395 for ( ; itr != render_order_.rend() ; ++itr) {
00396 vcl_string box_head, box_tail, check;
00397 if ( !get_tableau(*itr) ){
00398 box_head = "(";
00399 box_tail = ") ";
00400 }
00401 else{
00402 box_head = "[";
00403 box_tail = "] ";
00404 }
00405
00406 if ( *itr == active_child_ ) check = "x";
00407 else check = " ";
00408 active_menu.add(box_head+check+box_tail+(*itr),
00409 new vgui_selector_switch_command(this,*itr));
00410
00411 if ( is_visible(*itr) ) check = "x";
00412 else check = " ";
00413 visible_menu.add(box_head+check+box_tail+(*itr),
00414 new vgui_selector_toggle_command(this,*itr));
00415 }
00416
00417 position_menu.add("Move to Top", new vgui_selector_position_command(this, vgui_selector_position_command::TO_TOP));
00418 position_menu.add("Move Up", new vgui_selector_position_command(this, vgui_selector_position_command::RAISE));
00419 position_menu.add("Move Down", new vgui_selector_position_command(this,vgui_selector_position_command::LOWER));
00420 position_menu.add("Move to Bottom", new vgui_selector_position_command(this,vgui_selector_position_command::TO_BOTTOM));
00421
00422 submenu.add("Toggle Visible", visible_menu);
00423 submenu.add("Select Active", active_menu);
00424 submenu.add("Position Active", position_menu);
00425 add_to_menu(submenu);
00426 if (params.nested)
00427 {
00428
00429
00430 vgui_tableau_sptr a = active_tableau();
00431
00432 if (a && params.defaults) submenu.separator();
00433 a->get_popup(params, submenu);
00434 menu.add(type_name(), submenu);
00435 }
00436 else
00437 {
00438 menu.add(type_name(),submenu);
00439
00440 if (params.recurse) {
00441 vgui_tableau_sptr a = active_tableau();
00442 if (a)
00443 a->get_popup(params, menu);
00444 }
00445 }
00446 }
00447