Commit | Line | Data |
---|---|---|
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 |
22 | import wx |
23 | from wx.lib.buttons import GenButtonEvent | |
1fded56b | 24 | |
d14a1e28 | 25 | |
b881fc78 | 26 | class 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 | 150 | class 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 | 195 | class 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 | 258 | PopupCtrl = PopupControl |