]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wx/lib/popupctl.py
Don't scroll too far if the child getting the focus is large.
[wxWidgets.git] / wxPython / wx / lib / popupctl.py
CommitLineData
d14a1e28
RD
1#----------------------------------------------------------------------
2# Name: popup
3# Purpose: Generic popup control
4#
5# Author: Gerrit van Dyk
6#
7# Created: 2002/11/20
8# Version: 0.1
9# RCS-ID: $Id$
10# License: wxWindows license
11#----------------------------------------------------------------------
b881fc78
RD
12# 12/09/2003 - Jeff Grimmett (grimmtooth@softhome.net)
13#
14# o 2.5 compatability update.
15#
d4b73b1b
RD
16# 12/20/2003 - Jeff Grimmett (grimmtooth@softhome.net)
17#
18# o wxPopupDialog -> PopupDialog
19# o wxPopupControl -> PopupControl
20#
1fded56b 21
b881fc78
RD
22import wx
23from wx.lib.buttons import GenButtonEvent
1fded56b 24
d14a1e28 25
b881fc78 26class PopButton(wx.PyControl):
d14a1e28 27 def __init__(self,*_args,**_kwargs):
b881fc78 28 apply(wx.PyControl.__init__,(self,) + _args,_kwargs)
d14a1e28
RD
29
30 self.up = True
31 self.didDown = False
32
33 self.InitColours()
34
b881fc78
RD
35 self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
36 self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
37 self.Bind(wx.EVT_MOTION, self.OnMotion)
38 self.Bind(wx.EVT_PAINT, self.OnPaint)
d14a1e28
RD
39
40 def InitColours(self):
b881fc78 41 faceClr = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE)
d14a1e28
RD
42 self.faceDnClr = faceClr
43 self.SetBackgroundColour(faceClr)
44
b881fc78
RD
45 shadowClr = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)
46 highlightClr = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNHIGHLIGHT)
47 self.shadowPen = wx.Pen(shadowClr, 1, wx.SOLID)
48 self.highlightPen = wx.Pen(highlightClr, 1, wx.SOLID)
49 self.blackPen = wx.Pen(wx.BLACK, 1, wx.SOLID)
d14a1e28
RD
50
51 def Notify(self):
b881fc78 52 evt = GenButtonEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self.GetId())
d14a1e28
RD
53 evt.SetIsDown(not self.up)
54 evt.SetButtonObj(self)
55 evt.SetEventObject(self)
56 self.GetEventHandler().ProcessEvent(evt)
57
58 def OnEraseBackground(self, event):
59 pass
60
61 def OnLeftDown(self, event):
62 if not self.IsEnabled():
63 return
64 self.didDown = True
65 self.up = False
66 self.CaptureMouse()
67 self.GetParent().textCtrl.SetFocus()
68 self.Refresh()
69 event.Skip()
70
71 def OnLeftUp(self, event):
72 if not self.IsEnabled():
73 return
74 if self.didDown:
75 self.ReleaseMouse()
76 if not self.up:
77 self.Notify()
78 self.up = True
79 self.Refresh()
80 self.didDown = False
81 event.Skip()
82
83 def OnMotion(self, event):
84 if not self.IsEnabled():
85 return
86 if event.LeftIsDown():
87 if self.didDown:
b881fc78
RD
88 x,y = event.GetPosition()
89 w,h = self.GetClientSize()
d14a1e28
RD
90 if self.up and x<w and x>=0 and y<h and y>=0:
91 self.up = False
92 self.Refresh()
93 return
94 if not self.up and (x<0 or y<0 or x>=w or y>=h):
95 self.up = True
96 self.Refresh()
97 return
98 event.Skip()
99
100 def DrawBezel(self, dc, x1, y1, x2, y2):
101 # draw the upper left sides
102 if self.up:
103 dc.SetPen(self.highlightPen)
104 else:
105 dc.SetPen(self.shadowPen)
106 for i in range(2):
d7403ad2
RD
107 dc.DrawLine(x1+i, y1, x1+i, y2-i)
108 dc.DrawLine(x1, y1+i, x2-i, y1+i)
d14a1e28
RD
109
110 # draw the lower right sides
111 if self.up:
112 dc.SetPen(self.shadowPen)
113 else:
114 dc.SetPen(self.highlightPen)
115 for i in range(2):
d7403ad2
RD
116 dc.DrawLine(x1+i, y2-i, x2+1, y2-i)
117 dc.DrawLine(x2-i, y1+i, x2-i, y2)
d14a1e28
RD
118
119 def DrawArrow(self,dc):
b881fc78
RD
120 w, h = self.GetSize()
121 mx = w / 2
122 my = h / 2
d14a1e28 123 dc.SetPen(self.highlightPen)
d7403ad2
RD
124 dc.DrawLine(mx-5,my-5, mx+5,my-5)
125 dc.DrawLine(mx-5,my-5, mx,my+5)
d14a1e28 126 dc.SetPen(self.shadowPen)
d7403ad2 127 dc.DrawLine(mx+4,my-5, mx,my+5)
d14a1e28 128 dc.SetPen(self.blackPen)
d7403ad2 129 dc.DrawLine(mx+5,my-5, mx,my+5)
d14a1e28
RD
130
131 def OnPaint(self, event):
b881fc78 132 width, height = self.GetClientSize()
d14a1e28
RD
133 x1 = y1 = 0
134 x2 = width - 1
135 y2 = height - 1
b881fc78 136 dc = wx.BufferedPaintDC(self)
d14a1e28 137 if self.up:
b881fc78 138 dc.SetBackground(wx.Brush(self.GetBackgroundColour(), wx.SOLID))
d14a1e28 139 else:
b881fc78 140 dc.SetBackground(wx.Brush(self.faceDnClr, wx.SOLID))
d14a1e28
RD
141 dc.Clear()
142 self.DrawBezel(dc, x1, y1, x2, y2)
143 self.DrawArrow(dc)
144
145
146#---------------------------------------------------------------------------
147
148
149# Tried to use wxPopupWindow but the control misbehaves on MSW
d4b73b1b 150class PopupDialog(wx.Dialog):
d14a1e28 151 def __init__(self,parent,content = None):
b881fc78 152 wx.Dialog.__init__(self,parent,-1,'', style = wx.BORDER_SIMPLE|wx.STAY_ON_TOP)
d14a1e28
RD
153
154 self.ctrl = parent
b881fc78 155 self.win = wx.Window(self,-1,pos = (0,0),style = 0)
d14a1e28
RD
156
157 if content:
158 self.SetContent(content)
159
160 def SetContent(self,content):
161 self.content = content
162 self.content.Reparent(self.win)
163 self.content.Show(True)
164 self.win.SetClientSize(self.content.GetSize())
165 self.SetSize(self.win.GetSize())
166
167 def Display(self):
168 pos = self.ctrl.ClientToScreen( (0,0) )
b881fc78 169 dSize = wx.GetDisplaySize()
d14a1e28
RD
170 selfSize = self.GetSize()
171 tcSize = self.ctrl.GetSize()
172
7722248d
RD
173 pos.x -= (selfSize.width - tcSize.width) / 2
174 if pos.x + selfSize.width > dSize.width:
175 pos.x = dSize.width - selfSize.width
d14a1e28
RD
176 if pos.x < 0:
177 pos.x = 0
178
179 pos.y += tcSize.height
7722248d
RD
180 if pos.y + selfSize.height > dSize.height:
181 pos.y = dSize.height - selfSize.height
d14a1e28
RD
182 if pos.y < 0:
183 pos.y = 0
184
b881fc78 185 self.Move(pos)
d14a1e28
RD
186
187 self.ctrl.FormatContent()
188
189 self.ShowModal()
190
191
192#---------------------------------------------------------------------------
193
194
d4b73b1b 195class PopupControl(wx.PyControl):
d14a1e28
RD
196 def __init__(self,*_args,**_kwargs):
197 if _kwargs.has_key('value'):
198 del _kwargs['value']
b881fc78 199 apply(wx.PyControl.__init__,(self,) + _args,_kwargs)
d14a1e28 200
b881fc78 201 self.textCtrl = wx.TextCtrl(self,-1,'',pos = (0,0))
d14a1e28
RD
202 self.bCtrl = PopButton(self,-1)
203 self.pop = None
204 self.content = None
205 self.OnSize(None)
206
b881fc78
RD
207 self.Bind(wx.EVT_SIZE, self.OnSize)
208 self.bCtrl.Bind(wx.EVT_BUTTON, self.OnButton, self.bCtrl)
d14a1e28 209 # embedded control should get focus on TAB keypress
b881fc78 210 self.Bind(wx.EVT_SET_FOCUS, self.OnFocus)
d14a1e28
RD
211
212 def OnFocus(self,evt):
213 self.textCtrl.SetFocus()
214 evt.Skip()
215
216 def OnSize(self,evt):
b881fc78 217 w,h = self.GetClientSize()
d14a1e28
RD
218 self.textCtrl.SetDimensions(0,0,w-17,h)
219 self.bCtrl.SetDimensions(w-17,0,17,h)
220
221 def OnButton(self,evt):
222 if not self.pop:
223 if self.content:
d4b73b1b 224 self.pop = PopupDialog(self,self.content)
d14a1e28
RD
225 del self.content
226 else:
227 print 'No Content to pop'
228 if self.pop:
229 self.pop.Display()
230
231 def Enable(self,flag):
b881fc78 232 wx.PyControl.Enable(self,flag)
d14a1e28
RD
233 self.textCtrl.Enable(flag)
234 self.bCtrl.Enable(flag)
235
236 def SetPopupContent(self,content):
237 if not self.pop:
238 self.content = content
239 self.content.Show(False)
240 else:
241 self.pop.SetContent(content)
242
243 def FormatContent(self):
244 pass
245
246 def PopDown(self):
247 if self.pop:
248 self.pop.EndModal(1)
249
250 def SetValue(self,value):
251 self.textCtrl.SetValue(value)
252
253 def GetValue(self):
254 return self.textCtrl.GetValue()
255
256
257# an alias
d4b73b1b 258PopupCtrl = PopupControl