root/branch/PacketManipulator/widgets/PropertyGrid.py @ 3153

Revision 3153, 8.3 kB (checked in by nopper, 5 years ago)

Adding the old (not backed up) revision :(

Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# Copyright (C) 2008 Adriano Monteiro Marques
4#
5# Author: Francesco Piccinno <stack.box@gmail.com>
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
21import gtk
22import pango
23import gobject
24
25class Editor(gtk.HBox):
26    painter = None
27
28    def __init__(self, field):
29        gtk.HBox.__init__(self, 0, False)
30
31        self.field = field
32        self.create_widgets()
33        self.pack_widgets()
34        self.connect_signals()
35
36        self.show()
37
38    def create_widgets(self):  pass
39    def pack_widgets(self):    pass
40    def connect_signals(self): pass
41
42    def get_value(self):
43        return self.field
44
45    def set_value(self, value):
46        self.field = value
47
48    value = property(get_value, set_value)
49
50class IntEditor(Editor):
51    # Check the tipe in __init__
52
53    def create_widgets(self):
54        self.adj = gtk.Adjustment()
55        self.spin = gtk.SpinButton(self.adj)
56
57    def pack_widgets(self):
58        self.pack_start(self.spin)
59        self.spin.set_has_frame(False)
60        self.spin.show()
61
62class BitEditor(Editor):
63    def create_widgets(self):
64        self.btn = gtk.CheckButton()
65
66    def pack_widgets(self):
67        self.pack_start(self.btn)
68        self.btn.show()
69
70    def render(self, window, bounds, state):
71        if self.value:
72            sh = gtk.SHADOW_IN
73        else:
74            sh = gtk.SHADOW_OUT
75
76        size = 20
77       
78        if size > bounds.height:
79            size = bounds.height
80        if size > bounds.width:
81            size = bounds.width
82
83        print window
84
85        self.style.paint_check(window, state, sh, bounds, self.btn, "checkbutton", \
86                bounds.x, bounds.y, bounds.width, bounds.height)
87
88        cr = window.cairo_create()
89        cr.set_source_rgb(1, 0, 0)
90        cr.rectangle(bounds.x, bounds.y, bounds.width, bounds.height)
91
92class StrEditor(Editor):
93    def create_widgets(self):
94        self.entry = gtk.Entry()
95        self.btn = gtk.Button("...")
96
97    def pack_widgets(self):
98        self.entry.set_has_frame(False)
99        self.pack_start(self.entry)
100        self.pack_start(self.btn, False, False, 0)
101
102    def connect_signals(self):
103        self.btn.connect('clicked', self.__on_edit)
104
105    def __on_edit(self, widget):
106        print "Yeah launch a dialog to edit the field"
107
108class HackEntry(gtk.Entry):
109    __gtype_name__ = "HackEntry"
110
111    def __init__(self):
112        gtk.Entry.__init__(self)
113
114        self.box = gtk.EventBox()
115        self.box.modify_bg(gtk.STATE_NORMAL, self.style.white)
116        self.box.connect('button-press-event', lambda *w: True)
117
118        self.connect('parent-set', self.__on_parent_set)
119
120    def do_show(self):
121        return
122
123    def __on_parent_set(self, widget, parent):
124        if self.get_parent():
125            if self.get_parent_window():
126                self.box.set_parent_window(self.get_parent_window())
127            self.box.set_parent(self.get_parent())
128            self.box.show()
129        else:
130            self.box.unparent()
131
132    def do_size_allocate(self, alloc):
133        # I wanna be extra large! mc donalds rules
134        if self.allocation.width >= alloc.width and \
135           self.allocation.height >= alloc.height:
136            return
137
138        gtk.Entry.do_size_allocate(self, alloc)
139
140        # Reserving space for borders
141        alloc.height -= 1
142        alloc.width -= 1
143
144        self.box.size_request()
145        self.box.size_allocate(alloc)
146
147class CellRendererProperty(gtk.CellRendererText):
148    __gtype_name__ = "CellRendererProperty"
149
150    def __init__(self, tree):
151        super(CellRendererProperty, self).__init__()
152
153        self.tree = tree
154        self.set_property('xalign', 0)
155        self.set_property('xpad', 3)
156        self.set_property('mode', gtk.CELL_RENDERER_MODE_EDITABLE)
157
158        self.painter = None
159
160        dummy_entry = gtk.Entry()
161        dummy_entry.set_has_frame(False)
162        self.row_height = dummy_entry.size_request()[1]
163
164    def do_get_size(self, widget, area):
165        w, h = 0, 0
166
167        if h < self.row_height:
168            h = self.row_height
169
170        w += self.get_property('xpad') * 2
171        h += self.get_property('ypad') * 2
172
173        return (0, 0, w, h)
174
175    def do_render(self, window, widget, background_area, \
176                  cell_area, expose_area, flags):
177
178        # We draw two lines for emulating a box _|
179        widget.style.paint_hline(
180            window, gtk.STATE_NORMAL,
181            background_area, widget, "cell-line",
182            background_area.x, background_area.x + background_area.width,
183            background_area.y + background_area.height - 1)
184
185        widget.style.paint_vline( \
186            window, gtk.STATE_NORMAL,
187            background_area, widget, "cell-line",
188            background_area.y,
189            background_area.y + background_area.height - 1,
190            background_area.x + background_area.width - 1
191        )
192
193        if self.painter != None:
194            if self.flags() & gtk.CELL_RENDERER_SELECTED:
195                state = gtk.STATE_SELECTED
196            else:
197                state = gtk.STATE_NORMAL
198
199            self.painter.render(window, cell_area, state)
200        else:
201            return gtk.CellRendererText.do_render( \
202                self, window, widget, background_area, cell_area, expose_area, flags
203            )
204
205    def do_start_editing(self, event, widget, path, \
206                         background_area, cell_area, flags):
207
208        entry = HackEntry()
209
210        entry.box.add(StrEditor(None))
211        entry.box.show_all()
212
213        entry.size_allocate(background_area)
214
215        # Yes type error - PyGTK bug #542583
216        return entry
217
218gobject.type_register(CellRendererProperty)
219
220class PropertyGridTree(gtk.ScrolledWindow):
221    def __init__(self):
222        gtk.ScrolledWindow.__init__(self)
223
224        self.store = gtk.TreeStore(str, object, bool, object)
225        self.tree = gtk.TreeView(self.store)
226
227        self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
228        self.set_shadow_type(gtk.SHADOW_ETCHED_IN)
229
230        col = gtk.TreeViewColumn('Property')
231
232        crt = CellRendererProperty(self.tree)
233        crt.xpad = 0
234
235        col.pack_start(crt, True)
236        col.set_resizable(True)
237        col.set_expand(True)
238        col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
239        col.set_fixed_width(180)
240        col.set_attributes(crt, text=0)
241
242        col.set_cell_data_func(crt, self.__group_cell_func)
243        self.tree.append_column(col)
244
245        col = gtk.TreeViewColumn('Value')
246        crt = CellRendererProperty(self.tree)
247
248        col.pack_start(crt, True)
249        col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
250        col.set_resizable(False)
251        col.set_expand(True)
252        col.set_attributes(crt, text=2, editable=2)
253
254        col.set_cell_data_func(crt, self.__property_cell_func)
255        self.tree.append_column(col)
256        #self.tree.set_headers_visible(False)
257
258        self.add(self.tree)
259
260        it = self.store.append(None, ["test", None, True, True])
261        self.store.append(it, ["test", None, True, None])
262        self.store.append(it, ["test", None, True, None])
263        self.store.append(None, ["test", None, True, None])
264
265    def __property_cell_func(self, col, cell, model, iter):
266        if isinstance(model.get_value(iter, 3), bool):
267            cell.painter = BitEditor(None)
268
269    def __group_cell_func(self, col, cell, model, iter):
270        pass
271
272
273class PropertyGrid(gtk.VBox):
274    def __init__(self):
275        gtk.VBox.__init__(self)
276
277        self.__create_toolbar()
278        self.__create_widgets()
279
280    def __create_widgets(self):
281        self.tree = PropertyGridTree()
282        self.pack_end(self.tree)
283
284    def __create_toolbar(self):
285        pass
286
287if __name__ == "__main__":
288    w = gtk.Window()
289    w.add(PropertyGrid())
290    w.show_all()
291    w.connect('delete-event', lambda *w: gtk.main_quit())
292    gtk.main()
Note: See TracBrowser for help on using the browser.