00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "vgui_poly_tableau.h"
00026
00027 #include <vcl_iostream.h>
00028 #include <vcl_cassert.h>
00029
00030 #include <vgui/vgui_gl.h>
00031 #include <vgui/vgui_macro.h>
00032 #include <vgui/vgui_event.h>
00033 #include <vgui/vgui_matrix_state.h>
00034 #include <vgui/vgui_popup_params.h>
00035
00036
00037 vgui_poly_tableau::item::item(vgui_tableau* p, vgui_tableau_sptr const&c,
00038 float x_, float y_, float w_, float h_,
00039 int id_)
00040 : tab(p, c)
00041 , x(x_), y(y_)
00042 , w(w_), h(h_)
00043 , id(id_)
00044 {
00045 outline_color[0] = outline_color[1] = outline_color[2] = 1;
00046 }
00047
00048
00049 void vgui_poly_tableau::item::set_vp(GLint const vp[4])
00050 {
00051 int region[4]={
00052 int(vp[0] + x*vp[2]),
00053 int(vp[1] + y*vp[3]),
00054 int(w*vp[2]),
00055 int(h*vp[3])
00056 };
00057
00058 glViewport( region[0], region[1], region[2], region[3] );
00059 glScissor ( region[0], region[1], region[2], region[3] );
00060 }
00061
00062
00063
00064 bool vgui_poly_tableau::item::inside(GLint const vp[4],int vx, int vy) const
00065 {
00066 float rx = float(vx-vp[0])/vp[2];
00067 float ry = float(vy-vp[1])/vp[3];
00068 bool ans = (x<=rx && rx<x+w) && (y<=ry && ry<y+h);
00069 #ifdef DEBUG
00070 if (ans)
00071 vcl_cerr << "Point "<< vx << ' '<< vy <<" inside sub-window: "<< id << '\n';
00072 #endif
00073 return ans;
00074 }
00075
00076
00077
00078 vgui_poly_tableau::vgui_poly_tableau()
00079 : vgui_tableau()
00080 , current(-1)
00081 , may_switch_child(true)
00082 {
00083 }
00084
00085
00086
00087 vgui_poly_tableau::~vgui_poly_tableau()
00088 {
00089 }
00090
00091
00092
00093 void vgui_poly_tableau::erase(iterator i)
00094 {
00095 assert(sub.begin()<=i && i<sub.end());
00096
00097 if (current == i-sub.begin())
00098 current = -1;
00099
00100 sub.erase(i);
00101 }
00102
00103
00104
00105 void vgui_poly_tableau::remove(int id)
00106 {
00107 for (iterator i=begin(); i!=end(); ++i)
00108 if (i->id == id) {
00109 erase(i);
00110 return;
00111 }
00112 vgui_macro_warning << "no such id " << id << vcl_endl;
00113 }
00114
00115
00116
00117 void vgui_poly_tableau::move(int id, float x, float y, float w, float h)
00118 {
00119 for (iterator i=begin(); i!=end(); ++i)
00120 if (i->id == id) {
00121 i->x = x;
00122 i->y = y;
00123 i->w = w;
00124 i->h = h;
00125 post_redraw();
00126 return;
00127 }
00128 vgui_macro_warning << "no such id " << id << vcl_endl;
00129 }
00130
00131
00132
00133
00134 void vgui_poly_tableau::replace(int id, vgui_tableau_sptr const& tab)
00135 {
00136 for (iterator i=begin(); i!=end(); ++i)
00137 if (i->id == id) {
00138 i->tab.assign(tab);
00139 if (tab)
00140 tab->post_redraw();
00141 else
00142 post_redraw();
00143 return;
00144 }
00145 vgui_macro_warning << "no such id " << id << vcl_endl;
00146 }
00147
00148
00149
00150 vgui_tableau_sptr vgui_poly_tableau::get(int id) const
00151 {
00152 for (const_iterator i=begin(); i!=end(); ++i)
00153 if (i->id == id)
00154 return i->tab;
00155 return vgui_tableau_sptr();
00156 }
00157
00158
00159
00160 void vgui_poly_tableau::set_outline_color(const int id, const int r,
00161 const int g, const int b)
00162 {
00163 for (unsigned i=0; i<sub.size(); ++i) {
00164 if (sub[i].id == id) {
00165 sub[i].outline_color[0] = r;
00166 sub[i].outline_color[1] = g;
00167 sub[i].outline_color[2] = b;
00168 }
00169 }
00170 }
00171
00172
00173
00174
00175
00176 int vgui_poly_tableau::add(vgui_tableau_sptr const& t, float x, float y,
00177 float w, float h)
00178 {
00179 static int counter = 0;
00180 assert(counter < 1000000);
00181 item it(this, t, x, y, w, h, ++counter) ;
00182 sub.push_back(it);
00183 #ifdef DEBUG
00184 vcl_cerr << "id = " << sub.back().id << '\n'
00185 << "x = " << sub.back().x << '\n'
00186 << "y = " << sub.back().y << '\n'
00187 << "w = " << sub.back().w << '\n'
00188 << "h = " << sub.back().h << '\n';
00189 #endif
00190 return counter;
00191 }
00192
00193
00194
00195 int vgui_poly_tableau::get_active(GLint const vp[4], int wx, int wy) const
00196 {
00197 int act = -1;
00198 for (unsigned i=0; i<sub.size(); ++i)
00199 if (sub[i].inside(vp, wx, wy) )
00200 act = i;
00201 return act;
00202 }
00203
00204
00205
00206 int vgui_poly_tableau::get_current_id()
00207 {
00208 return (current != -1) ? sub[current].id : -1;
00209 }
00210
00211
00212
00213 void vgui_poly_tableau::set_current(GLint const vp[4], int index)
00214 {
00215 if (current == index)
00216 return;
00217
00218
00219 if (current != -1) {
00220 vgui_event e(vgui_LEAVE);
00221 sub[current].set_vp(vp);
00222 sub[current].tab->handle(e);
00223 }
00224
00225
00226 #ifdef DEBUG
00227 vcl_cerr << "vgui_poly_tableau::set_current: switch from " << current << " to " << index << '\n';
00228 #endif
00229 current = index;
00230
00231
00232 if (current != -1) {
00233 vgui_event e(vgui_ENTER);
00234 sub[current].set_vp(vp);
00235 sub[current].tab->handle(e);
00236 }
00237 }
00238
00239
00240
00241 bool vgui_poly_tableau::handle(GLint const vp[4], vgui_event const &e)
00242 {
00243
00244 if (e.type==vgui_DRAW || e.type==vgui_DRAW_OVERLAY) {
00245
00246
00247
00248 vgui_matrix_state PM(false);
00249 PM.save();
00250
00251 for (unsigned i=0; i<sub.size(); ++i) {
00252 PM.restore();
00253
00254
00255 sub[i].set_vp(vp);
00256
00257
00258 sub[i].tab && sub[i].tab->handle(e);
00259
00260 if (e.type == vgui_DRAW) {
00261
00262 vgui_matrix_state::identity_gl_matrices();
00263 glColor3f(sub[i].outline_color[0],
00264 sub[i].outline_color[1],
00265 sub[i].outline_color[2]);
00266 glLineWidth(3);
00267 glMatrixMode(GL_PROJECTION);
00268 glLoadIdentity();
00269 glMatrixMode(GL_MODELVIEW);
00270 glLoadIdentity();
00271 glOrtho(0, vp[2], 0, vp[3], -1, +1);
00272 glBegin(GL_LINE_LOOP);
00273 glVertex2d( 0, 0);
00274 glVertex2d(vp[2]-1, 0);
00275 glVertex2d(vp[2]-1, vp[3]-1);
00276 glVertex2d( 0, vp[3]-1);
00277 glEnd();
00278 }
00279 }
00280
00281 return true;
00282 }
00283
00284
00285 if (e.type == vgui_TIMER) {
00286 vgui_matrix_state PM(false);
00287 PM.save();
00288 bool handled = false;
00289 for (unsigned i=0; i<sub.size(); ++i) {
00290 PM.restore();
00291 sub[i].set_vp(vp);
00292 if (sub[i].tab && sub[i].tab->handle(e)) {
00293 handled = true;
00294 break;
00295 }
00296 }
00297 return handled;
00298 }
00299
00300
00301
00302 if (current != -1) {
00303 sub[current].set_vp(vp);
00304 return sub[current].tab && sub[current].tab->handle(e);
00305 }
00306
00307
00308 return false;
00309 }
00310
00311
00312
00313 vcl_string vgui_poly_tableau::type_name() const
00314 {
00315 return "vgui_poly_tableau";
00316 }
00317
00318
00319
00320 bool vgui_poly_tableau::handle(vgui_event const &e)
00321 {
00322
00323 vgui_poly_tableau_vp_sc_snapshot snap;
00324 glEnable(GL_SCISSOR_TEST);
00325
00326
00327 if (e.type == vgui_MOTION)
00328 {
00329
00330 if (may_switch_child) {
00331 int active = get_active(snap.vp, e.wx, e.wy);
00332 if (active!=-1 && active!=get_current())
00333 set_current(snap.vp, active);
00334 }
00335 return handle(snap.vp, e);
00336 }
00337
00338
00339 else if (e.type == vgui_BUTTON_DOWN)
00340 {
00341
00342 may_switch_child = false;
00343
00344 return handle(snap.vp, e);
00345 }
00346
00347
00348 else if (e.type == vgui_BUTTON_UP)
00349 {
00350
00351
00352 bool f = handle(snap.vp, e);
00353
00354
00355 may_switch_child = true;
00356
00357
00358 int active = get_active(snap.vp, e.wx, e.wy);
00359 if (active!=-1 && active!=get_current())
00360 set_current(snap.vp, active);
00361
00362 return f;
00363 }
00364 return handle(snap.vp, e);
00365 }
00366
00367
00368 void vgui_poly_tableau::get_popup(vgui_popup_params const ¶ms, vgui_menu &menu)
00369 {
00370 if (params.recurse) {
00371 int index = get_current();
00372 if (index >=0)
00373 sub[index].tab->get_popup(params, menu);
00374 }
00375 }