1 // This is core/vgui/vgui_displaybase_tableau.cxx
2 //:
3 // \file
4 // \author Philip C. Pritchett, RRG, University of Oxford
5 // \date 14 Sep 1999
6 // \brief See vgui_displaybase_tableau.h for a description of this file.
7
8 #include <iostream>
9 #include <vector>
10 #include <algorithm>
11 #include <utility>
12 #include "vgui_displaybase_tableau.h"
13 #include "vgui_macro.h"
14
15 #ifdef _MSC_VER
16 # include "vcl_msvc_warnings.h"
17 #endif
18
19 #include "vgui/vgui_gl.h"
20 #include "vgui/vgui_glu.h"
21 #include "vgui/vgui_event.h"
22 #include "vgui/vgui_message.h"
23 #include "vgui/vgui_style.h"
24 #include "vgui/vgui_soview.h"
25
26 bool
select(unsigned)27 vgui_displaybase_tableau_selection_callback::select(unsigned)
28 {
29 return false;
30 }
31
32 bool
deselect(unsigned)33 vgui_displaybase_tableau_selection_callback::deselect(unsigned)
34 {
35 return false;
36 }
37
38 bool
deselect_all()39 vgui_displaybase_tableau_selection_callback::deselect_all()
40 {
41 return false;
42 }
43
vgui_displaybase_tableau()44 vgui_displaybase_tableau::vgui_displaybase_tableau()
45 {
46 id = vgui_soview::create_id();
47
48 gl_mode = GL_RENDER;
49 highlighted = 0;
50 gl_display_list = GL_INVALID_VALUE;
51
52 cb_ = nullptr;
53
54 current_grouping = "default";
55 groupings.clear();
56 }
57
~vgui_displaybase_tableau()58 vgui_displaybase_tableau::~vgui_displaybase_tableau() {}
59
60 void
set_selection_callback(vgui_displaybase_tableau_selection_callback * cb)61 vgui_displaybase_tableau::set_selection_callback(vgui_displaybase_tableau_selection_callback * cb)
62 {
63 cb_ = cb;
64 }
65
66 void
add(vgui_soview * object)67 vgui_displaybase_tableau::add(vgui_soview * object)
68 {
69 #ifndef NDEBUG
70 std::vector<vgui_soview *>::iterator i = std::find(objects.begin(), objects.end(), object);
71 if (i == objects.end())
72 {
73 #endif
74 objects.push_back(object);
75 std::map<std::string, vgui_displaybase_tableau_grouping>::iterator it = groupings.find(current_grouping);
76 if (it == groupings.end())
77 {
78 vgui_displaybase_tableau_grouping temp;
79 temp.style = nullptr;
80 temp.hide = false;
81 temp.color_override = false;
82 temp.line_width_override = false;
83 temp.point_size_override = false;
84 temp.objects.push_back(object);
85 groupings.insert(std::pair<std::string, vgui_displaybase_tableau_grouping>(current_grouping, temp));
86 }
87 else
88 it->second.objects.push_back(object);
89 #ifndef NDEBUG
90 }
91 else
92 std::cerr << "Warning: attempt to add an soview twice.\n";
93 #endif
94 }
95
96 void
remove(vgui_soview * & object)97 vgui_displaybase_tableau::remove(vgui_soview *& object)
98 {
99 if (object->get_id() == highlighted)
100 {
101 // if the point to be removed is the currently highlighted
102 // one, zero out the 'highlighted' field. otherwise the
103 // point will still be rendered when the pointer moves.
104 highlighted = 0;
105 }
106
107 // must first unselect the object, if it's selected
108 deselect(object->get_id());
109
110 std::vector<vgui_soview *>::iterator i = std::find(objects.begin(), objects.end(), object);
111 if (i != objects.end())
112 {
113 objects.erase(i);
114 }
115
116 for (std::map<std::string, vgui_displaybase_tableau_grouping>::iterator it = groupings.begin(); it != groupings.end();
117 it++)
118 {
119 std::vector<vgui_soview *>::iterator a = std::find(it->second.objects.begin(), it->second.objects.end(), object);
120 if (a != it->second.objects.end())
121 {
122 it->second.objects.erase(a);
123 if (it->second.objects.size() == 0)
124 {
125 groupings.erase(it);
126 }
127 delete object;
128 break; // found obj, stop iterating
129 }
130 }
131 }
132
133 //: clear all soviews from the display.
134 // The soviews must be deleted otherwise we have a big memory leak.
135 // It is not clear that the design intended that the creator of the
136 // soview is responsible for deleting it. In any case, such management
137 // would be impossible without reference counting. If users are going
138 // to keep soviews for personal use, then the whole soview scheme
139 // should be changed to smart pointers. JLM
140 //
141 void
clear()142 vgui_displaybase_tableau::clear()
143 {
144 highlighted = 0;
145 deselect_all();
146
147 // destroy the objects
148 for (std::vector<vgui_soview *>::iterator so_iter = objects.begin(); so_iter != objects.end(); ++so_iter)
149 {
150 delete *so_iter;
151 }
152
153 objects.clear();
154
155 for (std::map<std::string, vgui_displaybase_tableau_grouping>::iterator it = groupings.begin(); it != groupings.end();
156 it++)
157 {
158 it->second.objects.clear();
159 }
160
161 groupings.clear();
162 }
163
164 void
draw_soviews_render()165 vgui_displaybase_tableau::draw_soviews_render()
166 {
167 vgui_macro_report_errors;
168 {
169 for (std::map<std::string, vgui_displaybase_tableau_grouping>::iterator it = groupings.begin();
170 it != groupings.end();
171 it++)
172 {
173 if (!it->second.hide)
174 {
175 for (std::vector<vgui_soview *>::iterator so_iter = it->second.objects.begin();
176 so_iter != it->second.objects.end();
177 ++so_iter)
178 {
179 vgui_soview * so = *so_iter;
180 vgui_style_sptr style = so->get_style();
181
182 if (!it->second.style && style)
183 style->apply_all();
184 else if (!style && it->second.style)
185 it->second.style->apply_all();
186 else if (style && it->second.style)
187 {
188 if (it->second.color_override)
189 it->second.style->apply_color();
190 else
191 style->apply_color();
192
193 if (it->second.line_width_override)
194 it->second.style->apply_line_width();
195 else
196 style->apply_line_width();
197
198 if (it->second.point_size_override)
199 it->second.style->apply_point_size();
200 else
201 style->apply_point_size();
202 }
203
204 if (is_selected(so->get_id()))
205 glColor3f(1.0f, 0.0f, 0.0f);
206
207 so->draw();
208 } // for all soviews
209 }
210 }
211 }
212 vgui_macro_report_errors;
213 }
214
215
216 void
draw_soviews_select()217 vgui_displaybase_tableau::draw_soviews_select()
218 {
219 // push the name of this displaylist onto the name stack
220 glPushName(id);
221
222 glPushName(0); // will be replaced by the id of each object
223
224 for (std::map<std::string, vgui_displaybase_tableau_grouping>::iterator it = groupings.begin(); it != groupings.end();
225 it++)
226 {
227 if (!it->second.hide)
228 {
229 for (std::vector<vgui_soview *>::iterator so_iter = it->second.objects.begin();
230 so_iter != it->second.objects.end();
231 ++so_iter)
232 {
233 // only highlight if the so is selectable
234 vgui_soview * so = *so_iter;
235 if (so->get_selectable())
236 {
237 so->load_name();
238 so->draw_select();
239 }
240 } // for all soviews
241 }
242 }
243
244 // remove name of last object
245 glPopName();
246
247 // remove the name of the displaylist from the name stack
248 glPopName();
249 }
250
251
252 bool
handle(const vgui_event & e)253 vgui_displaybase_tableau::handle(const vgui_event & e)
254 {
255 if (e.type == vgui_DRAW)
256 {
257 if (gl_mode == GL_SELECT)
258 draw_soviews_select();
259 else
260 draw_soviews_render();
261
262 return true;
263 }
264 else
265 return vgui_tableau::handle(e);
266 }
267
268 bool
is_selected(unsigned iden)269 vgui_displaybase_tableau::is_selected(unsigned iden)
270 {
271 std::vector<unsigned>::iterator result = std::find(selections.begin(), selections.end(), iden);
272 return result != selections.end();
273 }
274
275 std::vector<vgui_soview *>
get_selected_soviews() const276 vgui_displaybase_tableau::get_selected_soviews() const
277 {
278 std::vector<vgui_soview *> svs;
279 for (unsigned i = 0; i < selections.size(); ++i)
280 {
281 svs.push_back(vgui_soview::id_to_object(selections[i]));
282 }
283 return svs;
284 }
285
286 std::vector<unsigned>
get_all_ids() const287 vgui_displaybase_tableau::get_all_ids() const
288 {
289 std::vector<unsigned> ids;
290 for (unsigned int i = 0; i < objects.size(); ++i)
291 ids.push_back(objects[i]->get_id());
292
293 return ids;
294 }
295
296 bool
select(unsigned iden)297 vgui_displaybase_tableau::select(unsigned iden)
298 {
299 std::vector<unsigned>::iterator result = std::find(selections.begin(), selections.end(), iden);
300 if (result == selections.end())
301 {
302 // add selection to std::list
303 selections.push_back(iden);
304
305 // notify so's observers
306 vgui_soview * so = vgui_soview::id_to_object(iden);
307
308 if (so->get_selectable())
309 {
310 vgui_message msg;
311 #if 0
312 msg.text = "soview select";
313 #endif // 0
314 msg.user = (void const *)&vgui_soview::msg_select;
315 so->notify(msg);
316
317 if (cb_)
318 cb_->select(iden);
319 }
320 }
321
322 return true;
323 }
324
325 bool
deselect(unsigned iden)326 vgui_displaybase_tableau::deselect(unsigned iden)
327 {
328 std::vector<unsigned>::iterator result = std::find(selections.begin(), selections.end(), iden);
329 if (result != selections.end())
330 {
331 // remove selection from std::list
332 selections.erase(result);
333
334 // notify so's observers
335 vgui_soview * so = vgui_soview::id_to_object(iden);
336 vgui_message msg;
337 #if 0
338 msg.text = "soview deselect";
339 #endif // 0
340 msg.user = (void const *)&vgui_soview::msg_deselect;
341 so->notify(msg);
342
343 if (cb_)
344 cb_->deselect(iden);
345 }
346
347 return true;
348 }
349
350 bool
deselect_all()351 vgui_displaybase_tableau::deselect_all()
352 {
353 // this is a bit inelegant but you have to make a copy
354 // of the selections std::list as sending the deselect message
355 // may actually change the selections
356
357 std::vector<unsigned> oldselections = selections;
358
359 for (std::vector<unsigned>::iterator s_iter = oldselections.begin(); s_iter != oldselections.end(); ++s_iter)
360 {
361 unsigned iden = *s_iter;
362
363 // notify so's observers
364 vgui_soview * so = vgui_soview::id_to_object(iden);
365 vgui_message msg;
366 msg.user = (void const *)&vgui_soview::msg_deselect;
367 so->notify(msg);
368
369 if (cb_)
370 cb_->deselect(iden);
371 }
372
373 selections.clear();
374 this->post_redraw();
375
376 return true;
377 }
378
379
380 vgui_soview *
get_highlighted_soview()381 vgui_displaybase_tableau::get_highlighted_soview()
382 {
383 return vgui_soview::id_to_object(highlighted);
384 }
385
386 vgui_soview *
contains_hit(std::vector<unsigned> names)387 vgui_displaybase_tableau::contains_hit(std::vector<unsigned> names)
388 {
389 for (std::vector<vgui_soview *>::iterator i = objects.begin(); i != objects.end(); ++i)
390 {
391 // get id of soview
392 unsigned soview_id = (*i)->get_id();
393 #ifdef DEBUG
394 std::cerr << "vgui_displaybase_tableau::contains_hit soview_id=" << soview_id << '\n';
395 #endif
396 std::vector<unsigned>::iterator ni = std::find(names.begin(), names.end(), soview_id);
397 if (ni != names.end())
398 return *i;
399 }
400
401 return nullptr;
402 }
403
404 vgui_displaybase_tableau_grouping *
get_grouping_ptr(std::string t_name)405 vgui_displaybase_tableau::get_grouping_ptr(std::string t_name)
406 {
407 std::map<std::string, vgui_displaybase_tableau_grouping>::iterator it = groupings.find(t_name);
408 if (it != groupings.end())
409 return &it->second;
410 else
411 return nullptr;
412 }
413
414 std::vector<std::string>
get_grouping_names()415 vgui_displaybase_tableau::get_grouping_names()
416 {
417 std::vector<std::string> to_return;
418
419 for (std::map<std::string, vgui_displaybase_tableau_grouping>::iterator it = groupings.begin(); it != groupings.end();
420 it++)
421 {
422 to_return.push_back(it->first);
423 }
424
425 return to_return;
426 }
427