CVS: anygui/lib/anygui/backends gtkgui.py,1.25,1.26
Kalle Svensson <[email protected]> Sun, 26 Jan 2003 08:01:57 -0800
| Newsgroups | gmane.comp.python.anygui.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/anygui/anygui/lib/anygui/backends In directory sc8-pr-cvs1:/tmp/cvs-serv14202/lib/anygui/backends Modified Files: gtkgui.py Log Message: Patch from Eugene Pervago <[email protected]>, now functional GTK2 backend. Some tests still failing, but it's much better than nothing. Index: gtkgui.py =================================================================== RCS file: /cvsroot/anygui/anygui/lib/anygui/backends/gtkgui.py,v retrieving revision 1.25 retrieving revision 1.26 diff -C2 -r1.25 -r1.26 *** gtkgui.py 8 Nov 2002 10:52:23 -0000 1.25 --- gtkgui.py 26 Jan 2003 16:01:54 -0000 1.26 *************** *** 1,2 **** --- 1,45 ---- + """Test status: + + Missing: test_menu + + test_aboutdlg OK + test_backend OK + test_canvas NA + test_button OK + test_checkbox OK + test_combobox OK (Not native though) + test_component NA + test_curses OK + test_defaults OK + test_events OK + test_frame OK + test_interface NA (Others don't pass either) + test_invisible OK + test_label OK + test_layout OK + test_menu + test_modv1 OK + test_modv2 OK + test_modv3 OK + test_openfiledlg OK (Some bugs on exit) + test_place OK + test_radiobutton NA (Can't implement, doesn't work like a toggle button) + test_radiogroup OK + test_references OK + test_remove (Works only the first time) + test_rules NA + test_shake OK + test_tags NA + test_textarea OK + test_textfield OK + test_window OK + + demo/ttt.py OK + demo/ttt2.py NA (Fails on Tk & wx) + demo/ifs.py NA (Fails on Tk & wx. Canvas missing) + demo/chmodgui.py OK + + """ + try: # Import Anygui infrastructure. You shouldn't have to change these. *************** *** 10,14 **** # Import anything needed to access the backend API. This is # your job! ! from gtk import * import gtk # End backend API imports. --- 53,60 ---- # Import anything needed to access the backend API. This is # your job! ! import pygtk ! ! pygtk.require('2.0') ! import gtk # End backend API imports. *************** *** 57,60 **** --- 103,107 ---- if not self.widget: return self.widget.show() + self.proxy.push() def destroy(self): *************** *** 66,86 **** def setContainer(self,container): if container is None: ! self.destroy() return ! parent = container.wrapper.widget ! if parent is None: ! self.create(parent) self.proxy.push(blocked=['container']) ! self.setupChildWidgets() def setGeometry(self,x,y,width,height): if not self.widget: return self.widget.set_uposition(int(x), int(y)) - self.widget.set_usize(int(width), int(height)) ! def getGeometry(self): ! if not self.widget: return ! return self.widget.get_uposition(int(x), int(y)) + \ ! self.widget.get_usize(int(width), int(height)) def setVisible(self,visible): --- 113,150 ---- def setContainer(self,container): if container is None: ! try: ! self.destroy() ! except: ! pass return ! parent = container.wrapper ! if parent is not None: ! self.create() ! cont = parent._getContainer() ! self.widget.unparent() ! if hasattr(cont, 'put'): ! cont.put(self.widget, 0, 0) ! elif hasattr(cont, 'add'): ! cont.add(self.widget) self.proxy.push(blocked=['container']) ! ! def create(self): ! if not self.widget: ! self.widget = self.widgetFactory() ! self.widget.visible = self.proxy.state['visible'] ! self.widgetSetUp() def setGeometry(self,x,y,width,height): if not self.widget: return + if self.widget.parent and hasattr(self.widget.parent, 'move'): + self.widget.parent.move(self.widget, + int(x), int(y)) self.widget.set_uposition(int(x), int(y)) ! width = max(int(width), 1) ! height = max(int(height), 1) ! ! self.widget.set_size_request(int(width), int(height)) ! return def setVisible(self,visible): *************** *** 97,107 **** def setText(self,text): if not self.widget: return ! raise NotImplementedError, 'should be implemented by subclasses' class LabelWrapper(ComponentWrapper): def widgetFactory(self, *args, **kws): ! print "In LabelWrapper.widgetFactory()" ! return GtkLabel(*args, **kws) def setText(self, text): --- 161,175 ---- def setText(self,text): if not self.widget: return ! # raise NotImplementedError, 'should be implemented by subclasses' class LabelWrapper(ComponentWrapper): def widgetFactory(self, *args, **kws): ! try: ! label = args[0] or '' ! except: ! label = '' ! ! return gtk.Label(label, *args, **kws) def setText(self, text): *************** *** 109,121 **** self.widget.set_text(str(text)) ! class ScrollableListBox(GtkScrolledWindow): """ A scrollable list box. Used by ListBoxWrapper. """ def __init__(self, *args, **kw): ! GtkScrolledWindow.__init__(self, *args, **kw) ! self._listbox = GtkCList() self._listbox.show() ! self.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC) self.add_with_viewport(self._listbox) --- 177,200 ---- self.widget.set_text(str(text)) ! class _ComboBoxWrapper(ComponentWrapper): ! def widgetFactory(self, *args, **kws): ! return gtk.Combo() ! def getSelection(self): ! if not self.widget: return ! return int(self.widget.list.selection[0]) ! def setSelection(self, selection): ! if not self.widget: return ! self.widget.list.select_row(int(selection), 0) ! ! ! class ScrollableListBox(gtk.ScrolledWindow): """ A scrollable list box. Used by ListBoxWrapper. """ def __init__(self, *args, **kw): ! gtk.ScrolledWindow.__init__(self, *args, **kw) ! self._listbox = gtk.CList() self._listbox.show() ! self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.add_with_viewport(self._listbox) *************** *** 134,137 **** --- 213,217 ---- if not self.widget: return self.widget._listbox.clear() + self._items = items[:] for item in items: self.widget._listbox.append([str(item)]) *************** *** 142,146 **** """ if not self.widget: return ! return list(self.widget._listbox.rows) def setSelection(self,selection): --- 222,229 ---- """ if not self.widget: return ! items = [] ! for i in range(self.widget._listbox.rows): ! items.append(self.widget._listbox.get_text(i, 0)) ! return items def setSelection(self,selection): *************** *** 157,161 **** """ if not self.widget: return ! return int(self.widget._listbox.selection[0]) def widgetSetUp(self): --- 240,248 ---- """ if not self.widget: return ! listbox = self.widget._listbox ! if listbox.selection: ! return listbox.selection[0] ! else: ! return -1 def widgetSetUp(self): *************** *** 180,184 **** def widgetFactory(self, *args, **kws): ! return GtkButton(*args, **kws) def widgetSetUp(self): --- 267,271 ---- def widgetFactory(self, *args, **kws): ! return gtk.Button(*args, **kws) def widgetSetUp(self): *************** *** 188,203 **** """ if not self.connected: ! self.widget.connect("clicked", self._click) self.connected = 1 def setText(self, text): if not self.widget: return ! self.widget.children()[0].set_text(str(text)) ! def _click(self,*args,**kws): send(self.proxy,'click') - class ToggleButtonMixin(ButtonWrapper): def getOn(self): --- 275,297 ---- """ if not self.connected: ! self.widget.connect("clicked", self.clickHandler) self.connected = 1 def setText(self, text): if not self.widget: return ! ! if self.widget.get_children(): ! self.widget.get_children()[0].set_text(str(text)) ! else: ! label = gtk.Label(str(text)) ! label.show() ! self.widget.add(label) ! def clickHandler(self,*args,**kws): send(self.proxy,'click') class ToggleButtonMixin(ButtonWrapper): + def widgetFactory(self, *args, **kws): + return gtk.ToggleButton(*args, **kws) def getOn(self): *************** *** 206,209 **** --- 300,308 ---- return self.widget.get_active() + def widgetSetUp(self): + ButtonWrapper.widgetSetUp(self) + self._toggling = 0 + self.widget.connect('toggled', self.toggleHandler) + def setOn(self,on): """ Set the button's state. """ *************** *** 212,216 **** --- 311,327 ---- if val == int(on): return + + self._toggling = 1 self.widget.set_active(int(on)) + self._toggling = 0 + + def toggleHandler(self, data): + if not self._toggling: + send(self.proxy, 'click') + + def clickHandler(self, data): + if not self._toggling: + send(self.proxy, 'click') + class CheckBoxWrapper(ToggleButtonMixin): *************** *** 220,223 **** --- 331,337 ---- code here. """ + def widgetFactory(self, *args, **kws): + return gtk.CheckButton(*args, **kws) + class RadioButtonWrapper(ToggleButtonMixin): *************** *** 246,288 **** def widgetFactory(self, *args, **kws): if self.proxy.group and len(self.proxy.group._items) > 1: for item in self.proxy.group._items: if item is not self: ! break else: raise InternalError(self, "Couldn't find non-self group item!") ! return GtkRadioButton(item.widget, *args, **kws) else: ! return GtkRadioButton(None, *args, **kws) ! ! def _click(self,*args,**kws): ! try: ! # Ensure the other buttons in the group are updated ! # properly. Note that if for some reason you need to ! # implement getValue(), this code will no longer ! # work due to the pull mechanism. ! self.proxy.group.value = self.proxy.value ! except AttributeError: ! pass ! send(self.proxy,'click') ! ! class TextControlMixin: ! ! def setText(self,text): ! """ Set/get the text associated with the widget. This might be ! window title, frame caption, label text, entry field text, ! or whatever. ! """ ! if not self.widget: return ! raise NotImplementedError, 'should be implemented by subclasses' ! ! def getText(self): ! """ ! Fetch the widget's associated text. You *must* implement this ! to get the text from the native widget; the default getText() ! from ComponentWrapper (almost) certainly won't work. ! """ ! if not self.widget: return ! raise NotImplementedError, 'should be implemented by subclasses' def setEditable(self,editable): """ --- 360,383 ---- def widgetFactory(self, *args, **kws): if self.proxy.group and len(self.proxy.group._items) > 1: + item = None for item in self.proxy.group._items: if item is not self: ! break else: raise InternalError(self, "Couldn't find non-self group item!") ! return gtk.RadioButton(item.wrapper.widget, *args, **kws) else: ! return gtk.RadioButton(None, *args, **kws) + def setGroup(self,group): + if group is None: + return + if self.proxy not in group._items: + group._items.append(self.proxy) + + class TextFieldWrapper(ComponentWrapper): + """ + Wraps a native single-line entry field. + """ def setEditable(self,editable): """ *************** *** 292,296 **** """ if not self.widget: return ! raise NotImplementedError, 'should be implemented by subclasses' def getSelection(self): --- 387,391 ---- """ if not self.widget: return ! self.widget.set_editable(editable) def getSelection(self): *************** *** 300,304 **** """ if not self.widget: return ! raise NotImplementedError, 'should be implemented by subclasses' def setSelection(self,selection): --- 395,404 ---- """ if not self.widget: return ! bounds = self.widget.get_selection_bounds() ! if bounds: ! return bounds ! else: ! position = self.widget.get_position() ! return (position, position) def setSelection(self,selection): *************** *** 309,333 **** """ if not self.widget: return ! raise NotImplementedError, 'should be implemented by subclasses' ! class TextFieldWrapper(TextControlMixin,ComponentWrapper): ! """ ! Wraps a native single-line entry field. ! """ ! def widgetSetup(self): """ Arrange for a press of the "Enter" key to call self._return. """ ! raise NotImplementedError, 'should be implemented by subclasses' def _return(self,*args,**kws): send(self.proxy, 'enterkey') ! class TextAreaWrapper(TextControlMixin,ComponentWrapper): """ Wraps a native multiline text area. If TextControlMixin works for your backend, you shouldn't need to change anything here. """ # Incomplete: fix the remainder of this file! --- 409,499 ---- """ if not self.widget: return ! self.widget.select_region(selection[0], selection[1]) ! def setText(self,text): ! """ Set/get the text associated with the widget. This might be ! window title, frame caption, label text, entry field text, ! or whatever. ! """ ! if not self.widget: return ! self.widget.delete_text(0, -1) ! self.widget.insert_text(str(text)) ! def getText(self): ! """ ! Fetch the widget's associated text. You *must* implement this ! to get the text from the native widget; the default getText() ! from ComponentWrapper (almost) certainly won't work. ! """ ! if not self.widget: return ! return self.widget.get_chars(0, -1) ! ! def widgetFactory(self, *args, **kws): ! return gtk.Entry(*args, **kws) ! ! def widgetSetUp(self): """ Arrange for a press of the "Enter" key to call self._return. """ ! pass def _return(self,*args,**kws): send(self.proxy, 'enterkey') ! class ScrollableTextView(gtk.ScrolledWindow): ! """ ! A scrollable text view. Used by TextAreaWrapper. ! """ ! def __init__(self, *args, **kw): ! gtk.ScrolledWindow.__init__(self, *args, **kw) ! self._textview = gtk.TextView() ! self._textview.show() ! self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) ! self.add(self._textview) ! ! class TextAreaWrapper(ComponentWrapper): """ Wraps a native multiline text area. If TextControlMixin works for your backend, you shouldn't need to change anything here. """ + def widgetFactory(self, *args, **kws): + frame = gtk.Frame() + scrollable = ScrollableTextView(*args, **kws) + scrollable.show() + frame.add(scrollable) + frame._textview = scrollable._textview + return frame + + def widgetSetUp(self): + if self.widget: + self.widget._textview.set_wrap_mode(gtk.WRAP_WORD) + + def getText(self): + if not self.widget: return + buffer = self.widget._textview.get_buffer() + return buffer.get_text(buffer.get_start_iter(), + buffer.get_end_iter(), + False) + + def setText(self, text): + if not self.widget: return + self.widget._textview.get_buffer().set_text(str(text)) + + def setSelection(self, selection): + if not self.widget: return + start, end = selection + buffer = self.widget._textview.get_buffer() + buffer.move_mark_by_name('selection_bound', + buffer.get_iter_at_offset(start)) + buffer.move_mark_by_name('insert', + buffer.get_iter_at_offset(end)) + + def getSelection(self): + return self.widget._textview.get_selection_bounds() + + def setEditable(self, editable): + if not self.widget: return + self.widget._textview.set_editable(editable) + # Incomplete: fix the remainder of this file! *************** *** 346,349 **** --- 512,530 ---- ComponentWrapper.__init__(self,*args,**kws) + def widgetFactory(self): + return gtk.Frame() + + def _getContainer(self): + if not hasattr(self, '_gtk_container'): + self.create() + + return self._gtk_container + + def widgetSetUp(self): + if not hasattr(self, '_gtk_container'): + self._gtk_container = gtk.Layout() + self.widget.add(self._gtk_container) + self._gtk_container.show() + def addToContainer(self,container): """ *************** *** 354,357 **** --- 535,555 ---- raise NotImplementedError, 'should be implemented by subclasses' + def setContainer(self, *args, **kws): + """ + OK, this probably needs to be pulled into a mixin heritable by + various backends. + + Ensure all contents are properly created. This looks like it could + be handled at the Proxy level, but it probably *shouldn't* be - + it's handling a Tk-specific requirement about the order in which + widgets must be created. (I did it the Proxy way too. This way + is definitely "the simplest thing that could possibly work.") - jak + """ + ComponentWrapper.setContainer(self, *args, **kws) + # for component in self.proxy.contents: + # component.container = self.proxy + + + class WindowWrapper(ContainerMixin,ComponentWrapper): """ *************** *** 361,366 **** def widgetFactory(self, *args, **kws): ! print "In WindowWrapper.widgetFactory()" ! return GtkWindow(WINDOW_TOPLEVEL) def setTitle(self,title): --- 559,563 ---- def widgetFactory(self, *args, **kws): ! return gtk.Window(gtk.WINDOW_TOPLEVEL) def setTitle(self,title): *************** *** 368,371 **** --- 565,573 ---- self.widget.set_title(str(title)) + def _getContainer(self): + if not hasattr(self, '_gtk_container'): + self.widgetSetUp() + return self._gtk_container + def addToContainer(self,container): """ *************** *** 379,396 **** interactively resizes the window. """ ! self._gtk_container = GtkLayout() ! self.widget.add(self._gtk_container) ! self._gtk_container.show() if not self.connected: ! self.widget.connect('size_allocate', self.resize) self.connected = 1 ! def resize(self,dw,dh): ! """ ! Inform the proxy of a resize event. The proxy then takes care of ! laying out the container contents. Don't change this method, ! just call it from an event handler. ! """ self.proxy.resized(dw, dh) class MenuWrapper: --- 581,630 ---- interactively resizes the window. """ ! if not self.widget: ! self.create() ! ! if not hasattr(self, '_gtk_container'): ! self._gtk_container = gtk.Layout() ! self.widget.add(self._gtk_container) ! self._gtk_container.show() if not self.connected: ! self.widget.connect('size_allocate', self.resizeHandler) ! self.widget.connect('destroy', self.close) self.connected = 1 ! def close(self, event): ! self.widget.destroy() ! self.destroy() ! application().remove(self.proxy) ! ! def resizeHandler(self, *args): ! w = self.widget.get_allocation().width ! h = self.widget.get_allocation().height ! dw = w - self.proxy.state['width'] ! dh = h - self.proxy.state['height'] ! ! if (dw,dh) == (0,0): ! return ! ! #ensure proxy state is updated ! self.proxy.state['height'] = h ! self.proxy.state['width'] = w ! self.proxy.resized(dw, dh) + + def setContainer(self,container): + if not application().isRunning(): return + if container is None: return + if self.widget is None: + self.create() + self.proxy.push(blocked=['container']) + # Ensure contents are properly created. + for comp in self.proxy.contents: + comp.container = self.proxy + + def setGeometry(self, x, y, width, height): + if not self.widget: return + self.widget.set_uposition(x, y) + self.widget.set_default_size(width, height) class MenuWrapper: *************** *** 409,412 **** --- 643,647 ---- pass + class Application(AbstractApplication): """ *************** *** 419,423 **** Application.internalRun() method. """ ! def internalRun(self): """ --- 654,666 ---- Application.internalRun() method. """ ! def __init__(self, **kwds): ! AbstractApplication.__init__(self, **kwds) ! self._isRunning = True ! ! def isRunning(self): return self._isRunning ! def internalRemove(self): ! if not self._windows: ! gtk.main_quit() ! def internalRun(self): """ *************** *** 425,427 **** handling loop. """ ! mainloop() --- 668,671 ---- handling loop. """ ! gtk.main() ! ------------------------------------------------------- This SF.NET email is sponsored by: SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See! http://www.vasoftware.com