]>
Commit | Line | Data |
---|---|---|
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 | #---------------------------------------------------------------------- | |
12 | ||
13 | from wxPython.wx import * | |
14 | from wxPython.lib.buttons import wxGenButtonEvent | |
15 | ||
16 | ||
17 | class PopButton(wxPyControl): | |
18 | def __init__(self,*_args,**_kwargs): | |
19 | apply(wxPyControl.__init__,(self,) + _args,_kwargs) | |
20 | ||
21 | self.up = True | |
22 | self.didDown = False | |
23 | ||
24 | self.InitColours() | |
25 | ||
26 | EVT_LEFT_DOWN(self, self.OnLeftDown) | |
27 | EVT_LEFT_UP(self, self.OnLeftUp) | |
28 | EVT_MOTION(self, self.OnMotion) | |
29 | EVT_PAINT(self, self.OnPaint) | |
30 | ||
31 | def InitColours(self): | |
32 | faceClr = wxSystemSettings_GetColour(wxSYS_COLOUR_BTNFACE) | |
33 | self.faceDnClr = faceClr | |
34 | self.SetBackgroundColour(faceClr) | |
35 | ||
36 | shadowClr = wxSystemSettings_GetColour(wxSYS_COLOUR_BTNSHADOW) | |
37 | highlightClr = wxSystemSettings_GetColour(wxSYS_COLOUR_BTNHIGHLIGHT) | |
38 | self.shadowPen = wxPen(shadowClr, 1, wxSOLID) | |
39 | self.highlightPen = wxPen(highlightClr, 1, wxSOLID) | |
40 | self.blackPen = wxPen(wxBLACK, 1, wxSOLID) | |
41 | ||
42 | def Notify(self): | |
43 | evt = wxGenButtonEvent(wxEVT_COMMAND_BUTTON_CLICKED, self.GetId()) | |
44 | evt.SetIsDown(not self.up) | |
45 | evt.SetButtonObj(self) | |
46 | evt.SetEventObject(self) | |
47 | self.GetEventHandler().ProcessEvent(evt) | |
48 | ||
49 | def OnEraseBackground(self, event): | |
50 | pass | |
51 | ||
52 | def OnLeftDown(self, event): | |
53 | if not self.IsEnabled(): | |
54 | return | |
55 | self.didDown = True | |
56 | self.up = False | |
57 | self.CaptureMouse() | |
58 | self.GetParent().textCtrl.SetFocus() | |
59 | self.Refresh() | |
60 | event.Skip() | |
61 | ||
62 | def OnLeftUp(self, event): | |
63 | if not self.IsEnabled(): | |
64 | return | |
65 | if self.didDown: | |
66 | self.ReleaseMouse() | |
67 | if not self.up: | |
68 | self.Notify() | |
69 | self.up = True | |
70 | self.Refresh() | |
71 | self.didDown = False | |
72 | event.Skip() | |
73 | ||
74 | def OnMotion(self, event): | |
75 | if not self.IsEnabled(): | |
76 | return | |
77 | if event.LeftIsDown(): | |
78 | if self.didDown: | |
79 | x,y = event.GetPositionTuple() | |
80 | w,h = self.GetClientSizeTuple() | |
81 | if self.up and x<w and x>=0 and y<h and y>=0: | |
82 | self.up = False | |
83 | self.Refresh() | |
84 | return | |
85 | if not self.up and (x<0 or y<0 or x>=w or y>=h): | |
86 | self.up = True | |
87 | self.Refresh() | |
88 | return | |
89 | event.Skip() | |
90 | ||
91 | def DrawBezel(self, dc, x1, y1, x2, y2): | |
92 | # draw the upper left sides | |
93 | if self.up: | |
94 | dc.SetPen(self.highlightPen) | |
95 | else: | |
96 | dc.SetPen(self.shadowPen) | |
97 | for i in range(2): | |
98 | dc.DrawLine((x1+i, y1), (x1+i, y2-i)) | |
99 | dc.DrawLine((x1, y1+i), (x2-i, y1+i)) | |
100 | ||
101 | # draw the lower right sides | |
102 | if self.up: | |
103 | dc.SetPen(self.shadowPen) | |
104 | else: | |
105 | dc.SetPen(self.highlightPen) | |
106 | for i in range(2): | |
107 | dc.DrawLine((x1+i, y2-i), (x2+1, y2-i)) | |
108 | dc.DrawLine((x2-i, y1+i), (x2-i, y2)) | |
109 | ||
110 | def DrawArrow(self,dc): | |
111 | size = self.GetSize() | |
112 | mx = size.width / 2 | |
113 | my = size.height / 2 | |
114 | dc.SetPen(self.highlightPen) | |
115 | dc.DrawLine((mx-5,my-5), (mx+5,my-5)) | |
116 | dc.DrawLine((mx-5,my-5), (mx,my+5)) | |
117 | dc.SetPen(self.shadowPen) | |
118 | dc.DrawLine((mx+4,my-5), (mx,my+5)) | |
119 | dc.SetPen(self.blackPen) | |
120 | dc.DrawLine((mx+5,my-5), (mx,my+5)) | |
121 | ||
122 | def OnPaint(self, event): | |
123 | width, height = self.GetClientSizeTuple() | |
124 | x1 = y1 = 0 | |
125 | x2 = width - 1 | |
126 | y2 = height - 1 | |
127 | dc = wxBufferedPaintDC(self) | |
128 | if self.up: | |
129 | dc.SetBackground(wxBrush(self.GetBackgroundColour(), wxSOLID)) | |
130 | else: | |
131 | dc.SetBackground(wxBrush(self.faceDnClr, wxSOLID)) | |
132 | dc.Clear() | |
133 | self.DrawBezel(dc, x1, y1, x2, y2) | |
134 | self.DrawArrow(dc) | |
135 | ||
136 | ||
137 | #--------------------------------------------------------------------------- | |
138 | ||
139 | ||
140 | # Tried to use wxPopupWindow but the control misbehaves on MSW | |
141 | class wxPopupDialog(wxDialog): | |
142 | def __init__(self,parent,content = None): | |
143 | wxDialog.__init__(self,parent,-1,'', style = wxBORDER_SIMPLE|wxSTAY_ON_TOP) | |
144 | ||
145 | self.ctrl = parent | |
146 | self.win = wxWindow(self,-1,pos = wxPoint(0,0),style = 0) | |
147 | ||
148 | if content: | |
149 | self.SetContent(content) | |
150 | ||
151 | def SetContent(self,content): | |
152 | self.content = content | |
153 | self.content.Reparent(self.win) | |
154 | self.content.Show(True) | |
155 | self.win.SetClientSize(self.content.GetSize()) | |
156 | self.SetSize(self.win.GetSize()) | |
157 | ||
158 | def Display(self): | |
159 | pos = self.ctrl.ClientToScreen( (0,0) ) | |
160 | dSize = wxGetDisplaySize() | |
161 | selfSize = self.GetSize() | |
162 | tcSize = self.ctrl.GetSize() | |
163 | ||
164 | pos.x -= (selfSize.width - tcSize.width) / 2 | |
165 | if pos.x + selfSize.width > dSize.width: | |
166 | pos.x = dSize.width - selfSize.width | |
167 | if pos.x < 0: | |
168 | pos.x = 0 | |
169 | ||
170 | pos.y += tcSize.height | |
171 | if pos.y + selfSize.height > dSize.height: | |
172 | pos.y = dSize.height - selfSize.height | |
173 | if pos.y < 0: | |
174 | pos.y = 0 | |
175 | ||
176 | self.MoveXY(pos.x,pos.y) | |
177 | ||
178 | self.ctrl.FormatContent() | |
179 | ||
180 | self.ShowModal() | |
181 | ||
182 | ||
183 | #--------------------------------------------------------------------------- | |
184 | ||
185 | ||
186 | class wxPopupControl(wxPyControl): | |
187 | def __init__(self,*_args,**_kwargs): | |
188 | if _kwargs.has_key('value'): | |
189 | del _kwargs['value'] | |
190 | apply(wxPyControl.__init__,(self,) + _args,_kwargs) | |
191 | ||
192 | self.textCtrl = wxTextCtrl(self,-1,'',pos = wxPoint(0,0)) | |
193 | self.bCtrl = PopButton(self,-1) | |
194 | self.pop = None | |
195 | self.content = None | |
196 | self.OnSize(None) | |
197 | ||
198 | EVT_SIZE(self,self.OnSize) | |
199 | EVT_BUTTON(self.bCtrl,self.bCtrl.GetId(),self.OnButton) | |
200 | # embedded control should get focus on TAB keypress | |
201 | EVT_SET_FOCUS(self,self.OnFocus) | |
202 | ||
203 | def OnFocus(self,evt): | |
204 | self.textCtrl.SetFocus() | |
205 | evt.Skip() | |
206 | ||
207 | def OnSize(self,evt): | |
208 | w,h = self.GetClientSizeTuple() | |
209 | self.textCtrl.SetDimensions(0,0,w-17,h) | |
210 | self.bCtrl.SetDimensions(w-17,0,17,h) | |
211 | ||
212 | def OnButton(self,evt): | |
213 | if not self.pop: | |
214 | if self.content: | |
215 | self.pop = wxPopupDialog(self,self.content) | |
216 | del self.content | |
217 | else: | |
218 | print 'No Content to pop' | |
219 | if self.pop: | |
220 | self.pop.Display() | |
221 | ||
222 | def Enable(self,flag): | |
223 | wxPyControl.Enable(self,flag) | |
224 | self.textCtrl.Enable(flag) | |
225 | self.bCtrl.Enable(flag) | |
226 | ||
227 | def SetPopupContent(self,content): | |
228 | if not self.pop: | |
229 | self.content = content | |
230 | self.content.Show(False) | |
231 | else: | |
232 | self.pop.SetContent(content) | |
233 | ||
234 | def FormatContent(self): | |
235 | pass | |
236 | ||
237 | def PopDown(self): | |
238 | if self.pop: | |
239 | self.pop.EndModal(1) | |
240 | ||
241 | def SetValue(self,value): | |
242 | self.textCtrl.SetValue(value) | |
243 | ||
244 | def GetValue(self): | |
245 | return self.textCtrl.GetValue() | |
246 | ||
247 | ||
248 | # an alias | |
249 | wxPopupCtrl = wxPopupControl |