mouse_zoom_handler.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:19k
- /*
- * ===========================================================================
- * PRODUCTION $Log: mouse_zoom_handler.cpp,v $
- * PRODUCTION Revision 1000.3 2004/06/01 21:10:40 gouriano
- * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10
- * PRODUCTION
- * ===========================================================================
- */
- /* $Id: mouse_zoom_handler.cpp,v 1000.3 2004/06/01 21:10:40 gouriano Exp $
- * ===========================================================================
- *
- * PUBLIC DOMAIN NOTICE
- * National Center for Biotechnology Information
- *
- * This software/database is a "United States Government Work" under the
- * terms of the United States Copyright Act. It was written as part of
- * the author's official duties as a United States Government employee and
- * thus cannot be copyrighted. This software/database is freely available
- * to the public for use. The National Library of Medicine and the U.S.
- * Government have not placed any restriction on its use or reproduction.
- *
- * Although all reasonable efforts have been taken to ensure the accuracy
- * and reliability of the software and data, the NLM and the U.S.
- * Government do not and cannot warrant the performance or results that
- * may be obtained by using this software or data. The NLM and the U.S.
- * Government disclaim all warranties, express or implied, including
- * warranties of performance, merchantability or fitness for any particular
- * purpose.
- *
- * Please cite the author in any work or product based on this material.
- *
- * ===========================================================================
- *
- * Authors: Andrey Yazhuk
- *
- * File Description:
- *
- */
- #include <ncbi_pch.hpp>
- #include <corelib/ncbistd.hpp>
- #include <gui/opengl/glhelpers.hpp>
- #include <gui/widgets/gl/mouse_zoom_handler.hpp>
- #include <math.h>
- #include <FL/Fl.H>
- BEGIN_NCBI_SCOPE
- ////////////////////////////////////////////////////////////////////////////////
- /// class CMouseZoomHandler
- CMouseZoomHandler::CMouseZoomHandler()
- : m_pHost(NULL),
- m_State(eIdle),
- m_PixPerNorm(50),
- m_MouseStartX(0), m_MouseStartY(0),
- m_CurrPosX(0), m_CurrPosY(0),
- m_ScaleColor(0.0f, 0.5f, 0.0f, 0.5f),
- m_TickColor(1.0f, 1.0f, 1.0f),
- m_RectColor(0.0f, 0.5f, 0.0f, 0.25f)
- {
- }
- CMouseZoomHandler::~CMouseZoomHandler()
- {
- }
- void CMouseZoomHandler::SetHost(IMouseZoomHandlerHost* pHost)
- {
- m_pHost = pHost;
- }
- static int kMarkerSize = 20;
- static int kMarkerOffset = 10;
- static int kGaugeW = 60;
- static int kEndTickW = 20;
- static int kMajorTickW = 14;
- static int kMinorTickW = 8;
- static int kCenterOffset = 4;
- void CMouseZoomHandler::Render(CGlPane& pane)
- {
- CGlAttrGuard AttrGuard(GL_ENABLE_BIT | GL_POLYGON_BIT | GL_HINT_BIT);
- switch(m_State) {
- case eReadyScale:
- case eScale: x_RenderScale(pane); break;
- case eZoomRect: x_RenderZoomRect(pane); break;
- //case ePan: x_RenderPan(pane); break; // temporary disabled
- default: break;
- }
- }
- void CMouseZoomHandler::x_RenderScale(CGlPane& pane)
- {
- pane.OpenPixels();
- int base_x = m_MarkerPosX;
- int down_y = x_NormToPixels(m_CurrNorm);
- int top_y = x_NormToPixels(m_MinNorm);
- int bottom_y = x_NormToPixels(m_MaxNorm);
- glColorC(m_ScaleColor);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-
- //drawing "gauge box"
- glRectd(base_x - kGaugeW / 2, bottom_y - kCenterOffset,
- base_x + kGaugeW / 2, top_y + kCenterOffset);
-
- // drawing Markers
- int half = kMarkerSize / 2;
- x_DrawMarker(base_x - kGaugeW / 2 - kMarkerOffset, down_y, half);
- x_DrawMarker(base_x + kGaugeW / 2 + kMarkerOffset, down_y, -half);
-
- glColorC(m_TickColor);
- glLineWidth(1.0);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-
- //drawing "gauge box"
- glRectd(base_x - kGaugeW / 2, bottom_y - kCenterOffset,
- base_x + kGaugeW / 2, top_y + kCenterOffset);
-
- // drawing Markers
- x_DrawMarker(base_x - kGaugeW / 2 - kMarkerOffset, down_y, half);
- x_DrawMarker(base_x + kGaugeW / 2 + kMarkerOffset, down_y, -half);
- // draw Scale - lines and ticks
- glColorC(m_TickColor);
- int x1 = base_x - kCenterOffset;
- int x2 = base_x + kCenterOffset;
-
- glBegin(GL_LINES);
- // draw vertical lines
- glVertex2d(x1, top_y);
- glVertex2d(x1, bottom_y);
- glVertex2d(x2, top_y);
- glVertex2d(x2, bottom_y);
- // draw min-max ticks
- x_DrawTicks(base_x, top_y, kEndTickW);
- x_DrawTicks(base_x, bottom_y, kEndTickW);
-
- // draw minor ticks every 0.2 of norm value
- int start_i = (int) ceil(m_MinNorm * 5);
- int end_i = (int) floor(m_MaxNorm * 5);
-
- // draw regular ticks
- for( int i = start_i; i <= end_i; i++ ) {
- TModelUnit norm = 0.2 * i;
- int y = x_NormToPixels(norm);
- int width = ((i - start_i) % 5) ? kMinorTickW : kMajorTickW;
- x_DrawTicks(base_x, y, width);
- }
- glEnd();
- pane.Close();
- }
- void CMouseZoomHandler::x_RenderZoomRect(CGlPane& pane)
- {
- pane.OpenPixels();
-
- int x1 = m_MouseStartX;
- int y1 = m_pHost->MZHH_GetVPPosByY(m_MouseStartY);
- int x2 = m_CurrPosX;
- int y2 = m_pHost->MZHH_GetVPPosByY(m_CurrPosY);
- if(x2 < x1)
- swap(x1, x2);
- if(y2 < y1)
- swap(y1, y2);
- glLineWidth(1.0f);
- glColorC(m_ScaleColor);
-
- glLineStipple(1, 0x0F0F);
- glEnable(GL_LINE_STIPPLE);
- glBegin(GL_LINES);
- glVertex2d(x1, y2);
- glVertex2d(x2, y2);
- glVertex2d(x2, y2);
- glVertex2d(x2, y1);
- glVertex2d(x1, y2);
- glVertex2d(x1, y1);
-
- glVertex2d(x1, y1);
- glVertex2d(x2, y1);
- glEnd();
- glDisable(GL_LINE_STIPPLE);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glColorC(m_RectColor);
- glRectd(x1, y1, x2, y2);
-
- pane.Close();
- }
- static const int kArrowBodyW = 10;
- static const int kArrowHeadW = 20;
- static const int kArrowHeadL = 20;
- void CMouseZoomHandler::x_RenderPan(CGlPane& pane)
- {
- pane.OpenPixels();
- glLineWidth(1.0f);
- glColorC(m_ScaleColor);
-
- glEnable(GL_POLYGON_SMOOTH);
- glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
- int x1 = m_MouseStartX;
- int y1 = m_pHost->MZHH_GetVPPosByY(m_MouseStartY);
- int x2 = m_CurrPosX;
- int y2 = m_pHost->MZHH_GetVPPosByY(m_CurrPosY);
-
- double d_x = x2 - x1;
- double d_y = y2 - y1;
- double angle = 90.0 * atan2(d_y, d_x) / atan2(1.0, 0.0);
- double hyp = sqrt(d_x * d_x + d_y * d_y);
- // move and rotate origin and then draw arrow horizontally
- glTranslated(x1, y1, 0);
- glRotated(angle, 0.0, 0.0, 1.0);
-
- glBegin(GL_QUADS);
- if(hyp > kArrowHeadL) { // draw full arrow
- glVertex2d(0, kArrowBodyW);
- glVertex2d(hyp - kArrowHeadL, kArrowBodyW);
- glVertex2d(hyp - kArrowHeadL, -kArrowBodyW);
- glVertex2d(0, -kArrowBodyW);
- glVertex2d(hyp - kArrowHeadL, 0);
- glVertex2d(hyp - kArrowHeadL, kArrowHeadW);
- glVertex2d(hyp, 0);
- glVertex2d(hyp - kArrowHeadL, -kArrowHeadW);
- } else { // draw simplified arrow
- glVertex2d(0, 0);
- glVertex2d(0, kArrowHeadW);
- glVertex2d(hyp, 0);
- glVertex2d(0, -kArrowHeadW);
- }
- glEnd();
-
- glRotated(-angle, 0.0, 0.0, 1.0);
- glTranslated(-x1, -y1, 0);
-
- //glDisable(GL_POLYGON_SMOOTH);
-
- pane.Close();
- }
- void CMouseZoomHandler::x_DrawMarker(int x_c, int y_c, int half)
- {
- glBegin(GL_POLYGON);
- glVertex2d(x_c + half, y_c);
- glVertex2d(x_c, y_c - half);
- glVertex2d(x_c - half, y_c - half);
- glVertex2d(x_c - half, y_c + half);
- glVertex2d(x_c, y_c + half);
- glEnd();
- }
- void CMouseZoomHandler::x_DrawTicks(int center_x, int y, int tick_w)
- {
- int x1 = center_x - kCenterOffset;
- int x2 = center_x + kCenterOffset;
-
- glVertex2d(x1 - tick_w, y);
- glVertex2d(x1, y);
- glVertex2d(x2, y);
- glVertex2d(x2 + tick_w, y);
- }
- int CMouseZoomHandler::x_NormToPixels(TModelUnit norm) const
- {
- int y = m_pHost->MZHH_GetVPPosByY(m_CurrPosY);
- return y - (int) ((norm - m_CurrNorm) * m_PixPerNorm);
- }
- int CMouseZoomHandler::handle(CGUIEvent& event, CGlPane& Pane)
- {
- m_pPane = &Pane;
- int res = 0;
- switch(event.GetFLTKEvent()) {
- case FL_PUSH: res = x_OnMousePush(event); break;
- case FL_DRAG: res = x_OnMouseDrag(event); break;
- case FL_RELEASE: res = x_OnMouseRelease(event); break;
- case FL_MOVE: res = x_OnMouseMove(); break;
- case FL_MOUSEWHEEL: res = x_OnMouseWheel(event); break;
- case FL_KEYDOWN: res = x_OnKeyDown(event); break;
- case FL_UNFOCUS:
- case FL_KEYUP: res = x_OnKeyUp(event); break;
- }
- m_pPane = 0;
- return res;
- }
- ////////////////////////////////////////////////////////////////////////////////
- /// event handlers
- int CMouseZoomHandler::x_OnMousePush(CGUIEvent& event)
- {
- if(event.GetGUISignal() == CGUIEvent::ePush && Fl::event_clicks() == 0) {
- CGUIEvent::EGUIState state = event.GetGUIState();
-
- EState ready_st = eIdle, active_st = eIdle;
- switch(state) {
- case CGUIEvent::eZoomState: {
- ready_st = eReadyScale;
- active_st = eScale;
- }; break;
- case CGUIEvent::eZoomRectState: {
- ready_st = eReadyZoomRect;
- active_st = eZoomRect;
- x_OnSelectCursor();
- }; break;
- case CGUIEvent::ePanState: {
- ready_st = eReadyPan;
- active_st = ePan;
- }; break;
- default: break;
- }
-
- if(ready_st != eIdle) {
- x_SwitchToReadyState(ready_st, Fl::event_x(), Fl::event_y());
- x_SwithToActiveState(active_st, Fl::event_x(), Fl::event_y());
- x_OnSelectCursor();
- }
- return 1;
- }
- return 0;
- }
- int CMouseZoomHandler::x_OnMouseDrag(CGUIEvent& event)
- {
- switch(m_State) {
- case eScale: {
- int d_y = Fl::event_y() - m_MouseStartY;
- x_OnChangeScale(d_y);
- }; break;
- case eZoomRect: {
- x_OnChangeZoomRectPan(Fl::event_x(), Fl::event_y());
- }; break;
- case ePan: {
-
- x_OnChangePan();
- x_OnSelectCursor();
- }; break;
- default: break;
- }
- return 1; // always handle drags
- }
- void CMouseZoomHandler::x_OnChangePan()
- {
- m_CurrPosX = Fl::event_x();
- m_CurrPosY = Fl::event_y();
-
- int y1 = m_pHost->MZHH_GetVPPosByY(m_MouseStartY);
- int y2 = m_pHost->MZHH_GetVPPosByY(m_CurrPosY);
-
- TModelUnit m_x1 = m_pPane->UnProjectX(m_MouseStartX);
- TModelUnit m_y1 = m_pPane->UnProjectY(y1);
- TModelUnit m_x2 = m_pPane->UnProjectX(m_CurrPosX);
- TModelUnit m_y2 = m_pPane->UnProjectY(y2);
-
- m_pHost->MZHH_Scroll(m_x1 - m_x2, m_y1 - m_y2);
- m_pHost->MZHH_Redraw();
- m_MouseStartX = m_CurrPosX;
- m_MouseStartY = m_CurrPosY;
- }
- int CMouseZoomHandler::x_OnMouseRelease(CGUIEvent& event)
- {
- switch(m_State) {
- case eScale: {
- int d_y = Fl::event_y() - m_MouseStartY;
- x_OnChangeScale(d_y);
- x_OnEndScale(eReadyScale);
- x_OnSelectCursor();
- return 1;
- }; break;
- case eZoomRect: {
- x_OnChangeZoomRectPan(Fl::event_x(), Fl::event_y());
- x_OnEndZoomRect(eReadyZoomRect);
- x_OnSelectCursor();
- return 1;
- }; break;
- case ePan: {
- x_OnChangeZoomRectPan(Fl::event_x(), Fl::event_y());
- x_OnEndPan(eReadyPan);
- x_OnSelectCursor();
- return 1;
- }; break;
- default: break;
- }
- return 0;
- }
- int CMouseZoomHandler::x_OnMouseMove(void)
- {
- if(m_State != eIdle) {
- x_OnSelectCursor();
- return 1;
- }
- else return 0;
- }
- static int kWheelRatio = 10;
- int CMouseZoomHandler::x_OnMouseWheel(CGUIEvent& event)
- {
- if(event.GetGUIState() == CGUIEvent::eZoomState) {
- switch(m_State) {
- case eIdle:
- x_SwitchToReadyState(eReadyScale, Fl::event_x(), Fl::event_y()); // continue
- case eReadyScale: {
- m_WheelTotalShift = 0;
- x_SwithToActiveState(eScale, Fl::event_x(), Fl::event_y());
- }; // continue
- case eScale: {
- m_WheelTotalShift += Fl::event_dy() * kWheelRatio;
- x_OnChangeScale(m_WheelTotalShift);
-
- // updating shift after clipping with Min and Max norm values
- m_WheelTotalShift = (int) ((m_StartNorm - m_CurrNorm) * m_PixPerNorm);
- }; break;
- default: _ASSERT(false); break;
- }
- x_OnSelectCursor();
- return 1;
- } else return 0;
- }
- int CMouseZoomHandler::x_OnKeyDown(CGUIEvent& event)
- {
- if(m_State == eIdle) {
- EState ready_st = eIdle;
- switch(event.GetGUIState()) {
- case CGUIEvent::eZoomState: ready_st = eReadyScale; break;
- case CGUIEvent::eZoomRectState: ready_st = eReadyZoomRect; break;
- case CGUIEvent::ePanState: ready_st = eReadyPan; break;
- default: break;
- }
- if(ready_st != eIdle) {
- x_SwitchToReadyState(ready_st, Fl::event_x(), Fl::event_y());
- x_OnSelectCursor();
- }
- }
- return (m_State == eIdle) ? 0 : 1;
- }
- int CMouseZoomHandler::x_OnKeyUp(CGUIEvent& event)
- {
- CGUIEvent::EGUIState state = event.GetGUIState();
- if(state != CGUIEvent::eZoomState &&
- state != CGUIEvent::eZoomRectState) {
- switch(m_State) {
- case eIdle: break;
- case eReadyScale:
- case eReadyZoomRect:
- case eReadyPan:
- case eZoomRect:
- case ePan: {
- m_pHost->MZHH_Redraw();
- m_State = eIdle;
- x_OnSelectCursor();
- }; break;
- case eScale: {
- x_OnEndScale(eIdle);
- m_State = eIdle;
- x_OnSelectCursor();
- }; break;
- default: break;
- };
- }
- return (m_State == eIdle) ? 0 : 1;
- }
- ////////////////////////////////////////////////////////////////////////////////
- /// Signal handlers
- void CMouseZoomHandler::x_SwitchToReadyState(EState new_state, int pos_x, int pos_y)
- {
- _ASSERT(m_pHost);
- if(m_State != new_state) {
- m_State = new_state;
- m_CurrPosX = m_MarkerPosX = pos_x;
- m_CurrPosY = m_MarkerPosY = pos_y;
-
- if(m_State == eReadyScale) {
- m_CurrNorm = m_StartNorm = x_ScaleToNorm(m_pHost->MZHH_GetScale(IMouseZoomHandlerHost::eCurrent));
-
- m_MinNorm = x_ScaleToNorm(m_pHost->MZHH_GetScale(IMouseZoomHandlerHost::eMin));
- m_MaxNorm = x_ScaleToNorm(m_pHost->MZHH_GetScale(IMouseZoomHandlerHost::eMax));
- }
- m_pHost->MZHH_Redraw();
- }
- }
- void CMouseZoomHandler::x_SwithToActiveState(EState state, int pos_x, int pos_y)
- {
- _ASSERT(m_pHost);
-
- m_State = state;
- m_MouseStartX = pos_x;
- m_MouseStartY = pos_y;
- m_ptStart = m_pPane->UnProject(m_MouseStartX, m_pHost->MZHH_GetVPPosByY(m_MouseStartY));
- }
- /// d_y is the absolute shift in pixels from the position where m_StartNorm have
- /// been initialized
- void CMouseZoomHandler::x_OnChangeScale(int d_y)
- {
- if(d_y) {
- TModelUnit norm = m_StartNorm - ((TModelUnit) (d_y)) / m_PixPerNorm;
- norm = max(norm, m_MinNorm);
- norm = min(norm, m_MaxNorm);
- if(norm != m_CurrNorm) {
- m_CurrNorm = norm;
- TModelUnit scale = x_NormToScale(norm);
-
- m_pHost->MZHH_SetScale(scale, m_ptStart);
- }
- }
- }
- void CMouseZoomHandler::x_OnEndScale(EState new_state)
- {
- _ASSERT(new_state != eScale);
- m_State = new_state;
- m_StartNorm = m_CurrNorm;
-
- m_pHost->MZHH_Redraw();
- }
- void CMouseZoomHandler::x_OnChangeZoomRectPan(int x, int y)
- {
- if(x != m_CurrPosX || y != m_CurrPosY) {
- m_CurrPosX = x;
- m_CurrPosY = y;
- m_pHost->MZHH_Redraw();
- }
- }
- void CMouseZoomHandler::x_OnEndZoomRect(EState new_state)
- {
- m_State = new_state;
-
- TModelRect rc;
-
- int x1 = m_MouseStartX;
- int y1 = m_pHost->MZHH_GetVPPosByY(m_MouseStartY);
- int x2 = m_CurrPosX;
- int y2 = m_pHost->MZHH_GetVPPosByY(m_CurrPosY);
-
- rc.SetLeft(m_pPane->UnProjectX(min(x1, x2)));
- rc.SetRight(m_pPane->UnProjectX(max(x1, x2)));
- rc.SetBottom(m_pPane->UnProjectY(min(y1, y2)));
- rc.SetTop(m_pPane->UnProjectY(max(y1, y2)));
- m_pHost->MZHH_ZoomRect(rc);
- m_pHost->MZHH_Redraw();
- }
- void CMouseZoomHandler::x_OnEndPan(EState new_state)
- {
- m_State = new_state;
- int y1 = m_pHost->MZHH_GetVPPosByY(m_MouseStartY);
- int y2 = m_pHost->MZHH_GetVPPosByY(m_CurrPosY);
-
- TModelUnit m_x1 = m_pPane->UnProjectX(m_MouseStartX);
- TModelUnit m_y1 = m_pPane->UnProjectY(y1);
- TModelUnit m_x2 = m_pPane->UnProjectX(m_CurrPosX);
- TModelUnit m_y2 = m_pPane->UnProjectY(y2);
-
- m_pHost->MZHH_Scroll(m_x1 - m_x2, m_y1 - m_y2);
- m_pHost->MZHH_Redraw();
- }
- void CMouseZoomHandler::x_OnSelectCursor(void)
- {
- switch(m_State) {
- case eIdle:
- case eReadyScale: m_Cursor = FL_CURSOR_DEFAULT; break;
- case eScale: m_Cursor = FL_CURSOR_HAND; break;
- case eReadyPan:
- case ePan: m_Cursor = FL_CURSOR_MOVE; break;
- case eReadyZoomRect:
- case eZoomRect: m_Cursor = FL_CURSOR_CROSS; break;
- default: break;
- }
- //cout << "nCMouseZoomHandler::x_OnSelectCursor " << m_Cursor;
- fl_cursor(m_Cursor, FL_BLACK, FL_WHITE);
- }
- ////////////////////////////////////////////////////////////////////////////////
- /// helper functions
- TModelUnit CMouseZoomHandler::x_ScaleToNorm(TModelUnit scale) const
- {
- return log(scale);
- }
- TModelUnit CMouseZoomHandler::x_NormToScale(TModelUnit norm) const
- {
- return exp(norm);
- }
- END_NCBI_SCOPE
- /*
- * ===========================================================================
- * $Log: mouse_zoom_handler.cpp,v $
- * Revision 1000.3 2004/06/01 21:10:40 gouriano
- * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10
- *
- * Revision 1.10 2004/05/21 22:27:54 gorelenk
- * Added PCH ncbi_pch.hpp
- *
- * Revision 1.9 2004/03/26 15:03:48 yazhuk
- * Fixed stuff broken by previous changes
- *
- * Revision 1.8 2004/03/04 14:36:41 lebedev
- * Enable panning while mouse drag
- *
- * Revision 1.7 2004/03/02 21:54:52 yazhuk
- * Fixed CGlAttrGuard usage
- *
- * Revision 1.6 2004/02/17 15:23:01 yazhuk
- * Refactoring - replaced CGlParam with CGlAttrGuard
- *
- * Revision 1.5 2003/12/10 16:54:32 yazhuk
- * Added support for using mouse position to specify reference point for "active zoom".
- *
- * Revision 1.4 2003/12/08 15:12:48 yazhuk
- * Implemented deactivation on FL_UNFOCUS.
- *
- * Revision 1.3 2003/12/01 22:32:14 yazhuk
- * GCC ompilation fixes
- *
- * Revision 1.2 2003/12/01 16:41:30 yazhuk
- * Refactored event handling - introduced CGUIEvent; implemented zooming by
- * rectangle and panoraming.
- *
- * Revision 1.1 2003/11/17 20:24:51 yazhuk
- * Moved from widgetsaln_multiple
- *
- * Revision 1.3 2003/10/29 23:32:47 yazhuk
- * Updated includes
- *
- * Revision 1.2 2003/10/20 16:27:55 yazhuk
- * x_OnKeyUp() bug fix.
- *
- * Revision 1.1 2003/10/20 15:44:58 yazhuk
- * Initial revision.
- *
- * ===========================================================================
- */