📄 tooltip.cpp
字号:
/* * =========================================================================== * PRODUCTION $Log: tooltip.cpp,v $ * PRODUCTION Revision 1000.1 2004/06/01 21:09:23 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10 * PRODUCTION * =========================================================================== *//* $Id: tooltip.cpp,v 1000.1 2004/06/01 21:09:23 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 <gui/widgets/fl/tooltip.hpp>#include <FL/fl_draw.H>#include <FL/forms.H>BEGIN_NCBI_SCOPE/////////////////////////////////////////////////////////////////////////////////// CTooltipCTooltip::CTooltip(): m_bActiveMode(false), m_Mode(eHideOnMove), m_Delay(0.8f), m_bEnabled(true), m_Widget(NULL), m_TooltipWidget(NULL), m_bRecentTooltip(0), m_bRecursion(0){ m_Color = fl_color_cube(FL_NUM_RED - 1, FL_NUM_GREEN - 1, FL_NUM_BLUE - 2); m_TextColor = FL_BLACK; m_Font = FL_HELVETICA; m_FontSize = FL_SMALL_SIZE;}CTooltip::~CTooltip(){ Deactivate(true); delete m_TooltipWidget;}void CTooltip::SetMode(EMode mode){ m_Mode = mode;}CTooltip::EMode CTooltip::GetMode() const{ return m_Mode;}float CTooltip::GetDelay() const { return m_Delay; }void CTooltip::SetDelay(float delay) { m_Delay = delay; }int CTooltip::IsEnabled() const { return m_bEnabled; }void CTooltip::Enable(bool b_en) { m_bEnabled = b_en;}void CTooltip::Disable() { m_bEnabled = false; }Fl_Widget* CTooltip::current() { return m_Widget; }int CTooltip::GetFont() const { return m_Font; }void CTooltip::SetFont(int font) { m_Font = font; } int CTooltip::GetFontSize() const { return m_FontSize; } void CTooltip::SetFontSize(int size) { m_FontSize = size; }void CTooltip::SetColor(Fl_Color color) { m_Color = color; }Fl_Color CTooltip::GetColor() const { return m_Color; }void CTooltip::SetTextColor(Fl_Color color) { m_TextColor = color; }Fl_Color CTooltip::GetTextColor() const { return m_TextColor; }const string& CTooltip::GetText() const{ return m_Text;}void CTooltip::Activate(Fl_Widget* client, const string& text, int x, int y, int w, int h){ _ASSERT(client); _ASSERT(! m_bActiveMode); Fl::belowmouse(client); x_Activate(client, x, y, w, h, text.c_str());}// hides tooltipvoid CTooltip::Deactivate(bool b_reset){ Fl::remove_timeout(ShowTooltipTimeout); if(m_Widget || x_IsTooltipVisible()) { /// hide tooltip and remove timer callbacks if(x_IsTooltipVisible()) { m_TooltipWidget->hide(); } if(m_bRecentTooltip) { //needs to be reset if(b_reset) { m_bRecentTooltip = 0; // clear immediately } else { Fl::add_timeout(.2f, ClearRecentTimeout, this); // clear after 0.2 sec } } m_Widget = NULL; }}bool CTooltip::x_IsTooltipVisible(){ return m_TooltipWidget && m_TooltipWidget->visible();}void CTooltip::x_Activate(Fl_Widget* client, int x, int y, int w,int h, const string& text){ _ASSERT(! m_bActiveMode); if(IsEnabled() && ! m_bRecursion) { bool b_changed = client != m_Widget || text != m_Text || x != m_X || y != m_Y || w != m_W || h != m_H; bool b_pos_changed = (m_MouseX != Fl::event_x() || m_MouseY != Fl::event_y()); bool b_active = m_TooltipWidget && m_TooltipWidget->visible(); ETooltipCmd cmd = eDoNothing; if(m_Mode == eHideOnMove) { if(!b_active || b_changed || b_pos_changed) { cmd = eShowDelayed; } } else { if(b_active) { if(b_changed || (m_Mode == eTrackOnMove && b_pos_changed)) { cmd = eUpdateAndMove; } } else { cmd = m_bRecentTooltip ? eUpdateAndMove : eShowDelayed; } } if(cmd != eDoNothing) { Fl::remove_timeout(ShowTooltipTimeout); Fl::remove_timeout(ClearRecentTimeout); m_Widget = client; m_X = x; m_Y = y; m_W = w; m_H = h; m_MouseX = Fl::event_x(); m_MouseY = Fl::event_y(); m_Text = text; } switch(cmd) { case eUpdateAndMove: { x_UpdateTooltipWidget(cmd); // show immediately }; break; case eShowDelayed: { if(m_TooltipWidget && m_TooltipWidget->visible()) { m_TooltipWidget->hide(); } Fl::add_timeout(m_Delay, ShowTooltipTimeout, this); // show after delay }; break; default: break; } }}// callback for "recent" timer - after specified delay cleans m_bRecentTooltip void CTooltip::ClearRecentTimeout(void* ptr) { CTooltip* pTooltip = reinterpret_cast<CTooltip*>(ptr); _ASSERT(pTooltip); pTooltip->m_bRecentTooltip = 0;}// callback for "delay" timervoid CTooltip::ShowTooltipTimeout(void* ptr) { CTooltip* pTooltip = reinterpret_cast<CTooltip*>(ptr); _ASSERT(pTooltip); if(pTooltip->m_bActiveMode) { // ask the client and may be show tooltip pTooltip->x_AskClientAndUpdate(); } else { // we know that tootlip must be shown pTooltip->x_UpdateTooltipWidget(eShowDelayed); }}bool CTooltip::EnableActiveMode(ITooltipClient* client){ if(client) { Deactivate(true); m_IClient = client; m_bActiveMode = true; return true; } else return false;}void CTooltip::DisableActiveMode(){ if(m_bActiveMode) { Deactivate(true); m_bActiveMode = false; }}const static int kMouseJump = 4; // max mouse travel between two eventsint CTooltip::Handle(int event){ switch(event) { case FL_MOVE: { if(m_bActiveMode) { Fl_Widget* wid = dynamic_cast<Fl_Widget*>(m_IClient); bool b_client_active = (Fl::belowmouse() == wid); int d_x = m_MouseX - Fl::event_x(); int d_y = m_MouseY - Fl::event_y(); bool jump = (d_x * d_x + d_y * d_y) > (kMouseJump * kMouseJump); m_MouseX = Fl::event_x(); m_MouseY = Fl::event_y(); if(m_Mode == eHideOnMove || jump) { // hide and question client after delay Deactivate(true); if(b_client_active) { Fl::remove_timeout(ShowTooltipTimeout); Fl::add_timeout(m_Delay, ShowTooltipTimeout, this); } } else if(b_client_active) { if(x_IsTooltipVisible() || m_bRecentTooltip) { x_AskClientAndUpdate(); // update immediately } else { // question client after delay Fl::add_timeout(m_Delay, ShowTooltipTimeout, this); } } } }; break; case FL_PUSH: case FL_DRAG: case FL_RELEASE: case FL_UNFOCUS: case FL_LEAVE: { Deactivate(true); }; break; } return 0;}// shows tooltip void CTooltip::x_UpdateTooltipWidget(ETooltipCmd cmd){ if(! m_bRecursion) { m_bRecursion = 1; if (! m_TooltipWidget) { m_TooltipWidget = new CTooltipWidget(this); } if(cmd == eShowDelayed || cmd == eUpdateAndMove) { // this cast bypasses the normal Fl_Window label() code: ((Fl_Widget*)m_TooltipWidget)->label(m_Text.c_str()); m_TooltipWidget->SetOrigin(Fl::event_x_root(), Fl::event_y_root()); } if(cmd != eDoNothing) { m_TooltipWidget->layout(); } switch(cmd) { case eUpdateAndMove: { if(m_TooltipWidget->visible()) { m_TooltipWidget->damage(1); } else { m_TooltipWidget->show(); }; }; break; case eShowDelayed: { m_TooltipWidget->show(); }; break; default: break; } Fl::remove_timeout(ClearRecentTimeout); // remove "recent" timer m_bRecentTooltip = 1; m_bRecursion = 0; }}/// This functions queries the Client and shows tooltip if necessary. Funtion never/// delays showing (if function is called - delay have already elapsed)void CTooltip::x_AskClientAndUpdate(){ if(m_IClient) { bool b_ok = m_IClient->TC_NeedTooltip(m_MouseX, m_MouseY); if(b_ok) { // show/update tooltip int x = m_MouseX, y = m_MouseY, w = 1, h = 1; string text = m_IClient->TC_GetTooltip(x, y, w, h); bool b_changed = text != m_Text || x != m_X || y != m_Y || w != m_W || h != m_H; ETooltipCmd cmd = eDoNothing; if(! x_IsTooltipVisible()) { cmd = eShowDelayed; } else if(b_changed || m_Mode == eTrackOnMove) { cmd = eUpdateAndMove; } if(cmd != eDoNothing) { m_Text = text; m_X = x; m_Y = y; m_W = w; m_H = h; x_UpdateTooltipWidget(cmd); } } else Deactivate(false); // client doesn't want any tootlips }}/////////////////////////////////////////////////////////////////////////////////// CTooltipWidgetconst static int kSpaceX = 4;const static int kSpaceY = 2;const static int kOffsetY = 24;CTooltipWidget::CTooltipWidget(CTooltip* tooltip): Fl_Menu_Window(0, 0), m_Tooltip(tooltip){ set_override(); end(); clear_flag(VISIBLE_FOCUS);}void CTooltipWidget::SetOrigin(int x, int y){ m_OrigX = x; m_OrigY = y;}#define MAX_WIDTH 400 void CTooltipWidget::layout() { fl_font(m_Tooltip->GetFont(), m_Tooltip->GetFontSize()); int width = MAX_WIDTH; int height = 0; fl_measure(m_Tooltip->GetText().c_str(), width, height, FL_ALIGN_LEFT | FL_ALIGN_WRAP | FL_ALIGN_INSIDE); width += 2 * kSpaceX; height += 2 * kSpaceY; // horizontal positioning int ox = m_OrigX; if(ox + width > Fl::w()) { ox = Fl::w() - width; } if(ox < 0) ox = 0; // vertical positioning int oy = m_OrigY + kOffsetY; if(oy + height > Fl::h()) { oy = Fl::h() - height; } if(oy < 0 ) { oy = 0; } if (oy < 0) { oy = 0; } resize(ox, oy, width, height);}void CTooltipWidget::draw() { draw_box(FL_BORDER_BOX, 0, 0, w(), h(), m_Tooltip->GetColor()); fl_color(m_Tooltip->GetTextColor()); fl_font(m_Tooltip->GetFont(), m_Tooltip->GetFontSize()); fl_draw(m_Tooltip->GetText().c_str(), kSpaceX, kSpaceY, w() - 2* kSpaceX, h() - 2 * kSpaceY, Fl_Align(FL_ALIGN_LEFT | FL_ALIGN_WRAP | FL_ALIGN_INSIDE));}void CTooltipWidget::show() { Fl_Menu_Window::show();}int CTooltipWidget::handle(int event){ switch(event) { case FL_FOCUS: return 0; default: return Fl_Menu_Window::handle(event); }}END_NCBI_SCOPE/* * =========================================================================== * $Log: tooltip.cpp,v $ * Revision 1000.1 2004/06/01 21:09:23 gouriano * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10 * * Revision 1.10 2004/05/21 22:27:53 gorelenk * Added PCH ncbi_pch.hpp * * Revision 1.9 2004/05/13 17:20:48 yazhuk * clean-up * * Revision 1.8 2004/05/03 19:49:28 yazhuk * Hide tooltip if mouse moves too fast * * Revision 1.7 2004/04/22 16:59:10 yazhuk * Clean-up * * Revision 1.6 2004/02/11 15:26:24 yazhuk * Event handling fix * * Revision 1.5 2004/02/04 22:26:31 yazhuk * Fixed event handling in active mode * * Revision 1.4 2004/01/27 18:48:23 dicuccio * Added call to DisableActiveMode() in destructor. Make Deactivate() always * remove timeouts * * Revision 1.3 2004/01/21 14:23:20 rsmith * Remove debug output statement. * * Revision 1.2 2004/01/08 19:45:16 yazhuk * Implemented "active" tooltips, refactored code, added comments * * Revision 1.1 2003/12/29 21:12:22 yazhuk * Initial revision * * =========================================================================== */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -