uiutils/basemixins.py
author Pierre-Yves David <pierre-yves.david@logilab.fr>
Fri, 13 Jun 2008 15:37:48 +0200
changeset 5 ee38ef554863
parent 0 7710b138d4eb
permissions -rw-r--r--
remove apycot.ini

# -*- coding: ISO-8859-1 -*-
# pylint: disable-msg=W0142,W0232,R0903,W0613
# (disable some pylint message caused by use of mixin classes)
# Copyright (c) 2004 LOGILAB S.A. (Paris, FRANCE).
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

"""this module exports all base mixins used to build text_windows,
treeviews, etc.
"""

__revision__ = '$Id: basemixins.py,v 1.3 2004-12-13 17:22:12 syt Exp $'
__metaclass__ = type

__all__ = [ 'WindowMixIn', 'MenuControlledWindowMixIn', 'TreeViewMixIn',
            'PluggableFrameMixIn', 'DelegatedWindowMixIn', 'TextWindowMixIn',
            ]
import gtk

class WindowMixIn:
    """a mixin for implementing some method like show/hide whose call
    will be delegated to the mixed instance "win" attribute
    """
    def set_title(self, title):
        """sets the window title"""
        self.win.set_title(title)

    def show(self, *args):
        """show the window"""
        self.win.show_all()

    def hide(self, *args):
        """hides the window"""
        self.win.hide()
        return gtk.TRUE

class MenuControlledWindowMixIn:
    """a mix in class for windows that can be shown/hidden using a stateful
    button of the main window
    """

    def __init__(self, **kwargs):
        super(MenuControlledWindowMixIn, self).__init__(**kwargs)
        self.__mitem = None
        
    def set_menu_item(self, menuitem):
        """set the menu item used to show/hide the window"""
        assert self.__mitem is None
        self.win.connect('show', self.cb_visibility_changed)
        self.win.connect('hide', self.cb_visibility_changed)
        self.__mitem = menuitem
        
    def cb_visibility_changed(self, *args):
        """set the menu item used to show/hide the window"""
        self.__mitem.set_active(self.win.get_property('visible'))

    def cb_toggle_visibility(self, item, *args):
        """sync the window visibility according to the item activity"""
        if item.get_active():
            self.show()
        else:
            self.hide()


class TreeViewMixIn:
    """a mixin providing some convenience function for windows with a TreeView
    instance stored as the "treeview" attribute
    """
    def activate_keyboard_callbacks(self, kpress_data):
        """activates keyboard callbacks management.

        Once this method called, any keyboard's key pressed will be connected
        to a callback called 'on_%KEYNAME%_pressed' where KEYNAME is the
        key's name (on_a_pressed will be called after 'a' is pressed)

        :type kpress_data: tuple or None
        :param kpress_data: if specified, kpress_data will be passed as
                            additional arguments to the callback
        """
        if kpress_data:
            self.treeview.connect('key-press-event', self.on_key_pressed,
                                  *kpress_data)
        else:
            self.treeview.connect('key-press-event', self.on_key_pressed)

    
    def activate_mouse_callbacks(self, bpress_data = None):
        """activates mouse callbacks management.

        Once this method called, the methods :
          - on_right_click()
          - on_left_click()
          - on_double_click()
        will be considered as callbacks to call when the appropriate event
        is emiited
        
        :type bpress_data: tuple or None
        :param bpress_data: if specified, bpress_data will be passed as
                            additional arguments to the callback
        """
        if bpress_data:
            self.treeview.connect('button-press-event', self.on_button_pressed,
                                  *bpress_data)
        else:
            self.treeview.connect('button-press-event', self.on_button_pressed)


    def activate_default_callbacks(self, kpress_data = None, bpress_data = None):
        """activates default mouse and keyboard callbacks

        :type kpress_data: tuple or None
        :param kpress_data: the same as for activate_keyboard_callbacks

        :type bpress_data: tuple or None
        :param bpress_data: the same as for activate_mouse_callbacks
        """
        self.activate_keyboard_callbacks(kpress_data)
        self.activate_mouse_callbacks(bpress_data)

          
    def get_selected(self):
        """returns the object corresponding to the selected line and in columns
        store_col_index of the store
        
        :returns: the selected value or None if no selection
        """
        selection = self.treeview.get_selection()
        store, tree_iter = selection.get_selected()
        if tree_iter is None:
            return None
        treepath = store.get_path(tree_iter)
        return store[treepath]
    
    def clear(self, *args):
        """resets the treeview's content"""
        self.treeview.get_model().clear()        

    def on_button_pressed(self, treeview, event, *args):
        """called when the user clicks on the FS treeview"""
        click_cb = None
        # left click
        if event.button == 1:
            # double_click
            if event.type == gtk.gdk._2BUTTON_PRESS:
                try:
                    click_cb = getattr(self, 'on_double_click')
                except AttributeError:
                    pass
            else:
                try:
                    click_cb = getattr(self, 'on_left_click')
                except AttributeError:
                    pass
        elif event.button == 3:
            try:
                click_cb = getattr(self, 'on_right_click')
            except AttributeError:
                pass
        if click_cb:
            click_cb(self.get_selected(), event, *args)

    def on_key_pressed(self, treeview, event, *args):
        """called when a keyboard key is pressed"""
        key = event.keyval
        #if key < 256:
        keyname = gtk.gdk.keyval_name(key).lower()
        try:
            key_pressed_cb = getattr(self, 'on_%s_pressed' % keyname)
        except AttributeError:
            pass
        else:
            key_pressed_cb(self.get_selected(), event, *args)
           

class PluggableFrameMixIn:
    """a mixin implementing some usefulle methods for window made of a tree
    and a frame where plugins can set their own widget
    """

    def set_plugin_widget(self, plugin_widget):
        """resets the plugin widget (removes the current one if necessary)"""
        frame_children = self.plugin_frame.get_children()
        if frame_children:
            # should maybe save existing widget
            existing_widget = frame_children[0]
            self.plugin_frame.remove(existing_widget)
        if plugin_widget:
            self.plugin_frame.add(plugin_widget)

    
class DelegatedWindowMixIn(WindowMixIn):
    """a mixin implementing some method like show/hide whose call will
    be delegated to the mixed instance "win" attribute
    """

    def __init__(self, window_type=gtk.WINDOW_TOPLEVEL, **kwargs):
        super(DelegatedWindowMixIn, self).__init__(**kwargs)
        self.win = gtk.Window(window_type)
        self.win.connect('delete-event', self.hide)


class TextWindowMixIn(DelegatedWindowMixIn):
    """a mixin for a window containing a text view, with some method
    providing direct access to the text view (`write`, `reset`)
    """

    def __init__(self, **kwargs):
        super(TextWindowMixIn, self).__init__(**kwargs)
        scr = gtk.ScrolledWindow()
        scr.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        self.win.add(scr)
        self.text_view = gtk.TextView()
        scr.add(self.text_view)

    def write(self, msg):
        """appends a message to the text buffer"""
        text_buffer = self.text_view.get_buffer()
        enditer = text_buffer.get_end_iter()
        text_buffer.insert(enditer, msg)
        self.text_view.scroll_mark_onscreen(text_buffer.get_insert())

    def reset(self):
        """resets the text buffer"""
        text_buffer = self.text_view.get_buffer()
        text_buffer.set_text('')