Changes between Version 5 and Version 6 of PyGTK


Ignore:
Timestamp:
07/23/06 00:39:47 (18 years ago)
Author:
atzm
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • PyGTK

    v5 v6  
    6767                                'hogehoge', 'tag_name') 
    6868}}} 
     69 
     70== !TextView 内にハイパーリンク的なものを作ってみる == 
     71DnD は未実装. 
     72 
     73{{{ 
     74#!python 
     75#!/usr/bin/env python 
     76 
     77import gtk 
     78import gobject 
     79import pango 
     80 
     81class HyperTextView(gtk.TextView): 
     82    __gtype_name__ = 'HyperTextView' 
     83    __gsignals__ = { 
     84        'anchor-clicked': (gobject.SIGNAL_RUN_LAST, None, (str, str, int)), 
     85        } 
     86    __gproperties__ = { 
     87        'link':  (gobject.TYPE_PYOBJECT, 'link color', 'link color of TextView', gobject.PARAM_READWRITE), 
     88        'active':(gobject.TYPE_PYOBJECT, 'active color', 'active color of TextView', gobject.PARAM_READWRITE), 
     89        'hover': (gobject.TYPE_PYOBJECT, 'link:hover color', 'link:hover color of TextView', gobject.PARAM_READWRITE), 
     90        } 
     91    def do_get_property(self, prop): 
     92        try: 
     93            return getattr(self, prop.name) 
     94        except AttributeError: 
     95            raise AttributeError, 'unknown property %s' % prop.name 
     96    def do_set_property(self, prop, val): 
     97        if prop.name in self.__gproperties__.keys(): 
     98            setattr(self, prop.name, val) 
     99        else: 
     100            raise AttributeError, 'unknown property %s' % prop.name 
     101 
     102    def __init__(self, buffer=None): 
     103        gtk.TextView.__init__(self, buffer) 
     104        self.link   = {'background': 'white', 'foreground': 'blue', 'underline': pango.UNDERLINE_SINGLE} 
     105        self.active = {'background': 'light gray', 'foreground': 'red', 'underline': pango.UNDERLINE_SINGLE} 
     106        self.hover  = {'background': 'light gray', 'foreground': 'blue', 'underline': pango.UNDERLINE_SINGLE} 
     107 
     108        self.set_editable(False) 
     109        self.set_cursor_visible(False) 
     110 
     111        self.__tags = [] 
     112 
     113        self.connect('motion-notify-event', self._motion) 
     114        self.connect('focus-out-event', lambda w, e: self.get_buffer().get_tag_table().foreach(self.__tag_reset, e.window)) 
     115 
     116    def insert(self, text, _iter=None): 
     117        b = self.get_buffer() 
     118        if _iter is None: 
     119            _iter = b.get_end_iter() 
     120        b.insert(_iter, text) 
     121 
     122    def insert_with_anchor(self, text, anchor=None, _iter=None): 
     123        b = self.get_buffer() 
     124        if _iter is None: 
     125            _iter = b.get_end_iter() 
     126        if anchor is None: 
     127            anchor = text 
     128 
     129        tag = b.create_tag(None, **self.get_property('link')) 
     130        tag.set_data('is_anchor', True) 
     131        tag.connect('event', self._tag_event, text, anchor) 
     132        self.__tags.append(tag) 
     133        b.insert_with_tags(_iter, text, tag) 
     134 
     135    def _motion(self, view, ev): 
     136        window = ev.window 
     137        x, y, _ = window.get_pointer() 
     138        x, y = view.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, x, y) 
     139        tags = view.get_iter_at_location(x, y).get_tags() 
     140        for tag in tags: 
     141            if tag.get_data('is_anchor'): 
     142                for t in set(self.__tags) - set([tag]): 
     143                    self.__tag_reset(t, window) 
     144                self.__set_anchor(window, tag, gtk.gdk.Cursor(gtk.gdk.HAND2), self.get_property('hover')) 
     145                break 
     146        else: 
     147            tag_table = self.get_buffer().get_tag_table() 
     148            tag_table.foreach(self.__tag_reset, window) 
     149 
     150    def _tag_event(self, tag, view, ev, _iter, text, anchor): 
     151        _type = ev.type 
     152        if _type == gtk.gdk.MOTION_NOTIFY: 
     153            return 
     154        elif _type in [gtk.gdk.BUTTON_PRESS, gtk.gdk.BUTTON_RELEASE]: 
     155            button = ev.button 
     156            cursor = gtk.gdk.Cursor(gtk.gdk.HAND2) 
     157            if _type == gtk.gdk.BUTTON_RELEASE: 
     158                self.emit('anchor-clicked', text, anchor, button) 
     159                self.__set_anchor(ev.window, tag, cursor, self.get_property('hover')) 
     160            elif button in [1, 2]: 
     161                self.__set_anchor(ev.window, tag, cursor, self.get_property('active')) 
     162 
     163    def __tag_reset(self, tag, window): 
     164        if tag.get_data('is_anchor'): 
     165            self.__set_anchor(window, tag, None, self.get_property('link')) 
     166 
     167    def __set_anchor(self, window, tag, cursor, prop): 
     168        window.set_cursor(cursor) 
     169        for key, val in prop.iteritems(): 
     170            tag.set_property(key, val) 
     171 
     172gobject.type_register(HyperTextView) 
     173 
     174if __name__ == '__main__': 
     175    def clicked(widget, text, anchor, button): 
     176        print widget, text, anchor, button 
     177 
     178    t = HyperTextView() 
     179    t.connect('anchor-clicked', clicked) 
     180    t.link['foreground'] = 'dark blue' 
     181    t.insert_with_anchor('Google', 'http://www.google.com/') 
     182    t.insert('\n') 
     183    t.insert_with_anchor('Yahoo!', 'http://www.yahoo.com/') 
     184 
     185    w = gtk.Window() 
     186    w.set_default_size(200, 100) 
     187    w.connect('destroy', lambda w: gtk.main_quit()) 
     188    w.add(t) 
     189 
     190    w.show_all() 
     191    gtk.main() 
     192}}}