tooltip.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:14k
- /*
- * ===========================================================================
- * 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
- ////////////////////////////////////////////////////////////////////////////////
- /// CTooltip
- CTooltip::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 tooltip
- void 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" timer
- void 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 events
- int 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
- }
- }
- ////////////////////////////////////////////////////////////////////////////////
- /// CTooltipWidget
- const 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
- *
- * ===========================================================================
- */