Added wxPython.lib.popupctl by Gerrit van Dyk which is a combobox-like

gizmo for poping up arbitrary controls.  It is currently using
wxDialog because of some issues with wxPopupWindow...


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_4_BRANCH@18216 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2002-12-13 22:57:55 +00:00
parent 2a29de09fc
commit 26e3a24354
4 changed files with 343 additions and 0 deletions

View File

@@ -58,6 +58,9 @@ Added wxPython.lib.evtmgr by Rob Schecter, which is an easier, more
"Pythonic" and more OO method of registering handlers for wxWindows "Pythonic" and more OO method of registering handlers for wxWindows
events using the Publish/Subscribe pattern. events using the Publish/Subscribe pattern.
Added wxPython.lib.popupctl by Gerrit van Dyk which is a combobox-like
gizmo for poping up arbitrary controls. It is currently using
wxDialog because of some issues with wxPopupWindow...

View File

@@ -27,6 +27,7 @@ _treeList = [
('New since last release', [ ('New since last release', [
'wxRadioButton', 'wxRadioButton',
'Throbber', 'Throbber',
'wxPopupControl',
]), ]),
# managed windows == things with a caption you can close # managed windows == things with a caption you can close
@@ -108,6 +109,7 @@ _treeList = [
'PyCrustWithFilling', 'PyCrustWithFilling',
'SplitTree', 'SplitTree',
'TablePrint', 'TablePrint',
'Throbber',
'wxCalendar', 'wxCalendar',
'wxCalendarCtrl', 'wxCalendarCtrl',
'wxDynamicSashWindow', 'wxDynamicSashWindow',
@@ -117,6 +119,7 @@ _treeList = [
'wxIEHtmlWin', 'wxIEHtmlWin',
'wxLEDNumberCtrl', 'wxLEDNumberCtrl',
'wxMimeTypesManager', 'wxMimeTypesManager',
'wxPopupControl',
'wxRightTextCtrl', 'wxRightTextCtrl',
'wxStyledTextCtrl_1', 'wxStyledTextCtrl_1',
'wxStyledTextCtrl_2', 'wxStyledTextCtrl_2',

View File

@@ -0,0 +1,94 @@
from wxPython.wx import *
from wxPython.lib.popupctl import wxPopupControl
from wxPython.calendar import *
class TestDateControl(wxPopupControl):
def __init__(self,*_args,**_kwargs):
apply(wxPopupControl.__init__,(self,) + _args,_kwargs)
self.win = wxWindow(self,-1,pos = (0,0),style = 0)
self.cal = wxCalendarCtrl(self.win,-1,pos = (0,0))
bz = self.cal.GetBestSize()
self.win.SetSize(bz)
# This method is needed to set the contents that will be displayed
# in the popup
self.SetPopupContent(self.win)
# Event registration for date selection
EVT_CALENDAR_DAY(self.cal,self.cal.GetId(),self.OnCalSelected)
# Method called when a day is selected in the calendar
def OnCalSelected(self,evt):
self.PopDown()
date = self.cal.GetDate()
# Format the date that was selected for the text part of the control
self.SetValue('%02d/%02d/%04d' % (date.GetDay(),
date.GetMonth()+1,
date.GetYear()))
evt.Skip()
# Method overridden from wxPopupControl
# This method is called just before the popup is displayed
# Use this method to format any controls in the popup
def FormatContent(self):
# I parse the value in the text part to resemble the correct date in
# the calendar control
txtValue = self.GetValue()
dmy = txtValue.split('/')
didSet = false
if len(dmy) == 3:
date = self.cal.GetDate()
d = int(dmy[0])
m = int(dmy[1]) - 1
y = int(dmy[2])
if d > 0 and d < 31:
if m >= 0 and m < 12:
if y > 1000:
self.cal.SetDate(wxDateTimeFromDMY(d,m,y))
didSet = true
if not didSet:
self.cal.SetDate(wxDateTime_Today())
#---------------------------------------------------------------------------
class TestPanel(wxPanel):
def __init__(self, parent, log):
self.log = log
wxPanel.__init__(self, parent, -1)
date = TestDateControl(self, -1, pos = (30,30), size = (100,22))
#----------------------------------------------------------------------
def runTest(frame, nb, log):
win = TestPanel(nb, log)
return win
#----------------------------------------------------------------------
overview = """<html><body>
<h2><center>wxPopupControl</center></h2>
wxPopupControl is a class that can display a value and has a button
that will popup another window similar to how a wxComboBox works. The
popup window can contain whatever is needed to edit the value. This
example uses a wxCalendarCtrl.
<p>Currently a wxDialog is used for the popup. Eventually a
wxPopupWindow should be used...
</body></html>
"""
if __name__ == '__main__':
import sys,os
import run
run.main(['', os.path.basename(sys.argv[0])])

View File

@@ -0,0 +1,243 @@
#----------------------------------------------------------------------
# Name: popup
# Purpose: Generic popup control
#
# Author: Gerrit van Dyk
#
# Created: 2002/11/20
# Version: 0.1
# RCS-ID: $Id$
# License: wxWindows license
#----------------------------------------------------------------------
from wxPython.wx import *
from wxPython.lib.buttons import wxGenButtonEvent
class PopButton(wxPyControl):
def __init__(self,*_args,**_kwargs):
apply(wxPyControl.__init__,(self,) + _args,_kwargs)
self.up = true
self.didDown = false
self.InitColours()
EVT_LEFT_DOWN(self, self.OnLeftDown)
EVT_LEFT_UP(self, self.OnLeftUp)
EVT_MOTION(self, self.OnMotion)
EVT_PAINT(self, self.OnPaint)
def InitColours(self):
faceClr = wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNFACE)
self.faceDnClr = faceClr
self.SetBackgroundColour(faceClr)
shadowClr = wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNSHADOW)
highlightClr = wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNHIGHLIGHT)
self.shadowPen = wxPen(shadowClr, 1, wxSOLID)
self.highlightPen = wxPen(highlightClr, 1, wxSOLID)
self.blackPen = wxPen(wxBLACK, 1, wxSOLID)
def Notify(self):
evt = wxGenButtonEvent(wxEVT_COMMAND_BUTTON_CLICKED, self.GetId())
evt.SetIsDown(not self.up)
evt.SetButtonObj(self)
evt.SetEventObject(self)
self.GetEventHandler().ProcessEvent(evt)
def OnEraseBackground(self, event):
pass
def OnLeftDown(self, event):
if not self.IsEnabled():
return
self.didDown = true
self.up = false
self.CaptureMouse()
self.GetParent().textCtrl.SetFocus()
self.Refresh()
event.Skip()
def OnLeftUp(self, event):
if not self.IsEnabled():
return
if self.didDown:
self.ReleaseMouse()
if not self.up:
self.Notify()
self.up = true
self.Refresh()
self.didDown = false
event.Skip()
def OnMotion(self, event):
if not self.IsEnabled():
return
if event.LeftIsDown():
if self.didDown:
x,y = event.GetPositionTuple()
w,h = self.GetClientSizeTuple()
if self.up and x<w and x>=0 and y<h and y>=0:
self.up = false
self.Refresh()
return
if not self.up and (x<0 or y<0 or x>=w or y>=h):
self.up = true
self.Refresh()
return
event.Skip()
def DrawBezel(self, dc, x1, y1, x2, y2):
# draw the upper left sides
if self.up:
dc.SetPen(self.highlightPen)
else:
dc.SetPen(self.shadowPen)
for i in range(2):
dc.DrawLine(x1+i, y1, x1+i, y2-i)
dc.DrawLine(x1, y1+i, x2-i, y1+i)
# draw the lower right sides
if self.up:
dc.SetPen(self.shadowPen)
else:
dc.SetPen(self.highlightPen)
for i in range(2):
dc.DrawLine(x1+i, y2-i, x2+1, y2-i)
dc.DrawLine(x2-i, y1+i, x2-i, y2)
def DrawArrow(self,dc):
size = self.GetSize()
mx = size.x / 2
my = size.y / 2
dc.SetPen(self.highlightPen)
dc.DrawLine(mx-5,my-5,mx+5,my-5)
dc.DrawLine(mx-5,my-5,mx,my+5)
dc.SetPen(self.shadowPen)
dc.DrawLine(mx+4,my-5,mx,my+5)
dc.SetPen(self.blackPen)
dc.DrawLine(mx+5,my-5,mx,my+5)
def OnPaint(self, event):
width, height = self.GetClientSizeTuple()
x1 = y1 = 0
x2 = width - 1
y2 = height - 1
dc = wxBufferedPaintDC(self)
if self.up:
dc.SetBackground(wxBrush(self.GetBackgroundColour(), wxSOLID))
else:
dc.SetBackground(wxBrush(self.faceDnClr, wxSOLID))
dc.Clear()
self.DrawBezel(dc, x1, y1, x2, y2)
self.DrawArrow(dc)
#---------------------------------------------------------------------------
# Tried to use wxPopupWindow but the control misbehaves on MSW
class wxPopupDialog(wxDialog):
def __init__(self,parent,content = None):
wxDialog.__init__(self,parent,-1,'', style = wxSTAY_ON_TOP)
self.ctrl = parent
self.win = wxWindow(self,-1,pos = wxPoint(0,0),style = 0)
if content:
self.SetContent(content)
def SetContent(self,content):
self.content = content
self.content.Reparent(self.win)
self.content.Show(true)
self.win.SetClientSize(self.content.GetSize())
self.SetSize(self.win.GetSize())
def Display(self):
pos = self.ctrl.ClientToScreen( (0,0) )
dSize = wxGetDisplaySize()
selfSize = self.GetSize()
tcSize = self.ctrl.GetSize()
pos.x -= (selfSize.x - tcSize.x) / 2
if pos.x + selfSize.x > dSize.x:
pos.x = dSize.x - selfSize.x
if pos.x < 0:
pos.x = 0
pos.y += tcSize.height
if pos.y + selfSize.y > dSize.y:
pos.y = dSize.y - selfSize.y
if pos.y < 0:
pos.y = 0
self.MoveXY(pos.x,pos.y)
self.ctrl.FormatContent()
self.ShowModal()
#---------------------------------------------------------------------------
class wxPopupControl(wxPyControl):
def __init__(self,*_args,**_kwargs):
if 'value' in _kwargs:
del _kwargs['value']
apply(wxPyControl.__init__,(self,) + _args,_kwargs)
self.textCtrl = wxTextCtrl(self,-1,'',pos = wxPoint(0,0))
self.bCtrl = PopButton(self,-1)
self.pop = None
self.content = None
self.OnSize(None)
EVT_SIZE(self,self.OnSize)
EVT_BUTTON(self.bCtrl,self.bCtrl.GetId(),self.OnButton)
def OnSize(self,evt):
w,h = self.GetClientSizeTuple()
self.textCtrl.SetDimensions(0,0,w-17,h)
self.bCtrl.SetDimensions(w-17,0,17,h)
def OnButton(self,evt):
if not self.pop:
if self.content:
self.pop = wxPopupDialog(self,self.content)
del self.content
else:
print 'No Content to pop'
if self.pop:
self.pop.Display()
def Enable(self,flag):
wxPyControl.Enable(self,flag)
self.textCtrl.Enable(flag)
self.bCtrl.Enable(flag)
def SetPopupContent(self,content):
if not self.pop:
self.content = content
self.content.Show(false)
else:
self.pop.SetContent(content)
def FormatContent(self):
pass
def PopDown(self):
if self.pop:
self.pop.EndModal(1)
def SetValue(self,value):
self.textCtrl.SetValue(value)
def GetValue(self):
return self.textCtrl.GetValue()
# an alias
wxPopupCtrl = wxPopupControl