1# (C) Copyright 2005-2020 Enthought, Inc., Austin, TX
2# All rights reserved.
3#
4# This software is provided without warranty under the terms of the BSD
5# license included in LICENSE.txt and may be redistributed only under
6# the conditions described in the aforementioned license. The license
7# is also available online at http://www.enthought.com/licenses/BSD.txt
8#
9# Thanks for using Enthought open source!
10
11""" The workbench window layout interface. """
12
13
14from traits.api import Event, HasTraits, Instance, Interface, Str
15from traits.api import provides
16
17
18from .i_editor import IEditor
19from .i_view import IView
20
21
22class IWorkbenchWindowLayout(Interface):
23    """ The workbench window layout interface.
24
25    Window layouts are responsible for creating and managing the internal
26    structure of a workbench window (it knows how to add and remove views and
27    editors etc).
28
29    """
30
31    # The Id of the editor area.
32    # FIXME v3: This is toolkit specific.
33    editor_area_id = Str()
34
35    # The workbench window that this is the layout for.
36    window = Instance("pyface.workbench.api.WorkbenchWindow")
37
38    # Events ----
39
40    # Fired when an editor is about to be opened (or restored).
41    editor_opening = Event(IEditor)
42
43    # Fired when an editor has been opened (or restored).
44    editor_opened = Event(IEditor)
45
46    # Fired when an editor is about to be closed.
47    editor_closing = Event(IEditor)
48
49    # Fired when an editor has been closed.
50    editor_closed = Event(IEditor)
51
52    # Fired when a view is about to be opened (or restored).
53    view_opening = Event(IView)
54
55    # Fired when a view has been opened (or restored).
56    view_opened = Event(IView)
57
58    # Fired when a view is about to be closed (*not* hidden!).
59    view_closing = Event(IView)
60
61    # Fired when a view has been closed (*not* hidden!).
62    view_closed = Event(IView)
63
64    # FIXME v3: The "just for convenience" returns are a really bad idea.
65    #
66    # Why? They allow the call to be used on the LHS of an expression...
67    # Because they have nothing to do with what the call is supposed to be
68    # doing, they are unlikely to be used (because they are so unexpected and
69    # inconsistently implemented), and only serve to replace two shorter lines
70    # of code with one long one, arguably making code more difficult to read.
71    def activate_editor(self, editor):
72        """ Activate an editor.
73
74        Returns the editor (just for convenience).
75
76        """
77
78    def activate_view(self, view):
79        """ Activate a view.
80
81        Returns the view (just for convenience).
82
83        """
84
85    def add_editor(self, editor, title):
86        """ Add an editor.
87
88        Returns the editor (just for convenience).
89
90        """
91
92    def add_view(self, view, position=None, relative_to=None, size=(-1, -1)):
93        """ Add a view.
94
95        Returns the view (just for convenience).
96
97        """
98
99    def close_editor(self, editor):
100        """ Close an editor.
101
102        Returns the editor (just for convenience).
103
104        """
105
106    def close_view(self, view):
107        """ Close a view.
108
109        FIXME v3: Currently views are never 'closed' in the same sense as an
110        editor is closed. When we close an editor, we destroy its control.
111        When we close a view, we merely hide its control. I'm not sure if this
112        is a good idea or not. It came about after discussion with Dave P. and
113        he mentioned that some views might find it hard to persist enough state
114        that they can be re-created exactly as they were when they are shown
115        again.
116
117        Returns the view (just for convenience).
118
119        """
120
121    def close(self):
122        """ Close the entire window layout.
123
124        FIXME v3: Should this be called 'destroy'?
125
126        """
127
128    def create_initial_layout(self, parent):
129        """ Create the initial window layout.
130
131        Returns the layout.
132
133        """
134
135    def contains_view(self, view):
136        """ Return True if the view exists in the window layout.
137
138        Note that this returns True even if the view is hidden.
139
140        """
141
142    def hide_editor_area(self):
143        """ Hide the editor area.
144
145        """
146
147    def hide_view(self, view):
148        """ Hide a view.
149
150        Returns the view (just for convenience).
151
152        """
153
154    def refresh(self):
155        """ Refresh the window layout to reflect any changes.
156
157        """
158
159    def reset_editors(self):
160        """ Activate the first editor in every group.
161
162        """
163
164    def reset_views(self):
165        """ Activate the first view in every region.
166
167        """
168
169    def show_editor_area(self):
170        """ Show the editor area.
171
172        """
173
174    def show_view(self, view):
175        """ Show a view.
176
177        """
178
179    # Methods for saving and restoring the layout -------------------------#
180
181    def get_view_memento(self):
182        """ Returns the state of the views.
183
184        """
185
186    def set_view_memento(self, memento):
187        """ Restores the state of the views.
188
189        """
190
191    def get_editor_memento(self):
192        """ Returns the state of the editors.
193
194        """
195
196    def set_editor_memento(self, memento):
197        """ Restores the state of the editors.
198
199        """
200
201    def get_toolkit_memento(self):
202        """ Return any toolkit-specific data that should be part of the memento.
203        """
204
205    def set_toolkit_memento(self, memento):
206        """ Restores any toolkit-specific data.
207        """
208
209
210@provides(IWorkbenchWindowLayout)
211class MWorkbenchWindowLayout(HasTraits):
212    """ Mixin containing common code for toolkit-specific implementations. """
213
214    # 'IWorkbenchWindowLayout' interface -----------------------------------
215
216    # The Id of the editor area.
217    # FIXME v3: This is toolkit specific.
218    editor_area_id = Str()
219
220    # The workbench window that this is the layout for.
221    window = Instance("pyface.workbench.api.WorkbenchWindow")
222
223    # Events ----
224
225    # Fired when an editor is about to be opened (or restored).
226    editor_opening = Event(IEditor)
227
228    # Fired when an editor has been opened (or restored).
229    editor_opened = Event(IEditor)
230
231    # Fired when an editor is about to be closed.
232    editor_closing = Event(IEditor)
233
234    # Fired when an editor has been closed.
235    editor_closed = Event(IEditor)
236
237    # Fired when a view is about to be opened (or restored).
238    view_opening = Event(IView)
239
240    # Fired when a view has been opened (or restored).
241    view_opened = Event(IView)
242
243    # Fired when a view is about to be closed (*not* hidden!).
244    view_closing = Event(IView)
245
246    # Fired when a view has been closed (*not* hidden!).
247    view_closed = Event(IView)
248
249    # ------------------------------------------------------------------------
250    # 'IWorkbenchWindowLayout' interface.
251    # ------------------------------------------------------------------------
252
253    def activate_editor(self, editor):
254        """ Activate an editor. """
255
256        raise NotImplementedError()
257
258    def activate_view(self, view):
259        """ Activate a view. """
260
261        raise NotImplementedError()
262
263    def add_editor(self, editor, title):
264        """ Add an editor. """
265
266        raise NotImplementedError()
267
268    def add_view(self, view, position=None, relative_to=None, size=(-1, -1)):
269        """ Add a view. """
270
271        raise NotImplementedError()
272
273    def close_editor(self, editor):
274        """ Close an editor. """
275
276        raise NotImplementedError()
277
278    def close_view(self, view):
279        """ Close a view. """
280
281        raise NotImplementedError()
282
283    def close(self):
284        """ Close the entire window layout. """
285
286        raise NotImplementedError()
287
288    def create_initial_layout(self, parent):
289        """ Create the initial window layout. """
290
291        raise NotImplementedError()
292
293    def contains_view(self, view):
294        """ Return True if the view exists in the window layout. """
295
296        raise NotImplementedError()
297
298    def hide_editor_area(self):
299        """ Hide the editor area. """
300
301        raise NotImplementedError()
302
303    def hide_view(self, view):
304        """ Hide a view. """
305
306        raise NotImplementedError()
307
308    def refresh(self):
309        """ Refresh the window layout to reflect any changes. """
310
311        raise NotImplementedError()
312
313    def reset_editors(self):
314        """ Activate the first editor in every group. """
315
316        raise NotImplementedError()
317
318    def reset_views(self):
319        """ Activate the first view in every region. """
320
321        raise NotImplementedError()
322
323    def show_editor_area(self):
324        """ Show the editor area. """
325
326        raise NotImplementedError()
327
328    def show_view(self, view):
329        """ Show a view. """
330
331        raise NotImplementedError()
332
333    # Methods for saving and restoring the layout -------------------------#
334
335    def get_view_memento(self):
336        """ Returns the state of the views. """
337
338        raise NotImplementedError()
339
340    def set_view_memento(self, memento):
341        """ Restores the state of the views. """
342
343        raise NotImplementedError()
344
345    def get_editor_memento(self):
346        """ Returns the state of the editors. """
347
348        raise NotImplementedError()
349
350    def set_editor_memento(self, memento):
351        """ Restores the state of the editors. """
352
353        raise NotImplementedError()
354
355    def get_toolkit_memento(self):
356        """ Return any toolkit-specific data that should be part of the memento.
357        """
358        return None
359
360    def set_toolkit_memento(self, memento):
361        """ Restores any toolkit-specific data.
362        """
363        return
364
365    # ------------------------------------------------------------------------
366    # Protected 'MWorkbenchWindowLayout' interface.
367    # ------------------------------------------------------------------------
368
369    def _get_editor_references(self):
370        """ Returns a reference to every editor. """
371
372        editor_manager = self.window.editor_manager
373
374        editor_references = {}
375        for editor in self.window.editors:
376            # Create the editor reference.
377            #
378            # If the editor manager returns 'None' instead of a resource
379            # reference then this editor will not appear the next time the
380            # workbench starts up. This is useful for things like text files
381            # that have an editor but have NEVER been saved.
382            editor_reference = editor_manager.get_editor_memento(editor)
383            if editor_reference is not None:
384                editor_references[editor.id] = editor_reference
385
386        return editor_references
387