Skip to content

Commit

Permalink
Merge pull request #659 from RobinD42/port-gizmos
Browse files Browse the repository at this point in the history
Port old gizmos C++ wrapper module to Python
  • Loading branch information
RobinD42 committed Jan 11, 2018
2 parents 08421b3 + 0029d19 commit 0546340
Show file tree
Hide file tree
Showing 17 changed files with 1,823 additions and 94 deletions.
13 changes: 13 additions & 0 deletions CHANGES.rst
Expand Up @@ -80,6 +80,7 @@ Changes in this release include the following:
broken and the saved reference is deleted after the timer expires and the
callable has been called. (#457)


* Although it's more or less just an implementation detail, add wrappers for
wx.aui.AuiTabCtrl so references to it will get the correct type. (#664)

Expand All @@ -89,6 +90,18 @@ Changes in this release include the following:
child = panel.GetChildren()[-1]


* Ported some of the classes in Classic's gizmos module from C++ to Python,
including LEDNumberCtrl, DynamicSashWindow, and TreeListCtrl. The classes
are now located in the wx.lib.gizmos package, with a compatibility module at
the old wx.gizmos location. Please note that this TreeListCtrl class is a
very different implementation than wx.dataview.TreeListCtrl, although there
is some overlap in purpose. In addition, the new TreeListCtrl class is not
actually a port from the old gizmos.TreeListCtrl but rather just a thin
layer around AGW's HyperTreeList. This means that if you are using a non-
default style flag you'll need to pass it to the agwStyle parameter instead
of the style parameter.





Expand Down
50 changes: 30 additions & 20 deletions demo/DynamicSashWindow.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python

import wx
import wx.gizmos as gizmos
import wx.lib.gizmos as gizmos # Formerly wx.gizmos in Classic
import wx.stc as stc

#----------------------------------------------------------------------
Expand All @@ -10,19 +10,22 @@

class TestView(stc.StyledTextCtrl):
def __init__(self, parent, ID, log):
stc.StyledTextCtrl.__init__(self, parent, ID, style=wx.NO_BORDER)
#super(TestView, self).__init__() # Test 2-phase
#self.Create(parent, ID, style=wx.NO_BORDER)
super(TestView, self).__init__(parent, ID, style=wx.NO_BORDER) # or 1-phase
self.dyn_sash = parent
self.log = log
self.SetupScrollBars()
self.SetMarginWidth(1,0)

self.StyleSetFont(stc.STC_STYLE_DEFAULT,
wx.Font(10, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
wx.Font(12, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))

self.Bind(gizmos.EVT_DYNAMIC_SASH_SPLIT, self.OnSplit)
self.Bind(gizmos.EVT_DYNAMIC_SASH_UNIFY, self.OnUnify)
#self.SetScrollWidth(500)


def SetupScrollBars(self):
# hook the scrollbars provided by the wxDynamicSashWindow
# to this view
Expand All @@ -39,18 +42,15 @@ def SetupScrollBars(self):
self.SetHScrollBar(h_bar)


def __del__(self):
self.log.write("TestView.__del__\n")

def OnSplit(self, evt):
self.log.write("TestView.OnSplit\n");
self.log.write("TestView.OnSplit\n")
newview = TestView(self.dyn_sash, -1, self.log)
newview.SetDocPointer(self.GetDocPointer()) # use the same document
self.SetupScrollBars()


def OnUnify(self, evt):
self.log.write("TestView.OnUnify\n");
self.log.write("TestView.OnUnify\n")
self.SetupScrollBars()


Expand Down Expand Up @@ -78,37 +78,47 @@ def OnSBFocus(self, evt):
# except the default wxDynamicSashWindow behaviour

class SimpleView(wx.Panel):
count = 0

def __init__(self, parent, ID, log):
wx.Panel.__init__(self, parent, ID)
#wx.Panel.__init__(self) # 2-phase create
#self.Create(parent, ID)
super(SimpleView, self).__init__(parent, ID) # 1-phase
self.dyn_sash = parent
self.log = log
self.SetBackgroundColour("LIGHT BLUE")
self.Bind(gizmos.EVT_DYNAMIC_SASH_SPLIT, self.OnSplit)
self.Bind(gizmos.EVT_DYNAMIC_SASH_UNIFY, self.OnUnify)

SimpleView.count += 1
st = wx.StaticText(self, label=str(SimpleView.count), pos=(15,15))
font = st.GetFont()
st.SetFont(font.Bold().Scaled(2.0))


def OnSplit(self, evt):
v = SimpleView(self.dyn_sash, -1, self.log)
self.log.write("SimpleView.OnSplit\n")
newview = SimpleView(self.dyn_sash, -1, self.log)
# It's automatically added to the proper place in the sash window

def OnUnify(self, evt):
self.log.write("SimpleView.OnUnify\n")


#----------------------------------------------------------------------

def runTest(frame, nb, log):
## if wx.Platform == "__WXMAC__":
## from wx.lib.msgpanel import MessagePanel
## win = MessagePanel(nb, 'This demo currently fails on the Mac. The problem is being looked into...',
## 'Sorry', wx.ICON_WARNING)
## return win

if 1:
win = gizmos.DynamicSashWindow(nb, -1, style = wx.CLIP_CHILDREN

if True:
win = gizmos.DynamicSashWindow(nb, -1, #style=0
#| wxDS_MANAGE_SCROLLBARS
#| wxDS_DRAG_CORNER
)

win.SetFont(wx.Font(10, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
view = TestView(win, -1, log)
view.SetText(sampleText)
else:
win = wx.DynamicSashWindow(nb, -1)
win = gizmos.DynamicSashWindow(nb, -1)
view = SimpleView(win, -1, log)
return win

Expand Down
10 changes: 7 additions & 3 deletions demo/LEDNumberCtrl.py
Expand Up @@ -3,7 +3,7 @@
import time

import wx
import wx.gizmos as gizmos
import wx.lib.gizmos as gizmos # Formerly wx.gizmos in Classic

#----------------------------------------------------------------------

Expand All @@ -13,15 +13,19 @@ def __init__(self, parent, log):
self.log = log

led = gizmos.LEDNumberCtrl(self, -1, (25,25), (280, 50))
led.SetValue("01234")
led.SetValue("012.34")

led = gizmos.LEDNumberCtrl(self, -1, (25,100), (280, 50))
led.SetValue("56789")
led.SetAlignment(gizmos.LED_ALIGN_RIGHT)
led.SetDrawFaded(False)
led.SetForegroundColour('yellow')

led = gizmos.LEDNumberCtrl(self, -1, (25,175), (280, 50),
gizmos.LED_ALIGN_CENTER)# | gizmos.LED_DRAW_FADED)
led.SetForegroundColour('black')
led.SetBackgroundColour('white')

self.clock = led
self.OnTimer(None)

Expand All @@ -32,7 +36,7 @@ def __init__(self, parent, log):

def OnTimer(self, evt):
t = time.localtime(time.time())
st = time.strftime("%I-%M-%S", t)
st = time.strftime("%H:%M:%S", t)
self.clock.SetValue(st)


Expand Down
75 changes: 38 additions & 37 deletions demo/TreeListCtrl.py
@@ -1,7 +1,6 @@
#!/usr/bin/env python

import wx
import wx.dataview
import wx.lib.gizmos as gizmos # Formerly wx.gizmos in Classic

import images

Expand All @@ -13,14 +12,15 @@ def __init__(self, parent, log):
wx.Panel.__init__(self, parent, -1)
self.Bind(wx.EVT_SIZE, self.OnSize)

self.tree = wx.dataview.TreeListCtrl(self, -1, style =
wx.TR_DEFAULT_STYLE
#| wx.TR_HAS_BUTTONS
#| wx.TR_TWIST_BUTTONS
#| wx.TR_ROW_LINES
#| wx.TR_COLUMN_LINES
#| wx.TR_NO_LINES
| wx.TR_FULL_ROW_HIGHLIGHT
self.tree = gizmos.TreeListCtrl(self, -1, style=0, agwStyle=
gizmos.TR_DEFAULT_STYLE
#| gizmos.TR_HAS_BUTTONS
#| gizmos.TR_TWIST_BUTTONS
#| gizmos.TR_ROW_LINES
#| gizmos.TR_COLUMN_LINES
#| gizmos.TR_NO_LINES
#| gizmos.TR_LINES_AT_ROOT
| gizmos.TR_FULL_ROW_HIGHLIGHT
)

isz = (16,16)
Expand All @@ -34,61 +34,62 @@ def __init__(self, parent, log):
self.il = il

# create some columns
self.tree.AppendColumn("Main column")
self.tree.AppendColumn("Column 1")
self.tree.AppendColumn("Column 2")
##self.tree.SetMainColumn(0) # the one with the tree in it...
self.tree.AddColumn("Main column")
self.tree.AddColumn("Column 1")
self.tree.AddColumn("Column 2")
self.tree.SetMainColumn(0) # the one with the tree in it...
self.tree.SetColumnWidth(0, 175)

self.root = self.tree.InsertItem(self.tree.GetRootItem(), wx.dataview.TLI_FIRST, "The Root Item")

self.tree.SetItemText(self.root, 1, "col 1 root")
self.tree.SetItemText(self.root, 2, "col 2 root")
self.tree.SetItemImage(self.root, closed=fldridx, opened=fldropenidx)
self.root = self.tree.AddRoot("The Root Item")
self.tree.SetItemText(self.root, "col 1 root", 1)
self.tree.SetItemText(self.root, "col 2 root", 2)
self.tree.SetItemImage(self.root, fldridx, which = wx.TreeItemIcon_Normal)
self.tree.SetItemImage(self.root, fldropenidx, which = wx.TreeItemIcon_Expanded)


for x in range(15):
txt = "Item %d" % x
child = self.tree.AppendItem(self.root, txt)
self.tree.SetItemText(child, 1, txt + "(c1)")
self.tree.SetItemText(child, 2, txt + "(c2)")
self.tree.SetItemImage(child, closed=fldridx, opened=fldropenidx)
self.tree.SetItemText(child, txt + "(c1)", 1)
self.tree.SetItemText(child, txt + "(c2)", 2)
self.tree.SetItemImage(child, fldridx, which = wx.TreeItemIcon_Normal)
self.tree.SetItemImage(child, fldropenidx, which = wx.TreeItemIcon_Expanded)

for y in range(5):
txt = "item %d-%s" % (x, chr(ord("a")+y))
last = self.tree.AppendItem(child, txt)
self.tree.SetItemText(last, 1, txt + "(c1)")
self.tree.SetItemText(last, 2, txt + "(c2)")
self.tree.SetItemImage(last, closed=fldridx, opened=fldropenidx)
self.tree.SetItemText(last, txt + "(c1)", 1)
self.tree.SetItemText(last, txt + "(c2)", 2)
self.tree.SetItemImage(last, fldridx, which = wx.TreeItemIcon_Normal)
self.tree.SetItemImage(last, fldropenidx, which = wx.TreeItemIcon_Expanded)

for z in range(5):
txt = "item %d-%s-%d" % (x, chr(ord("a")+y), z)
item = self.tree.AppendItem(last, txt)
self.tree.SetItemText(item, 1, txt + "(c1)")
self.tree.SetItemText(item, 2, txt + "(c2)")
#TODO: Phoenix change selected to smiley
self.tree.SetItemImage(item, closed=fileidx, opened=smileidx)
## self.tree.SetItemImage(item, fileidx, which = wx.TreeItemIcon_Normal)
## self.tree.SetItemImage(item, smileidx, which = wx.TreeItemIcon_Selected)

self.tree.SetItemText(item, txt + "(c1)", 1)
self.tree.SetItemText(item, txt + "(c2)", 2)
self.tree.SetItemImage(item, fileidx, which = wx.TreeItemIcon_Normal)
self.tree.SetItemImage(item, smileidx, which = wx.TreeItemIcon_Selected)

self.tree.Expand(self.root)

## self.tree.GetMainWindow().Bind(wx.EVT_RIGHT_UP, self.OnRightUp)
self.tree.GetMainWindow().Bind(wx.EVT_RIGHT_UP, self.OnRightUp)
self.tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnActivate)


def OnActivate(self, event):
self.log.write('OnActivate: %s' % self.tree.GetItemText(event.GetItem()))
def OnActivate(self, evt):
self.log.write('OnActivate: %s' % self.tree.GetItemText(evt.GetItem()))


def OnRightUp(self, event):
pos = event.GetPosition()
def OnRightUp(self, evt):
pos = evt.GetPosition()
item, flags, col = self.tree.HitTest(pos)
if item:
self.log.write('Flags: %s, Col:%s, Text: %s' %
(flags, col, self.tree.GetItemText(item, col)))

def OnSize(self, event):
def OnSize(self, evt):
self.tree.SetSize(self.GetSize())


Expand Down
10 changes: 6 additions & 4 deletions demo/demodata.py
Expand Up @@ -39,6 +39,9 @@
# new stuff
('Recent Additions/Updates', [
'Simplebook',
'LEDNumberCtrl',
'DynamicSashWindow',
'TreeListCtrl',
]),

# managed windows == things with a (optional) caption you can close
Expand Down Expand Up @@ -144,12 +147,12 @@
'GenericButtons',
'GenericDirCtrl',
'ItemsPicker',
#'LEDNumberCtrl', # TODO
'LEDNumberCtrl',
'MultiSash',
'PlateButton',
'PopupControl',
'PyColourChooser',
'TreeListCtrl', # TODO or toss it?
'TreeListCtrl',
]),

# controls coming from other libraries
Expand All @@ -165,7 +168,7 @@
'ComboCtrl',
'ContextHelp',
'DatePickerCtrl',
#'DynamicSashWindow', # TODO
'DynamicSashWindow',
'EditableListBox',
'ExpandoTextCtrl',
'FancyText',
Expand All @@ -189,7 +192,6 @@
'ResizeWidget',
'RichTextCtrl',
'ScrolledPanel',
#'SplitTree', # TODO or toss it?
'StyledTextCtrl_1',
'StyledTextCtrl_2',
'TablePrint',
Expand Down
23 changes: 23 additions & 0 deletions docs/MigrationGuide.rst
Expand Up @@ -550,6 +550,29 @@ the editor instance properly::
return wx.propgrid.PropertyGridInterface.GetEditorByName(self.GetEditor())


wx.gizmos
---------

The ``wx.gizmos`` module in Classic was a set of wrappers around some 3rd-party
C++ classes. Unfortunately that code has been rotting a little since it has
been unmaintained for a while. Instead of perpetuating this problem into
Phoenix the C++ wrappers have been tossed out and some of the more commonly
used classes from wx.gizmos has been ported to pure Python code, which now
lives in the ``wx.lib.gizmos`` package. There is also a temporary
``wx.gizmos`` module provided in order to provide the class names at the old
location too in order to ease transitioning to the new packge. Please migrate
your code to use ``wx.lib.gizmos`` as ``wx.gizmos`` will likely go away in a
future release.

Please note that the new ``TreeListCtrl`` class is actually a thin wrapper
around AGW's HyperTreeList class since it was already a near perfect superset
of the old TreeListCtrl features and API. One compatibility difference that
may arise is that like most widgets in the AGW library the style flags have
been split into 2 parameters, ``style`` and ``agwSgtyle``, but it should be a
simple matter of changing existing code to pass the tree-specific style flags
in the ``agwStyle`` parameter, and wxWidgets common style flags in the
``style`` parameter.


.. toctree::
:maxdepth: 2
Expand Down
9 changes: 9 additions & 0 deletions etg/treectrl.py
Expand Up @@ -9,6 +9,7 @@

import etgtools
import etgtools.tweaker_tools as tools
from etgtools import MethodDef, ParamDef

PACKAGE = "wx"
MODULE = "_core"
Expand Down Expand Up @@ -38,6 +39,14 @@ def run():
#-------------------------------------------------------
c = module.find('wxTreeItemId')
assert isinstance(c, etgtools.ClassDef)

# add the void* ctor missing from the interface
ctor = MethodDef(name='wxTreeItemId', isCtor=True,
items=[ ParamDef(name='pItem', type='void*') ])
# add it as an overload to the existing ctor
c.find('wxTreeItemId').overloads.append(ctor)


c.addCppMethod('int', '__nonzero__', '()', """\
return self->IsOk();
""")
Expand Down

0 comments on commit 0546340

Please sign in to comment.