2
# Purpose: Listener for dispatching events from view to presenter
3
# Author: Roman Rolinsky <rolinsky@femagsoft.com>
5
# RCS-ID: $Id: listener.py 71790 2012-06-17 15:43:08Z ROL $
8
import os,sys,shutil,tempfile
10
from presenter import Presenter
11
from component import Manager
12
from model import Model
15
from generate import PythonOptions
19
Installs event handlers to view objects and delegates some events
22
def Install(self, frame, tree, panel, toolFrame, testWin):
23
'''Set event handlers.'''
27
self.toolFrame = toolFrame
28
self.testWin = testWin
29
self.lastSearch = None
31
self.dataElem = wx.CustomDataObject('XRCED_elem')
32
self.dataNode = wx.CustomDataObject('XRCED_node')
35
self.inUpdateUI = self.inIdle = False
36
self.clipboardHasData = False
39
wx.EVT_MENU_RANGE(frame, Manager.firstId, Manager.lastId,
40
self.OnComponentCreate)
41
wx.EVT_MENU_RANGE(frame, Manager.firstId + ID.SHIFT, Manager.lastId + ID.SHIFT,
42
self.OnComponentReplace)
44
wx.EVT_MENU(frame, ID.REF, self.OnReference)
45
wx.EVT_MENU(frame, ID.COMMENT, self.OnComment)
48
frame.Bind(wx.EVT_IDLE, self.OnIdle)
49
frame.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
50
# frame.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
51
# wx.EVT_KEY_UP(frame, tools.OnKeyUp)
52
# wx.EVT_ICONIZE(frame, self.OnIconize)
54
frame.Bind(wx.EVT_ACTIVATE, self.OnFrameActivate)
56
toolFrame.Bind(wx.EVT_ACTIVATE, self.OnFrameActivate)
58
frame.miniFrame.Bind(wx.EVT_ACTIVATE, self.OnFrameActivate)
62
frame.Bind(wx.EVT_MENU, self.OnRecentFile, id=wx.ID_FILE1, id2=wx.ID_FILE9)
63
wx.EVT_MENU(frame, wx.ID_NEW, self.OnNew)
64
wx.EVT_MENU(frame, wx.ID_OPEN, self.OnOpen)
65
wx.EVT_MENU(frame, wx.ID_SAVE, self.OnSaveOrSaveAs)
66
wx.EVT_MENU(frame, wx.ID_SAVEAS, self.OnSaveOrSaveAs)
67
wx.EVT_MENU(frame, frame.ID_GENERATE_PYTHON, self.OnGeneratePython)
68
wx.EVT_MENU(frame, wx.ID_PREFERENCES, self.OnPrefs)
69
wx.EVT_MENU(frame, wx.ID_EXIT, self.OnExit)
71
wx.EVT_MENU(frame.miniFrame, wx.ID_EXIT, self.OnExit)
74
wx.EVT_MENU(frame, wx.ID_UNDO, self.OnUndo)
75
wx.EVT_MENU(frame, wx.ID_REDO, self.OnRedo)
76
wx.EVT_MENU(frame, wx.ID_CUT, self.OnCut)
77
wx.EVT_MENU(frame, wx.ID_COPY, self.OnCopy)
78
wx.EVT_MENU(frame, wx.ID_PASTE, self.OnMenuPaste)
79
wx.EVT_MENU(frame, ID.PASTE, self.OnCmdPaste)
80
wx.EVT_MENU(frame, ID.PASTE_SIBLING, self.OnPasteSibling)
81
wx.EVT_MENU(frame, wx.ID_DELETE, self.OnDelete)
82
wx.EVT_MENU(frame, frame.ID_UNSELECT, self.OnUnselect)
83
wx.EVT_MENU(frame, frame.ID_TOOL_PASTE, self.OnToolPaste)
84
wx.EVT_MENU(frame, wx.ID_FIND, self.OnFind)
85
wx.EVT_MENU(frame, frame.ID_FINDAGAIN, self.OnFindAgain)
86
wx.EVT_MENU(frame, frame.ID_LOCATE, self.OnLocate)
87
wx.EVT_MENU(frame, frame.ID_TOOL_LOCATE, self.OnLocate)
89
wx.EVT_MENU(frame, frame.ID_EMBED_PANEL, self.OnEmbedPanel)
90
wx.EVT_MENU(frame, frame.ID_SHOW_TOOLS, self.OnShowTools)
91
wx.EVT_MENU(frame, frame.ID_TEST, self.OnTest)
92
wx.EVT_MENU(frame, wx.ID_REFRESH, self.OnRefresh)
93
wx.EVT_MENU(frame, frame.ID_AUTO_REFRESH, self.OnAutoRefresh)
94
wx.EVT_MENU(frame, frame.ID_TEST_HIDE, self.OnTestHide)
95
wx.EVT_MENU(frame, frame.ID_SHOW_XML, self.OnShowXML)
97
wx.EVT_MENU(frame, frame.ID_MOVEUP, self.OnMoveUp)
98
wx.EVT_MENU(frame, frame.ID_MOVEDOWN, self.OnMoveDown)
99
wx.EVT_MENU(frame, frame.ID_MOVELEFT, self.OnMoveLeft)
100
wx.EVT_MENU(frame, frame.ID_MOVERIGHT, self.OnMoveRight)
102
wx.EVT_MENU(frame, wx.ID_ABOUT, self.OnHelpAbout)
103
wx.EVT_MENU(frame, wx.ID_HELP_CONTENTS, self.OnHelpContents)
104
wx.EVT_MENU(frame, frame.ID_README, self.OnHelpReadme)
106
wx.EVT_MENU(frame, frame.ID_DEBUG_CMD, self.OnDebugCMD)
108
# Pulldown menu commands
109
wx.EVT_MENU(frame, ID.SUBCLASS, self.OnSubclass)
110
wx.EVT_MENU(frame, ID.COLLAPSE, self.OnCollapse)
111
wx.EVT_MENU(frame, ID.COLLAPSE_ALL, self.OnCollapseAll)
112
wx.EVT_MENU(frame, ID.EXPAND, self.OnExpand)
115
wx.EVT_UPDATE_UI(frame, wx.ID_SAVE, self.OnUpdateUI)
116
wx.EVT_UPDATE_UI(frame, wx.ID_CUT, self.OnUpdateUI)
117
wx.EVT_UPDATE_UI(frame, wx.ID_COPY, self.OnUpdateUI)
118
wx.EVT_UPDATE_UI(frame, wx.ID_PASTE, self.OnUpdateUI)
119
wx.EVT_UPDATE_UI(frame, wx.ID_DELETE, self.OnUpdateUI)
120
wx.EVT_UPDATE_UI(frame, frame.ID_LOCATE, self.OnUpdateUI)
121
wx.EVT_UPDATE_UI(frame, frame.ID_FINDAGAIN, self.OnUpdateUI)
122
wx.EVT_UPDATE_UI(frame, frame.ID_TOOL_LOCATE, self.OnUpdateUI)
123
wx.EVT_UPDATE_UI(frame, frame.ID_TOOL_PASTE, self.OnUpdateUI)
124
wx.EVT_UPDATE_UI(frame, wx.ID_UNDO, self.OnUpdateUI)
125
wx.EVT_UPDATE_UI(frame, wx.ID_REDO, self.OnUpdateUI)
126
wx.EVT_UPDATE_UI(frame, frame.ID_TEST, self.OnUpdateUI)
127
wx.EVT_UPDATE_UI(frame, frame.ID_MOVEUP, self.OnUpdateUI)
128
wx.EVT_UPDATE_UI(frame, frame.ID_MOVEDOWN, self.OnUpdateUI)
129
wx.EVT_UPDATE_UI(frame, frame.ID_MOVELEFT, self.OnUpdateUI)
130
wx.EVT_UPDATE_UI(frame, frame.ID_MOVERIGHT, self.OnUpdateUI)
131
wx.EVT_UPDATE_UI(frame, wx.ID_REFRESH, self.OnUpdateUI)
132
wx.EVT_UPDATE_UI(frame, frame.ID_SHOW_XML, self.OnUpdateUI)
133
wx.EVT_UPDATE_UI(frame, ID.COLLAPSE, self.OnUpdateUI)
134
wx.EVT_UPDATE_UI(frame, ID.EXPAND, self.OnUpdateUI)
135
wx.EVT_UPDATE_UI(frame, ID.SUBCLASS, self.OnUpdateUI)
137
wx.EVT_MENU_HIGHLIGHT_ALL(self.frame, self.OnMenuHighlight)
140
tree.Bind(wx.EVT_LEFT_DOWN, self.OnTreeLeftDown)
141
tree.Bind(wx.EVT_RIGHT_DOWN, self.OnTreeRightDown)
142
tree.Bind(wx.EVT_TREE_SEL_CHANGING, self.OnTreeSelChanging)
143
tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnTreeSelChanged)
144
tree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnTreeItemCollapsed)
146
# AttributePanel events
147
panel.nb.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.OnPanelPageChanging)
148
panel.nb.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPanelPageChanged)
149
panel.pinButton.Bind(wx.EVT_BUTTON, self.OnPanelTogglePin)
151
# Make important keys work when focus is in the panel frame
152
self.accels = wx.AcceleratorTable([
153
(wx.ACCEL_NORMAL, wx.WXK_F5, frame.ID_TEST),
154
(wx.ACCEL_NORMAL, wx.WXK_F6, frame.ID_TEST_HIDE),
155
(wx.ACCEL_CTRL, ord('r'), wx.ID_REFRESH),
158
self.frame.miniFrame.SetAcceleratorTable(self.accels)
159
# Propagate all menu commands to the frame
160
self.frame.miniFrame.Bind(wx.EVT_MENU, lambda evt: frame.ProcessEvent(evt))
163
toolPanel = g.toolPanel
164
toolPanel.tp.Bind(wx.EVT_TOOLBOOK_PAGE_CHANGED, self.OnToolPanelPageChanged)
165
wx.EVT_COMMAND_RANGE(toolPanel.tp, Manager.firstId, Manager.lastId,
166
wx.wxEVT_COMMAND_BUTTON_CLICKED,
167
self.OnComponentTool)
169
toolFrame.Bind(wx.EVT_CLOSE, self.OnCloseToolFrame)
171
def InstallTestWinEvents(self):
172
self.idleAfterSizeBound = False
173
frame = self.testWin.GetFrame()
174
frame.Bind(wx.EVT_CLOSE, self.OnCloseTestWin)
175
frame.Bind(wx.EVT_SIZE, self.OnSizeTestWin)
176
frame.SetAcceleratorTable(self.accels)
177
frame.Bind(wx.EVT_MENU, self.OnTestWinEvent)
178
frame.Bind(wx.EVT_BUTTON, self.OnTestWinEvent)
180
def OnTestWinEvent(self, evt):
181
TRACE('Test window event: %s', evt)
184
'''Unbind some event before destroying.'''
185
self.frame.Unbind(wx.EVT_IDLE)
187
def OnComponentCreate(self, evt):
188
'''Hadnler for creating new elements.'''
189
state = self.tree.GetFullState() # state just before
190
comp = Manager.findById(evt.GetId())
191
if comp.groups[0] == 'component':
192
node = Model.createComponentNode('Component')
193
item = Presenter.create(comp, node)
195
item = Presenter.create(comp)
196
itemIndex = self.tree.ItemFullIndex(item)
197
g.undoMan.RegisterUndo(undo.UndoPasteCreate(itemIndex, state))
199
def OnComponentReplace(self, evt):
200
'''Hadnler for creating new elements.'''
201
comp = Manager.findById(evt.GetId() - ID.SHIFT)
202
item = self.tree.GetSelection()
203
index = self.tree.ItemFullIndex(item)
204
oldComp = Presenter.comp
205
oldNode = Presenter.replace(comp)
206
g.undoMan.RegisterUndo(undo.UndoReplace(index, oldComp, oldNode))
208
def OnReference(self, evt):
209
'''Create reference to an existing object.'''
210
ref = wx.GetTextFromUser('Create reference to:', 'Create reference')
212
Presenter.createRef(ref)
214
def OnComment(self, evt):
215
'''Create comment node.'''
216
Presenter.createComment()
218
def OnNew(self, evt):
219
'''wx.ID_NEW hadndler.'''
220
if not self.AskSave(): return
221
if self.testWin.IsShown(): self.testWin.Destroy()
224
def OnOpen(self, evt):
225
'''wx.ID_OPEN handler.'''
226
if not self.AskSave(): return
227
exts = 'XRC files (*.xrc)|*.xrc'
228
if g.useMeta: exts += '|CRX files (*.crx)|*.crx'
229
dlg = wx.FileDialog(self.frame, 'Open', os.path.dirname(Presenter.path),
230
'', exts, wx.OPEN | wx.CHANGE_DIR)
231
if dlg.ShowModal() == wx.ID_OK:
232
if self.testWin.IsShown(): self.testWin.Destroy()
233
# Clear old undo data
239
self.frame.SetStatusText('Data loaded')
240
self.SaveRecent(path)
245
def OnRecentFile(self, evt):
246
'''wx.ID_FILE<n> handler.'''
247
if not self.AskSave(): return
249
# get the pathname based on the menu ID
250
fileNum = evt.GetId() - wx.ID_FILE1
251
path = g.fileHistory.GetHistoryFile(fileNum)
255
if self.testWin.IsShown(): self.testWin.Destroy()
257
self.frame.SetStatusText('Data loaded')
258
# add it back to the history so it will be moved up the list
259
self.SaveRecent(path)
263
def OnSaveOrSaveAs(self, evt):
264
'''wx.ID_SAVE and wx.ID_SAVEAS handler'''
265
path = Presenter.path
266
if evt.GetId() == wx.ID_SAVEAS or not path:
267
dirname = os.path.abspath(os.path.dirname(path))
268
exts = 'XRC files (*.xrc)|*.xrc'
269
if g.useMeta: exts += '|CRX files (*.crx)|*.crx'
270
dlg = wx.FileDialog(self.frame, 'Save As', dirname, '', exts,
271
wx.SAVE | wx.OVERWRITE_PROMPT | wx.CHANGE_DIR)
272
if dlg.ShowModal() == wx.ID_OK:
274
if isinstance(path, unicode):
275
path = path.encode(sys.getfilesystemencoding())
276
if not os.path.splitext(path)[1]:
287
# if we already have a localconf then it needs to be
288
# copied to a new config with the new name
289
lc = g.conf.localconf
290
nc = Presenter.createLocalConf(path)
291
flag, key, idx = lc.GetFirstEntry()
293
nc.Write(key, lc.Read(key))
294
flag, key, idx = lc.GetNextEntry(idx)
295
g.conf.localconf = nc
297
# otherwise create a new one
298
g.conf.localconf = Presenter.createLocalConf(path)
301
Presenter.save(path) # save temporary file first
302
if g.conf.localconf.ReadBool("autogenerate", False):
303
pypath = g.conf.localconf.Read("filename")
304
embed = g.conf.localconf.ReadBool("embedResource", False)
305
genGettext = g.conf.localconf.ReadBool("genGettext", False)
306
Presenter.generatePython(path, pypath, embed, genGettext)
307
self.frame.SetStatusText('Data saved')
308
self.SaveRecent(path)
312
def OnPrefs(self, evt):
313
self.frame.ShowPrefs()
315
def OnExit(self, evt):
316
'''wx.ID_EXIT handler'''
319
def OnGeneratePython(self, evt):
320
if Presenter.modified or not g.conf.localconf:
321
wx.MessageBox("Save the XRC file first!", "Error")
324
dlg = PythonOptions(view.frame, g.conf.localconf, Presenter.path)
328
def SaveRecent(self, path):
329
'''Append path to recently used files.'''
330
g.fileHistory.AddFileToHistory(path)
333
'''Show confirmation dialog.'''
334
if not Presenter.modified: return True
335
flags = wx.ICON_EXCLAMATION | wx.YES_NO | wx.CANCEL | wx.CENTRE
336
dlg = wx.MessageDialog(self.frame, 'File is modified. Save before exit?',
337
'Save before too late?', flags)
338
say = dlg.ShowModal()
342
self.OnSaveOrSaveAs(wx.CommandEvent(wx.EVT_MENU.typeId, wx.ID_SAVE))
343
# If save was successful, modified flag is unset
344
if not Presenter.modified: return True
345
elif say == wx.ID_NO:
346
Presenter.setModified(False)
350
def OnCloseWindow(self, evt):
351
'''wx.EVT_CLOSE handler'''
352
if not self.AskSave(): return
353
if self.testWin.object: self.testWin.Destroy()
354
self.panel.undo = False # prevent undo
356
# Remember sizes and position
359
conf.perspective = view.frame.mgr.SavePerspective()
360
if not self.frame.IsIconized():
361
conf.pos = self.frame.GetPosition()
362
if wx.Platform == '__WXMAC__':
363
conf.size = self.frame.GetClientSize()
365
conf.size = self.frame.GetSize()
368
conf.sashPos = self.frame.splitter.GetSashPosition()
370
if self.frame.miniFrame:
371
conf.panelPos = self.frame.miniFrame.GetPosition()
372
conf.panelSize = self.frame.miniFrame.GetSize()
373
if conf.showToolPanel and self.toolFrame:
374
conf.toolPanelPos = self.toolFrame.GetPosition()
375
conf.toolPanelSize = self.toolFrame.GetSize()
376
#self.tree.UnselectAll()
378
#self.panel.Destroy() # destroy panel before tree
382
def OnUndo(self, evt):
383
if g.undoMan.CanUndo():
386
def OnRedo(self, evt):
387
if g.undoMan.CanRedo():
390
def OnCut(self, evt):
391
'''wx.ID_CUT handler.'''
392
item = self.tree.GetSelection()
393
index = self.tree.ItemFullIndex(item)
394
state = self.tree.GetFullState()
395
node = Presenter.cut()
396
g.undoMan.RegisterUndo(undo.UndoCutDelete(index, state, node))
398
def OnDelete(self, evt):
399
'''wx.ID_DELETE handler.'''
400
if len(self.tree.GetSelections()) == 1:
401
item = self.tree.GetSelection()
402
index = self.tree.ItemFullIndex(item)
403
state = self.tree.GetFullState()
404
node = Presenter.delete(self.tree.GetSelection())
405
g.undoMan.RegisterUndo(undo.UndoCutDelete(index, state, node))
407
# Save all if multiselection
408
g.undoMan.RegisterUndo(undo.UndoGlobal())
409
Presenter.deleteMany(self.tree.GetSelections())
411
def OnCopy(self, evt):
412
'''wx.ID_COPY handler.'''
415
def OnMenuPaste(self, evt):
416
'''wx.ID_PASTE handler (for XMLTreeMenu).'''
417
state = self.tree.GetFullState() # state just before
418
item = Presenter.paste()
419
if not item: return # error in paste()
420
itemIndex = self.tree.ItemFullIndex(item)
421
g.undoMan.RegisterUndo(undo.UndoPasteCreate(itemIndex, state))
423
def OnCmdPaste(self, evt):
424
'''ID.PASTE handler (for Edit menu and shortcuts).'''
426
state = wx.GetMouseState()
427
forceSibling = state.AltDown()
428
forceInsert = state.ShiftDown()
429
g.Presenter.updateCreateState(forceSibling, forceInsert)
430
state = self.tree.GetFullState() # state just before
431
item = Presenter.paste()
432
if not item: return # error in paste()
433
itemIndex = self.tree.ItemFullIndex(item)
434
g.undoMan.RegisterUndo(undo.UndoPasteCreate(itemIndex, state))
436
def OnToolPaste(self, evt):
437
'''frame.ID_TOOL_PASTE handler.'''
438
state = wx.GetMouseState()
439
# Ctrl+click does not work with tools on Mac, Alt+click often
440
# bound to window move on wxGTK
441
if wx.Platform == '__WXMAC__':
442
forceSibling = state.AltDown()
444
forceSibling = state.ControlDown()
445
forceInsert = state.ShiftDown()
446
g.Presenter.updateCreateState(forceSibling, forceInsert)
447
treeState = self.tree.GetFullState() # state just before
448
item = Presenter.paste()
449
if not item: return # error in paste()
450
itemIndex = self.tree.ItemFullIndex(item)
451
g.undoMan.RegisterUndo(undo.UndoPasteCreate(itemIndex, treeState))
453
def OnPasteSibling(self, evt):
454
'''ID.PASTE_SIBLING handler.'''
456
state = wx.GetMouseState()
457
forceInsert = state.ShiftDown()
458
g.Presenter.updateCreateState(forceSibling, forceInsert)
459
treeState = self.tree.GetFullState() # state just before
460
item = Presenter.paste()
461
itemIndex = self.tree.ItemFullIndex(item)
462
g.undoMan.RegisterUndo(undo.UndoPasteCreate(itemIndex, treeState))
464
def OnUnselect(self, evt):
465
self.tree.UnselectAll()
466
if not Presenter.applied: Presenter.update()
467
Presenter.setData(self.tree.root)
469
def OnMoveUp(self, evt):
471
g.undoMan.RegisterUndo(undo.UndoGlobal())
475
def OnMoveDown(self, evt):
477
g.undoMan.RegisterUndo(undo.UndoGlobal())
481
def OnMoveLeft(self, evt):
483
g.undoMan.RegisterUndo(undo.UndoGlobal())
487
def OnMoveRight(self, evt):
489
g.undoMan.RegisterUndo(undo.UndoGlobal())
490
Presenter.moveRight()
493
def OnFind(self, evt):
494
name = wx.GetTextFromUser('Find name:', caption='Find')
496
self.lastSearch = name
497
self.frame.SetStatusText('Looking for "%s"' % name)
498
if Presenter.item == self.tree.root:
499
item = self.tree.Find(self.tree.root, name)
501
# Find from current position
502
item = Presenter.item
504
found = self.tree.Find(item, name)
508
# Search the rest of the current subtree, then go up
509
next = self.tree.GetNextSibling(item)
511
next = self.tree.GetItemParent(item)
512
if next == self.tree.root:
516
next = self.tree.GetNextSibling(next)
519
ask = wx.MessageBox('Search failed. Search from the root?',
520
'Question', wx.YES_NO)
522
item = self.tree.Find(self.tree.root, name)
524
self.frame.SetStatusText('')
527
self.frame.SetStatusText('Search failed')
528
wx.LogError('No such name')
530
self.frame.SetStatusText('Search succeded')
532
self.tree.EnsureVisible(item)
533
self.tree.SelectItem(item)
535
def OnFindAgain(self, evt):
536
self.frame.SetStatusText('Looking for "%s"' % self.lastSearch)
537
if Presenter.item == self.tree.root:
538
item = self.tree.Find(self.tree.root, self.lastSearch)
540
# Find from current position
541
item = Presenter.item
543
# Search the rest of the current subtree, then go up
544
next = self.tree.GetNextSibling(item)
546
next = self.tree.GetItemParent(item)
547
if next == self.tree.root:
551
next = self.tree.GetNextSibling(next)
554
found = self.tree.Find(item, self.lastSearch)
559
ask = wx.MessageBox('Search failed. Search from the root?',
560
'Question', wx.YES_NO)
562
item = self.tree.Find(self.tree.root, name)
564
self.frame.SetStatusText('Search failed')
565
wx.LogError('Search from the root failed.')
568
self.frame.SetStatusText('')
570
self.lastFoundItem = item
571
self.frame.SetStatusText('Search succeded')
573
self.tree.EnsureVisible(item)
574
self.tree.SelectItem(item)
576
def OnLocate(self, evt):
577
frame = self.testWin.GetFrame()
578
frame.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDownTestWin)
579
frame.Bind(wx.EVT_MOUSE_CAPTURE_LOST, self.OnCaptureLostTestWin)
581
wx.SetCursor(wx.CROSS_CURSOR)
583
def OnRefresh(self, evt):
584
if self.testWin.IsShown():
585
self.testWin.isDirty = True
586
Presenter.refreshTestWin()
588
def OnAutoRefresh(self, evt):
589
g.conf.autoRefresh = evt.IsChecked()
590
self.frame.menuBar.Check(self.frame.ID_AUTO_REFRESH, g.conf.autoRefresh)
591
if g.conf.embedPanel:
592
self.frame.tb.ToggleTool(self.frame.ID_AUTO_REFRESH, g.conf.autoRefresh)
594
self.frame.miniFrame.tb.ToggleTool(self.frame.ID_AUTO_REFRESH, g.conf.autoRefresh)
596
def OnHelpAbout(self, evt):
600
(c) Roman Rolinsky <rollrom@users.sourceforge.net>
601
Homepage: http://xrced.sourceforge.net\
603
dlg = wx.MessageDialog(self.frame, str, 'About XRCed', wx.OK | wx.CENTRE)
607
def OnHelpContents(self, evt):
608
self.frame.htmlCtrl.DisplayContents()
610
def OnHelpReadme(self, evt):
611
self.frame.ShowReadme()
613
# Simple emulation of python command line
614
def OnDebugCMD(self, evt):
617
exec raw_input('C:\> ')
623
(etype, value, tb) =sys.exc_info()
624
tblist =traceback.extract_tb(tb)[1:]
625
msg =' '.join(traceback.format_exception_only(etype, value)
626
+traceback.format_list(tblist))
629
def OnEmbedPanel(self, evt):
630
self.frame.EmbedUnembed(evt.IsChecked())
632
def OnShowTools(self, evt):
634
self.toolFrame.Show()
635
conf.showToolPanel = True
637
def OnTest(self, evt):
638
if not Presenter.item: return
639
Presenter.createTestWin(Presenter.item)
643
def OnCloseTestWin(self, evt):
644
TRACE('OnCloseTestWin')
645
Presenter.closeTestWin()
647
def OnSizeTestWin(self, evt):
648
TRACE('OnSizeTestWin')
649
if view.testWin.hl and not self.idleAfterSizeBound:
650
self.idleAfterSizeBound = True
651
frame = self.testWin.GetFrame()
652
frame.Bind(wx.EVT_IDLE, self.OnIdleAfterSize)
655
def OnIdleAfterSize(self, evt):
656
frame = self.testWin.GetFrame()
657
frame.Unbind(wx.EVT_IDLE)
658
self.idleAfterSizeBound = False
659
TRACE('OnIdleAfterSize')
660
Presenter.highlight(Presenter.item)
662
def OnTestHide(self, evt):
663
Presenter.closeTestWin()
665
def OnCaptureLostTestWin(self, evt):
666
frame = self.testWin.GetFrame()
667
wx.SetCursor(wx.NullCursor)
669
frame.Unbind(wx.EVT_LEFT_DOWN)
670
self.frame.tb.ToggleTool(view.frame.ID_TOOL_LOCATE, False)
671
self.frame.miniFrame.tb.ToggleTool(view.frame.ID_TOOL_LOCATE, False)
673
def OnLeftDownTestWin(self, evt):
674
frame = self.testWin.GetFrame()
675
wx.SetCursor(wx.NullCursor)
677
frame.Unbind(wx.EVT_LEFT_DOWN)
678
self.frame.tb.ToggleTool(view.frame.ID_TOOL_LOCATE, False)
679
self.frame.miniFrame.tb.ToggleTool(view.frame.ID_TOOL_LOCATE, False)
681
scrPos = view.testWin.object.ClientToScreen(evt.GetPosition())
682
obj = wx.FindWindowAtPoint(scrPos)
684
item = self.testWin.FindObjectItem(self.testWin.item, obj)
686
# If window has a sizer use it as parent
689
item = self.testWin.FindObjectItem(self.testWin.item, obj)
691
self.tree.EnsureVisible(item)
692
self.tree.SelectItem(item)
694
def OnShowXML(self, evt):
697
def OnMenuHighlight(self, evt):
698
menuId = evt.GetMenuId()
700
menu = evt.GetEventObject()
702
help = menu.GetHelpString(menuId)
703
if menuId == wx.ID_UNDO:
704
help += ' ' + g.undoMan.GetUndoLabel()
705
elif menuId == wx.ID_REDO:
706
help += ' ' + g.undoMan.GetRedoLabel()
707
self.frame.SetStatusText(help)
709
self.frame.SetStatusText('')
711
self.frame.SetStatusText('')
713
def OnUpdateUI(self, evt):
714
if self.inUpdateUI: return # Recursive call protection
715
self.inUpdateUI = True
716
container = Presenter.container
717
comp = Presenter.comp
718
treeNode = self.tree.GetPyData(Presenter.item)
719
isComment = treeNode and treeNode.nodeType == treeNode.COMMENT_NODE
720
# Wokraround for wxMSW: view.tree.GetPrevSibling crashes
721
if evt.GetId() in [self.frame.ID_MOVEUP, self.frame.ID_MOVERIGHT,
722
self.frame.ID_MOVEDOWN, self.frame.ID_MOVELEFT] and \
723
Presenter.item is view.tree.root:
725
elif evt.GetId() in [wx.ID_CUT, wx.ID_COPY, wx.ID_DELETE]:
726
evt.Enable(bool(self.tree.GetSelection()))
727
elif evt.GetId() in [self.frame.ID_MOVEUP, self.frame.ID_MOVERIGHT]:
728
evt.Enable(view.tree.GetPrevSibling(Presenter.item).IsOk())
729
elif evt.GetId() == self.frame.ID_MOVEDOWN:
730
evt.Enable(view.tree.GetNextSibling(Presenter.item).IsOk())
731
elif evt.GetId() == self.frame.ID_MOVELEFT:
732
evt.Enable(container is not Manager.rootComponent and \
733
view.tree.GetItemParent(Presenter.item).IsOk())
734
elif evt.GetId() == wx.ID_SAVE:
735
evt.Enable(Presenter.modified)
736
# elif evt.GetId() in [self.frame.ID_SHOW_XML]:
737
# evt.Enable(len(self.tree.GetSelections()) == 1)
738
elif evt.GetId() in [wx.ID_PASTE, self.frame.ID_TOOL_PASTE]:
739
evt.Enable(self.clipboardHasData)
740
elif evt.GetId() in [self.frame.ID_TEST,
741
self.frame.ID_MOVEUP, self.frame.ID_MOVEDOWN,
742
self.frame.ID_MOVELEFT, self.frame.ID_MOVERIGHT]:
743
evt.Enable(bool(self.tree.GetSelection()))
744
elif evt.GetId() in [self.frame.ID_LOCATE, self.frame.ID_TOOL_LOCATE,
746
evt.Enable(self.testWin.IsShown())
747
elif evt.GetId() == self.frame.ID_FINDAGAIN:
748
evt.Enable(self.lastSearch is not None)
749
elif evt.GetId() == wx.ID_UNDO: evt.Enable(g.undoMan.CanUndo())
750
elif evt.GetId() == wx.ID_REDO: evt.Enable(g.undoMan.CanRedo())
751
elif evt.GetId() in [ID.COLLAPSE, ID.EXPAND]:
752
evt.Enable(not self.tree.GetSelection() or
753
len(self.tree.GetSelections()) == 1 and \
754
self.tree.ItemHasChildren(self.tree.GetSelection()))
755
elif evt.GetId() == ID.SUBCLASS:
756
evt.Enable(not isComment)
757
self.inUpdateUI = False
759
def OnIdle(self, evt):
760
if self.inIdle: return # Recursive call protection
762
if not Presenter.applied:
763
item = self.tree.GetSelection()
764
if item: Presenter.update(item)
767
if not wx.TheClipboard.IsOpened():
768
self.clipboardHasData = False
769
if wx.TheClipboard.IsSupported(self.dataElem.GetFormat()):
770
self.clipboardHasData = True
771
elif wx.TheClipboard.IsSupported(self.dataNode.GetFormat()):
772
self.clipboardHasData = True
776
def OnIconize(self, evt):
779
conf.pos = self.frame.GetPosition()
780
conf.size = self.frame.GetSize()
782
conf.sashPos = self.frame.splitter.GetSashPosition()
784
conf.panelPos = self.miniFrame.GetPosition()
785
conf.panelSize = self.miniFrame.GetSize()
786
self.miniFrame.Show(False)
788
if not conf.embedPanel and self.miniFrame:
789
self.miniFrame.Show(True)
792
def OnSubclass(self, evt):
793
node = self.tree.GetPyData(Presenter.item)
794
subclass = node.getAttribute('subclass')
795
dlg = wx.TextEntryDialog(self.frame, 'Subclass:', defaultValue=subclass)
796
if dlg.ShowModal() == wx.ID_OK:
797
subclass = dlg.GetValue()
798
Presenter.subclass(Presenter.item, subclass)
801
# Expand/collapse subtree
802
def OnExpand(self, evt):
803
if self.tree.GetSelection():
804
map(self.tree.ExpandAllChildren, self.tree.GetSelections())
806
self.tree.ExpandAll()
808
def OnCollapse(self, evt):
809
# Prevent multiple calls to setData
810
self.tree.Unbind(wx.EVT_TREE_ITEM_COLLAPSED)
811
if self.tree.GetSelection():
812
map(self.tree.CollapseAllChildren, self.tree.GetSelections())
814
self.tree.CollapseAll()
815
self.tree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnTreeItemCollapsed)
816
if not self.tree.GetSelection():
817
if not Presenter.applied: Presenter.update()
818
Presenter.setData(self.tree.root)
820
def OnCollapseAll(self, evt):
821
# Prevent multiple calls to setData
822
self.tree.Unbind(wx.EVT_TREE_ITEM_COLLAPSED)
823
self.tree.UnselectAll()
824
self.tree.CollapseAll()
825
self.tree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnTreeItemCollapsed)
826
if not Presenter.applied: Presenter.update()
827
Presenter.setData(self.tree.root)
830
# XMLTree event handlers
833
def OnTreeLeftDown(self, evt):
834
pt = evt.GetPosition();
835
item, flags = self.tree.HitTest(pt)
836
if flags & wx.TREE_HITTEST_NOWHERE or not item:
837
# Unselecting seems to be broken on wxGTK!!!
841
def OnTreeRightDown(self, evt):
842
if wx.Platform == '__WXMAC__':
843
forceSibling = evt.AltDown()
845
forceSibling = evt.ControlDown()
846
forceInsert = evt.ShiftDown()
847
Presenter.popupMenu(forceSibling, forceInsert, evt.GetPosition())
849
def OnTreeSelChanging(self, evt):
850
#TRACE('OnTreeSelChanging: %s=>%s', evt.GetOldItem(), evt.GetItem())
851
#TRACE('Selection: %s', self.tree.GetSelections())
852
if not self.tree.GetSelections(): return
853
# Permit multiple selection for same level only
854
state = wx.GetMouseState()
855
oldItem = evt.GetOldItem()
856
if oldItem and (state.ShiftDown() or state.ControlDown()) and \
857
self.tree.GetItemParent(oldItem) != self.tree.GetItemParent(evt.GetItem()):
859
self.frame.SetStatusText('Veto selection (not same level)')
861
# If panel has a pending undo, register it
862
if Presenter.panelIsDirty():
863
Presenter.registerUndoEdit()
866
def OnTreeSelChanged(self, evt):
867
TRACE('OnTreeSelChanged: %s=>%s', evt.GetOldItem(), evt.GetItem())
868
TRACE('Selection: %s', self.tree.GetSelections())
869
# On wxMSW (at least) two selection events are generated
870
if not self.tree.GetSelections(): return
872
if not Presenter.applied:
873
Presenter.update(evt.GetOldItem())
874
# Refresh test window after finishing
875
if g.conf.autoRefresh and self.testWin.IsDirty():
876
wx.CallAfter(Presenter.refreshTestWin)
877
# Tell presenter to update current data and view
879
if not item: item = self.tree.root
880
wx.CallAfter(Presenter.setData, item)
881
# Set initial sibling/insert modes
882
Presenter.createSibling = not Presenter.comp.isContainer()
883
Presenter.insertBefore = False
886
def OnTreeItemCollapsed(self, evt):
887
# If no selection, reset panel
888
if not self.tree.GetSelection():
889
if not Presenter.applied: Presenter.update()
890
Presenter.setData(self.tree.root)
893
def OnPanelPageChanging(self, evt):
894
TRACE('OnPanelPageChanging: %d=>%d', evt.GetOldSelection(), evt.GetSelection())
895
# Register undo if something was changed
896
i = evt.GetOldSelection()
897
if i >= 0 and Presenter.panelIsDirty():
898
g.undoMan.RegisterUndo(self.panel.undo)
901
def OnPanelPageChanged(self, evt):
902
TRACE('OnPanelPageChanged: %d=>%d', evt.GetOldSelection(), evt.GetSelection())
904
if Presenter.panelIsDirty():
905
Presenter.createUndoEdit(page=evt.GetSelection())
906
# Refresh test window after finishing
907
if g.conf.autoRefresh and self.testWin.IsDirty():
908
wx.CallAfter(Presenter.refreshTestWin)
911
def OnPanelTogglePin(self, evt):
912
g.conf.panelPinState = evt.GetIsDown()
917
def OnToolPanelPageChanged(self, evt):
918
TRACE('OnToolPanelPageChanged: %d > %d', evt.GetOldSelection(), evt.GetSelection())
919
# Update tool frame (if exists)
920
panel = g.toolPanel.panels[evt.GetSelection()]
922
self.toolFrame.SetTitle(panel.name)
925
def OnComponentTool(self, evt):
926
'''Hadnler for creating new elements.'''
927
comp = Manager.findById(evt.GetId())
928
# Check compatibility
929
if Presenter.checkCompatibility(comp):
930
state = self.tree.GetFullState() # state just before
931
if comp.groups[0] == 'component':
932
node = Model.createComponentNode('Component')
933
item = Presenter.create(comp, node)
935
item = Presenter.create(comp)
936
itemIndex = self.tree.ItemFullIndex(item)
937
g.undoMan.RegisterUndo(undo.UndoPasteCreate(itemIndex, state))
940
def OnCloseToolFrame(self, evt):
941
'''wx.EVT_CLOSE handler'''
943
if not self.toolFrame.IsIconized():
944
if conf.showToolPanel:
945
conf.toolPanelPos = self.toolFrame.GetPosition()
946
conf.toolPanelSize = self.toolFrame.GetSize()
947
self.toolFrame.Show(False)
948
conf.showToolPanel = False
950
def OnFrameActivate(self, evt):
952
TRACE('Setting active frame')
953
g.lastActiveFrame = evt.GetEventObject()
958
Listener = g.Listener = _Listener()