CVS: anygui/lib/anygui/backends gtkgui.py,1.23,1.24

Kalle Svensson <[email protected]> Sat, 26 Oct 2002 09:22:06 -0700
Newsgroups gmane.comp.python.anygui.cvs
Message-ID <[email protected]>
Update of /cvsroot/anygui/anygui/lib/anygui/backends
In directory usw-pr-cvs1:/tmp/cvs-serv16103

Modified Files:
	gtkgui.py 
Log Message:
Move to new API.  Totally b0rken at the moment.

Index: gtkgui.py
===================================================================
RCS file: /cvsroot/anygui/anygui/lib/anygui/backends/gtkgui.py,v
retrieving revision 1.23
retrieving revision 1.24
diff -C2 -r1.23 -r1.24
*** gtkgui.py	12 Feb 2002 17:16:54 -0000	1.23
--- gtkgui.py	26 Oct 2002 16:22:03 -0000	1.24
***************
*** 1,155 ****
! 
! from anygui.backends import *
! __all__ = anygui.__all__
! 
! ################################################################
! 
! from gtk import *
! import gtk
! 
! class ComponentMixin:
!     _gtk_comp = None
!     _gtk_id = None
!     _gtk_style = 0
!     _connected = 0
!     
!     def _is_created(self):
!         return self._gtk_comp is not None
! 
!     def _ensure_created(self):
!         if self._gtk_comp is None:
!             self._gtk_comp = self._gtk_class(*self._init_args)
!             self._ensure_visibility()
!             self._ensure_events()
!             self._ensure_geometry()
!             self._ensure_enabled_state()
!             if self._container is not None:
!                 self._container._gtk_add(self)
!             return 1
!         return 0
! 
!     def _ensure_events(self):
!         pass
! 
!     def _ensure_geometry(self):
!         if self._gtk_comp:
!             self._gtk_comp.set_uposition(int(self._x), int(self._y))
!             self._gtk_comp.set_usize(int(self._width), int(self._height))
! 
!     def _ensure_visibility(self):
!         if self._gtk_comp:
!             if self._visible:
!                 self._gtk_comp.show()
!             else:
!                 self._gtk_comp.hide()
! 
!     def _ensure_enabled_state(self):
!         if self._gtk_comp:
!             self._gtk_comp.set_sensitive(int(self._enabled))
! 
!     def _ensure_destroyed(self):
!         if self._gtk_comp:
!             self._gtk_comp.destroy()
!             self._gtk_comp = None
!             self._connected = 0
! 
!     def _get_gtk_text(self):
!         return str(self._text)
! 
!     def _ensure_text(self):
!         pass
! 
! ################################################################
! 
! class Label(ComponentMixin, AbstractLabel):
!     _gtk_class = GtkLabel
! 
!     def _ensure_created(self):
!         self._init_args = (str(self._text),)
!         return ComponentMixin._ensure_created(self)
! 
!     def _ensure_text(self):
!         if self._gtk_comp:
!             self._gtk_comp.set_text(str(self._text))
! 
! ################################################################
! 
! class Button(ComponentMixin, AbstractButton):
!     _gtk_class = GtkButton
! 
!     def _ensure_created(self):
!         self._init_args = (str(self._text),)
!         ret = ComponentMixin._ensure_created(self)
!         return ret
! 
!     def _ensure_events(self):
!         if self._gtk_comp and not self._connected:
!             self._gtk_comp.connect("clicked", self._gtk_clicked)
!             self._connected = 1
! 
!     def _ensure_text(self):
!         if self._gtk_comp:
!             self._gtk_comp.children()[0].set_text(str(self._text))
! 
!     def _gtk_clicked(self, *args):
!         send(self, 'click')
! 
! class ToggleButtonMixin(ComponentMixin):
!     def _ensure_state(self):
!         if self._gtk_comp:
!             self._gtk_comp.set_active(int(self._on))
! 
!     def _ensure_events(self):
!         if self._gtk_comp and not self._connected:
!             self._gtk_comp.connect("toggled", self._gtk_toggled)
!             self._connected = 1
! 
!     def _gtk_toggled(self, *args):
!         val = self._gtk_comp.get_active()
!         if val == int(self._on):
              return
!         self.modify(on=val)
!         #self.do_action()
!         send(self, 'click')
! 
!     def _ensure_text(self):
!         if self._gtk_comp:
!             self._gtk_comp.children()[0].set_text(str(self._text))
! 
! class CheckBox(ToggleButtonMixin, AbstractCheckBox):
!     _gtk_class = GtkCheckButton
! 
!     def _ensure_created(self):
!         self._init_args = (str(self._text),)
!         return ComponentMixin._ensure_created(self)
! 
! class RadioButton(ToggleButtonMixin, AbstractRadioButton):
!     _gtk_class = GtkRadioButton
! 
!     def _ensure_created(self):
!         if self._group and len(self._group._items) > 1:
!             for item in self._group._items:
!                 if item is not self:
!                     break
!             else:
!                 raise InternalError(self, "Couldn't find non-self group item!")
!             self._init_args = (item._gtk_comp, str(self._text))
          else:
!             self._init_args = (None, str(self._text))
!         return ComponentMixin._ensure_created(self)
! 
!     def _gtk_toggled(self, *args):
!         val = self._gtk_comp.get_active()
!         if val == int(self._on):
!             return
!         self.modify(on=val)
!         if int(self._on):
!             if self.group is not None:
!                 self.group.modify(value=self.value)
!             send(self, 'click')
  
! ################################################################
  
  class ScrollableListBox(GtkScrolledWindow):
      def __init__(self, *args, **kw):
          GtkScrolledWindow.__init__(self, *args, **kw)
--- 1,240 ----
! """
! skelgui.py is an empty skeleton waiting for you to implement an
! Anygui back-end.
! 
! You should probably read IRFC14 (nondist/irfc/irfc-0014.txt
! in the CVS repository) before trying to implement an
! Anygui backend. Specifically, you should understand the
! terms "proxy", "wrapper", and "(native) widget" as
! they're used in Anygui. The classes implemented in
! a backend (and the classes in this file) are "wrappers"
! around "native widgets".
! 
! To use this skeleton, simply copy it to a file in the
! anygui/lib/backends directory called <yourbackend>gui.py,
! and implement all of the methods and event handlers
! described below. Depending on your particular backend, there
! may be some opportunities to combine methods into mixin classes.
! 
! The fastest way to resolve any questions or ambiguities
! about this file, is to look at one of the existing
! back-end implementations in the anygui/lib/anygui/backends
! directory. Failing that, post your question to
! the Anygui development list ([email protected]).
! 
! If you are implementing an Anygui backend, you should
! be subscribed to the development list. See
! 
! http://lists.sourceforge.net/lists/listinfo/anygui-devel
! 
! for subscription instructions.
! 
! Comments and criticism to [email protected] (Joe Knapka).
! """
! try:
!     # Import Anygui infrastructure. You shouldn't have to change these.
!     from anygui.backends import *
!     from anygui.Applications import AbstractApplication
!     from anygui.Wrappers import AbstractWrapper
!     from anygui.Events import *
!     from anygui import application
!     # End Anygui imports.
! 
!     # Import anything needed to access the backend API. This is
!     # your job!
!     from gtk import *
!     import gtk
!     # End backend API imports.
! except:
!     import traceback
!     traceback.print_exc()
! 
! __all__ = '''
! 
!   Application
!   ButtonWrapper
!   WindowWrapper
!   LabelWrapper
!   TextFieldWrapper
!   TextAreaWrapper
!   ListBoxWrapper
!   RadioButtonWrapper
!   CheckBoxWrapper
!   MenuWrapper
!   MenuCommandWrapper
!   MenuCheckWrapper
!   MenuSeparatorWrapper
!   MenuBarWrapper
! 
! '''.split()
! 
! class ComponentWrapper(AbstractWrapper):
!     """
!     The ComponentWrapper class should abstract away all behavior
!     that (nearly) all backend widgets perform similarly. Normally,
!     this will include geometry and visibility management, and in some
!     cases widget creation can be handled here as well (see wxgui.py
!     for example).
!     """
! 
!     def __init__(self, *args, **kwds):
!         """
!         Common widget wrapper initialization code. The main thing that
!         we would normally do here is set any backend-specific
!         attribute constraints.
!         
!         Whenever the application code alters a widget proxy, the front end
!         will "push" any changed widget attributes into the backend by
!         calling the wrapper.set<Attribute>(self,new_value) method for any
!         attribute that changes. The setContraints() method allows the
!         backend to specify the order in which the set<Attribute>()
!         method calls are made, by specifying the order in which attribute
!         names are set. The constraints set here are just examples.
!         However, it is almost certainly a good idea to ensure that
!         'container' is set before any other attribute, so at minimum
!         you should call "self.setConstraints('container')" here.
!         """
!         AbstractWrapper.__init__(self, *args, **kwds)
! 
!         # 'container' before everything, then geometry.
!         self.setConstraints('container','x','y','width','height')
! 
!         # addConstraint(self,before,after) adds a constraint that attribute
!         # 'before' must be set before 'after', when both appear in the
!         # same push operation. An attempt to set mutually contradictory
!         # constraints will result in an exception.
!         self.addConstraint('geometry', 'visible')
! 
!     def widgetFactory(self,*args,**kws):
!         """ Create and return the backend widget for this wrapper. For
!         example, mswgui.py uses the win32gui.CreateWindowEx() call
!         here to create a Windows native widget. The value returned
!         will be immediately assigned to self.widget by the Anygui
!         framework; henceforth you should refer to self.widget. """
!         raise NotImplementedError, 'should be implemented by subclasses'
! 
!     def enterMainLoop(self): # ...
!         """ enterMainLoop() is called when the application event loop is
!         started for the first time. """
!         if not self.widget: return
!         self.widget.show()
! 
!     def destroy(self):
!         """
!         destroy() is called when the application needs to destroy the
!         native widget. You can also call it within the wrapper code if
!         you need to destroy your native widget for some reason. You
!         should set self.widget to DummyWidget()
!         here, after destroying the native widget.
!         """
!         if self.widget:
!             self.widget.destroy()
!         self.widget = None
! 
!     # From here on, all methods in this class are getters and setters.
!     # Setters must be implemented; they are called automatically in
!     # response to application-code manipulation of the associated
!     # proxy object, and perform the required magic on self.widget
!     # to implement the change.
!     #
!     # Getters need not be implemented unless the backend requires
!     # special handling, or if the attribute in question can be changed
!     # by user actions as well as by application code. Getters are
!     # called automatically during proxy attribute access, if they
!     # exist; otherwise the last value set in the proxy is returned.
!     # This file provides empty getter definitions for those attributes
!     # that will nearly always require special handling for get
!     # operations.
!     #
!     # The setters and getters here are a typical example of
!     # attribute handling that's common to all of a backend's
!     # widgets. For example, getGeometry() and setGeometry() work
!     # the same for any backend widget, thus they're included
!     # here in the common wrapper base class.
!     #
!     # Note that you must implement all the setter and getter
!     # methods in this file in order for your backend to work
!     # properly!
! 
!     def setContainer(self,container):
!         """
!         setContainer() is called whenever the proxy's container (the
!         Frame or top-level Window) in which the widget will appear is
!         set. It's called implicitly when a widget is added to a
!         container via the container.add(widget) method.
! 
!         In most backends, you'll call self.create() here in order to
!         actually create the backend widget. create() is a template
!         method that calls self.widgetFactory() to create the widget,
!         and then performs some bookkeeping for the wrapper.
! 
!         When the widget is removed from its container, setContainer()
!         will be called with container==None; you must handle that case
!         correctly, whatever that means for your backend.
!         """
!         if container is None:
!             # Handle "removed from container" case.
!             self.destroy()
              return
!         parent = container
!         self.create(parent)
!         self.proxy.push(blocked=['container'])
! 
!     def setGeometry(self,x,y,width,height):
!         """ Set the native widget's geometry. Note that we call
!         self.noWidget() here to see if the wrapper has a native widget
!         to manage. You should probably use this idiom at the start of
!         all setter and getter methods, unless you have a very good
!         reason not to. """
!         if not self.widget: return
!         self.widget.set_uposition(int(x), int(y))
!         self.widget.set_usize(int(width), int(height))
! 
!     def getGeometry(self):
!         """ Get the native widget's geometry as an (x,y,w,h) tuple.
!         Since the geometry can be changed by the user dragging the
!         window frame, you must implement this method. """
!         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):
!         """ Set/get the native widget's visibility. """
!         if not self.widget: return
!         if visible:
!             self.widget.show()
          else:
!             self.widget.hide()
  
!     def setEnabled(self,enabled):
!         """ Set/get the native widget's enabled/disabled state. """
!         if not self.widget: return
!         self.widget.set_sensitive(int(enabled))
! 
!     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'
! 
! class LabelWrapper(ComponentWrapper):
!     """
!     Wraps a backend "label" widget - static text.
!     You may need to implement setText() here.
!     """
!     def widgetFactory(self, *args, **kws):
!         print "In LabelWrapper.widgetFactory()"
!         return GtkLabel(*args, **kws)
! 
!     def setText(self, text):
!         if not self.widget: return
!         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)
***************
*** 159,381 ****
          self.add_with_viewport(self._listbox)
  
! class ListBox(ComponentMixin, AbstractListBox):
!     _gtk_class = ScrollableListBox
! 
!     def _ensure_created(self):
!         self._init_args = ()
!         return ComponentMixin._ensure_created(self)
! 
!     def _backend_selection(self):
!         if self._gtk_comp:
!             return int(self._gtk_comp._listbox.selection[0])
! 
!     def _ensure_items(self):
!         if self._gtk_comp:
!             self._gtk_comp._listbox.clear()
!             for item in self._items:
!                 self._gtk_comp._listbox.append([str(item)])
! 
!     def _ensure_events(self):
!         if self._gtk_comp and not self._connected:
!             self._gtk_comp._listbox.connect("select_row", self._row_selected)
!             self._connected = 1
! 
!     def _row_selected(self, *args):
!         #self.do_action()
!         send(self, 'select')
! 
!     def _ensure_selection(self):
!         if self._gtk_comp:
!             self._gtk_comp._listbox.select_row(int(self._selection),0)
! 
! ################################################################
! 
! class TextField(ComponentMixin, AbstractTextField):
!     _gtk_class = GtkEntry
!     _ignore_changed = 0
! 
!     def _ensure_created(self):
!         self._init_args = ()
!         return ComponentMixin._ensure_created(self)
! 
!     def _ensure_text(self):
!         if self._gtk_comp:
!             self._ignore_changed = 1
!             if str(self._text) != self._backend_text():
!                 self._gtk_comp.set_text(str(self._text))
!             self._ignore_changed = 0
! 
!     def _ensure_selection(self):
!         if self._gtk_comp:
!             start, end = self._selection
!             self._gtk_comp.select_region(start, end)
! 
!     def _ensure_editable(self):
!         if self._gtk_comp:
!             self._gtk_comp.set_editable(int(self._editable))
! 
!     def _ensure_events(self):
!         if self._gtk_comp and not self._connected:
!             self._gtk_comp.connect("activate", self._entry_activated)
!             # XXX, currently updates on any change in the textfield.
!             # Perhaps too CPU intensive?
!             self._gtk_comp.connect("changed", self._entry_changed)
!             self._connected = 1
! 
!     def _backend_selection(self):
!         if self._gtk_comp:
!             start, end = int(self._gtk_comp.selection_start_pos), \
!                         int(self._gtk_comp.selection_end_pos)
!             if start > end:
!                 return end, start
!             else:
!                 return start, end
! 
!     def _backend_text(self):
!         if self._gtk_comp:
!             return str(self._gtk_comp.get_text())
! 
!     def _entry_activated(self, *args):
!         #self.do_action()
!         send(self, 'enterkey')
! 
!     def _entry_changed(self, *args):
!         if not self._ignore_changed:
!             self.modify(text=self._backend_text())
! 
! class ScrollableTextArea(GtkScrolledWindow):
!     def __init__(self, *args, **kw):
!         GtkScrolledWindow.__init__(self, *args, **kw)
!         self._textarea = GtkText()
!         self._textarea.show()
!         self.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
!         self.add(self._textarea) # _with_viewport(self._textarea)
  
! class TextArea(ComponentMixin, AbstractTextArea):
!     _gtk_class = ScrollableTextArea
!     _connected = 0
!     _ignore_changed = 0
! 
!     def _ensure_created(self):
!         self._init_args = ()
!         return ComponentMixin._ensure_created(self)
! 
!     def _ensure_text(self):
!         if self._gtk_comp:
!             if str(self._text) != self._backend_text():
!                 self._ignore_changed = 1
!                 p = self._gtk_comp._textarea.get_point()
!                 self._gtk_comp._textarea.freeze()
!                 self._gtk_comp._textarea.set_point(0)
!                 self._gtk_comp._textarea.delete_text(0, -1)
!                 self._gtk_comp._textarea.insert_defaults(str(self._text))
!                 self._gtk_comp._textarea.set_point(p)
!                 self._gtk_comp._textarea.thaw()
!                 self._ignore_changed = 0
! 
!     def _ensure_events(self):
!         if self._gtk_comp and not self._connected:
!             self._gtk_comp._textarea.connect("changed", self._text_changed)
!             self._connected = 1
! 
!     def _ensure_editable(self):
!         if self._gtk_comp:
!             self._gtk_comp._textarea.set_editable(int(self._editable))
! 
!     def _ensure_selection(self):
!         if self._gtk_comp:
!             start, end = self._selection
!             self._gtk_comp._textarea.select_region(start, end)
! 
!     def _backend_selection(self):
!         if self._gtk_comp:
!             start, end = int(self._gtk_comp._textarea.selection_start_pos), \
!                         int(self._gtk_comp._textarea.selection_end_pos)
!             if start > end:
!                 return end, start
              else:
!                 return start, end
  
!     def _backend_text(self):
!         if self._gtk_comp:
!             end = self._gtk_comp._textarea.get_length()
!             return str(self._gtk_comp._textarea.get_chars(0, end))
! 
!     def _text_changed(self, *args):
!         if not self._ignore_changed:
!             self.modify(text=self._backend_text())
! 
! ################################################################
! 
! class Frame(ComponentMixin, AbstractFrame):
!     _gtk_class = GtkLayout
!     _visible = 0
!     _init_args = ()
! 
!     def _gtk_add(self, comp):
!         self._gtk_comp.put(comp._gtk_comp, int(comp._x), int(comp._y))
! 
! ################################################################
! 
! class Window(ComponentMixin, AbstractWindow):
!     _gtk_class = GtkWindow
!     _gtk_style = 0
! 
!     def _ensure_created(self):
!         if self._gtk_comp is None:
!             self._gtk_comp = self._gtk_class(WINDOW_TOPLEVEL)
!             self._gtk_container = GtkLayout()
!             self._gtk_comp.add(self._gtk_container)
!             self._gtk_container.show()
!             return 1
!         return 0
! 
!     def _ensure_events(self):
!         self._gtk_comp.connect('destroy', self._gtk_close_handler)
!         self._gtk_comp.connect('size_allocate', self._gtk_resize_handler)
! 
!     def _ensure_title(self):
!         if self._gtk_comp:
!             self._gtk_comp.set_title(str(self._title))
! 
!     def _gtk_close_handler(self, *args):
!         global _app
!         self._gtk_comp.destroy()
!         self.destroy()
!         _app._window_deleted()
!     
!     def _gtk_resize_handler(self, *args):
!         w = self._gtk_comp.get_allocation()[2] #width
!         h = self._gtk_comp.get_allocation()[3] #height
!         dw = w - self._width
!         dh = h - self._height
!         #self.modify(width=w, height=h) #this is broken!
!         self._width = w
!         self._height = h
!         self.resized(dw, dh)
  
!     def _get_gtk_text(self):
!         return str(self._title)
  
!     def _gtk_add(self, comp):
!         self._gtk_container.put(comp._gtk_comp, int(comp._x), int(comp._y))
  
! ################################################################
  
  class Application(AbstractApplication):
!     def __init__(self):
!         AbstractApplication.__init__(self)
!         global _app
!         _app = self
! 
!     def _window_deleted(self):
!         if not self._windows:
!             mainquit()
!     
!     def _mainloop(self):
          mainloop()
- 
- ################################################################
- # Local Variables:
- # compile-command: "pychecker -s gtkgui.py"
- # End:
--- 244,585 ----
          self.add_with_viewport(self._listbox)
  
! class ListBoxWrapper(ComponentWrapper):
!     """
!     Wraps a backend listbox.
! 
!     At the moment, Anygui supports only single-select mode.
!     """
!     connected = 0
! 
!     def widgetFactory(self, *args, **kws):
!         return ScrollableListBox()
! 
!     def setItems(self,items):
!         """
!         Set the contents of the listbox widget. 'items' is a list of
!         strings, or of str()-able objects.
!         """
!         if not self.widget: return
!         self.widget._listbox.clear()
!         for item in items:
!             self.widget._listbox.append([str(item)])
! 
!     def getItems(self):
!         """
!         Return ths listbox contents, in order, as a list of strings.
!         """
!         if not self.widget: return
!         return self.widget._listbox.rows
! 
!     def setSelection(self,selection):
!         """
!         Set the selection. 'selection' is an integer indicating the
!         item to be selected.
!         """
!         if not self.widget: return
!         self.widget._listbox.select_row(int(selection), 0)
! 
!     def getSelection(self):
!         """
!         Return the selected listbox item index as an integer.
!         """
!         if not self.widget: return
!         return int(self.widget._listbox.selection[0])
! 
!     def widgetSetUp(self):
!         """
!         widgetSetUp() is called by the Anygui framework immediately after
!         the native widget has been created and assigned to self.widget.
!         The most common use of widgetSetUp() is to register any event
!         handlers necessary to deal with user actions.
! 
!         The ListBox widget requires that an Anygui 'select' event be
!         fired whenever the user selects an item of the listbox.
!         self._select() sends the event, so here you should associate
!         the back-end's selection event with the self._select method.
!         """
!         if not self.connected:
!             self.widget._listbox.connect("select_row", self._select)
!             self.connected = 1
! 
!     def _select(self,*args):
!         """
!         Send an Anygui 'select' event when the user clicks or otherwise
!         selects a listbox item. Note that the source of the event is
!         self.proxy, not self; that's because application code only
!         knows about proxies, not wrappers, so the source of the Anygui
!         event must be a proxy.
!         """
!         send(self.proxy,'select')
! 
! #class CanvasWrapper(ComponentWrapper):
! # Fix me!
! #    _twclass = tw.Canvas
! 
! class ButtonWrapper(ComponentWrapper):
!     """
!     Wraps a backend command-button widget - the kind you click
!     on to initiate an action, eg "OK", "Cancel", etc.
!     """
!     connected = 0
! 
!     def widgetFactory(self, *args, **kws):
!         return GtkButton(*args, **kws)
! 
!     def widgetSetUp(self):
!         """
!         Register a backend event handler to call self.click when
!         the user clicks the button.
!         """
!         if not self.connected:
!             self.widget.connect("clicked", self._click)
!             self.connected = 1
! 
!     def setText(self, text):
!         self.widget.children()[0].set_text(str(text))
! 
!     def _click(self,*args,**kws):
!         send(self.proxy,'click')
! 
! 
! class ToggleButtonMixin(ButtonWrapper):
!     """
!     Checkboxes and radio buttons often have common behavior that can
!     be abstracted away; on the other hand, sometimes they don't.
!     Consider this an example only.
! 
!     They also should generate 'click' events, so we'll just inherit
!     ButtonWrapper here to get the event setup code. Your backend
!     may not permit this, however; do what needs to be done.
!     """
! 
!     def getOn(self):
!         """ Return the button's state: 1 for checked, 0 for not. """
!         if not self.widget: return
!         return self.widget.get_active()
! 
!     def setOn(self,on):
!         """ Set the button's state. """
!         if not self.widget: return
!         val = self.widget.get_active()
!         if val == int(on):
!             return
!         self.widget.set_active(int(on))
  
! class CheckBoxWrapper(ToggleButtonMixin):
!     """
!     Usually ToggleButtonMixin completely handles the CheckBox
!     behavior, but in case it doesn't, you may need to write some
!     code here.
!     """
! 
! class RadioButtonWrapper(ToggleButtonMixin):
!     """
!     Radio buttons are a pain. Only one member of an RB "group" may be
!     active at a time. Anygui provides the RadioGroup front-end
!     class, which takes care of querying the state of radiobuttons
!     and setting their state in a mutually exclusive manner.
!     However, many backends also enforce this mutual exclusion,
!     which means that things can get complicated. The RadioGroup
!     class is implemented in as non-intrusive a way as possible,
!     but it can be a challenge to arrange for them to act in
!     the correct way, backend-wise. Look at the other backend
!     implementations for some clues.
! 
!     In the case where a backend implements radiobuttons as a simple
!     visual variant of checkboxes with no mutual-exclusion behavior,
!     this class already does everything you need; just create the
!     proper backend widget in RadioButtonWrapper.widgetFactory(). You
!     can usually fake that kind of backend implementation by playing
!     tricks with the backend's mutual-exclusion mechanism. For example,
!     create a tiny frame to encapsulate the backend radiobutton, if
!     your backend enforces mutual exclusion on a per-frame basis.
!     """
! 
!     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:
!     """
!     Single-line entry fields and multiline text controls usually
!     have a lot of common behavior that can be abstracted away. Do
!     that here.
!     """
! 
!     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):
!         """
!         Set the editable state of the widget. If 'editable' is 0,
!         the widget should allow selection and copying of its text,
!         but should not accept user input.
!         """
!         if not self.widget: return
!         raise NotImplementedError, 'should be implemented by subclasses'
! 
!     def getSelection(self):
!         """
!         Return the first and last+1 character indexes covered by the
!         selection, as a tuple; or (0,0) if there's no selection.
!         """
!         if not self.widget: return
!         raise NotImplementedError, 'should be implemented by subclasses'
! 
!     def setSelection(self,selection):
!         """
!         Select the indicated text. 'selection' is a tuple of two
!         integers indicating the first and last+1 indexes within
!         the widget text that should be covered by the selection.
!         """
!         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!
! 
! class ContainerMixin:
!     """
!     Frames - that is, widgets whose job is to visually group
!     other widgets - often have a lot of behavior in common
!     with top-level windows. Abstract that behavior here.
!     """
!     pass
! 
! class FrameWrapper(ContainerMixin,ComponentWrapper):
! 
!     def __init__(self,*args,**kws):
!         ComponentWrapper.__init__(self,*args,**kws)
! 
!     def addToContainer(self,container):
!         """
!         Add the Frame to its back-end container (another
!         Frame or a Window).
!         """
!         #container.wrapper.widget.add(self.widget)
!         raise NotImplementedError, 'should be implemented by subclasses'
! 
! class WindowWrapper(ContainerMixin,ComponentWrapper):
!     """
!     Wraps a top-level window frame.
!     """
!     connected = 0
! 
!     def widgetFactory(self, *args, **kws):
!         print "In WindowWrapper.widgetFactory()"
!         return GtkWindow(WINDOW_TOPLEVEL)
! 
!     def setTitle(self,title):
!         if not self.widget: return
!         self.widget.set_title(str(title))
! 
!     def addToContainer(self,container):
!         """
!         Add self to the backend application, if required.
!         """
!         raise NotImplementedError, 'should be implemented by subclasses'
! 
!     def widgetSetUp(self):
!         """
!         Arrange for self.resize() to be called whenever the user
!         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:
!     pass
! 
! class MenuCommandWrapper:
!     pass
  
! class MenuCheckWrapper:
!     pass
  
! class MenuSeparatorWrapper:
!     pass
  
! class MenuBarWrapper:
!     pass
  
  class Application(AbstractApplication):
!     """
!     Wraps a backend Application object (or implements one from
!     scratch if necessary).
! 
!     wxgui's Application class inherits wxPython's Application class.
!     On the other hand, Tk has no Application class, so tkgui's
!     Application class simply calls Tk.mainloop() in its
!     Application.internalRun() method.
!     """
! 
!     def internalRun(self):
!         """
!         Do whatever is necessary to start your backend's event-
!         handling loop.
!         """
          mainloop()



-------------------------------------------------------
This SF.net email is sponsored by: ApacheCon, November 18-21 in
Las Vegas (supported by COMDEX), the only Apache event to be
fully supported by the ASF. http://www.apachecon.com