00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008
00009
00010
00011 #include "vgui_viewer2D_tableau.h"
00012
00013 #include <vcl_cmath.h>
00014 #include <vbl/vbl_bool_ostream.h>
00015
00016 #include <vgui/vgui_gl.h>
00017 #include <vgui/vgui_glu.h>
00018 #include <vgui/vgui.h>
00019 #include <vgui/vgui_event.h>
00020 #include <vgui/vgui_window.h>
00021 #include <vgui/vgui_adaptor.h>
00022 #include <vgui/vgui_event_condition.h>
00023 #include <vgui/vgui_drag_mixin.h>
00024 #include <vgui/vgui_matrix_state.h>
00025 #include <vgui/vgui_find.h>
00026 #include <vgui/vgui_utils.h>
00027 #include <vgui/vgui_image_tableau.h>
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 const void * const vgui_viewer2D_tableau::CENTER_EVENT="x";
00038
00039
00040 vgui_event_condition c_pan(vgui_MIDDLE, vgui_CTRL);
00041 #if 0 // was:
00042 vgui_event_condition c_pan(vgui_LEFT, vgui_modifier(vgui_CTRL + vgui_SHIFT));
00043 #endif // 0
00044
00045 vgui_viewer2D_tableau::vgui_viewer2D_tableau(vgui_tableau_sptr const& s) :
00046 vgui_wrapper_tableau(s),
00047 nice_points(true),
00048 nice_lines(true),
00049 zoom_type(normal_zoom),
00050 panning(false),
00051 smooth_zooming(false),
00052 sweep_zooming(false),
00053 sweep_next(false),
00054 prev_x(0), prev_y(0),
00055 zoom_x(0), zoom_y(0),
00056 new_x(0), new_y(0),
00057 zoom_factor(1.5f),
00058 npos_x(0), npos_y(0)
00059 {
00060 }
00061
00062 vgui_viewer2D_tableau::~vgui_viewer2D_tableau()
00063 {
00064 }
00065
00066 void vgui_viewer2D_tableau::setup_gl_matrices()
00067 {
00068 GLint vp[4];
00069 glGetIntegerv(GL_VIEWPORT, vp);
00070 int width = vp[2];
00071 int height = vp[3];
00072
00073
00074
00075 glMatrixMode(GL_PROJECTION);
00076 glLoadIdentity();
00077 glOrtho(0, width,
00078 height, 0,
00079 -1,+1);
00080
00081
00082
00083
00084
00085
00086 glMatrixMode(GL_MODELVIEW);
00087 glLoadIdentity();
00088 glTranslatef(token.offsetX, token.offsetY, 0);
00089 glScalef(token.scaleX, token.scaleY, 1);
00090 }
00091
00092
00093
00094
00095
00096 void vgui_viewer2D_tableau::zoomin(float zoom_fac, int x, int y)
00097 {
00098
00099 token.scaleX *= zoom_fac;
00100 token.scaleY *= zoom_fac;
00101
00102
00103 GLint vp[4]; glGetIntegerv(GL_VIEWPORT,vp);
00104 float dx = ( (x-vp[0])) - token.offsetX;
00105 float dy = (vp[3]-1-(y-vp[1])) - token.offsetY;
00106
00107 float tmpx = zoom_fac*dx - dx;
00108 float tmpy = zoom_fac*dy - dy;
00109
00110 token.offsetX -= tmpx;
00111 token.offsetY -= tmpy;
00112 }
00113
00114
00115 void vgui_viewer2D_tableau::zoomout(float zoom_fac, int x, int y)
00116 {
00117 zoomin(1.0f / zoom_fac, x, y);
00118 }
00119
00120 void vgui_viewer2D_tableau::center_image(int w, int h)
00121 {
00122 GLfloat vp[4];
00123 glGetFloatv(GL_VIEWPORT, vp);
00124 float width = vp[2];
00125 float height = vp[3];
00126
00127 token.offsetX = width/2 - token.scaleX*(float(w)/2.0f);
00128 token.offsetY = height/2 - token.scaleY*(float(h)/2.0f);
00129 post_redraw();
00130 }
00131
00132
00133 vcl_string vgui_viewer2D_tableau::type_name() const {return "vgui_viewer2D_tableau";}
00134
00135 static void draw_rect(float x0, float y0, float x1, float y1)
00136 {
00137 glColor3f(1,0,0);
00138
00139 glLineWidth(2);
00140 glBegin(GL_LINE_LOOP);
00141 glVertex2f(x0,y0);
00142 glVertex2f(x0,y1);
00143 glVertex2f(x1,y1);
00144 glVertex2f(x1,y0);
00145 glEnd();
00146 }
00147
00148 bool vgui_viewer2D_tableau::handle(const vgui_event& e)
00149 {
00150 if (e.type == vgui_DRAW)
00151 {
00152
00153 glDisable(GL_CULL_FACE);
00154 glDisable(GL_DEPTH_TEST);
00155 glDisable(GL_TEXTURE_2D);
00156 glDisable(GL_LIGHTING);
00157 glShadeModel(GL_FLAT);
00158
00159 if (nice_points)
00160 glEnable(GL_POINT_SMOOTH);
00161 else
00162 glDisable(GL_POINT_SMOOTH);
00163
00164 if (nice_lines)
00165 {
00166 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
00167 glEnable(GL_LINE_SMOOTH);
00168 glLineWidth (1.5);
00169 }
00170 else
00171 glDisable(GL_LINE_SMOOTH);
00172
00173 if (nice_points || nice_lines)
00174 {
00175 glEnable (GL_BLEND);
00176 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00177
00178 }
00179 else
00180 glDisable(GL_BLEND);
00181
00182 setup_gl_matrices();
00183
00184 return child->handle(e);
00185 }
00186
00187
00188
00189
00190 if (e.type ==vgui_KEY_PRESS)
00191 if (e.key=='c')
00192 {
00193 vgui_adaptor* adap = e.origin;
00194 vgui_window* win = adap->get_window();
00195 if (win)
00196 {
00197
00198
00199
00200 int cpos = 50;
00201 win->set_hscrollbar(cpos);
00202 win->set_vscrollbar(cpos);
00203 npos_x = cpos;
00204 npos_y = cpos;
00205 }
00206 }
00207
00208
00209
00210
00211
00212 if (e.type == vgui_HSCROLL)
00213 {
00214 int w, h;
00215 this->image_size(w,h);
00216 float xs = w/100.0f;
00217 this->token.offsetX -= this->token.scaleX*xs*(*((const int*)e.data)-npos_x);
00218 this->post_redraw();
00219 npos_x = *((const int *)e.data);
00220 }
00221
00222 if (e.type == vgui_VSCROLL)
00223 {
00224 int w, h;
00225 this->image_size(w, h);
00226 float ys = h/100.0f;
00227 this->token.offsetY -= this->token.scaleY*ys*(*((const int*)e.data)-npos_y);
00228 this->post_redraw();
00229 npos_y = *((const int *)e.data);
00230 }
00231 setup_gl_matrices();
00232
00233 if (vgui_drag_mixin::handle(e))
00234 return true;
00235
00236 if (vgui_tableau::handle(e))
00237 return true;
00238
00239 return child->handle(e);
00240 }
00241
00242 bool vgui_viewer2D_tableau::mouse_down(int x, int y, vgui_button button, vgui_modifier modifier)
00243 {
00244
00245
00246 if (c_pan(button, modifier))
00247 {
00248 #ifdef DEBUG
00249 vcl_cerr << "vgui_viewer2D_tableau::mouse_down: middle\n";
00250 #endif
00251 prev_x = x;
00252 prev_y = y;
00253 panning = true;
00254 return true;
00255 }
00256 if (this->zoom_type == vgui_viewer2D_tableau::normal_zoom && !sweep_next)
00257 {
00258 if (button == vgui_LEFT && (modifier & vgui_CTRL))
00259 {
00260 #ifdef DEBUG
00261 vcl_cerr << "vgui_viewer2D_tableau::mouse_down: left\n";
00262 #endif
00263 this->zoomin(zoom_factor, int(x), int(y));
00264 this->post_redraw();
00265 return true;
00266 }
00267 else if (button == vgui_RIGHT && (modifier & vgui_CTRL))
00268 {
00269 #ifdef DEBUG
00270 vcl_cerr << "vgui_viewer2D_tableau::mouse_down: right\n";
00271 #endif
00272 this->zoomout(zoom_factor, int(x), int(y));
00273 this->post_redraw();
00274 return true;
00275 }
00276 }
00277 else if (this->zoom_type == vgui_viewer2D_tableau::smooth_zoom && !sweep_next)
00278 {
00279 if (button == vgui_LEFT && (modifier & vgui_CTRL))
00280 {
00281 #ifdef DEBUG
00282 vcl_cerr << "vgui_viewer2D_tableau::mouse_down: left\n";
00283 #endif
00284 prev_x = x;
00285 prev_y = y;
00286 zoom_x = x;
00287 zoom_y = y;
00288 smooth_zooming = true;
00289
00290 return true;
00291 }
00292 }
00293 else if (button == vgui_LEFT && (sweep_next || (modifier & vgui_CTRL)))
00294 {
00295
00296
00297
00298 prev_x = x;
00299 prev_y = y;
00300 zoom_x = x;
00301 zoom_y = y;
00302 sweep_zooming = true;
00303 #ifdef DEBUG
00304 vcl_cerr << "copy_back_to_front...";
00305 #endif
00306 vgui_utils::copy_back_to_front();
00307 #ifdef DEBUG
00308 vcl_cerr << "done\n";
00309 #endif
00310
00311 return true;
00312 }
00313
00314 return false;
00315 }
00316
00317 bool vgui_viewer2D_tableau::mouse_drag(int x, int y, vgui_button , vgui_modifier )
00318 {
00319 #ifdef DEBUG
00320 vcl_cerr << __FILE__ ": vgui_viewer2D_tableau_handler::mouse_drag\n";
00321 #endif
00322
00323 if (!panning && !smooth_zooming && !sweep_zooming)
00324 return false;
00325
00326 if (panning)
00327 {
00328
00329
00330 this->token.offsetX += (x-prev_x);
00331 this->token.offsetY -= (y-prev_y);
00332 this->post_redraw();
00333 }
00334
00335 if (smooth_zooming)
00336 {
00337 GLdouble vp[4];
00338 glGetDoublev(GL_VIEWPORT, vp);
00339 double height = vp[3];
00340
00341 float newscale = 1.f - (1.5f*(prev_y - y)/(float)height);
00342
00343 this->zoomin(newscale, int(zoom_x), int(zoom_y));
00344 this->post_redraw();
00345 }
00346
00347 if (sweep_zooming)
00348 {
00349
00350
00351
00352 vgui_matrix_state gl_state; gl_state.save();
00353
00354 #ifdef DEBUG
00355 vcl_cerr << "begin_sw_overlay...";
00356 #endif
00357 vgui_utils::begin_sw_overlay();
00358 #ifdef DEBUG
00359 vcl_cerr << "done\n"
00360 << "copy_back_to_front...";
00361 #endif
00362 vgui_utils::copy_back_to_front();
00363 #ifdef DEBUG
00364 vcl_cerr << "done\n";
00365 #endif
00366
00367
00368 GLdouble vp[4];
00369 glGetDoublev(GL_VIEWPORT, vp);
00370 double width = vp[2];
00371 double height = vp[3];
00372
00373 glMatrixMode(GL_PROJECTION);
00374 glLoadIdentity();
00375 gluOrtho2D(0, width, 0, height);
00376
00377 glMatrixMode(GL_MODELVIEW);
00378 glLoadIdentity();
00379
00380
00381 float W_H_ratio = float(width/height);
00382
00383
00384 new_x = x;
00385 new_y = y;
00386
00387
00388 float xdiff = vcl_fabs(zoom_x - new_x);
00389 float ydiff = vcl_fabs(zoom_y - new_y);
00390
00391
00392
00393 if (xdiff > ydiff*W_H_ratio)
00394 {
00395 if ((zoom_y - y) > 0)
00396 new_y = zoom_y - xdiff/W_H_ratio;
00397 else
00398 new_y = zoom_y + xdiff/W_H_ratio;
00399 }
00400 else
00401 {
00402 if ((zoom_x - x) > 0)
00403 new_x = zoom_x - ydiff*W_H_ratio;
00404 else
00405 new_x = zoom_x + ydiff*W_H_ratio;
00406 }
00407
00408
00409
00410 draw_rect(zoom_x - float(vp[0]), zoom_y - float(vp[1]), new_x - float(vp[0]), new_y - float(vp[1]));
00411
00412 vgui_utils::end_sw_overlay();
00413 }
00414
00415
00416 prev_x = x;
00417 prev_y = y;
00418 return true;
00419 }
00420
00421 bool vgui_viewer2D_tableau::mouse_up(int , int , vgui_button button, vgui_modifier )
00422 {
00423 #ifdef DEBUG
00424 vcl_cerr << "vgui_viewer2D_tableau_handler::mouse_up\n";
00425 #endif
00426
00427 if (sweep_zooming && button == vgui_LEFT)
00428 {
00429
00430
00431
00432
00433
00434
00435
00436 sweep_zooming = false;
00437 sweep_next = false;
00438
00439
00440 GLfloat vp[4];
00441 glGetFloatv(GL_VIEWPORT, vp);
00442
00443
00444 float x1 = ( (zoom_x-vp[0]) - this->token.offsetX) / this->token.scaleX;
00445 float y1 = (vp[3]-1-(zoom_y-vp[1]) - this->token.offsetY) / this->token.scaleY;
00446 float x2 = ( ( new_x-vp[0]) - this->token.offsetX) / this->token.scaleX;
00447 float y2 = (vp[3]-1-( new_y-vp[1]) - this->token.offsetY) / this->token.scaleY;
00448
00449
00450 this->token.scaleX = vp[2]/(x2-x1);
00451 this->token.scaleY = vp[3]/(y2-y1);
00452 this->token.offsetX = - this->token.scaleX*x1;
00453 this->token.offsetY = - this->token.scaleY*y1;
00454
00455 this->post_redraw();
00456 }
00457
00458 if (smooth_zooming && button == vgui_LEFT)
00459 smooth_zooming = false;
00460
00461 if (panning && button == c_pan.button)
00462 panning = false;
00463
00464 return false;
00465 }
00466
00467 bool vgui_viewer2D_tableau::help()
00468 {
00469 vcl_cerr << "\n-- vgui_viewer2D_tableau ----------\n"
00470 << "| mouse |\n"
00471 << "| ctrl+left zoom in |\n"
00472 << "| ctrlt+middle pan |\n"
00473 << "| ctrl+right zoom out |\n"
00474 << "| |\n"
00475 << "| keys |\n"
00476 << "| ctrl+`c' center image |\n"
00477 << "| ctrl+`x' resize image |\n"
00478 << "| `-' lower zoom factor |\n"
00479 << "| `=' raise zoom factor |\n"
00480 << "| `n' toggle aliasing |\n"
00481 << "| `z' toggle zoom type |\n"
00482 << "| `d' sweep zoom |\n"
00483 << "--------------------------\n\n";
00484 return false;
00485 }
00486
00487 bool vgui_viewer2D_tableau::image_size(int& width, int& height)
00488 {
00489 vgui_tableau_sptr t = vgui_find_below_by_type_name(this,"vgui_image_tableau");
00490 if (!t)
00491 t = vgui_find_below_by_type_name(this, "xcv_image_tableau");
00492 if (t)
00493 {
00494 vgui_image_tableau_sptr im; im.vertical_cast(t);
00495 width = im->width();
00496 height = im->height();
00497 return true;
00498 }
00499 else
00500 {
00501 width = 0; height = 0;
00502 vcl_cerr << __FILE__ " : no image found\n";
00503 }
00504 return false;
00505 }
00506
00507 void vgui_viewer2D_tableau::center_event()
00508 {
00509 int width=0, height=0;
00510 this->image_size(width, height);
00511 this->center_image(width, height);
00512 }
00513
00514 bool vgui_viewer2D_tableau::key_press(int , int , vgui_key key, vgui_modifier modifier)
00515 {
00516 #ifdef DEBUG
00517 vcl_cerr << "vgui_viewer2D_tableau_handler::key_press " << key << '\n';
00518 #endif
00519 if (modifier & vgui_CTRL) vgui::out << "CTRL+" << char(key) << " pressed: CTRL ignored\n";
00520 switch (key)
00521 {
00522 case 'x':
00523 vgui::out << "viewer2D : resizing image\n";
00524 this->token.scaleX = 1;
00525 this->token.scaleY = 1;
00526 center_event();
00527 this->post_redraw();
00528 return true;
00529 case 'c':
00530 vgui::out << "viewer2D : centering image\n";
00531 center_event();
00532 return true;
00533 case '-':
00534 zoom_factor -= 0.1f;
00535 vgui::out << "viewer2D : zoom_factor = " << zoom_factor << '\n';
00536 return true;
00537 case '=':
00538 zoom_factor += 0.1f;
00539 vgui::out << "viewer2D : zoom_factor = " << zoom_factor << '\n';
00540 return true;
00541 case 'n':
00542 this->nice_points = !this->nice_points;
00543 this->nice_lines = !this->nice_lines;
00544 vgui::out << "viewer2D : antialiased points & lines "
00545 << vbl_bool_ostream::on_off(this->nice_points) << '\n';
00546 this->post_redraw();
00547 return true;
00548 case 'd':
00549 sweep_next = true;
00550 return true;
00551 case 'z':
00552 if (this->zoom_type == vgui_viewer2D_tableau::normal_zoom)
00553 {
00554 this->zoom_type = vgui_viewer2D_tableau::smooth_zoom;
00555 vgui::out << "viewer2D : smooth zoom\n";
00556 }
00557 else
00558 {
00559 this->zoom_type = vgui_viewer2D_tableau::normal_zoom;
00560 vgui::out << "viewer2D : normal zoom\n";
00561 }
00562 return true;
00563 default:
00564 return false;
00565 }
00566 }