13
0

basic design of Canvas item tooltip mechanism.

No window yet to actually display the tooltip.
This commit is contained in:
Paul Davis 2014-09-25 21:43:15 -04:00
parent 3ec0f367c1
commit d0dafc171c
4 changed files with 129 additions and 2 deletions

View File

@ -26,6 +26,7 @@
#include <cassert>
#include <gtkmm/adjustment.h>
#include <gtkmm/label.h>
#include <gtkmm/window.h>
#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<Rect> bounding_box)
_focused_item = 0;
}
if (current_tooltip_item) {
current_tooltip_item = 0;
stop_tooltip_timeout ();
}
ScrollGroup* sg = dynamic_cast<ScrollGroup*>(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.

View File

@ -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

View File

@ -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;

View File

@ -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<Item const *>& 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
{