File: editor_area_pane.py

package info (click to toggle)
python-pyface 8.0.0-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 13,944 kB
  • sloc: python: 54,107; makefile: 82
file content (179 lines) | stat: -rw-r--r-- 6,157 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# (C) Copyright 2005-2023 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!

import logging


from pyface.tasks.i_editor_area_pane import IEditorAreaPane, MEditorAreaPane
from traits.api import observe, provides


import wx
from pyface.wx.aui import aui, PyfaceAuiNotebook


from .task_pane import TaskPane

# Logging
logger = logging.getLogger(__name__)


# ----------------------------------------------------------------------------
# 'EditorAreaPane' class.
# ----------------------------------------------------------------------------


@provides(IEditorAreaPane)
class EditorAreaPane(TaskPane, MEditorAreaPane):
    """ The toolkit-specific implementation of a EditorAreaPane.

    See the IEditorAreaPane interface for API documentation.
    """

    style = (
        aui.AUI_NB_WINDOWLIST_BUTTON
        | aui.AUI_NB_TAB_MOVE
        | aui.AUI_NB_SCROLL_BUTTONS
        | aui.AUI_NB_CLOSE_ON_ACTIVE_TAB
    )

    # ------------------------------------------------------------------------
    # 'TaskPane' interface.
    # ------------------------------------------------------------------------

    def create(self, parent):
        """ Create and set the toolkit-specific control that represents the
            pane.
        """
        logger.debug("editor pane parent: %s" % parent)
        # Create and configure the tab widget.
        self.control = control = PyfaceAuiNotebook(parent, agwStyle=self.style)

        # Connect to the widget's signals.
        control.Bind(
            aui.EVT_AUINOTEBOOK_PAGE_CHANGED, self._update_active_editor
        )
        control.Bind(aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self._close_requested)

    def destroy(self):
        """ Destroy the toolkit-specific control that represents the pane.
        """
        for editor in self.editors:
            self.remove_editor(editor)

        super().destroy()

    # ------------------------------------------------------------------------
    # 'IEditorAreaPane' interface.
    # ------------------------------------------------------------------------

    def activate_editor(self, editor):
        """ Activates the specified editor in the pane.
        """
        index = self.control.GetPageIndex(editor.control)
        self.control.SetSelection(index)

    def add_editor(self, editor):
        """ Adds an editor to the pane.
        """
        editor.editor_area = self
        editor.create(self.control)
        self.control.AddPage(editor.control, self._get_label(editor))
        try:
            index = self.control.GetPageIndex(editor.control)
            self.control.SetPageToolTip(index, editor.tooltip)
        except AttributeError:
            pass
        self.editors.append(editor)
        self._update_tab_bar(event=None)

        # The EVT_AUINOTEBOOK_PAGE_CHANGED event is not sent when the first
        # editor is added.
        if len(self.editors) == 1:
            self.active_editor = editor

    def remove_editor(self, editor):
        """ Removes an editor from the pane.
        """
        self.editors.remove(editor)
        index = self.control.GetPageIndex(editor.control)
        logger.debug("Removing page %d" % index)
        self.control.RemovePage(index)
        editor.destroy()
        editor.editor_area = None
        self._update_tab_bar(event=None)
        if not self.editors:
            self.active_editor = None

    # ------------------------------------------------------------------------
    # Protected interface.
    # ------------------------------------------------------------------------

    def _get_label(self, editor):
        """ Return a tab label for an editor.
        """
        label = editor.name
        if editor.dirty:
            label = "*" + label
        if not label:
            label = " "  # bug in agw that fails on empty label
        return label

    def _get_editor_with_control(self, control):
        """ Return the editor with the specified control.
        """
        for editor in self.editors:
            if editor.control == control:
                return editor
        return None

    # Trait change handlers ------------------------------------------------

    @observe("editors:items:[dirty, name]")
    def _update_label(self, event):
        editor = event.object
        index = self.control.GetPageIndex(editor.control)
        self.control.SetPageText(index, self._get_label(editor))

    @observe("editors:items:tooltip")
    def _update_tooltip(self, event):
        editor = event.object
        self.control.SetPageToolTip(editor.control, editor.tooltip)

    # Signal handlers -----------------------------------------------------#

    def _close_requested(self, evt):
        index = evt.GetSelection()
        logger.debug("_close_requested: index=%d" % index)
        control = self.control.GetPage(index)
        editor = self._get_editor_with_control(control)

        # Veto the event even though we are going to delete the tab, otherwise
        # the notebook will delete the editor wx control and the call to
        # editor.close() will fail.  IEditorAreaPane.remove_editor() needs
        # the control to exist so it can remove it from the list of managed
        # editors.
        evt.Veto()
        editor.close()

    def _update_active_editor(self, evt):
        index = evt.GetSelection()
        logger.debug("index=%d" % index)
        if index == wx.NOT_FOUND:
            self.active_editor = None
        else:
            logger.debug("num pages=%d" % self.control.GetPageCount())
            control = self.control.GetPage(index)
            self.active_editor = self._get_editor_with_control(control)

    @observe("hide_tab_bar")
    def _update_tab_bar(self, event):
        if self.control is not None:
            pass  # Can't actually hide the tab bar on wx.aui