From d0dafc171c75146e16081c263e92190570b88a0f Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 25 Sep 2014 21:43:15 -0400 Subject: [PATCH] basic design of Canvas item tooltip mechanism. No window yet to actually display the tooltip. --- libs/canvas/canvas.cc | 81 +++++++++++++++++++++++++++++++++++++ libs/canvas/canvas/canvas.h | 17 +++++++- libs/canvas/canvas/item.h | 7 ++++ libs/canvas/item.cc | 26 ++++++++++++ 4 files changed, 129 insertions(+), 2 deletions(-) diff --git a/libs/canvas/canvas.cc b/libs/canvas/canvas.cc index b61afed751..c671ce253e 100644 --- a/libs/canvas/canvas.cc +++ b/libs/canvas/canvas.cc @@ -26,6 +26,7 @@ #include #include #include +#include #include "pbd/compose.h" #include "pbd/stacktrace.h" @@ -345,6 +346,8 @@ GtkCanvas::GtkCanvas () , _new_current_item (0) , _grabbed_item (0) , _focused_item (0) + , current_tooltip_item (0) + , tooltip_window (0) { /* these are the events we want to know about */ add_events (Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK | @@ -607,7 +610,9 @@ GtkCanvas::deliver_enter_leave (Duple const & point, int state) _new_current_item->Event ((GdkEvent*)&enter_event); } + start_tooltip_timeout (_new_current_item); _current_item = _new_current_item; + } @@ -689,6 +694,11 @@ GtkCanvas::item_going_away (Item* item, boost::optional bounding_box) _focused_item = 0; } + if (current_tooltip_item) { + current_tooltip_item = 0; + stop_tooltip_timeout (); + } + ScrollGroup* sg = dynamic_cast(item); if (sg) { scrollers.remove (sg); @@ -834,6 +844,8 @@ GtkCanvas::get_mouse_position (Duple& winpos) const bool GtkCanvas::on_motion_notify_event (GdkEventMotion* ev) { + hide_tooltip (); + /* translate event coordinates from window to canvas */ GdkEvent copy = *((GdkEvent*)ev); @@ -974,6 +986,75 @@ GtkCanvas::height() const return get_allocation().get_height(); } +void +GtkCanvas::start_tooltip_timeout (Item* item) +{ + stop_tooltip_timeout (); + + if (item) { + current_tooltip_item = item; + + /* wait for the first idle that happens after this is + called. this means that we've stopped processing events, which + in turn implies that the user has stopped doing stuff for a + little while. + */ + + std::cerr << "wait for idle now that we're in " << item->name << std::endl; + + Glib::signal_idle().connect (sigc::mem_fun (*this, &GtkCanvas::really_start_tooltip_timeout)); + } +} + +bool +GtkCanvas::really_start_tooltip_timeout () +{ + /* an idle has occured since we entered a tooltip-bearing widget. Now + * wait 1 second and if the timeout isn't cancelled, show the tooltip. + */ + + std::cerr << "gone idle\n"; + + + if (current_tooltip_item) { + std::cerr << "have an item " << current_tooltip_item->name << " now wait 1second\n"; + _current_timeout_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &GtkCanvas::show_tooltip), 1000); + } + + return false; /* this is called from an idle callback, don't call it again */ +} + +void +GtkCanvas::stop_tooltip_timeout () +{ + if (current_tooltip_item) { + std::cerr << "Stop timeout for " << current_tooltip_item->name << "\n"; + } + current_tooltip_item = 0; + _current_timeout_connection.disconnect (); +} + +bool +GtkCanvas::show_tooltip () +{ + if (current_tooltip_item) { + std::cerr << "Would show a tooltip for " << current_tooltip_item->name << '\n'; + } else { + std::cerr << "tooltip timeout expired, but no item\n"; + } + + /* called from a timeout handler, don't call it again */ + return false; +} + +void +GtkCanvas::hide_tooltip () +{ + if (tooltip_window) { + tooltip_window->hide (); + } +} + /** Create a GtkCanvaSViewport. * @param hadj Adjustment to use for horizontal scrolling. * @param vadj Adjustment to use for vertica scrolling. diff --git a/libs/canvas/canvas/canvas.h b/libs/canvas/canvas/canvas.h index c3ab322b67..a7da4517bb 100644 --- a/libs/canvas/canvas/canvas.h +++ b/libs/canvas/canvas/canvas.h @@ -140,13 +140,16 @@ public: an enter event for it. */ virtual void re_enter () = 0; - + + virtual void start_tooltip_timeout (Item*) {} + virtual void stop_tooltip_timeout () {} + protected: void queue_draw_item_area (Item *, Rect); /** our root item */ Root _root; - + virtual void pick_current_item (int state) = 0; virtual void pick_current_item (Duple const &, int state) = 0; @@ -176,6 +179,9 @@ public: void re_enter (); + void start_tooltip_timeout (Item*); + void stop_tooltip_timeout (); + protected: bool on_scroll_event (GdkEventScroll *); bool on_expose_event (GdkEventExpose *); @@ -205,6 +211,13 @@ private: Item * _grabbed_item; /** the item that currently has key focus or 0 */ Item * _focused_item; + + sigc::connection _current_timeout_connection; + Item* current_tooltip_item; + Gtk::Window* tooltip_window; + bool show_tooltip (); + void hide_tooltip (); + bool really_start_tooltip_timeout (); }; /** A GTK::Alignment with a GtkCanvas inside it plus some Gtk::Adjustments for diff --git a/libs/canvas/canvas/item.h b/libs/canvas/canvas/item.h index 9b058ab83a..4492cb8651 100644 --- a/libs/canvas/canvas/item.h +++ b/libs/canvas/canvas/item.h @@ -228,6 +228,12 @@ public: void grab_focus (); #endif + const std::string& tooltip () const { return _tooltip; } + void set_tooltip (const std::string&); + + void start_tooltip_timeout (); + void stop_tooltip_timeout (); + virtual void dump (std::ostream&) const; std::string whatami() const; @@ -288,6 +294,7 @@ protected: private: void init (); + std::string _tooltip; bool _ignore_events; Duple scroll_offset() const; diff --git a/libs/canvas/item.cc b/libs/canvas/item.cc index 9be1f62d92..5aef4cc779 100644 --- a/libs/canvas/item.cc +++ b/libs/canvas/item.cc @@ -45,6 +45,8 @@ Item::Item (Canvas* canvas) , _lut (0) , _ignore_events (false) { + _tooltip = "This is a tooltip"; + DEBUG_TRACE (DEBUG::CanvasItems, string_compose ("new canvas item %1\n", this)); } @@ -59,6 +61,8 @@ Item::Item (Item* parent) , _lut (0) , _ignore_events (false) { + _tooltip = "This is a tooltip"; + DEBUG_TRACE (DEBUG::CanvasItems, string_compose ("new canvas item %1\n", this)); if (parent) { @@ -80,6 +84,8 @@ Item::Item (Item* parent, Duple const& p) , _lut (0) , _ignore_events (false) { + _tooltip = "This is a tooltip"; + DEBUG_TRACE (DEBUG::CanvasItems, string_compose ("new canvas item %1\n", this)); if (parent) { @@ -981,6 +987,26 @@ Item::add_items_at_point (Duple const point, vector& items) const } } +void +Item::set_tooltip (const std::string& s) +{ + _tooltip = s; +} + +void +Item::start_tooltip_timeout () +{ + if (!_tooltip.empty()) { + _canvas->start_tooltip_timeout (this); + } +} + +void +Item::stop_tooltip_timeout () +{ + _canvas->stop_tooltip_timeout (); +} + void Item::dump (ostream& o) const {