linear_sel_handler.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:17k
- /*
- * ===========================================================================
- * PRODUCTION $Log: linear_sel_handler.cpp,v $
- * PRODUCTION Revision 1000.2 2004/06/01 21:10:38 gouriano
- * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.11
- * PRODUCTION
- * ===========================================================================
- */
- /* $Id: linear_sel_handler.cpp,v 1000.2 2004/06/01 21:10:38 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/widgets/gl/linear_sel_handler.hpp>
- #include <FL/Fl.H>
- #include <math.h>
- BEGIN_NCBI_SCOPE
- static int kDragThreshold = 4; // make this configurable
- ISelHandlerHost::~ISelHandlerHost()
- {
- }
- ////////////////////////////////////////////////////////////////////////////////
- /// class CLinearSelHandler
- CLinearSelHandler::CLinearSelHandler(EOrientation orient)
- : m_Orientation(orient),
- m_ExtState(eNoExt),
- m_OpType(eNoOp),
- m_bResizeCursor(false),
- m_pHost(NULL),
- m_SelColor(0.5f, 0.5f, 0.5f, 0.25f),
- m_PassiveSelColor(0.6f, 0.6f, 0.6f, 0.25f),
- m_SymbolColor(0.0f, 0.0f, 1.0f, 1.0f),
- m_Font(CGlBitmapFont::eHelvetica24)
- {
- }
- CLinearSelHandler::~CLinearSelHandler()
- {
- }
- void CLinearSelHandler::SetHost(ISelHandlerHost* pHost)
- {
- m_pHost = pHost;
- }
- int CLinearSelHandler::handle(CGUIEvent& event, CGlPane& pane)
- {
- m_pPane = &pane;
- int res = 0;
- switch(event.GetFLTKEvent()) {
- case FL_PUSH: res = x_OnMousePush(event, pane); break;
- case FL_DRAG: res = x_OnMouseDrag(event, pane); break;
- case FL_RELEASE: res = x_OnMouseRelease(event, pane); break;
- case FL_MOVE: res = x_OnMouseMove(event, pane); break;
- case FL_KEYDOWN: res = x_OnKeyDown(event); break;
- case FL_KEYUP: res = x_OnKeyUp(event); break;
- }
- m_pPane = 0;
- return res;
- }
- TSeqRange CLinearSelHandler::GetSelectionLimits() const
- {
- return m_Selection.GetLimits();
- }
- const CLinearSelHandler::TRangeColl& CLinearSelHandler::GetSelection() const
- {
- return m_Selection;
- }
- void CLinearSelHandler::SetSelection(const TRangeColl& C, bool b_redraw)
- {
- m_Selection = C;
- if(b_redraw)
- m_pHost->SHH_Redraw();
- }
- void CLinearSelHandler::ResetSelection(bool b_redraw)
- {
- m_Selection.clear();
- if(b_redraw)
- m_pHost->SHH_Redraw();
- }
- void CLinearSelHandler::SetColor(EColorType type, const CGlColor& color)
- {
- switch(type) {
- case eSelection: m_SelColor = color; break;
- case ePasssiveSelection: m_PassiveSelColor = color; break;
- case eSymbol: m_SymbolColor = color; break;
- default: _ASSERT(false);
- }
- }
- ////////////////////////////////////////////////////////////////////////////////
- // event handlers
- int CLinearSelHandler::x_OnMousePush(CGUIEvent& event, CGlPane& pane)
- {
- CGUIEvent::EGUIState state = event.GetGUIState();
- if((state == CGUIEvent::eSelectState || state == CGUIEvent::eSelectAltState)
- && event.GetGUISignal() == CGUIEvent::eSelectSignal) {
-
- if(Fl::event_clicks() == 0) {
- x_OnStartSel(event);
- x_OnSelectCursor();
- } else { // doubleclick
- x_OnResetAll();
- }
- return 1;
- }
- return 0;
- }
- int CLinearSelHandler::x_OnMouseDrag(CGUIEvent& event, CGlPane& pane)
- {
- CGUIEvent::EGUIState state = event.GetGUIState();
- if(m_OpType != eNoOp &&
- (state == CGUIEvent::eSelectState || state == CGUIEvent::eSelectAltState)) {
- x_OnChangeSelRange();
- }
- return 1; // always handle drags
- }
- int CLinearSelHandler::x_OnMouseRelease(CGUIEvent& event, CGlPane& pane)
- {
- CGUIEvent::EGUIState state = event.GetGUIState();
- if(event.GetGUISignal() == CGUIEvent::eRelease &&
- (state == CGUIEvent::eSelectState || state == CGUIEvent::eSelectAltState)) {
-
- m_OpType = x_GetOpTypeByEvent(event);
- x_OnChangeSelRange();
- x_OnEndSelRange();
- x_OnSelectCursor();
- return 1;
- }
- return 0;
- }
- int CLinearSelHandler::x_OnMouseMove(CGUIEvent& event, CGlPane& pane)
- {
- CGUIEvent::EGUIState state = event.GetGUIState();
- x_OnSelectCursor();
- if(state == CGUIEvent::eSelectState || state == CGUIEvent::eSelectAltState) {
- return 1;
- } else return 0;
- }
- int CLinearSelHandler::x_OnKeyDown(CGUIEvent& event)
- {
- x_OnOpChange(event);
- return 0;
- }
- int CLinearSelHandler::x_OnKeyUp(CGUIEvent& event)
- {
- x_OnOpChange(event);
- return 0;
- }
- ////////////////////////////////////////////////////////////////////////////////
- /// Signal handlers
- void CLinearSelHandler::x_OnStartSel(CGUIEvent& event)
- {
- TSeqRange HitR;
- bool b_hit_start = false;
- x_HitTest(HitR, b_hit_start);
-
- if(HitR.NotEmpty()) { // hit a border of the selected range
- m_OpType = eChange;
- m_ExtState = b_hit_start ? eExtRangeStart : eExtRangeEnd;
- m_CurrRange = HitR;
- x_RemoveFromSelection(HitR);
- } else {
- m_ExtState = eExtRangeEnd;
- m_OpType = x_GetOpTypeByEvent(event);
- TModelUnit m_Z = x_MouseToSeqPos();
- TSeqPos pos = (TSeqPos) floor(m_Z);
- m_CurrRange.SetFrom(pos);
- m_CurrRange.SetToOpen(pos);
- }
- m_pHost->SHH_Redraw();
- }
- void CLinearSelHandler::x_OnChangeSelRange()
- {
- TModelUnit m_Z = x_MouseToSeqPos();
- TSeqPos pos = (TSeqPos) floor(m_Z);
- pos = x_ClipPosByRange(pos);
- TSeqRange old_r = m_CurrRange;
- if(m_ExtState == eNoExt && pos != m_CurrRange.GetFrom()) {
- if(pos > m_CurrRange.GetFrom()) {
- m_CurrRange.SetToOpen(pos);
- m_ExtState = eExtRangeEnd;
- } else {
- m_CurrRange.SetToOpen(m_CurrRange.GetFrom());
- m_CurrRange.SetFrom(pos);
- m_ExtState = eExtRangeStart;
- }
- } else if(m_ExtState == eExtRangeEnd && pos != m_CurrRange.GetToOpen()) {
- if(pos > m_CurrRange.GetFrom()) {
- m_CurrRange.SetToOpen(pos);
- } else { //flip
- m_CurrRange.SetToOpen(m_CurrRange.GetFrom());
- m_CurrRange.SetFrom(pos);
- m_ExtState = eExtRangeStart;
- }
- } else if(m_ExtState == eExtRangeStart && pos != m_CurrRange.GetFrom()) {
- if(pos <= m_CurrRange.GetToOpen()) {
- m_CurrRange.SetFrom(pos);
- } else {
- m_CurrRange.SetFrom(m_CurrRange.GetToOpen());
- m_CurrRange.SetToOpen(pos);
- m_ExtState = eExtRangeEnd;
- }
- };
-
- if(m_CurrRange != old_r)
- m_pHost->SHH_Redraw();
- }
- void CLinearSelHandler::x_OnEndSelRange()
- {
- if(! m_CurrRange.Empty()) {
- switch(m_OpType) {
- case eAdd:
- case eChange: x_AddToSelection(m_CurrRange); break;
- case eRemove: x_RemoveFromSelection(m_CurrRange); break;
- case eNoOp: break;
- }
- }
- m_CurrRange.SetLength(0);
-
- m_ExtState = eNoExt;
- m_OpType = eNoOp;
-
- m_pHost->SHH_Redraw();
- }
- void CLinearSelHandler::x_OnResetAll()
- {
- bool b_update = ! m_Selection.empty();
- m_Selection.clear();
- m_ExtState = eNoExt;
- m_OpType = eNoOp;
- if(b_update)
- m_pHost->SHH_Redraw();
- }
- void CLinearSelHandler::x_OnOpChange(CGUIEvent& event)
- {
- if(m_ExtState != eNoExt) {
- EOpType NewType = x_GetOpTypeByEvent(event);
-
- if(NewType != m_OpType) {
- m_OpType = NewType;
- x_OnSelectCursor();
- m_pHost->SHH_Redraw();
- }
- }
- }
- void CLinearSelHandler::x_OnSelectCursor()
- {
- switch(m_OpType) {
- case eNoOp: {
- TSeqRange HitR;
- bool b_hit_start = false;
- x_HitTest(HitR, b_hit_start);
-
- m_bResizeCursor = HitR.NotEmpty();
- }; break;
- case eAdd:
- case eRemove:
- case eChange: m_bResizeCursor = true; break;
- }
- x_SetCursor();
- }
- void CLinearSelHandler::x_SetCursor()
- {
- Fl_Cursor Cur = FL_CURSOR_DEFAULT;
- if(m_bResizeCursor) {
- Cur = (m_Orientation == eHorz) ? FL_CURSOR_WE : FL_CURSOR_NS;
- }
- fl_cursor(Cur, FL_BLACK, FL_WHITE);
- }
- ////////////////////////////////////////////////////////////////////////////////
- /// helper functions
- // translate modificators to operation type
- CLinearSelHandler::EOpType CLinearSelHandler::x_GetOpTypeByEvent(CGUIEvent& event) const
- {
- switch(event.GetGUIState()) {
- case CGUIEvent::eSelectState: return eAdd;
- case CGUIEvent::eSelectAltState: return eRemove;
- default: return eNoOp;
- }
- }
- TModelUnit CLinearSelHandler::x_MouseToSeqPos()
- {
- _ASSERT(m_pPane);
- int z = (m_Orientation == eHorz) ? Fl::event_x() : Fl::event_y();
- return m_pHost->SHH_GetModelByWindow(z, m_Orientation) + 0.5;
- }
- void CLinearSelHandler::x_HitTest(TSeqRange& range, bool& b_hit_start)
- {
- _ASSERT(m_pPane);
- int z = (m_Orientation == eHorz) ? Fl::event_x() : Fl::event_y();
-
- int min_D = -1;
- bool b_min_start = false;
- const TSeqRange* p_min_range = 0;
- const TRangeColl& C = m_Selection;
- ITERATE(TRangeColl, it, C) {
- const TSeqRange& R = *it;
- int from_Z = m_pHost->SHH_GetWindowByModel(R.GetFrom(), m_Orientation);
- int to_Z = m_pHost->SHH_GetWindowByModel(R.GetToOpen(), m_Orientation);
- int D = abs(z - from_Z);
- if(min_D < 0 || min_D > D) {
- min_D = D;
- b_min_start = true;
- p_min_range = &R;
- }
- D = abs(z - to_Z);
- if(min_D > D) {
- min_D = D;
- b_min_start = false;
- p_min_range = &R;
- }
- }
- if(min_D > -1 && min_D <= kDragThreshold) {
- b_hit_start = b_min_start;
- _ASSERT(p_min_range);
- range = *p_min_range;
- } else range.SetLength(0);
- }
- TSeqPos CLinearSelHandler::x_ClipPosByRange(TSeqPos pos)
- {
- bool b_horz = (m_Orientation == eHorz);
- TModelRect rc_lim = m_pPane->GetModelLimitsRect();
- pos = max(pos, (TSeqPos) (b_horz ? rc_lim.Left() : rc_lim.Bottom()));
- pos = min(pos, (TSeqPos) (b_horz ? rc_lim.Right() : rc_lim.Top()));
- return pos;
- }
- void CLinearSelHandler::x_AddToSelection(const TSeqRange& range)
- {
- m_Selection.CombineWith(range);
- }
- void CLinearSelHandler::x_RemoveFromSelection(const TSeqRange& range)
- {
- m_Selection.Subtract(range);
- }
- void CLinearSelHandler::Render(CGlPane& pane, ERenderingOption option)
- {
- TModelRect rc_vis = pane.GetVisibleRect();
-
- if(! rc_vis.IsEmpty()) {
- pane.OpenOrtho();
-
- TModelUnit offset_x = pane.GetOffsetX();
- TModelUnit offset_y = pane.GetOffsetY();
- bool b_horz = (m_Orientation == eHorz);
- // draw exisiting selection
- glColorC( (option == eActiveState) ? m_SelColor : m_PassiveSelColor);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-
- const TRangeColl& C = m_Selection;
- ITERATE(TRangeColl, it, C) { // for every segment
- const TSeqRange& r = *it;
- switch(m_Orientation) {
- case eHorz: glRectd(r.GetFrom() - offset_x, rc_vis.Bottom() - offset_y,
- r.GetToOpen() - offset_x, rc_vis.Top() - offset_y); break;
- case eVert: glRectd(rc_vis.Left() - offset_x, r.GetFrom() - offset_y,
- rc_vis.Right() - offset_x, r.GetToOpen() - offset_y); break;
- }
- }
-
- if(m_OpType != eNoOp) { // draw current range
- TModelRect rc_curr(rc_vis);
- if(b_horz) {
- rc_curr.SetLeft( max(rc_vis.Left(), (TModelUnit) m_CurrRange.GetFrom()) );
- rc_curr.SetRight( min(rc_vis.Right(), (TModelUnit) m_CurrRange.GetToOpen()) );
- } else {
- rc_curr.SetBottom( max(rc_vis.Bottom(), (TModelUnit) m_CurrRange.GetFrom()) );
- rc_curr.SetTop( min(rc_vis.Top(), (TModelUnit) m_CurrRange.GetToOpen()) );
- }
- glRectd(rc_curr.Left() - offset_x, rc_curr.Top() - offset_y,
- rc_curr.Right() - offset_x, rc_curr.Bottom() - offset_y);
-
- if(option == eActiveState) {
- glColorC(m_SymbolColor);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- glRectd(rc_curr.Left() - offset_x, rc_curr.Bottom() - offset_y,
- rc_curr.Right() - offset_x, rc_curr.Top() - offset_y);
-
- // drwaing Operation symbol
- const char* s = 0;
- switch(m_OpType) {
- case eAdd: s = "+"; break;
- case eRemove: s = "-"; break;
- case eChange: s = "<->"; break;
- case eNoOp: break;
- }
-
- float w = m_Font.TextWidth(s) * pane.GetScaleX();
- float kY = pane.GetScaleY() < 0 ? -1.0f : 1.0f;
- float h = kY * m_Font.TextHeight() * pane.GetScaleY(); // make it positive
-
- // if there is enougth space - draw operation symbol
- if(w < rc_curr.Width() && h < fabs(rc_curr.Height())) {
- float x = (rc_curr.Left() + rc_curr.Right() - w) / 2 - offset_x;
- float y = (rc_curr.Bottom() + rc_curr.Top() - h) / 2 - offset_y;
- m_Font.TextOut(x, y, s);
- }
- }
- }
- pane.Close();
- }
- }
- END_NCBI_SCOPE
- /*
- * ===========================================================================
- * $Log: linear_sel_handler.cpp,v $
- * Revision 1000.2 2004/06/01 21:10:38 gouriano
- * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.11
- *
- * Revision 1.11 2004/05/21 22:27:54 gorelenk
- * Added PCH ncbi_pch.hpp
- *
- * Revision 1.10 2004/04/06 16:07:58 yazhuk
- * Clean-up
- *
- * Revision 1.9 2004/03/23 14:07:37 dicuccio
- * Fixed compiler warnings
- *
- * Revision 1.8 2004/03/11 17:52:33 dicuccio
- * Use TSeqRange instead of TRange
- *
- * Revision 1.7 2004/02/12 21:00:47 yazhuk
- * Support of CGlPane "offset" mode
- *
- * Revision 1.6 2004/02/09 14:36:54 lebedev
- * Restore glPolygonMode to default state after rendering
- *
- * Revision 1.5 2004/02/09 13:49:14 lebedev
- * Added methods for customizing selection colors
- *
- * Revision 1.4 2004/01/08 19:46:01 yazhuk
- * Clean-up
- *
- * Revision 1.3 2003/12/05 17:51:04 yazhuk
- * Fixed cursor selection for vertical orientation.
- *
- * Revision 1.2 2003/12/01 20:52:36 ucko
- * Use fabs, not abs, for floating-point numbers.
- *
- * Revision 1.1 2003/12/01 16:33:19 yazhuk
- * Former alnmulti_sel_handler.cpp moved to gui/widgets/gl
- *
- * Revision 1.12 2003/10/29 23:28:34 yazhuk
- * Changed includes
- *
- * Revision 1.11 2003/10/20 15:51:58 yazhuk
- * Changed keyboard events handling policy.
- *
- * Revision 1.10 2003/10/15 21:25:03 yazhuk
- * Fixed "selection last position" bug. Eliminated excessive updates.
- *
- * Revision 1.9 2003/10/10 19:07:36 yazhuk
- * Replaced glColor3fv with glColorC
- *
- * Revision 1.8 2003/10/08 14:17:25 dicuccio
- * use glColor3fv instead of glColorC
- *
- * Revision 1.7 2003/09/29 17:00:09 dicuccio
- * fl.H -> Fl.H
- *
- * Revision 1.6 2003/09/29 15:53:42 dicuccio
- * Reordered #include statements
- *
- * Revision 1.5 2003/09/23 21:11:21 yazhuk
- * Removed x_ModifiersOk() and x_ClipPosByRange() definitions
- *
- * Revision 1.4 2003/09/14 14:03:44 ucko
- * #include <math.h> (needed with GCC)
- *
- * Revision 1.3 2003/09/10 20:44:21 yazhuk
- * Improved drawing of the current range
- *
- * Revision 1.2 2003/09/08 20:49:42 yazhuk
- * Added functions for manipulating with Selection
- *
- * Revision 1.1 2003/09/08 16:31:49 yazhuk
- * Initial revision
- *
- * ===========================================================================
- */