diff options
Diffstat (limited to 'portato/gui/gtk/TreeViewTooltips.py')
-rw-r--r-- | portato/gui/gtk/TreeViewTooltips.py | 423 |
1 files changed, 0 insertions, 423 deletions
diff --git a/portato/gui/gtk/TreeViewTooltips.py b/portato/gui/gtk/TreeViewTooltips.py deleted file mode 100644 index 120d4df..0000000 --- a/portato/gui/gtk/TreeViewTooltips.py +++ /dev/null @@ -1,423 +0,0 @@ -# Copyright (c) 2006, Daniel J. Popowich -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation files -# (the "Software"), to deal in the Software without restriction, -# including without limitation the rights to use, copy, modify, merge, -# publish, distribute, sublicense, and/or sell copies of the Software, -# and to permit persons to whom the Software is furnished to do so, -# subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -# Send bug reports and contributions to: -# -# dpopowich AT astro dot umass dot edu -# - -''' -TreeViewTooltips.py - -Provides TreeViewTooltips, a class which presents tooltips for cells, -columns and rows in a gtk.TreeView. - ------------------------------------------------------------- - This file includes a demo. Just execute the file: - - python TreeViewTooltips.py ------------------------------------------------------------- - -To use, first subclass TreeViewTooltips and implement the get_tooltip() -method; see below. Then add any number of gtk.TreeVew widgets to a -TreeViewTooltips instance by calling the add_view() method. Overview -of the steps: - - # 1. subclass TreeViewTooltips - class MyTooltips(TreeViewTooltips): - - # 2. overriding get_tooltip() - def get_tooltip(...): - ... - - # 3. create an instance - mytips = MyTooltips() - - # 4. Build up your gtk.TreeView. - myview = gtk.TreeView() - ...# create columns, set the model, etc. - - # 5. Add the view to the tooltips - mytips.add_view(myview) - -How it works: the add_view() method connects the TreeView to the -"motion-notify" event with the callback set to a private method. -Whenever the mouse moves across the TreeView the callback will call -get_tooltip() with the following arguments: - - get_tooltip(view, column, path) - -where, - - view: the gtk.TreeView instance. - column: the gtk.TreeViewColumn instance that the mouse is - currently over. - path: the path to the row that the mouse is currently over. - -Based on whether or not column and path are checked for specific -values, get_tooltip can return tooltips for a cell, column, row or the -whole view: - - Column Checked Path Checked Tooltip For... - Y Y cell - Y N column - N Y row - N N view - -get_tooltip() should return None if no tooltip should be displayed. -Otherwise the return value will be coerced to a string (with the str() -builtin) and stripped; if non-empty, the result will be displayed as -the tooltip. By default, the tooltip popup window will be displayed -centered and just below the pointer and will remain shown until the -pointer leaves the cell (or column, or row, or view, depending on how -get_tooltip() is implemented). - -''' - - -import pygtk -pygtk.require('2.0') - -import gtk -import gtk.gdk -import gobject - -if gtk.gtk_version < (2, 8): - import warnings - - msg = ('''This module was developed and tested with version 2.8.18 of gtk. You are using version %d.%d.%d. Your milage may vary.''' - % gtk.gtk_version) - warnings.warn(msg) - - -# major, minor, patch -version = 1, 0, 0 - -class TreeViewTooltips: - - def __init__(self): - - ''' - Initialize the tooltip. After initialization there are two - attributes available for advanced control: - - window: the popup window that holds the tooltip text, an - instance of gtk.Window. - label: a gtk.Label that is packed into the window. The - tooltip text is set in the label with the - set_label() method, so the text can be plain or - markup text. - - Be default, the tooltip is enabled. See the enabled/disabled - methods. - ''' - - # create the window - self.window = window = gtk.Window(gtk.WINDOW_POPUP) - window.set_name('gtk-tooltips') - window.set_resizable(False) - window.set_border_width(4) - window.set_app_paintable(True) - window.connect("expose-event", self.__on_expose_event) - - - # create the label - self.label = label = gtk.Label() - label.set_line_wrap(True) - label.set_alignment(0.5, 0.5) - label.set_use_markup(True) - label.show() - window.add(label) - - # by default, the tooltip is enabled - self.__enabled = True - # saves the current cell - self.__save = None - # the timer id for the next tooltip to be shown - self.__next = None - # flag on whether the tooltip window is shown - self.__shown = False - - def enable(self): - 'Enable the tooltip' - - self.__enabled = True - - def disable(self): - 'Disable the tooltip' - - self.__enabled = False - - def __show(self, tooltip, x, y): - - '''show the tooltip popup with the text/markup given by - tooltip. - - tooltip: the text/markup for the tooltip. - x, y: the coord. (root window based) of the pointer. - ''' - - window = self.window - - # set label - self.label.set_label(tooltip) - # resize window - w, h = window.size_request() - # move the window - window.move(*self.location(x,y,w,h)) - # show it - window.show() - self.__shown = True - - def __hide(self): - 'hide the tooltip' - - self.__queue_next() - self.window.hide() - self.__shown = False - - def __leave_handler(self, view, event): - 'when the pointer leaves the view, hide the tooltip' - - self.__hide() - - def __motion_handler(self, view, event): - 'As the pointer moves across the view, show a tooltip.' - - path = view.get_path_at_pos(int(event.x), int(event.y)) - - if self.__enabled and path: - path, col, x, y = path - tooltip = self.get_tooltip(view, col, path) - if tooltip is not None: - tooltip = str(tooltip).strip() - if tooltip: - self.__queue_next((path, col), tooltip, - int(event.x_root), - int(event.y_root)) - return - - self.__hide() - - def __queue_next(self, *args): - - 'queue next request to show a tooltip' - - # if args is non-empty it means a request was made to show a - # tooltip. if empty, no request is being made, but any - # pending requests should be cancelled anyway. - - cell = None - - # if called with args, break them out - if args: - cell, tooltip, x, y = args - - # if it's the same cell as previously shown, just return - if self.__save == cell: - return - - # if we have something queued up, cancel it - if self.__next: - gobject.source_remove(self.__next) - self.__next = None - - # if there was a request... - if cell: - # if the tooltip is already shown, show the new one - # immediately - if self.__shown: - self.__show(tooltip, x, y) - # else queue it up in 1/2 second - else: - self.__next = gobject.timeout_add(500, self.__show, - tooltip, x, y) - - # save this cell - self.__save = cell - - - def __on_expose_event(self, window, event): - - # this magic is required so the window appears with a 1-pixel - # black border (default gtk Style). This code is a - # transliteration of the C implementation of gtk.Tooltips. - w, h = window.size_request() - window.style.paint_flat_box(window.window, gtk.STATE_NORMAL, - gtk.SHADOW_OUT, None, window, - 'tooltip', 0, 0, w, h) - - def location(self, x, y, w, h): - - '''Given the x,y coordinates of the pointer and the width and - height (w,h) demensions of the tooltip window, return the x, y - coordinates of the tooltip window. - - The default location is to center the window on the pointer - and 4 pixels below it. - ''' - - return x - w/2, y + 4 - - def add_view(self, view): - - 'add a gtk.TreeView to the tooltip' - - assert isinstance(view, gtk.TreeView), \ - ('This handler should only be connected to ' - 'instances of gtk.TreeView') - - view.connect("motion-notify-event", self.__motion_handler) - view.connect("leave-notify-event", self.__leave_handler) - - def get_tooltip(self, view, column, path): - 'See the module doc string for a description of this method' - - raise NotImplementedError, 'Subclass must implement get_tooltip()' - - -if __name__ == '__main__': - - ############################################################ - # DEMO - ############################################################ - - # First, subclass TreeViewTooltips - - class DemoTips(TreeViewTooltips): - - def __init__(self, customer_column): - # customer_column is an instance of gtk.TreeViewColumn and - # is being used in the gtk.TreeView to show customer names. - self.cust_col = customer_column - - # call base class init - TreeViewTooltips.__init__(self) - - def get_tooltip(self, view, column, path): - - # we have a two column view: customer, phone; we'll make - # tooltips cell-based for the customer column, but generic - # column-based for the phone column. - - # customer - if column is self.cust_col: - - # By checking both column and path we have a - # cell-based tooltip. - model = view.get_model() - customer = model[path][2] - return '<big>%s %s</big>\n<i>%s</i>' % (customer.fname, - customer.lname, - customer.notes) - # phone - else: - return ('<big><u>Generic Column Tooltip</u></big>\n' - 'Unless otherwise noted, all\narea codes are 888') - - def XX_location(self, x, y, w, h): - # rename me to "location" so I override the base class - # method. This will demonstrate being able to change - # where the tooltip window popups, relative to the - # pointer. - - # this will place the tooltip above and to the right - return x + 10, y - (h + 10) - - # Here's our customer - class Customer: - - def __init__(self, fname, lname, phone, notes): - self.fname = fname - self.lname = lname - self.phone = phone - self.notes = notes - - # create a bunch of customers - customers = [] - for fname, lname, phone, notes in [ - ('Joe', 'Schmoe', '555-1212', 'Likes to Morris dance.'), - ('Jane', 'Doe', '555-2323', - 'Wonders what the hell\nMorris dancing is.'), - ('Phred', 'Phantastic', '900-555-1212', 'Dreams of Betty.'), - ('Betty', 'Boop', '555-3434', 'Dreams in b&w.'), - ('Red Sox', 'Fan', '555-4545', - "Still livin' 2004!\nEspecially after 2006.")]: - customers.append(Customer(fname, lname, phone, notes)) - - # Build our model and view - model = gtk.ListStore(str, str, object) - for c in customers: - model.append(['%s %s' % (c.fname, c.lname), c.phone, c]) - - view = gtk.TreeView(model) - view.get_selection().set_mode(gtk.SELECTION_NONE) - - # two columns, name and phone - cell = gtk.CellRendererText() - cell.set_property('xpad', 20) - namecol = gtk.TreeViewColumn('Customer Name', cell, text=0) - namecol.set_min_width(200) - view.append_column(namecol) - - cell = gtk.CellRendererText() - phonecol = gtk.TreeViewColumn('Phone', cell, text=1) - view.append_column(phonecol) - - # finally, connect the tooltip, specifying the name column as the - # column we want the tooltip to popup over. - tips = DemoTips(namecol) - tips.add_view(view) - - # We're going to demonstrate enable/disable. First we need a - # callback function to connect to the toggled signal. - def toggle(button): - if button.get_active(): - tips.disable() - else: - tips.enable() - - # create a checkbutton and connect our handler - check = gtk.CheckButton('Check to disable view tooltips') - check.connect('toggled', toggle) - - # a standard gtk.Tooltips to compare to - tt = gtk.Tooltips() - tt.set_tip(check, ('This is a standard gtk tooltip.\n' - 'Compare me to the tooltips above.')) - - # create a VBox to pack the view and checkbutton - vbox = gtk.VBox() - vbox.pack_start(view) - vbox.pack_start(check, False) - vbox.show_all() - - # pack the vbox into a simple dialog and run it - dialog = gtk.Dialog('TreeViewTooltips Demo') - close = dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_NONE) - - # add a tooltip for the close button - tt.set_tip(close, 'Click to end the demo.') - - dialog.set_default_size(400,400) - dialog.vbox.pack_start(vbox) - dialog.run() |