NCBI C++ ToolKit
mouse_zoom_handler.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: mouse_zoom_handler.cpp 43037 2019-05-08 18:48:24Z katargir $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Andrey Yazhuk
27  *
28  * File Description:
29  *
30  */
31 #include <ncbi_pch.hpp>
32 #include <corelib/ncbistd.hpp>
33 
35 
36 #include <gui/opengl/glhelpers.hpp>
37 #include <gui/opengl/irender.hpp>
38 
39 #include <math.h>
40 
42 
43 ////////////////////////////////////////////////////////////////////////////////
44 /// class CMouseZoomHandler
45 
46 BEGIN_EVENT_TABLE(CMouseZoomHandler, wxEvtHandler)
47  EVT_LEFT_DOWN(CMouseZoomHandler::OnLeftDown)
48  EVT_LEFT_DCLICK(CMouseZoomHandler::OnLeftDown)
49  EVT_LEFT_UP(CMouseZoomHandler::OnLeftUp)
50  EVT_MOTION(CMouseZoomHandler::OnMotion)
51  EVT_MIDDLE_DOWN(CMouseZoomHandler::OnMiddleDown)
52  EVT_MIDDLE_UP(CMouseZoomHandler::OnMiddleUp)
53  EVT_MOUSEWHEEL(CMouseZoomHandler::OnMouseWheel)
55  EVT_KEY_DOWN(CMouseZoomHandler::OnKeyDown)
56  EVT_KEY_UP(CMouseZoomHandler::OnKeyUp)
57  EVT_MOUSE_CAPTURE_LOST(CMouseZoomHandler::OnMouseCaptureLost)
58  EVT_KILL_FOCUS(CMouseZoomHandler::OnKillFocus)
60 
61 
63 : m_Mode(e2D),
64  m_Host(NULL),
65  m_Pane(NULL),
66  m_State(eIdle),
67  m_CursorId(wxCURSOR_ARROW),
68  m_PanMode(eLmouse),
69  m_PanOnMouseDown(false),
70  m_Reversed(false),
71  m_PixPerNorm(50),
72  m_MaxNorm(0),
73  m_MinNorm(0),
74  m_StartNorm(0),
75  m_CurrNorm(0),
76  m_MarkerPos(0, 0),
77  m_CurrMouse(0, 0),
78  m_MouseStart(0, 0),
79  m_CurrPos(0, 0),
80  m_HasCapture(false),
81  m_WheelTotalShift(0),
82  m_ScaleColor(0.0f, 0.5f, 0.0f, 0.3f),
83  m_TickColor(1.0f, 1.0f, 1.0f),
84  m_RectColor(0.0f, 0.5f, 0.0f, 0.1f)
85 {
86  /// Genome Workbench specific stuff ///////////////////////////////////////
87 }
88 
89 
91 {
92 }
93 
94 
96 {
97  m_Pane = pane;
98 }
99 
100 
102 {
103  return this;
104 }
105 
106 
108 {
109  m_Mode = mode;
110 }
111 
112 
114 {
115  m_Host = pHost;
116 }
117 
118 
120 {
121  return dynamic_cast<IGenericHandlerHost*>(m_Host);
122 }
123 
124 
125 static int kMarkerSize = 20;
126 static int kMarkerOffset = 10;
127 static int kGaugeW = 60;
128 static int kEndTickW = 20;
129 static int kMajorTickW = 14;
130 static int kMinorTickW = 8;
131 static int kCenterOffset = 4;
132 
133 
135 {
136  CGlAttrGuard AttrGuard(GL_LINE_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT | GL_HINT_BIT);
137 
138  switch( m_State ){
139  case eReadyScale:
140  case eScale:
141  x_RenderScale(pane);
142  break;
143  case eZoomRect:
144  x_RenderZoomRect(pane);
145  break;
146  //case ePan: x_RenderPan(pane); break; // temporary disabled
147  default:
148  break;
149  }
150 }
151 
152 
154 {
155  pane.OpenPixels();
156 
157  IRender& gl = GetGl();
158 
159  int base_x = m_MarkerPos.x;
160 
161  int down_y = x_NormToPixels(m_CurrNorm);
162  int top_y = x_NormToPixels(m_MinNorm);
163  int bottom_y = x_NormToPixels(m_MaxNorm);
164 
165  gl.ColorC(m_ScaleColor);
166  gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
167 
168  //drawing "gauge box"
169  gl.Rectd(base_x - kGaugeW / 2, bottom_y - kCenterOffset,
170  base_x + kGaugeW / 2, top_y + kCenterOffset);
171 
172  // drawing Markers
173  int half = kMarkerSize / 2;
174  x_DrawMarker(true, base_x - kGaugeW / 2 - kMarkerOffset, down_y, half);
175  x_DrawMarker(true, base_x + kGaugeW / 2 + kMarkerOffset, down_y, -half);
176 
177  gl.ColorC(m_TickColor);
178  gl.LineWidth(1.0);
179 
180  //drawing "gauge box"
181  //gl.Rectd(base_x - kGaugeW / 2, bottom_y - kCenterOffset,
182  //base_x + kGaugeW / 2, top_y + kCenterOffset);
183  gl.Begin(GL_LINE_STRIP);
184  gl.Vertex2d(base_x - kGaugeW / 2, bottom_y - kCenterOffset);
185  gl.Vertex2d(base_x - kGaugeW / 2, top_y + kCenterOffset);
186  gl.Vertex2d(base_x + kGaugeW / 2, top_y + kCenterOffset);
187  gl.Vertex2d(base_x + kGaugeW / 2, bottom_y - kCenterOffset);
188  gl.Vertex2d(base_x - kGaugeW / 2, bottom_y - kCenterOffset);
189  gl.End();
190 
191  // drawing Markers
192  x_DrawMarker(false, base_x - kGaugeW / 2 - kMarkerOffset, down_y, half);
193  x_DrawMarker(false, base_x + kGaugeW / 2 + kMarkerOffset, down_y, -half);
194 
195  // draw Scale - lines and ticks
196  gl.ColorC(m_TickColor);
197 
198  int x1 = base_x - kCenterOffset;
199  int x2 = base_x + kCenterOffset;
200 
201  gl.Begin(GL_LINES);
202  // draw vertical lines
203  gl.Vertex2d(x1, top_y);
204  gl.Vertex2d(x1, bottom_y);
205 
206  gl.Vertex2d(x2, top_y);
207  gl.Vertex2d(x2, bottom_y);
208 
209  // draw min-max ticks
210  x_DrawTicks(base_x, top_y, kEndTickW);
211  x_DrawTicks(base_x, bottom_y, kEndTickW);
212 
213  // draw minor ticks every 0.2 of norm value
214  int start_i = (int) ceil(m_MinNorm * 5);
215  int end_i = (int) floor(m_MaxNorm * 5);
216 
217  // draw regular ticks
218  for( int i = start_i; i <= end_i; i++ ) {
219  TModelUnit norm = 0.2 * i;
220  int y = x_NormToPixels(norm);
221  int width = ((i - start_i) % 5) ? kMinorTickW : kMajorTickW;
222 
223  x_DrawTicks(base_x, y, width);
224  }
225  gl.End();
226 
227  pane.Close();
228 }
229 
230 
231 // draw green transparent rectangle for the "Zoom Rectangle" operation
233 {
234  pane.OpenPixels();
235  const TVPRect& rc_vp = pane.GetViewport();
236 
237  int x1, x2, y1, y2;
238 
239  // horizontal bounds
240  if(m_Mode == eVert) {
241  x1 = rc_vp.Left();
242  x2 = rc_vp.Right();
243  } else {
244  x1 = m_MouseStart.x;
245  x2 = m_CurrPos.x;
246  }
247  if( x2 < x1 ){
248  swap(x1, x2);
249  }
250 
251  // vertical bounds
252  if(m_Mode == eHorz) {
253  y1 = rc_vp.Bottom();
254  y2 = rc_vp.Top();
255  } else {
258  }
259  if(y2 < y1)
260  swap(y1, y2);
261 
262  IRender& gl = GetGl();
263 
264  // fill rectangle
265  gl.Enable(GL_BLEND);
266  gl.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
267 
268  gl.PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
269  gl.ColorC(m_RectColor);
270 
271  gl.Rectd(x1, y1, x2, y2);
272 
273  gl.LineWidth(1.0f);
274  gl.ColorC(m_ScaleColor);
275 
276  // draw rectangle countour
277  gl.LineStipple(1, 0x0F0F);
278  gl.Enable(GL_LINE_STIPPLE);
279 
280  gl.Begin(GL_LINES);
281  gl.Vertex2d(x1, y2);
282  gl.Vertex2d(x2, y2);
283 
284  gl.Vertex2d(x2, y2);
285  gl.Vertex2d(x2, y1);
286 
287  gl.Vertex2d(x1, y2);
288  gl.Vertex2d(x1, y1);
289 
290  gl.Vertex2d(x1, y1);
291  gl.Vertex2d(x2, y1);
292  gl.End();
293 
294  gl.Disable(GL_LINE_STIPPLE);
295 
296  pane.Close();
297 }
298 
299 
300 static const int kArrowBodyW = 10;
301 static const int kArrowHeadW = 20;
302 static const int kArrowHeadL = 20;
303 
304 
306 {
307  pane.OpenPixels();
308 
309  IRender& gl = GetGl();
310 
311  gl.LineWidth(1.0f);
312  gl.ColorC(m_ScaleColor);
313 
314  gl.Enable(GL_POLYGON_SMOOTH);
315  glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
316 
317  int x1 = m_MouseStart.x;
318  int y1 = m_Host->MZHH_GetVPPosByY(m_MouseStart.y);
319  int x2 = m_CurrPos.x;
320  int y2 = m_Host->MZHH_GetVPPosByY(m_CurrPos.y);
321 
322  double d_x = x2 - x1;
323  double d_y = y2 - y1;
324  double angle = 90.0 * atan2(d_y, d_x) / atan2(1.0, 0.0);
325  double hyp = sqrt(d_x * d_x + d_y * d_y);
326 
327  // move and rotate origin and then draw arrow horizontally
328  gl.Translated(x1, y1, 0);
329  gl.Rotated(angle, 0.0, 0.0, 1.0);
330 
331  gl.Begin(GL_QUADS);
332  if(hyp > kArrowHeadL) { // draw full arrow
333  gl.Vertex2d(0, kArrowBodyW);
334  gl.Vertex2d(hyp - kArrowHeadL, kArrowBodyW);
335  gl.Vertex2d(hyp - kArrowHeadL, -kArrowBodyW);
336  gl.Vertex2d(0, -kArrowBodyW);
337 
338  gl.Vertex2d(hyp - kArrowHeadL, 0);
339  gl.Vertex2d(hyp - kArrowHeadL, kArrowHeadW);
340  gl.Vertex2d(hyp, 0);
341  gl.Vertex2d(hyp - kArrowHeadL, -kArrowHeadW);
342  } else { // draw simplified arrow
343  gl.Vertex2d(0, 0);
344  gl.Vertex2d(0, kArrowHeadW);
345  gl.Vertex2d(hyp, 0);
346  gl.Vertex2d(0, -kArrowHeadW);
347  }
348  gl.End();
349 
350  gl.Rotated(-angle, 0.0, 0.0, 1.0);
351  gl.Translated(-x1, -y1, 0);
352 
353  //glDisable(GL_POLYGON_SMOOTH);
354 
355  pane.Close();
356 }
357 
358 
359 void CMouseZoomHandler::x_DrawMarker(bool fill, int x_c, int y_c, int half)
360 {
361  IRender& gl = GetGl();
362 
363  if (fill) {
364  gl.Begin(GL_TRIANGLE_STRIP);
365  gl.Vertex2d(x_c - half, y_c + half);
366  gl.Vertex2d(x_c - half, y_c - half);
367  gl.Vertex2d(x_c, y_c + half);
368  gl.Vertex2d(x_c, y_c - half);
369  gl.Vertex2d(x_c + half, y_c);
370  gl.End();
371  }
372  else {
373  gl.Begin(GL_LINE_STRIP);
374  gl.Vertex2d(x_c + half, y_c);
375  gl.Vertex2d(x_c, y_c - half);
376  gl.Vertex2d(x_c - half, y_c - half);
377  gl.Vertex2d(x_c - half, y_c + half);
378  gl.Vertex2d(x_c, y_c + half);
379  gl.Vertex2d(x_c + half, y_c);
380  gl.End();
381  }
382 }
383 
384 
385 void CMouseZoomHandler::x_DrawTicks(int center_x, int y, int tick_w)
386 {
387  int x1 = center_x - kCenterOffset;
388  int x2 = center_x + kCenterOffset;
389 
390  IRender& gl = GetGl();
391 
392  gl.Vertex2d(x1 - tick_w, y);
393  gl.Vertex2d(x1, y);
394 
395  gl.Vertex2d(x2, y);
396  gl.Vertex2d(x2 + tick_w, y);
397 }
398 
399 
401 {
402  int y = m_Host->MZHH_GetVPPosByY(m_CurrPos.y);
403  return y - (int) ((norm - m_CurrNorm) * m_PixPerNorm);
404 }
405 
406 
408 {
409  if(wxGetKeyState(wxKeyCode('Z'))) {
410  return eZoomState;
411  } else if(wxGetKeyState(wxKeyCode('R'))) {
412  return eZoomRectState;
413  } else if(wxGetKeyState(wxKeyCode('P'))) {
414  return ePanState;
415  }
416 
418  // also go into pan mode on left mouse if NO key is pressed -
419  // so go through all the 'major' keys here:
420  // FIXME: Problems
421  // - First, the keys listed below are not complete. Many other
422  // keys may be used in some of the views, such as up/down
423  // page up/down, -/+, Tab, left/right arrow
424  // - Not efficient to go though all the keys one by one.
425  int k;
426  for ( k='A'; k<='Z'; ++k) {
427  if (wxGetKeyState((wxKeyCode)k))
428  return eDefaultState;
429  }
430  for ( k='0'; k<='9'; ++k) {
431  if (wxGetKeyState((wxKeyCode)k))
432  return eDefaultState;
433  }
434 
435  if (wxGetKeyState(WXK_SHIFT) ||
436  wxGetKeyState(WXK_ALT) ||
437  wxGetKeyState(WXK_CONTROL) ||
438  wxGetKeyState(WXK_COMMAND))
439  return eDefaultState;
440 
441  // No other keys pressed (char/number/special) so return pan state:
442  return ePanState;
443  }
444 
445  return eDefaultState;
446 }
447 
448 
450 {
451  // There is a key event, never call x_GetKeyState() since
452  // it may still return ePanState when certain keys are pressed
453  // which is incorrect.
455  // EKeyState state = x_GetKeyState();
456  switch(event.GetKeyCode()) {
457  case 'Z':
458  state = eZoomState;
459  break;
460  case 'R':
462  break;
463  case 'P':
464  state = ePanState;
465  break;
466  default:
467  break;
468  }
469  return state;
470 }
471 
472 
473 void CMouseZoomHandler::OnLeftDown(wxMouseEvent& event)
474 {
475  //LOG_POST("CMouseZoomHandler::OnLeftDown() m_State " << m_State);
477 
478  EState ready_st = eIdle, active_st = eIdle;
479  switch(state) {
480  case eZoomState: {
481  ready_st = eReadyScale;
482  active_st = eScale;
483  }; break;
484  case eZoomRectState: {
485  ready_st = eReadyZoomRect;
486  active_st = eZoomRect;
488  }; break;
489  case ePanState: {
490  ready_st = eReadyPan;
491  active_st = ePan;
492  }; break;
493  default: break;
494  }
495 
496  if(ready_st != eIdle) {
497  m_CurrMouse = event.GetPosition();
499 
500  if (ready_st != eReadyPan || m_PanOnMouseDown) {
503  }
504  else {
505  event.Skip();
506  }
507  } else {
508  event.Skip();
509  }
510  //LOG_POST("CMouseZoomHandler::OnLeftDown() END m_State " << m_State);
511 }
512 
513 
514 void CMouseZoomHandler::OnLeftUp(wxMouseEvent& event)
515 {
516  //LOG_POST("CMouseZoomHandler::OnLeftUp() m_State " << m_State);
517 
518  wxPoint ms_pos = event.GetPosition();
519 
520  switch(m_State) {
521  case eScale: {
522  int d_y = ms_pos.y - m_MouseStart.y;
523  x_OnChangeScale(d_y);
526  break;
527  }
528  case eZoomRect: {
529  x_OnChangeZoomRectPan(ms_pos);
532  break;
533  }
534  // Only switches to pan if mouse moves during pan:
535  case eReadyPan: {
536  m_State = eIdle;
537  event.Skip();
538 
539  break;
540  }
541  case ePan: {
542  x_OnChangeZoomRectPan(ms_pos);
543 
544  if (!wxGetKeyState(wxKeyCode('P'))) {
545  x_OnEndPan(eIdle);
546  }
547  else {
549  }
550  x_OnSelectCursor();
551 
552  break;
553  }
554  default:
555  event.Skip();
556  }
557  //LOG_POST("CMouseZoomHandler::OnLeftUp() END m_State " << m_State);
558 }
559 
560 
561 void CMouseZoomHandler::OnMotion(wxMouseEvent& event)
562 {
563  wxPoint pos = event.GetPosition();
564 
565  if(event.Dragging()) {
566  switch(m_State) {
567  case eScale: {
568  int d_y = pos.y - m_MouseStart.y;
569  x_OnChangeScale(d_y);
570  break;
571  }
572  case eZoomRect: {
574  break;
575  }
576  case eReadyPan: {
577  // Don't capture mouse on pan until mouse starts to move.
578  // otherwise the event may be used for selection.
579  if(!m_HasCapture) {
582  }
583  break;
584  }
585  case ePan: {
586  x_OnChangePan(pos);
588  break;
589  }
590  default:
591  event.Skip();
592  }
593  } else {
594  if (m_State != eIdle) {
596  } else {
597  m_CurrMouse = pos;
598  event.Skip();
599  }
600  }
601 
602  m_CurrMouse = pos;
603 }
604 
605 
606 void CMouseZoomHandler::OnMouseWheel(wxMouseEvent& event)
607 {
609  wxPoint pos = event.GetPosition();
610 
611  if(state == eZoomState) {
612  switch(m_State) {
613  case eIdle:
614  x_SwitchToReadyState(eReadyScale, pos); // continue
615  case eReadyScale: {
616  m_WheelTotalShift = 0;
618  } // continue
619  case eScale: {
620  //int delta =
621  m_WheelTotalShift += event.GetWheelRotation()/10;
623 
624  // updating shift after clipping with Min and Max norm values
626  break;
627  }
628  default:
629  //_ASSERT(false);
630  break;
631  }
633  } else {
634  event.Skip();
635  }
636 }
637 
638 
639 void CMouseZoomHandler::OnOtherMouseEvents(wxMouseEvent& event)
640 {
641  if (m_State == eIdle) {
642  event.Skip();
643  }
644  // Otherwise, ignore the event.
645 }
646 
647 
648 void CMouseZoomHandler::OnMiddleDown(wxMouseEvent& event)
649 {
650  if( m_State == eIdle ){
651  m_CurrMouse = event.GetPosition();
655  } else {
656  event.Skip();
657  }
658 }
659 
660 
661 void CMouseZoomHandler::OnMiddleUp(wxMouseEvent& event)
662 {
663  if( m_State == eScale ){
664  x_OnCancel();
665  } else {
666  event.Skip();
667  }
668 }
669 
670 
671 void CMouseZoomHandler::OnKeyDown(wxKeyEvent& event)
672 {
673  //LOG_POST("CMouseZoomHandler::OnKeyDown() m_State " << m_State);
674 
675  if( m_State == eIdle ){
676  EState ready_st = eIdle;
677  EKeyState state = x_GetKeyState(event);
678 
679  switch(state) {
680  case eZoomState:
681  ready_st = eReadyScale;
682  break;
683  case eZoomRectState:
684  ready_st = eReadyZoomRect;
685  break;
686  case ePanState:
687  ready_st = eReadyPan;
688  break;
689  default:
690  break;
691  }
692 
693  if( ready_st != eIdle ){
694  //m_CurrMouse = event.GetPosition();
697  }
698  }
699 
700  if( m_State == eIdle ){
701  event.Skip();
702  }
703  //LOG_POST("CMouseZoomHandler::OnKeyDown() END m_State " << m_State);
704 }
705 
706 void CMouseZoomHandler::OnKeyUp(wxKeyEvent& event)
707 {
709 
710  if( state != eZoomState && state != eZoomRectState ){
711  x_OnCancel();
712  }
713 
714  if( m_State == eIdle ){
715  event.Skip();
716  }
717 }
718 
719 
720 void CMouseZoomHandler::x_OnChangePan(const wxPoint& ms_pos)
721 {
722  m_CurrPos = ms_pos;
723 
726 
727  int y1 = m_Host->MZHH_GetVPPosByY(m_MouseStart.y);
728  int y2 = m_Host->MZHH_GetVPPosByY(m_CurrPos.y);
729  TModelUnit m_y1 = m_Pane->UnProjectY(y1);
730  TModelUnit m_y2 = m_Pane->UnProjectY(y2);
731 
732  m_Host->MZHH_Scroll(m_x1 - m_x2, m_y1 - m_y2);
734 
736 }
737 
738 
740 {
741  switch( m_State ){
742  case eIdle:
743  break;
744  case eReadyScale:
745  case eReadyZoomRect:
746  case eReadyPan:
747  case eZoomRect:
748  case ePan: {
750  if( m_HasCapture ){
751  x_ReleaseMouse();
752  }
753  m_State = eIdle;
755  break;
756  }
757  case eScale: {
758  x_OnEndScale( eIdle );
760  break;
761  }
762  default:
763  break;
764  };
765 }
766 
767 ////////////////////////////////////////////////////////////////////////////////
768 /// Signal handlers
769 
770 void CMouseZoomHandler::x_SwitchToReadyState(EState new_state, const wxPoint& pos)
771 {
772  //LOG_POST("CMouseZoomHandler::x_SwitchToReadyState()");
773 
774  _ASSERT(m_Host);
775  if(m_State != new_state) {
776  m_State = new_state;
777 
778  m_CurrPos = m_MarkerPos = pos;
779 
780  if(m_State == eReadyScale) {
782  m_CurrNorm = m_StartNorm = x_ScaleToNorm(curr_sc);
783  m_Reversed = curr_sc < 0;
784 
787  }
789 
790  if(m_HasCapture) {
791  x_ReleaseMouse();
792  }
793  }
794 }
795 
796 
798 {
799  _ASSERT(m_Host);
800 
801  //LOG_POST("CMouseZoomHandler::x_SwitchToActiveState() m_State " << m_State << " state " << state);
802 
803  m_State = state;
804  m_MouseStart = pos;
805 
806  int vp_y = m_Host->MZHH_GetVPPosByY(m_MouseStart.y);
808 
809  x_CaptureMouse();
810 }
811 
812 /// d_y is the absolute shift in pixels from the position where m_StartNorm have
813 /// been initialized
815 {
816  if(d_y) {
817  TModelUnit norm = m_StartNorm - ((TModelUnit) (d_y)) / m_PixPerNorm;
818  norm = max(norm, m_MinNorm);
819  norm = min(norm, m_MaxNorm);
820 
821  if(norm != m_CurrNorm) {
822  m_CurrNorm = norm;
823  TModelUnit scale = x_NormToScale(norm);
824 
825  // Get mouse position relative to current transformation:
826  int vp_y = m_Host->MZHH_GetVPPosByY(m_MouseStart.y);
828 
829  m_Host->MZHH_SetScale(scale, m_ptStart);
830  }
831  }
832 }
833 
834 
836 {
837  _ASSERT(new_state != eScale);
838 
839  m_State = new_state;
841 
842  m_Host->MZHH_EndOp();
844  x_ReleaseMouse();
845 }
846 
847 
849 {
850  if(m_CurrPos != pos) {
851  m_CurrPos = pos;
852 
854  }
855 }
856 
857 
859 {
860  m_State = new_state;
861 
862  TModelRect rc;
863 
864  int x1 = m_MouseStart.x;
865  int y1 = m_Host->MZHH_GetVPPosByY(m_MouseStart.y);
866  int x2 = m_CurrPos.x;
867  int y2 = m_Host->MZHH_GetVPPosByY(m_CurrPos.y);
868 
869  if(x2 != x1 || y2 != y1) {
870  //const TVPRect& rc_vp = m_Pane->GetViewport();
871  int left = min(x1, x2);
872  int right = max(x1, x2);
873  int bottom = min(y1, y2);
874  int top = max(y1, y2);
875 
876  rc.SetLeft(m_Pane->UnProjectX(left));
877  rc.SetRight(m_Pane->UnProjectX(right));
878  rc.SetBottom(m_Pane->UnProjectY(bottom));
879  rc.SetTop(m_Pane->UnProjectY(top));
880 
881  const TModelRect& rc_lim = m_Pane->GetModelLimitsRect();
882  rc.IntersectWith(rc_lim);
883 
884  m_Host->MZHH_ZoomRect(rc);
885  m_Host->MZHH_EndOp();
886  }
888  x_ReleaseMouse();
889 }
890 
891 
893 {
894  m_State = new_state;
895 
896  int y1 = m_Host->MZHH_GetVPPosByY(m_MouseStart.y);
897  int y2 = m_Host->MZHH_GetVPPosByY(m_CurrPos.y);
898 
900  TModelUnit m_y1 = m_Pane->UnProjectY(y1);
902  TModelUnit m_y2 = m_Pane->UnProjectY(y2);
903 
904  m_Host->MZHH_Scroll(m_x1 - m_x2, m_y1 - m_y2);
905  m_Host->MZHH_EndOp();
907  x_ReleaseMouse();
908 }
909 
910 
912 {
913  switch(m_State) {
914  case eIdle:
915  case eReadyScale:
916  m_CursorId = wxCURSOR_ARROW;
917  break;
918  case eScale:
919  m_CursorId = wxCURSOR_HAND;
920  break;
921  case eReadyPan:
922  case ePan:
923  m_CursorId = wxCURSOR_SIZING;
924  break;
925  case eReadyZoomRect:
926  case eZoomRect:
927  m_CursorId = wxCURSOR_CROSS;
928  break;
929  default:
930  break;
931  }
932 
934 }
935 
936 
937 void CMouseZoomHandler::OnMouseCaptureLost(wxMouseCaptureLostEvent& evt)
938 {
939  x_OnCancel();
940 }
941 
942 
943 void CMouseZoomHandler::OnKillFocus(wxFocusEvent& event)
944 {
945  x_OnCancel();
946 }
947 
948 ////////////////////////////////////////////////////////////////////////////////
949 /// helper functions
950 
952 {
953  return log(fabs(scale));
954 }
955 
956 
958 {
959  double sc = exp(norm);
960  return m_Reversed ? -sc : sc;
961 }
962 
963 
965 {
966  _ASSERT( ! m_HasCapture);
968  m_HasCapture = true;
969 }
970 
971 
973 {
976  m_HasCapture = false;
977 }
978 
979 
CGlAttrGuard - guard class for restoring OpenGL attributes.
Definition: glutils.hpp:130
class CGlPane
Definition: glpane.hpp:62
CMouseZoomHandler provides support for mouse-driven zoom and pan operations.
void x_OnChangeZoomRectPan(const wxPoint &pos)
void x_OnChangeScale(int d_y)
d_y is the absolute shift in pixels from the position where m_StartNorm have been initialized
void OnOtherMouseEvents(wxMouseEvent &event)
virtual void SetHost(IMouseZoomHandlerHost *pHost)
int x_NormToPixels(TModelUnit norm) const
void x_RenderZoomRect(CGlPane &pane)
void OnMotion(wxMouseEvent &event)
void x_OnChangePan(const wxPoint &ms_pos)
void x_SwitchToReadyState(EState new_state, const wxPoint &ms_pos)
signal handlers - functions doing the real job
void x_DrawMarker(bool fill, int x_c, int y_c, int half)
void x_OnEndZoomRect(EState new_state)
TModelUnit x_ScaleToNorm(TModelUnit scale) const
helper functions
IMouseZoomHandlerHost * m_Host
void OnKeyUp(wxKeyEvent &event)
virtual wxEvtHandler * GetEvtHandler()
void OnKeyDown(wxKeyEvent &event)
void OnMiddleUp(wxMouseEvent &event)
void OnLeftUp(wxMouseEvent &event)
virtual void SetMode(EMode mode)
void OnKillFocus(wxFocusEvent &event)
void OnMouseWheel(wxMouseEvent &event)
void x_RenderPan(CGlPane &pane)
void x_OnEndPan(EState new_state)
virtual IGenericHandlerHost * GetGenericHost()
void x_SwitchToActiveState(EState state, const wxPoint &ms_pos)
TModelUnit x_NormToScale(TModelUnit norm) const
void x_OnEndScale(EState new_state)
void x_RenderScale(CGlPane &pane)
void OnMiddleDown(wxMouseEvent &event)
virtual void SetPane(CGlPane *pane)
void OnMouseCaptureLost(wxMouseCaptureLostEvent &evt)
void x_DrawTicks(int center_x, int y, int tick_w)
void OnLeftDown(wxMouseEvent &event)
virtual void Render(CGlPane &Pane)
IGenericHandlerHost.
virtual void GHH_ReleaseMouse()=0
releases captured mouse
virtual void GHH_Redraw()=0
redraws the Host and the handler
virtual void GHH_CaptureMouse()=0
captures mouse events in the hosting window for D&D
virtual void GHH_SetCursor(const wxCursor &cursor)=0
changes the cursor in the hosting window
Interface IMouseZoomHandlerHost represents a context in which CMouseZoomHandler functions.
virtual void MZHH_ZoomRect(const TModelRect &rc)=0
virtual void MZHH_SetScale(TModelUnit scale, const TModelPoint &point)=0
virtual TVPUnit MZHH_GetVPPosByY(int y) const =0
converts window coord to Viewport coord
virtual void MZHH_EndOp()=0
virtual TModelUnit MZHH_GetScale(EScaleType type)=0
virtual void MZHH_Scroll(TModelUnit d_x, TModelUnit d_y)=0
Include a standard set of the NCBI C++ Toolkit most basic headers.
#define false
Definition: bool.h:36
void swap(NCBI_NS_NCBI::pair_base_member< T1, T2 > &pair1, NCBI_NS_NCBI::pair_base_member< T1, T2 > &pair2)
Definition: ncbimisc.hpp:1508
#define NULL
Definition: ncbistd.hpp:225
virtual void Translated(GLdouble x, GLdouble y, GLdouble z)=0
CGlRect & IntersectWith(const CGlRect &r)
Definition: glrect.hpp:194
GLdouble TModelUnit
Definition: gltypes.hpp:48
void SetRight(T right)
Definition: glrect.hpp:114
virtual void Enable(GLenum glstate)=0
virtual void LineStipple(GLint factor, GLushort pattern)=0
Set line stipple pattern: glLineStipple(). Deprecated in gl 3.2+.
virtual void Begin(GLenum mode)=0
Start rendering.
void SetBottom(T bottom)
Definition: glrect.hpp:113
T Top() const
Definition: glrect.hpp:84
virtual void BlendFunc(GLenum sfactor, GLenum dfactor)=0
Options to be used when GL_BLEND is enabled.
T Bottom() const
Definition: glrect.hpp:82
TModelPoint UnProject(TVPUnit m_x, TVPUnit m_y) const
Definition: glpane.cpp:738
bool OpenPixels()
Definition: glpane.hpp:432
IRender & GetGl()
convenience function for getting current render manager
void Vertex2d(GLdouble x, GLdouble y)
Definition: irender.hpp:185
T Right() const
Definition: glrect.hpp:83
TVPRect & GetViewport(void)
Definition: glpane.hpp:332
TModelUnit UnProjectX(TVPUnit m_x) const
Definition: glpane.cpp:706
TModelRect & GetModelLimitsRect(void)
Definition: glpane.hpp:347
T Left() const
Definition: glrect.hpp:81
virtual void Rotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z)=0
virtual void End()=0
Finish rendering (create buffer and send to renderer)
void Close(void)
Definition: glpane.cpp:178
virtual void PolygonMode(GLenum face, GLenum mode)=0
Set the polygon rasterization mode.
TModelUnit UnProjectY(TVPUnit m_y) const
Definition: glpane.cpp:722
void SetLeft(T left)
Definition: glrect.hpp:112
virtual void Disable(GLenum glstate)=0
glDisable()
virtual void LineWidth(GLfloat w)=0
Set line width for drawing: glLineWidth()
virtual void ColorC(const CRgbaColor &c)=0
Set current color (glColor{3,4}{f,d}{v,})
void SetTop(T top)
Definition: glrect.hpp:115
void Rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)
Definition: irender.hpp:193
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
END_EVENT_TABLE()
int i
static int kMajorTickW
static int kMinorTickW
static int kGaugeW
static int kMarkerOffset
static int kCenterOffset
static const int kArrowHeadW
static int kMarkerSize
static int kEndTickW
static const int kArrowHeadL
static const int kArrowBodyW
mdb_mode_t mode
Definition: lmdb++.h:38
#define fabs(v)
Definition: ncbi_dispd.c:46
T max(T x_, T y_)
T min(T x_, T y_)
double f(double x_, const double &y_)
Definition: njn_root.hpp:188
@ eIdle
#define _ASSERT
Modified on Tue Apr 23 07:40:18 2024 by modify_doxy.py rev. 669887