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:
@@ -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...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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',
|
||||||
|
94
wxPython/demo/wxPopupControl.py
Normal file
94
wxPython/demo/wxPopupControl.py
Normal 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])])
|
||||||
|
|
243
wxPython/wxPython/lib/popupctl.py
Normal file
243
wxPython/wxPython/lib/popupctl.py
Normal 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
|
Reference in New Issue
Block a user