]>
Commit | Line | Data |
---|---|---|
1 | #---------------------------------------------------------------------------- | |
2 | # Name: Service.py | |
3 | # Purpose: Basic Reusable Service View for wx.lib.pydocview | |
4 | # | |
5 | # Author: Morgan Hua | |
6 | # | |
7 | # Created: 11/4/04 | |
8 | # CVS-ID: $Id$ | |
9 | # Copyright: (c) 2004-2005 ActiveGrid, Inc. | |
10 | # License: wxWindows License | |
11 | #---------------------------------------------------------------------------- | |
12 | ||
13 | import wx | |
14 | import wx.lib.docview | |
15 | import wx.lib.pydocview | |
16 | _ = wx.GetTranslation | |
17 | ||
18 | ||
19 | FLOATING_MINIFRAME = -1 | |
20 | ||
21 | ||
22 | class ServiceView(wx.EvtHandler): | |
23 | """ Basic Service View. | |
24 | """ | |
25 | bottomTab = None | |
26 | ||
27 | #---------------------------------------------------------------------------- | |
28 | # Overridden methods | |
29 | #---------------------------------------------------------------------------- | |
30 | ||
31 | def __init__(self, service): | |
32 | wx.EvtHandler.__init__(self) | |
33 | self._viewFrame = None | |
34 | self._service = service | |
35 | self._control = None | |
36 | self._embeddedWindow = None | |
37 | ||
38 | ||
39 | def Destroy(self): | |
40 | wx.EvtHandler.Destroy(self) | |
41 | ||
42 | ||
43 | def GetFrame(self): | |
44 | return self._viewFrame | |
45 | ||
46 | ||
47 | def SetFrame(self, frame): | |
48 | self._viewFrame = frame | |
49 | ||
50 | ||
51 | def _CreateControl(self, parent, id): | |
52 | return None | |
53 | ||
54 | ||
55 | def GetControl(self): | |
56 | return self._control | |
57 | ||
58 | ||
59 | def SetControl(self, control): | |
60 | self._control = control | |
61 | ||
62 | ||
63 | def OnCreate(self, doc, flags): | |
64 | config = wx.ConfigBase_Get() | |
65 | windowLoc = self._service.GetEmbeddedWindowLocation() | |
66 | if windowLoc == FLOATING_MINIFRAME: | |
67 | pos = config.ReadInt(self._service.GetServiceName() + "FrameXLoc", -1), config.ReadInt(self._service.GetServiceName() + "FrameYLoc", -1) | |
68 | # make sure frame is visible | |
69 | screenWidth = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X) | |
70 | screenHeight = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y) | |
71 | if pos[0] < 0 or pos[0] >= screenWidth or pos[1] < 0 or pos[1] >= screenHeight: | |
72 | pos = wx.DefaultPosition | |
73 | ||
74 | size = wx.Size(config.ReadInt(self._service.GetServiceName() + "FrameXSize", -1), config.ReadInt(self._service.GetServiceName() + "FrameYSize", -1)) | |
75 | title = _(self._service.GetServiceName()) | |
76 | if wx.GetApp().GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI and wx.GetApp().GetAppName(): | |
77 | title = title + " - " + wx.GetApp().GetAppName() | |
78 | frame = wx.MiniFrame(wx.GetApp().GetTopWindow(), -1, title, pos = pos, size = size, style = wx.CLOSE_BOX|wx.CAPTION|wx.SYSTEM_MENU) | |
79 | wx.EVT_CLOSE(frame, self.OnCloseWindow) | |
80 | elif wx.GetApp().IsMDI(): | |
81 | self._embeddedWindow = wx.GetApp().GetTopWindow().GetEmbeddedWindow(windowLoc) | |
82 | frame = self._embeddedWindow | |
83 | else: | |
84 | pos = config.ReadInt(self._service.GetServiceName() + "FrameXLoc", -1), config.ReadInt(self._service.GetServiceName() + "FrameYLoc", -1) | |
85 | # make sure frame is visible | |
86 | screenWidth = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X) | |
87 | screenHeight = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y) | |
88 | if pos[0] < 0 or pos[0] >= screenWidth or pos[1] < 0 or pos[1] >= screenHeight: | |
89 | pos = wx.DefaultPosition | |
90 | ||
91 | size = wx.Size(config.ReadInt(self._service.GetServiceName() + "FrameXSize", -1), config.ReadInt(self._service.GetServiceName() + "FrameYSize", -1)) | |
92 | title = _(self._service.GetServiceName()) | |
93 | if wx.GetApp().GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI and wx.GetApp().GetAppName(): | |
94 | title = title + " - " + wx.GetApp().GetAppName() | |
95 | frame = wx.GetApp().CreateDocumentFrame(self, doc, flags, pos = pos, size = size) | |
96 | frame.SetTitle(title) | |
97 | if config.ReadInt(self._service.GetServiceName() + "FrameMaximized", False): | |
98 | frame.Maximize(True) | |
99 | wx.EVT_CLOSE(frame, self.OnCloseWindow) | |
100 | ||
101 | self.SetFrame(frame) | |
102 | sizer = wx.BoxSizer(wx.VERTICAL) | |
103 | ||
104 | windowLoc = self._service.GetEmbeddedWindowLocation() | |
105 | if self._embeddedWindow or windowLoc == FLOATING_MINIFRAME: | |
106 | if (self._service.GetEmbeddedWindowLocation() == wx.lib.pydocview.EMBEDDED_WINDOW_BOTTOM): | |
107 | if ServiceView.bottomTab == None: | |
108 | ServiceView.bottomTab = wx.Notebook(frame, wx.NewId(), (0,0), (100,100), wx.LB_DEFAULT, "Bottom Tab") | |
109 | wx.EVT_RIGHT_DOWN(ServiceView.bottomTab, self.OnNotebookRightClick) | |
110 | wx.EVT_MIDDLE_DOWN(ServiceView.bottomTab, self.OnNotebookMiddleClick) | |
111 | sizer.Add(ServiceView.bottomTab, 1, wx.TOP|wx.EXPAND, 4) | |
112 | def OnFrameResize(event): | |
113 | ServiceView.bottomTab.SetSize(ServiceView.bottomTab.GetParent().GetSize()) | |
114 | frame.Bind(wx.EVT_SIZE, OnFrameResize) | |
115 | # Factor this out. | |
116 | self._control = self._CreateControl(ServiceView.bottomTab, wx.NewId()) | |
117 | if self._control != None: | |
118 | ServiceView.bottomTab.AddPage(self._control, self._service.GetServiceName()) | |
119 | ServiceView.bottomTab.Layout() | |
120 | else: | |
121 | # Factor this out. | |
122 | self._control = self._CreateControl(frame, wx.NewId()) | |
123 | sizer.Add(self._control) | |
124 | else: | |
125 | # Factor this out. | |
126 | self._control = self._CreateControl(frame, wx.NewId()) | |
127 | sizer.Add(self._control, 1, wx.EXPAND, 0) | |
128 | frame.SetSizer(sizer) | |
129 | frame.Layout() | |
130 | self.Activate() | |
131 | return True | |
132 | ||
133 | ||
134 | def OnNotebookMiddleClick(self, event): | |
135 | index, type = ServiceView.bottomTab.HitTest(event.GetPosition()) | |
136 | # 0 tab is always message. This code assumes the rest are run/debug windows | |
137 | if index > 0: | |
138 | page = ServiceView.bottomTab.GetPage(index) | |
139 | if hasattr(page, 'StopAndRemoveUI'): | |
140 | page.StopAndRemoveUI(event) | |
141 | ||
142 | ||
143 | def OnNotebookRightClick(self, event): | |
144 | index, type = ServiceView.bottomTab.HitTest(event.GetPosition()) | |
145 | menu = wx.Menu() | |
146 | x, y = event.GetX(), event.GetY() | |
147 | # 0 tab is always message. This code assumes the rest are run/debug windows | |
148 | if index > 0: | |
149 | page = ServiceView.bottomTab.GetPage(index) | |
150 | id = wx.NewId() | |
151 | menu.Append(id, _("Close")) | |
152 | def OnRightMenuSelect(event): | |
153 | if hasattr(page, 'StopAndRemoveUI'): | |
154 | page.StopAndRemoveUI(event) | |
155 | wx.EVT_MENU(ServiceView.bottomTab, id, OnRightMenuSelect) | |
156 | if ServiceView.bottomTab.GetPageCount() > 1: | |
157 | id = wx.NewId() | |
158 | menu.Append(id, _("Close All but \"Message\"")) | |
159 | def OnRightMenuSelect(event): | |
160 | for i in range(ServiceView.bottomTab.GetPageCount()-1, 0, -1): # Go from len-1 to 1 | |
161 | page = ServiceView.bottomTab.GetPage(i) | |
162 | if hasattr(page, 'StopAndRemoveUI'): | |
163 | page.StopAndRemoveUI(event) | |
164 | wx.EVT_MENU(ServiceView.bottomTab, id, OnRightMenuSelect) | |
165 | ||
166 | ServiceView.bottomTab.PopupMenu(menu, wx.Point(x, y)) | |
167 | menu.Destroy() | |
168 | ||
169 | ||
170 | def OnCloseWindow(self, event): | |
171 | frame = self.GetFrame() | |
172 | config = wx.ConfigBase_Get() | |
173 | if frame and not self._embeddedWindow: | |
174 | if not frame.IsMaximized(): | |
175 | config.WriteInt(self._service.GetServiceName() + "FrameXLoc", frame.GetPositionTuple()[0]) | |
176 | config.WriteInt(self._service.GetServiceName() + "FrameYLoc", frame.GetPositionTuple()[1]) | |
177 | config.WriteInt(self._service.GetServiceName() + "FrameXSize", frame.GetSizeTuple()[0]) | |
178 | config.WriteInt(self._service.GetServiceName() + "FrameYSize", frame.GetSizeTuple()[1]) | |
179 | config.WriteInt(self._service.GetServiceName() + "FrameMaximized", frame.IsMaximized()) | |
180 | ||
181 | if not self._embeddedWindow: | |
182 | windowLoc = self._service.GetEmbeddedWindowLocation() | |
183 | if windowLoc == FLOATING_MINIFRAME: | |
184 | # don't destroy it, just hide it | |
185 | frame.Hide() | |
186 | else: | |
187 | # Call the original OnCloseWindow, could have subclassed SDIDocFrame and MDIDocFrame but this is easier since it will work for both SDI and MDI frames without subclassing both | |
188 | frame.OnCloseWindow(event) | |
189 | ||
190 | ||
191 | def Activate(self, activate = True): | |
192 | """ Dummy function for SDI mode """ | |
193 | pass | |
194 | ||
195 | ||
196 | def Close(self, deleteWindow = True): | |
197 | """ | |
198 | Closes the view by calling OnClose. If deleteWindow is true, this | |
199 | function should delete the window associated with the view. | |
200 | """ | |
201 | if deleteWindow: | |
202 | self.Destroy() | |
203 | ||
204 | return True | |
205 | ||
206 | ||
207 | #---------------------------------------------------------------------------- | |
208 | # Callback Methods | |
209 | #---------------------------------------------------------------------------- | |
210 | ||
211 | def SetCallback(self, callback): | |
212 | """ Sets in the event table for a doubleclick to invoke the given callback. | |
213 | Additional calls to this method overwrites the previous entry and only the last set callback will be invoked. | |
214 | """ | |
215 | wx.stc.EVT_STC_DOUBLECLICK(self.GetControl(), self.GetControl().GetId(), callback) | |
216 | ||
217 | ||
218 | #---------------------------------------------------------------------------- | |
219 | # Display Methods | |
220 | #---------------------------------------------------------------------------- | |
221 | ||
222 | def IsShown(self): | |
223 | if not self.GetFrame(): | |
224 | return False | |
225 | return self.GetFrame().IsShown() | |
226 | ||
227 | ||
228 | def Hide(self): | |
229 | self.Show(False) | |
230 | ||
231 | ||
232 | def Show(self, show = True): | |
233 | if self.GetFrame(): | |
234 | self.GetFrame().Show(show) | |
235 | if self._embeddedWindow: | |
236 | mdiParentFrame = wx.GetApp().GetTopWindow() | |
237 | mdiParentFrame.ShowEmbeddedWindow(self.GetFrame(), show) | |
238 | ||
239 | ||
240 | class Service(wx.lib.pydocview.DocService): | |
241 | ||
242 | ||
243 | #---------------------------------------------------------------------------- | |
244 | # Constants | |
245 | #---------------------------------------------------------------------------- | |
246 | SHOW_WINDOW = wx.NewId() # keep this line for each subclass, need unique ID for each Service | |
247 | ||
248 | ||
249 | def __init__(self, serviceName, embeddedWindowLocation = wx.lib.pydocview.EMBEDDED_WINDOW_LEFT): | |
250 | self._serviceName = serviceName | |
251 | self._embeddedWindowLocation = embeddedWindowLocation | |
252 | self._view = None | |
253 | ||
254 | ||
255 | def GetEmbeddedWindowLocation(self): | |
256 | return self._embeddedWindowLocation | |
257 | ||
258 | ||
259 | def SetEmbeddedWindowLocation(self, embeddedWindowLocation): | |
260 | self._embeddedWindowLocation = embeddedWindowLocation | |
261 | ||
262 | ||
263 | def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None): | |
264 | viewMenu = menuBar.GetMenu(menuBar.FindMenu(_("&View"))) | |
265 | menuItemPos = self.GetMenuItemPos(viewMenu, viewMenu.FindItem(_("&Status Bar"))) + 1 | |
266 | ||
267 | viewMenu.InsertCheckItem(menuItemPos, self.SHOW_WINDOW, self.GetMenuString(), self.GetMenuDescr()) | |
268 | wx.EVT_MENU(frame, self.SHOW_WINDOW, frame.ProcessEvent) | |
269 | wx.EVT_UPDATE_UI(frame, self.SHOW_WINDOW, frame.ProcessUpdateUIEvent) | |
270 | ||
271 | return True | |
272 | ||
273 | ||
274 | def GetServiceName(self): | |
275 | """ String used to save out Service View configuration information """ | |
276 | return self._serviceName | |
277 | ||
278 | ||
279 | def GetMenuString(self): | |
280 | """ Need to override this method to provide menu item for showing Service View """ | |
281 | return _(self.GetServiceName()) | |
282 | ||
283 | ||
284 | def GetMenuDescr(self): | |
285 | """ Need to override this method to provide menu item for showing Service View """ | |
286 | return _("Show or hides the %s window") % self.GetMenuString() | |
287 | ||
288 | ||
289 | #---------------------------------------------------------------------------- | |
290 | # Event Processing Methods | |
291 | #---------------------------------------------------------------------------- | |
292 | ||
293 | def ProcessEvent(self, event): | |
294 | id = event.GetId() | |
295 | if id == self.SHOW_WINDOW: | |
296 | self.ToggleWindow(event) | |
297 | return True | |
298 | else: | |
299 | return False | |
300 | ||
301 | ||
302 | def ProcessUpdateUIEvent(self, event): | |
303 | id = event.GetId() | |
304 | if id == self.SHOW_WINDOW: | |
305 | event.Check(self._view != None and self._view.IsShown()) | |
306 | event.Enable(True) | |
307 | return True | |
308 | else: | |
309 | return False | |
310 | ||
311 | ||
312 | #---------------------------------------------------------------------------- | |
313 | # View Methods | |
314 | #---------------------------------------------------------------------------- | |
315 | ||
316 | def _CreateView(self): | |
317 | """ This method needs to be overridden with corresponding ServiceView """ | |
318 | return ServiceView(self) | |
319 | ||
320 | ||
321 | def GetView(self): | |
322 | # Window Menu Service Method | |
323 | return self._view | |
324 | ||
325 | ||
326 | def SetView(self, view): | |
327 | self._view = view | |
328 | ||
329 | ||
330 | def ShowWindow(self, show = True): | |
331 | if show: | |
332 | if self._view: | |
333 | if not self._view.IsShown(): | |
334 | self._view.Show() | |
335 | else: | |
336 | view = self._CreateView() | |
337 | view.OnCreate(None, flags = 0) | |
338 | self.SetView(view) | |
339 | else: | |
340 | if self._view: | |
341 | if self._view.IsShown(): | |
342 | self._view.Hide() | |
343 | ||
344 | ||
345 | def HideWindow(self): | |
346 | self.ShowWindow(False) | |
347 | ||
348 | ||
349 | def ToggleWindow(self, event): | |
350 | show = event.IsChecked() | |
351 | wx.ConfigBase_Get().WriteInt(self.GetServiceName()+"Shown", show) | |
352 | self.ShowWindow(show) | |
353 | ||
354 | ||
355 | def OnCloseFrame(self, event): | |
356 | if not self._view: | |
357 | return True | |
358 | ||
359 | if wx.GetApp().IsMDI(): | |
360 | self._view.OnCloseWindow(event) | |
361 | # This is called when any SDI frame is closed, so need to check if message window is closing or some other window | |
362 | elif self._view == event.GetEventObject().GetView(): | |
363 | self.SetView(None) | |
364 | ||
365 | return True | |
366 |