|
From: Kevin A. <al...@se...> - 2002-02-12 03:07:35
|
Over the weekend I got direct subclasses of wxPython controls working. I
haven't checked it into cvs yet because I wanted to discuss the issues
before we cross over to this new way of doing things, plus I'm still
pondering the changes I've made. [If you want to test what I have so far,
email me directly and I'll send you a zip.]
I've been struggling with this email for the last couple of days trying to
cover as many issues as possible so that most of it should at least make
sense to those of you that have used wxPython and PythonCard even if you
might not have delved into much of the PythonCard framework itself. It is
likely that I've still overlooked some crucial issue that I won't think of
until I've pressed Send, but this should get us started. Please discuss any
and all issues below.
A little mantra to keep in mind while we ponder these issues...
"Simple apps should be simple, complex apps should be possible."
Let me start with a little history. Rowland Smith and I put together the
first PythonCard modules last summer after a week of discussion about basic
capabilities and design goals. At the time we thought it would be a good
idea to hide everything about the underlying GUI toolkit (wxPython was our
first target) so that it would be possible to substitute different toolkits
at a later date. The other big reason for wrapping the underlying API was so
that we could, at least in our minds, simplify the API and make it more
consistent.
That was a noble goal but completely unrealistic if we ever wanted to finish
it. There simply weren't enough people to do all the work. Also, it is hard
enough to not suffer lowest common denominator disease when dealing with one
toolkit that works on multiple platforms and probably impossible with
multiple toolkits on multiple platforms. [I'm hoping Magnus will prove me
wrong with anygui, but I wasn't willing to wait for a version of anygui that
does everything I need.] So, in the fall the decision was made to focus on
and leverage just one very powerful backend, wxPython. The trick is adding
value on top of wxPython while simplifying its use.
Some Goals
1. Get rid of _delegate attribute that used to be the actual reference to a
wxPython control
2. Reduce the amount of effort required to make a wxPython control available
as a native PythonCard component
3. Make PythonCard components compatible as parameters to existing wxPython
methods. The new form should allow us to pass our classes to other wxPython
methods transparently, but I haven't done extensive testing of this.
4. Dot notation for common attributes. For example, the ability to use
fld1.text instead of fld1.GetValue() and fld1.SetValue(). Dot notation also
ends up hiding some differences in wxPython method names.
5. Load layouts and menus from resources, including component default
initialization beyond wxPython and post-initialization (backgroundColor,
foregroundColor, font, toolTip, etc.)
6. Automatically bind events to components
7. Enforce a spec for each component
8. Leverage the existing wxPython documentation
9. Standardize on using an alphanumeric name attribute as the unique id for
components, windows, and menus.
10. Make the components self-describing, including type information.
Items 4, 5, 6, and 7 are things that PythonCard components currently do that
are not provided by the default wxPython controls. Item 9 is something that
is doable in wxPython for anything derived from the wxWindow class; menus
require additional wrapping to get that functionality. Item 10 has to do
with our move toward a true component model, which I won't get into in this
email.
Complexity exposed
Some components in PythonCard release 0.6.3.2 and earlier only have
attributes and no additional methods. However, once the switch is made to
direct subclasses of wxPython controls, all of the functionality and
complexity of a wxPython control is exposed.
To give you a better idea of what I'm talking about at the end of this
message I've listed the attributes and methods of the Button component
before (release 0.6.3.2 and earlier) and after I removed the _delegate
attribute and made Button derive from both the Widget class and wxButton.
There are over 160 additional methods and attributes exposed.
Do the new classes end up being more complex to use?
Most of these methods can simply be ignored, just as most programs only need
the mouseClick and select events and can ignore mouseDown, mouseMove,
mouseContextClick, etc. For programming from the shell we can add a toggle
to automatically hide the base wxPython methods to simplify the autoComplete
list that the user sees most of the time.
wxPython uses British English spellings for most if not all of its classes
and methods (colour instead of color). PythonCard has been using American
English.
wxPython uppercases the first letter of a method (AppendText) while
PythonCard has been following the convention of lowercasing the first letter
of a method (appendText).
We need to be careful to avoid name conflicts with internal wxPython
attributes and methods such as this, thisone, etc.
Most of the PythonCard component methods simply call their counterparts in
wxPython and we can probably safely get rid of these duplicated methods. For
example:
def setInsertionPointEnd(self):
self.SetInsertionPointEnd()
But there are some methods in PythonCard components that provide extra
functionality over their wxPython counterparts either to hide differences
between Windows and GTK or to correct some behavior of the wxPython method.
Should we continue to have separate PythonCard components such as TextField,
PassworldField, TextArea or expose all of the possible styles for wxTextCtrl
and just have a single text field control? I lean towards the former because
it reduces the initial complexity of use and allows us to follow usage
conventions such as always using wxTE_RICH for multi-line text fields to
make GTK and Windows behave the same.
In some areas I think we will need to expose the underlying wxPython
constants and styles. The dialog classes are the first thing that comes to
mind, but it could also apply to the components. Perhaps the solution is to
allow an optional 'styles' parameter that would override our defaults?
PythonCard has used some attribute caching, but that needs to go away to
make sure that if somebody changes an attribute using a native wxPython
method, there is no chance of a cached attribute getting out-of-sync.
If Robin figures out a good way to build Python-specific documentation for
wxPython and provide more meaningful arg lists than (*_args, **_kwargs) then
we should be able to build on top of that. Riaan has already done some work
in this area for Boa.
As we transition, should we keep the old methods around for a release or two
or just make a clean break?
In many ways, PythonCard ends up defining a set of naming and coding
conventions and helper classes to simplify many tasks that can be difficult,
especially for a beginner to grasp when using wxPython by itself. But,
because PythonCard sits on top of wxPython, you have the option of using
wxPython directly when necessary to build more complicated solutions.
ka
---
The following comparison does not include attributes and methods that start
with one or more underscores.
Attributes and methods of the Button component (class) in release 0.6.3.2
and earlier:
attributes:
backgroundColor, command, default, enabled, font, foregroundColor, label,
name, position, size, toolTip, visible
methods:
addEventListener, getId, notifyEventListeners, setFocus
Additional attributes and methods after the change to direct subclasses:
wxButton attributes and methods; wxButton is derived from wxControl,
wxWindow, wxEvtHandler, and wxObject:
AcceptsFocus, AddPendingEvent, CaptureMouse, Center, CenterOnParent,
CenterOnScreen, Centre, CentreOnParent, CentreOnScreen, Clear,
ClientToScreen, ClientToScreenXY, Close, Command, Connect,
ConvertDialogPointToPixels, ConvertDialogSizeToPixels,
ConvertPixelPointToDialog, ConvertPixelSizeToDialog, Create, Destroy,
DestroyChildren, Disconnect, DLG_PNT, DLG_SZE, DragAcceptFiles, Enable,
FindWindowById, FindWindowByName, Fit, Freeze, GetAcceleratorTable,
GetAutoLayout, GetBackgroundColour, GetBestSize, GetCaret, GetCharHeight,
GetCharWidth, GetChildren, GetClassName, GetClientSize, GetClientSizeTuple,
GetConstraints, GetDropTarget, GetEventHandler, GetEvtHandlerEnabled,
GetFont, GetForegroundColour, GetFullTextExtent, GetGrandParent, GetHandle,
GetHelpText, GetId, GetLabel, GetName, GetNextHandler, GetParent,
GetPosition, GetPositionTuple, GetPreviousHandler, GetRect, GetScrollPos,
GetScrollRange, GetScrollThumb, GetSize, GetSizer, GetSizeTuple,
GetTextExtent, GetTitle, GetToolTip, GetUpdateRegion, GetValidator,
GetWindowStyleFlag, Hide, InitDialog, IsBeingDeleted, IsEnabled, IsExposed,
IsExposedPoint, IsExposedRect, IsRetained, IsShown, IsTopLevel, Layout,
LineDown, LineUp, LoadFromResource, Lower, MakeModal, Move, MoveXY, OnPaint,
PageDown, PageUp, PopEventHandler, PopupMenu, PopupMenuXY, ProcessEvent,
PushEventHandler, Raise, Refresh, RefreshRect, ReleaseMouse, RemoveChild,
Reparent, ScreenToClient, ScreenToClientXY, ScrollLines, ScrollPages,
ScrollWindow, SetAcceleratorTable, SetAutoLayout, SetBackgroundColour,
SetCaret, SetClientSize, SetClientSizeWH, SetConstraints, SetCursor,
SetDefault, SetDimensions, SetDropTarget, SetEventHandler,
SetEvtHandlerEnabled, SetExtraStyle, SetFocus, SetFont, SetForegroundColour,
SetHelpText, SetId, SetImageLabel, SetImageMargins, SetLabel, SetName,
SetNextHandler, SetPosition, SetPreviousHandler, SetRect, SetScrollbar,
SetScrollPos, SetSize, SetSizeHints, SetSizer, SetTitle, SetToolTip,
SetToolTipString, SetValidator, SetWindowStyle, SetWindowStyleFlag, Show,
Thaw, this, thisown, TransferDataFromWindow, TransferDataToWindow,
UnsetConstraints, Update, Validate, WarpPointer
|