~ubuntu-branches/ubuntu/raring/wxwidgets2.8/raring

« back to all changes in this revision

Viewing changes to wxPython/wx/tools/Editra/src/ed_main.py

  • Committer: Package Import Robot
  • Author(s): Stéphane Graber
  • Date: 2012-01-07 13:59:25 UTC
  • mfrom: (1.1.9) (5.1.10 sid)
  • Revision ID: package-import@ubuntu.com-20120107135925-2601miy9ullcon9j
Tags: 2.8.12.1-6ubuntu1
* Resync from Debian, changes that were kept:
  - debian/rules: re-enable mediactrl. This allows libwx_gtk2u_media-2.8 to be
    built, as this is required by some applications (LP: #632984)
  - debian/control: Build-dep on libxt-dev for mediactrl.
  - Patches
    + fix-bashism-in-example
* Add conflict on python-wxgtk2.8 (<< 2.8.12.1-6ubuntu1~) to python-wxversion
  to guarantee upgrade ordering when moving from pycentral to dh_python2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
"""
16
16
 
17
17
__author__ = "Cody Precord <cprecord@editra.org>"
18
 
__svnid__ = "$Id: ed_main.py 63826 2010-04-02 03:50:15Z CJP $"
19
 
__revision__ = "$Revision: 63826 $"
 
18
__svnid__ = "$Id: ed_main.py 67857 2011-06-05 00:16:24Z CJP $"
 
19
__revision__ = "$Revision: 67857 $"
20
20
 
21
21
#--------------------------------------------------------------------------#
22
 
# Dependancies
 
22
# Dependencies
23
23
import os
24
24
import sys
25
25
import time
56
56
#--------------------------------------------------------------------------#
57
57
 
58
58
class MainWindow(wx.Frame, viewmgr.PerspectiveManager):
59
 
    """Editras Main Window
60
 
    @todo: modularize the event handling more (pubsub?)
61
 
 
62
 
    """
 
59
    """Editras Main Window"""
63
60
    # Clipboard ring is limited to 25, why? Because any more is a waste of
64
 
    # memory and an inefficient waste of your time to cyle through.
 
61
    # memory and an inefficient waste of your time to cycle through.
65
62
    CLIPBOARD = util.EdClipboard(25)
66
63
    PRINTER = None
67
64
 
73
70
        """
74
71
        wx.Frame.__init__(self, parent, id_, title, size=wsize,
75
72
                          style=wx.DEFAULT_FRAME_STYLE)
76
 
 
77
 
        hint = wx.aui.AUI_MGR_TRANSPARENT_HINT
78
 
        if wx.Platform == '__WXGTK__':
79
 
            # Use venetian blinds style as trasparent can cause crashes
80
 
            # on linux when desktop compositing is used.
81
 
            hint = wx.aui.AUI_MGR_VENETIAN_BLINDS_HINT
82
 
 
83
 
        self._mgr = wx.aui.AuiManager(flags=wx.aui.AUI_MGR_DEFAULT |
84
 
                                      wx.aui.AUI_MGR_TRANSPARENT_DRAG |
85
 
                                      hint |
86
 
                                      wx.aui.AUI_MGR_ALLOW_ACTIVE_PANE)
87
 
        self._mgr.SetManagedWindow(self)
88
 
        viewmgr.PerspectiveManager.__init__(self, self._mgr, \
89
 
                                            CONFIG['CACHE_DIR'])
 
73
        viewmgr.PerspectiveManager.__init__(self, CONFIG['CACHE_DIR'])
90
74
 
91
75
        # Setup app icon and title
92
 
        self.SetTitle()
93
76
        util.SetWindowIcon(self)
94
77
 
95
78
        # Attributes
96
79
        self._loaded = False
 
80
        self._initialized = False # for GTK OnActivate HACK
 
81
        self._mlock = ebmlib.CallLock()
97
82
        self._last_save = u''
98
83
        self.LOG = wx.GetApp().GetLog()
99
84
        self._exiting = False
100
85
        self._handlers = dict(menu=list(), ui=list())
101
86
 
102
87
        #---- Setup File History ----#
103
 
        self.filehistory = wx.FileHistory(_PGET('FHIST_LVL', 'int', 9))
 
88
        self.filehistory = ebmlib.EFileHistory(_PGET('FHIST_LVL', 'int', 9))
104
89
 
105
90
        #---- Status bar on bottom of window ----#
106
91
        self.SetStatusBar(ed_statbar.EdStatBar(self))
107
92
        self.GetStatusBar().Show(_PGET('STATBAR', default=True))
108
 
 
109
93
        #---- End Statusbar Setup ----#
110
94
 
111
 
        #---- Notebook that contains the editting buffers ----#
 
95
        #---- Notebook that contains the editing buffers ----#
112
96
        self._mpane = ed_mpane.MainPanel(self)
113
97
        self.nb = self._mpane.GetWindow()
114
 
        self._mgr.AddPane(self._mpane, wx.aui.AuiPaneInfo(). \
115
 
                          Name("EditPane").Center().Layer(1).Dockable(False). \
116
 
                          CloseButton(False).MaximizeButton(False). \
117
 
                          CaptionVisible(False))
118
 
        self._mpane.InitCommandBar() # <- required due to nb dependancies...
 
98
        self.PanelMgr.AddPane(self._mpane, wx.aui.AuiPaneInfo(). \
 
99
                              Name("EditPane").Center().Layer(1).Dockable(False). \
 
100
                              CloseButton(False).MaximizeButton(False). \
 
101
                              CaptionVisible(False))
 
102
        self._mpane.InitCommandBar() # <- required due to nb dependencies...
119
103
 
120
104
        #---- Command Bar ----#
121
105
        self._mpane.HideCommandBar()
128
112
            MainWindow.PRINTER = ed_print.EdPrinter(self)
129
113
 
130
114
        #---- Setup Toolbar ----#
131
 
        self.SetToolBar(ed_toolbar.EdToolBar(self))
132
 
        self.GetToolBar().Show(_PGET('TOOLBAR'))
 
115
        self.SetupToolBar()
133
116
        #---- End Toolbar Setup ----#
134
117
 
135
118
        #---- Menus ----#
179
162
                                       (ID_COLUMN_MODE, self.DispatchToControl),
180
163
                                       (ID_TOGGLE_FOLD, self.DispatchToControl),
181
164
                                       (ID_TOGGLE_ALL_FOLDS, self.DispatchToControl),
 
165
                                       (ID_SHOW_AUTOCOMP, self.DispatchToControl),
 
166
                                       (ID_SHOW_CALLTIP, self.DispatchToControl),
182
167
                                       (ID_QUICK_FIND, self.OnCommandBar),
183
168
                                       (ID_PREF, OnPreferences),
184
169
 
270
255
        # Frame
271
256
        self.Bind(wx.EVT_ACTIVATE, self.OnActivate)
272
257
        self.Bind(wx.EVT_CLOSE, self.OnClose)
 
258
        self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self)
273
259
        self.Bind(ed_event.EVT_STATUS, self.OnStatus)
274
260
 
275
261
        # Find Dialog
289
275
        self._handlers['menu'].extend(addons.GetEventHandlers())
290
276
        self._handlers['ui'].extend(addons.GetEventHandlers(ui_evt=True))
291
277
        shelf = ed_shelf.Shelf(plgmgr)
292
 
        shelf.Init(self)
293
 
        self._handlers['ui'].extend(shelf.GetUiHandlers())
294
 
        self._shelf = ed_shelf.Shelf.delegate
295
 
        ed_shelf.Shelf.delegate = None
 
278
        self._shelf = shelf.Init(self)
 
279
        self._handlers['ui'].extend(shelf.GetUiHandlers(self._shelf))
296
280
 
297
281
        self.LOG("[ed_main][info] Loading Generator plugins")
298
282
        generator.Generator(plgmgr).InstallMenu(menbar.GetMenuByName("tools"))
299
283
 
300
284
        # Set Perspective and other UI settings
301
285
        self.SetPerspective(_PGET('DEFAULT_VIEW'))
302
 
        self._mgr.Update()
 
286
        self.PanelMgr.Update()
 
287
        # Make sure all clients are updated to user specified display font.
303
288
        ed_msg.PostMessage(ed_msg.EDMSG_DSP_FONT,
304
289
                           _PGET('FONT3', 'font', wx.NORMAL_FONT))
305
290
 
312
297
 
313
298
    __name__ = u"MainWindow"
314
299
 
315
 
    def __del__(self):
316
 
        ed_msg.Unsubscribe(self.OnUpdateFileHistory)
 
300
    def OnDestroy(self, evt):
 
301
        """Disconnect Message Handlers"""
 
302
        if evt.GetId() == self.GetId():
 
303
            ed_msg.Unsubscribe(self.OnUpdateFileHistory)
 
304
        evt.Skip()
317
305
 
318
306
    #---- End Private Member Functions/Variables ----#
319
307
 
324
312
        @type evt: wx.ActivateEvent
325
313
 
326
314
        """
 
315
        if self._mlock.IsLocked():
 
316
            # Deactivated for popup, leave handlers hooked up
 
317
            wx.UpdateUIEvent.SetMode(wx.UPDATE_UI_PROCESS_ALL)
 
318
            evt.Skip()
 
319
            return
 
320
 
327
321
        app = wx.GetApp()
328
322
        active = evt.GetActive()
329
323
 
330
 
        # Don't needlessly push and pop events if we only have one window open
331
 
        if self._loaded and len(app.GetMainWindows()) == 1:
332
 
            if active:
333
 
                wx.GetApp().SetTopWindow(self)
334
 
                wx.UpdateUIEvent.SetUpdateInterval(215)
335
 
                wx.UpdateUIEvent.SetMode(wx.UPDATE_UI_PROCESS_SPECIFIED)
336
 
                self.SetExtraStyle(wx.WS_EX_PROCESS_UI_UPDATES)
337
 
            else:
338
 
                self.SetExtraStyle(0)
339
 
                wx.UpdateUIEvent.SetMode(wx.UPDATE_UI_PROCESS_ALL)
340
 
            evt.Skip()
341
 
            return
342
 
 
343
324
        # Add or remove handlers from the event stack
344
 
        if active:
 
325
        if active and not self._loaded:
 
326
            self._loaded = True
345
327
            app.SetTopWindow(self)
346
 
            self._loaded = True
347
328
 
348
329
            # Slow the update interval to reduce overhead
349
330
            wx.UpdateUIEvent.SetUpdateInterval(215)
360
341
            #      window doesn't get activated until later than it does on the
361
342
            #      other platforms. So for panels that depend on updating their
362
343
            #      initial state we need to send out a fake update message here.
363
 
            if wx.Platform == '__WXGTK__':
 
344
            if wx.Platform == '__WXGTK__' and not self._initialized:
 
345
                self._initialized = True
364
346
                nb = self.GetNotebook()
365
347
                ed_msg.PostMessage(ed_msg.EDMSG_UI_NB_CHANGED,
366
348
                                   (nb, nb.GetSelection()))
367
 
        else:
368
 
            self.SetExtraStyle(0)
369
 
 
370
 
            # HACK set update ui events back to process all here in case
371
 
            # opened dialog needs them. Not sure why this is necessary but it
372
 
            # is the only solution I could find to fix the external find
373
 
            # dialogs so that their buttons become enabled when typing in the
374
 
            # text control.
375
 
            #
376
 
            # If the windows that took the active position is another mainwindow
377
 
            # it will set the events back to UPDATE_UI_PROCESS_SPECIFIED to
378
 
            # prevent all the toolbars/menu items of each window from updating
379
 
            # when they dont need to.
380
 
            wx.UpdateUIEvent.SetMode(wx.UPDATE_UI_PROCESS_ALL)
381
 
            for handler in self._handlers['menu']:
382
 
                app.RemoveHandlerForID(handler[0])
383
 
 
384
 
            for handler in self._handlers['ui']:
385
 
                app.RemoveUIHandlerForID(handler[0])
386
 
 
 
349
        elif not active:
387
350
            self._loaded = False
 
351
            self.DeActivate()
388
352
 
389
353
        evt.Skip()
390
354
 
393
357
        @param msg: Message object (data == filename)
394
358
 
395
359
        """
396
 
        try:
397
 
            self.filehistory.AddFileToHistory(msg.GetData())
398
 
        except wx.PyAssertionError:
399
 
            # ignore errors that wxMac sometimes raises about unicode data
400
 
            pass
 
360
        # May get notified after/during delete
 
361
        if self:
 
362
            try:
 
363
                self.filehistory.AddFileToHistory(msg.GetData())
 
364
            except wx.PyAssertionError:
 
365
                # ignore errors that wxMac sometimes raises about unicode data
 
366
                pass
401
367
 
402
368
    def AddFileToHistory(self, fname):
403
369
        """Add a file to the windows file history as well as any
460
426
 
461
427
            dlg = wx.FileDialog(self, _("Editra: Open"), fdir, "",
462
428
                                ''.join(syntax.GenFileFilters()),
463
 
                                wx.OPEN | wx.MULTIPLE)
 
429
                                wx.OPEN | wx.MULTIPLE | wx.CHANGE_DIR)
464
430
            dlg.SetFilterIndex(_PGET('FFILTER', 'int', 0))
465
431
 
466
 
            if dlg.ShowModal() == wx.ID_OK:
 
432
            if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK:
467
433
                _PSET('FFILTER', dlg.GetFilterIndex())
468
434
                for path in dlg.GetPaths():
469
435
                    if _PGET('OPEN_NW', default=False):
487
453
 
488
454
            self.Raise()
489
455
 
 
456
    def DeActivate(self):
 
457
        """Helper method for the App to tell this window to remove
 
458
        all its event handlers.
 
459
 
 
460
        """
 
461
        self.SetExtraStyle(0)
 
462
 
 
463
        # HACK set update ui events back to process all here in case
 
464
        # opened dialog needs them. Not sure why this is necessary but it
 
465
        # is the only solution I could find to fix the external find
 
466
        # dialogs so that their buttons become enabled when typing in the
 
467
        # text control.
 
468
        #
 
469
        # If the windows that took the active position is another mainwindow
 
470
        # it will set the events back to UPDATE_UI_PROCESS_SPECIFIED to
 
471
        # prevent all the toolbars/menu items of each window from updating
 
472
        # when they dont need to.
 
473
        wx.UpdateUIEvent.SetMode(wx.UPDATE_UI_PROCESS_ALL)
 
474
        self.FlushEventStack()
 
475
 
 
476
    def FlushEventStack(self):
 
477
        """Clear the Menu and UpdateUI event handler stack
 
478
        @note: only unregisters this frames handlers from the app
 
479
 
 
480
        """
 
481
        app = wx.GetApp()
 
482
        for handler in self._handlers['menu']:
 
483
            app.RemoveHandlerForID(handler[0])
 
484
 
 
485
        for handler in self._handlers['ui']:
 
486
            app.RemoveUIHandlerForID(handler[0])
 
487
 
490
488
    def GetCommandbar(self):
491
489
        """Get this windows command bar
492
490
        @return: ed_cmdbar.CommandBarBase
501
499
        """
502
500
        return self._mpane
503
501
 
504
 
    def GetFrameManager(self):
505
 
        """Returns the manager for this frame
506
 
        @return: Reference to the AuiMgr of this window
507
 
 
508
 
        """
509
 
        return self._mgr
510
 
 
511
502
    def GetNotebook(self):
512
503
        """Get the windows main notebook that contains the editing buffers
513
504
        @return: reference to L{extern.flatnotebook.FlatNotebook} instance
549
540
            hist_list = _PGET('FHIST', default=list())
550
541
            if len(hist_list) > size:
551
542
                hist_list = hist_list[:size]
552
 
 
553
 
            for fname in hist_list:
554
 
                if isinstance(fname, basestring) and fname:
555
 
                    # TODO: find out why these errors are happening
556
 
                    #       when loading the pickled strings on some systems
557
 
                    #       The pickled strings are not in unicode format.
558
 
                    try:
559
 
                        self.filehistory.AddFileToHistory(fname)
560
 
                    except wx.PyAssertionError:
561
 
                        pass
 
543
            self.filehistory.History = hist_list
562
544
        except UnicodeEncodeError, msg:
563
 
            self.LOG("[ed_main][err] Filehistory load failed: %s" % str(msg))
 
545
            self.LOG("[ed_main][err] Filehistory load failed: %s" % msg)
564
546
 
565
547
    def OnNew(self, evt):
566
548
        """Start a New File in a new tab
601
583
                                    fname, _("File Not Found"),
602
584
                                    wx.OK | wx.ICON_WARNING)
603
585
            mdlg.CenterOnParent()
604
 
            mdlg.ShowModal()
 
586
            ebmlib.LockCall(self._mlock, mdlg.ShowModal)
605
587
            mdlg.Destroy()
606
588
            # Remove offending file from history
607
589
            self.filehistory.RemoveFileFromHistory(fnum)
626
608
        else:
627
609
            evt.Skip()
628
610
 
 
611
    def SaveFile(self, tablbl, buf):
 
612
        """Save the given page in the notebook
 
613
        @param tablbl: main notebook tab label
 
614
        @param buf: EdEditView instance
 
615
        @note: intended for internal use! method signature may change
 
616
 
 
617
        """
 
618
        fname = ebmlib.GetFileName(buf.GetFileName())
 
619
        if fname != u'':
 
620
            fpath = buf.GetFileName()
 
621
            result = buf.SaveFile(fpath)
 
622
            self._last_save = fpath
 
623
            if result:
 
624
                self.PushStatusText(_("Saved File: %s") % fname, SB_INFO)
 
625
            else:
 
626
                err = buf.GetDocument().GetLastError()
 
627
                self.PushStatusText(_("ERROR: %s") % err, SB_INFO)
 
628
                ed_mdlg.SaveErrorDlg(self, fname, err)
 
629
                buf.GetDocument().ResetAll()
 
630
        else:
 
631
            self.OnSaveAs(ID_SAVEAS, tablbl, buf)
 
632
 
 
633
    def SaveCurrentBuffer(self):
 
634
        """Save the file in the currently selected editor buffer"""
 
635
        page = self.nb.GetSelection()
 
636
        self.SaveFile(self.nb.GetPageText(page), self.nb.GetCurrentCtrl())
 
637
 
 
638
    def SaveAllBuffers(self):
 
639
        """Save all open editor buffers"""
 
640
        for page in xrange(self.nb.GetPageCount()):
 
641
            buff = self.nb.GetPage(page)
 
642
            if isinstance(buff, wx.stc.StyledTextCtrl):
 
643
                if buff.GetModify():
 
644
                    self.SaveFile(self.nb.GetPageText(page), buff)
 
645
 
629
646
    def OnSave(self, evt):
630
647
        """Save Current or All Buffers
631
648
        @param evt: Event fired that called this handler
633
650
 
634
651
        """
635
652
        e_id = evt.GetId()
636
 
        ctrls = list()
637
653
        if e_id == ID_SAVE:
638
 
            page = self.nb.GetSelection()
639
 
            ctrls = [(self.nb.GetPageText(page),
640
 
                      self.nb.GetCurrentCtrl(), page)]
 
654
            self.SaveCurrentBuffer()
641
655
        elif e_id == ID_SAVEALL:
642
 
            # Collect all open editor buffers
643
 
            for page in xrange(self.nb.GetPageCount()):
644
 
                if issubclass(self.nb.GetPage(page).__class__,
645
 
                                           wx.stc.StyledTextCtrl):
646
 
                    ctrls.append((self.nb.GetPageText(page),
647
 
                                  self.nb.GetPage(page), page))
 
656
            self.SaveAllBuffers()
648
657
        else:
649
658
            evt.Skip()
650
659
            return
651
660
 
652
 
        # TODO: detect when save fails due to encoding and prompt to
653
 
        #       request an encoding from the user.
654
 
        for ctrl in ctrls:
655
 
            fname = ebmlib.GetFileName(ctrl[1].GetFileName())
656
 
            if fname != '':
657
 
                fpath = ctrl[1].GetFileName()
658
 
                result = ctrl[1].SaveFile(fpath)
659
 
                self._last_save = fpath
660
 
                if result:
661
 
                    self.PushStatusText(_("Saved File: %s") % fname, SB_INFO)
662
 
                else:
663
 
                    err = ctrl[1].GetDocument().GetLastError()
664
 
                    self.PushStatusText(_("ERROR: %s") % err, SB_INFO)
665
 
                    ed_mdlg.SaveErrorDlg(self, fname, err)
666
 
                    ctrl[1].GetDocument().ResetAll()
667
 
            else:
668
 
                self.OnSaveAs(ID_SAVEAS, ctrl[0], ctrl[1])
669
 
 
670
661
    def OnSaveAs(self, evt, title=u'', page=None):
671
662
        """Save File Using a new/different name
672
663
        @param evt: Event fired that called this handler
691
682
                            u''.join(syntax.GenFileFilters()),
692
683
                            wx.SAVE | wx.OVERWRITE_PROMPT)
693
684
 
694
 
        if dlg.ShowModal() == wx.ID_OK:
 
685
        if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK:
695
686
            path = dlg.GetPath()
696
687
            dlg.Destroy()
697
688
 
725
716
                               _("Profile") + " (*.ppb)|*.ppb",
726
717
                                wx.SAVE | wx.OVERWRITE_PROMPT)
727
718
 
728
 
            if dlg.ShowModal() == wx.ID_OK:
 
719
            if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK:
729
720
                profiler.TheProfile.Write(dlg.GetPath())
730
721
                self.PushStatusText(_("Profile Saved as: %s") % \
731
722
                                    dlg.GetFilename(), SB_INFO)
745
736
                                CONFIG['PROFILE_DIR'], "default.ppb",
746
737
                                _("Profile") + " (*.ppb)|*.ppb", wx.OPEN)
747
738
 
748
 
            result = dlg.ShowModal()
749
 
            if result == wx.ID_OK:
 
739
            if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK:
750
740
                profiler.TheProfile.Load(dlg.GetPath())
751
741
                self.PushStatusText(_("Loaded Profile: %s") % \
752
742
                                    dlg.GetFilename(), SB_INFO)
770
760
                               _("Session") + " (*.session)|*.session",
771
761
                                wx.SAVE | wx.OVERWRITE_PROMPT)
772
762
 
773
 
            if dlg.ShowModal() == wx.ID_OK:
 
763
            if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK:
774
764
                fname = dlg.GetPath()
775
765
                if fname is None or not len(fname):
776
766
                    return
796
786
                                CONFIG['SESSION_DIR'], u"",
797
787
                                _("Session") + " (*.session)|*.session", wx.OPEN)
798
788
 
799
 
            if dlg.ShowModal() == wx.ID_OK:
 
789
            if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK:
800
790
                fname = dlg.GetPath()
801
791
                nbook = self.GetNotebook()
802
792
                rval = nbook.LoadSessionFile(fname)
818
808
        @param evt: event that called this handler
819
809
 
820
810
        """
821
 
        statbar = self.GetStatusBar()
822
 
        if statbar:
823
 
            # The frames Set/PushStatusText methods don't seem to call the
824
 
            # method of the statusbar class instance when setting the text so
825
 
            # get and set the text in the status bar directly so that our
826
 
            # statusbar's overridden settext method gets called
827
 
            statbar.SetStatusText(evt.GetMessage(), evt.GetSection())
828
 
#            self.SetStatusText(evt.GetMessage(), evt.GetSection())
 
811
        self.SetStatusText(evt.GetMessage(), evt.GetSection())
829
812
 
830
813
    def OnPrint(self, evt):
831
814
        """Handles sending the current document to the printer,
870
853
 
871
854
        """
872
855
        # Save session files
873
 
        session = _PGET('LAST_SESSION')
874
 
        if not isinstance(session, basestring) or not len(session):
875
 
            session = os.path.join(CONFIG['SESSION_DIR'], u"__default.session")
876
 
        _PSET('LAST_SESSION', session)
877
 
        result = self.nb.SaveSessionFile(session)
878
 
        if result is not None:
879
 
            pass # TODO: report error?
 
856
        self.nb.SaveCurrentSession()
880
857
 
881
858
        # Cleanup Controls
882
859
        self._exiting = True
883
860
        controls = self.nb.GetPageCount()
884
861
        self.LOG("[ed_main][evt] OnClose: Number of controls: %d" % controls)
 
862
        self.Freeze()
885
863
        while controls:
886
864
            if controls <= 0:
887
865
                self.Close(True) # Force exit since there is a problem
888
866
 
889
867
            self.LOG("[ed_main][evt] OnClose: Requesting Page Close")
890
868
            if not self.nb.ClosePage():
 
869
                self.Thaw()
891
870
                self._exiting = False
892
871
                ed_msg.PostMessage(ed_msg.EDMSG_UI_NB_CHANGED,
893
872
                                   (self.nb, self.nb.GetSelection()))
894
873
                return True
895
874
            controls -= 1
 
875
        self.Thaw()
896
876
 
897
877
        ### If we get to here there is no turning back so cleanup
898
878
        ### additional items and save user settings
903
883
 
904
884
        # Save Shelf contents
905
885
        _PSET('SHELF_ITEMS', self._shelf.GetItemStack())
 
886
        _PSET('SHELF_LAYOUT', self._shelf.GetPerspective())
 
887
        _PSET('SHELF_SELECTION', self._shelf.GetSelection())
906
888
 
907
889
        # Save Window Size/Position for next launch
908
890
        self.UpdateAutoPerspective()
928
910
        # TODO: Find out why filehistory can be undefined by this point
929
911
        #       sometimes.
930
912
        try:
931
 
            profiler.AddFileHistoryToProfile(self.filehistory)
932
 
            del self.filehistory
 
913
            _PSET('FHIST', self.filehistory.History)
933
914
        except AttributeError:
934
915
            self.LOG("[ed_main][err] OnClose: Trapped AttributeError OnExit")
935
916
 
939
920
        self.LOG("[ed_main][info] Saving profile to %s" % ppath)
940
921
 
941
922
        # Post exit notice to all aui panes
942
 
        panes = self._mgr.GetAllPanes()
 
923
        panes = self.PanelMgr.GetAllPanes()
943
924
        exit_evt = ed_event.MainWindowExitEvent(ed_event.edEVT_MAINWINDOW_EXIT,
944
925
                                                wx.ID_ANY)
945
926
        for pane in panes:
948
929
        # Finally close the window
949
930
        self.LOG("[ed_main][evt] OnClose: Closing Main Frame")
950
931
        wx.GetApp().UnRegisterWindow(repr(self))
 
932
 
 
933
        # Ensure that event handlers have been un registered from the app
 
934
        wx.UpdateUIEvent.SetMode(wx.UPDATE_UI_PROCESS_ALL)
 
935
 
 
936
        # Cleanup
951
937
        self.Destroy()
952
938
 
953
939
    #---- End File Menu Functions ----#
998
984
        @param evt: CommandEvent instance
999
985
 
1000
986
        """
1001
 
        paneInfo = self._mgr.GetPane("EditPane")
 
987
        paneInfo = self.PanelMgr.GetPane("EditPane")
1002
988
        if paneInfo.IsMaximized():
1003
 
            self._mgr.RestorePane(paneInfo)
 
989
            self.PanelMgr.RestorePane(paneInfo)
1004
990
            ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_RESTORE, context=self.GetId())
1005
991
        else:
1006
 
            self._mgr.RestoreMaximizedPane()
1007
 
            self._mgr.MaximizePane(paneInfo)
1008
 
        self._mgr.Update()
 
992
            self.PanelMgr.RestoreMaximizedPane()
 
993
            self.PanelMgr.MaximizePane(paneInfo)
 
994
        self.PanelMgr.Update()
1009
995
        
1010
996
    #---- End View Menu Functions ----#
1011
997
 
1024
1010
            fdata = wx.FontData()
1025
1011
            fdata.SetInitialFont(ctrl.GetDefaultFont())
1026
1012
            dlg = wx.FontDialog(self, fdata)
1027
 
            result = dlg.ShowModal()
 
1013
            result = ebmlib.LockCall(self._mlock, dlg.ShowModal)
1028
1014
            data = dlg.GetFontData()
1029
1015
            dlg.Destroy()
1030
1016
            if result == wx.ID_OK:
1031
1017
                font = data.GetChosenFont()
1032
1018
                ctrl.SetGlobalFont(self.nb.control.FONT_PRIMARY, \
1033
1019
                                   font.GetFaceName(), font.GetPointSize())
 
1020
                ctrl.SetGlobalFont(self.nb.control.FONT_SECONDARY, \
 
1021
                                   font.GetFaceName(), font.GetPointSize())
1034
1022
                ctrl.UpdateAllStyles()
1035
1023
        else:
1036
1024
            evt.Skip()
1048
1036
            import style_editor
1049
1037
            dlg = style_editor.StyleEditor(self)
1050
1038
            dlg.CenterOnParent()
1051
 
            dlg.ShowModal()
 
1039
            ebmlib.LockCall(self._mlock, dlg.ShowModal)
1052
1040
            dlg.Destroy()
1053
1041
        else:
1054
1042
            evt.Skip()
1114
1102
                        ID_PASTE, ID_LINE_BEFORE, ID_LINE_AFTER, ID_DUP_LINE,
1115
1103
                        ID_PASTE_AFTER, ID_COLUMN_MODE, ID_TOGGLE_FOLD,
1116
1104
                        ID_CYCLE_CLIPBOARD,
1117
 
                        ID_TOGGLE_ALL_FOLDS, ID_DELETE_LINE ]
 
1105
                        ID_TOGGLE_ALL_FOLDS, ID_DELETE_LINE,
 
1106
                        ID_SHOW_AUTOCOMP, ID_SHOW_CALLTIP ]
1118
1107
 
1119
1108
        # Special handling for common clipboard related actions
1120
1109
        has_focus = self.FindFocus()
1210
1199
                dlg.SetBitmap(bmp)
1211
1200
            dlg.CenterOnParent()
1212
1201
 
1213
 
            if dlg.ShowModal() == wx.ID_OK:
 
1202
            if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK:
1214
1203
                nenc = dlg.GetEncoding()
1215
1204
                doc.SetEncoding(nenc)
1216
1205
                success = ctrl.ReloadFile()[0]
1217
1206
                if not success:
1218
1207
                    msg = _("Failed to reload the file with: %(encoding)s") % dict(encoding=nenc)
1219
1208
                    wx.MessageBox(msg, style=wx.OK|wx.ICON_ERROR)
 
1209
                    # Revert to previous encoding
1220
1210
                    doc.SetEncoding(cenc)
1221
1211
                    ctrl.ReloadFile()
1222
1212
            dlg.Destroy()
1233
1223
                return
1234
1224
 
1235
1225
            bmp = wx.ArtProvider.GetBitmap(str(ID_NEW_WINDOW), wx.ART_MENU)
1236
 
            self._paneNavi = eclib.AuiPaneNavigator(self, self._mgr, bmp,
 
1226
            self._paneNavi = eclib.AuiPaneNavigator(self, self.PanelMgr, bmp,
1237
1227
                                                      _("Aui Pane Navigator"))
1238
1228
            self._paneNavi.SetReturnCode(wx.ID_OK)
1239
 
            self._paneNavi.ShowModal()
 
1229
            ebmlib.LockCall(self._mlock, self._paneNavi.ShowModal)
1240
1230
 
1241
1231
            sel = self._paneNavi.GetSelection()
1242
1232
            self._paneNavi.Destroy()
1243
1233
            self._paneNavi = None
1244
1234
 
1245
1235
            if isinstance(sel, basestring):
1246
 
                paneInfo = self._mgr.GetPane(sel)
 
1236
                paneInfo = self.PanelMgr.GetPane(sel)
1247
1237
                if paneInfo.IsOk():
1248
1238
                    if not paneInfo.IsShown():
1249
1239
                        paneInfo.Show()
1250
 
                        self._mgr.Update()
 
1240
                        self.PanelMgr.Update()
 
1241
                        # Notify activation if the window supports it
 
1242
                        if hasattr(paneInfo.window, "OnShowAUIPane"):
 
1243
                            paneInfo.window.OnShowAUIPane()
1251
1244
                    paneInfo.window.SetFocus()
1252
1245
        else:
1253
1246
            evt.Skip()
1405
1398
        elif e_id == ID_INDENT_GUIDES:
1406
1399
            evt.Check(bool(ctrl.GetIndentationGuides()))
1407
1400
        elif e_id == ID_MAXIMIZE_EDITOR:
1408
 
            paneInfo = self._mgr.GetPane("EditPane")
 
1401
            paneInfo = self.PanelMgr.GetPane("EditPane")
1409
1402
            binder = self.MenuBar.GetKeyBinder()
1410
1403
            binding = binder.GetBinding(ID_MAXIMIZE_EDITOR)
1411
1404
            txt = _("Maximize Editor")
1443
1436
            dlg.SetInitialSize()
1444
1437
            dlg.CenterOnParent()
1445
1438
 
1446
 
            if dlg.ShowModal() == wx.ID_OK:
 
1439
            if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK:
1447
1440
                includes = dlg.GetIncludes()
1448
1441
                includes.sort()
1449
1442
                _PSET("LEXERMENU", includes)
1477
1470
 
1478
1471
        # It seems under some cases when running under windows the call to
1479
1472
        # subprocess in webbrowser will fail and raise an exception here. So
1480
 
        # simply trap and ingnore it.
 
1473
        # simply trap and ignore it.
1481
1474
        try:
1482
1475
            self.PushStatusText(_("Opening %s") % page, SB_INFO)
1483
1476
            webbrowser.open(page, 1)
1490
1483
 
1491
1484
        """
1492
1485
        sb = self.GetStatusBar()
1493
 
        sb.PushStatusText(txt, field)
 
1486
        if sb:
 
1487
            sb.PushStatusText(txt, field)
1494
1488
 
1495
1489
    SetStatusText = PushStatusText
1496
1490
 
1500
1494
        @type title: string
1501
1495
 
1502
1496
        """
1503
 
        name = "%s v%s" % (PROG_NAME, VERSION)
 
1497
        name = u"%s v%s" % (PROG_NAME, VERSION)
1504
1498
        if len(title):
1505
 
            name = " - " + name
1506
 
        wx.Frame.SetTitle(self, title + name)
 
1499
            name = u" - " + name
 
1500
        super(MainWindow, self).SetTitle(title + name)
 
1501
 
 
1502
    def SetupToolBar(self):
 
1503
        """Setup or reinitialize the windows ToolBar"""
 
1504
        tb = self.GetToolBar()
 
1505
        if tb:
 
1506
            tb.Destroy()
 
1507
        self.SetToolBar(ed_toolbar.EdToolBar(self))
 
1508
        self.GetToolBar().Show(_PGET('TOOLBAR'))
 
1509
        self.Layout()
1507
1510
 
1508
1511
    @classmethod
1509
1512
    def UpdateClipboardRing(cls):
1595
1598
        handlers = list()
1596
1599
        for observer in self.observers:
1597
1600
            try:
 
1601
                items = None
1598
1602
                if ui_evt:
1599
 
                    items = observer.GetUIHandlers()
 
1603
                    if hasattr(observer, 'GetUIHandlers'):
 
1604
                        items = observer.GetUIHandlers()
 
1605
                        assert isinstance(items, list), "Must be a list()!"
1600
1606
                else:
1601
 
                    items = observer.GetMenuHandlers()
 
1607
                    if hasattr(observer, 'GetMenuHandlers'):
 
1608
                        items = observer.GetMenuHandlers()
 
1609
                        assert isinstance(items, list), "Must be a list()!"
1602
1610
            except Exception, msg:
1603
 
                util.Log("[ed_main][err] MainWindoAddOn.GetEventHandlers: %s" % str(msg))
 
1611
                util.Log("[ed_main][err] MainWindowAddOn.GetEventHandlers: %s" % str(msg))
1604
1612
                continue
1605
 
            handlers.extend(items)
 
1613
 
 
1614
            if items is not None:
 
1615
                handlers.extend(items)
 
1616
 
1606
1617
        return handlers