1#  Copyright (c) 2005-18, Enthought, Inc.
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
6#  under 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#  Author: David C. Morrill
12#  Date:   10/07/2004
13
14"""
15Defines the stub functions used for creating concrete implementations of
16the standard EditorFactory subclasses supplied with the Traits package.
17
18Most of the logic for determining which backend toolkit to use can now be
19found in :py:mod:`pyface.base_toolkit`.
20"""
21
22
23import logging
24
25from traits.trait_base import ETSConfig
26from pyface.base_toolkit import Toolkit, find_toolkit
27
28
29logger = logging.getLogger(__name__)
30
31not_implemented_message = "the '{}' toolkit does not implement this method"
32
33#: The current GUI toolkit object being used:
34_toolkit = None
35
36
37def assert_toolkit_import(names):
38    """ Raise an error if a toolkit with the given name should not be allowed
39    to be imported.
40    """
41    if ETSConfig.toolkit and ETSConfig.toolkit not in names:
42        raise RuntimeError(
43            "Importing from %s backend after selecting %s "
44            "backend!" % (names[0], ETSConfig.toolkit)
45        )
46
47
48def toolkit_object(name, raise_exceptions=False):
49    """ Return the toolkit specific object with the given name.
50
51    Parameters
52    ----------
53    name : str
54        The relative module path and the object name separated by a colon.
55    raise_exceptions : bool
56        Whether or not to raise an exception if the name cannot be imported.
57
58    Raises
59    ------
60    TraitError
61        If no working toolkit is found.
62    RuntimeError
63        If no ETSConfig.toolkit is set but the toolkit cannot be loaded for
64        some reason.  This is also raised if raise_exceptions is True the
65        backend does not implement the desired object.
66    """
67    global _toolkit
68
69    if _toolkit is None:
70        toolkit()
71    obj = _toolkit(name)
72
73    if raise_exceptions and obj.__name__ == "Unimplemented":
74        raise RuntimeError(
75            "Can't import {} for backend {}".format(
76                repr(name), _toolkit.toolkit
77            )
78        )
79
80    return obj
81
82
83def toolkit(*toolkits):
84    """ Selects and returns a low-level GUI toolkit.
85
86    Use this function to get a reference to the current toolkit.
87
88    Parameters
89    ----------
90    *toolkits : strings
91        Toolkit names to try if toolkit not already selected.  If not supplied,
92        will try all ``traitsui.toolkits`` entry points until a match is found.
93
94    Returns
95    -------
96    toolkit
97        Appropriate concrete Toolkit subclass for selected toolkit.
98
99    Raises
100    ------
101    TraitError
102        If no working toolkit is found.
103    RuntimeError
104        If no ETSConfig.toolkit is set but the toolkit cannot be loaded for
105        some reason.
106    """
107    global _toolkit
108
109    if _toolkit is None:
110        if len(toolkits) > 0:
111            _toolkit = find_toolkit("traitsui.toolkits", toolkits)
112        else:
113            _toolkit = find_toolkit("traitsui.toolkits")
114    return _toolkit
115
116
117class Toolkit(Toolkit):
118    """ Abstract base class for GUI toolkits.
119    """
120
121    def ui_panel(self, ui, parent):
122        """ Creates a GUI-toolkit-specific panel-based user interface using
123            information from the specified UI object.
124        """
125        raise NotImplementedError(
126            not_implemented_message.format(ETSConfig.toolkit)
127        )
128
129    def ui_subpanel(self, ui, parent):
130        """ Creates a GUI-toolkit-specific subpanel-based user interface using
131            information from the specified UI object.
132        """
133        raise NotImplementedError(
134            not_implemented_message.format(ETSConfig.toolkit)
135        )
136
137    def ui_livemodal(self, ui, parent):
138        """ Creates a GUI-toolkit-specific modal "live update" dialog user
139            interface using information from the specified UI object.
140        """
141        raise NotImplementedError(
142            not_implemented_message.format(ETSConfig.toolkit)
143        )
144
145    def ui_live(self, ui, parent):
146        """ Creates a GUI-toolkit-specific non-modal "live update" window user
147            interface using information from the specified UI object.
148        """
149        raise NotImplementedError(
150            not_implemented_message.format(ETSConfig.toolkit)
151        )
152
153    def ui_modal(self, ui, parent):
154        """ Creates a GUI-toolkit-specific modal dialog user interface using
155            information from the specified UI object.
156        """
157        raise NotImplementedError(
158            not_implemented_message.format(ETSConfig.toolkit)
159        )
160
161    def ui_nonmodal(self, ui, parent):
162        """ Creates a GUI-toolkit-specific non-modal dialog user interface using
163            information from the specified UI object.
164        """
165        raise NotImplementedError(
166            not_implemented_message.format(ETSConfig.toolkit)
167        )
168
169    def ui_popup(self, ui, parent):
170        """ Creates a GUI-toolkit-specific temporary "live update" popup dialog
171            user interface using information from the specified UI object.
172        """
173        raise NotImplementedError(
174            not_implemented_message.format(ETSConfig.toolkit)
175        )
176
177    def ui_popover(self, ui, parent):
178        """ Creates a GUI-toolkit-specific temporary "live update" popup dialog
179            user interface using information from the specified UI object.
180        """
181        raise NotImplementedError(
182            not_implemented_message.format(ETSConfig.toolkit)
183        )
184
185    def ui_info(self, ui, parent):
186        """ Creates a GUI-toolkit-specific temporary "live update" popup dialog
187            user interface using information from the specified UI object.
188        """
189        raise NotImplementedError(
190            not_implemented_message.format(ETSConfig.toolkit)
191        )
192
193    def ui_wizard(self, ui, parent):
194        """ Creates a GUI-toolkit-specific wizard dialog user interface using
195            information from the specified UI object.
196        """
197        raise NotImplementedError(
198            not_implemented_message.format(ETSConfig.toolkit)
199        )
200
201    def view_application(
202        self,
203        context,
204        view,
205        kind=None,
206        handler=None,
207        id="",
208        scrollable=None,
209        args=None,
210    ):
211        """ Creates a GUI-toolkit-specific modal dialog user interface that
212            runs as a complete application using information from the
213            specified View object.
214
215        Parameters
216        ----------
217        context : object or dictionary
218            A single object or a dictionary of string/object pairs, whose trait
219            attributes are to be edited. If not specified, the current object
220            is used.
221        view : view or string
222            A View object that defines a user interface for editing trait
223            attribute values.
224        kind : string
225            The type of user interface window to create. See the
226            **traitsui.view.kind_trait** trait for values and
227            their meanings. If *kind* is unspecified or None, the **kind**
228            attribute of the View object is used.
229        handler : Handler object
230            A handler object used for event handling in the dialog box. If
231            None, the default handler for Traits UI is used.
232        id : string
233            A unique ID for persisting preferences about this user interface,
234            such as size and position. If not specified, no user preferences
235            are saved.
236        scrollable : Boolean
237            Indicates whether the dialog box should be scrollable. When set to
238            True, scroll bars appear on the dialog box if it is not large
239            enough to display all of the items in the view at one time.
240
241        """
242        raise NotImplementedError(
243            not_implemented_message.format(ETSConfig.toolkit)
244        )
245
246    def position(self, ui):
247        """ Positions the associated dialog window on the display.
248        """
249        raise NotImplementedError(
250            not_implemented_message.format(ETSConfig.toolkit)
251        )
252
253    def show_help(self, ui, control):
254        """ Shows a Help window for a specified UI and control.
255        """
256        raise NotImplementedError(
257            not_implemented_message.format(ETSConfig.toolkit)
258        )
259
260    def set_title(self, ui):
261        """ Sets the title for the UI window.
262        """
263        raise NotImplementedError(
264            not_implemented_message.format(ETSConfig.toolkit)
265        )
266
267    def set_icon(self, ui):
268        """ Sets the icon for the UI window.
269        """
270        raise NotImplementedError(
271            not_implemented_message.format(ETSConfig.toolkit)
272        )
273
274    def save_window(self, ui):
275        """ Saves user preference information associated with a UI window.
276        """
277        raise NotImplementedError(
278            not_implemented_message.format(ETSConfig.toolkit)
279        )
280
281    def rebuild_ui(self, ui):
282        """ Rebuilds a UI after a change to the content of the UI.
283        """
284        raise NotImplementedError(
285            not_implemented_message.format(ETSConfig.toolkit)
286        )
287
288    def key_event_to_name(self, event):
289        """ Converts a keystroke event into a corresponding key name.
290        """
291        raise NotImplementedError(
292            not_implemented_message.format(ETSConfig.toolkit)
293        )
294
295    def hook_events(self, ui, control, events=None, handler=None):
296        """ Hooks all specified events for all controls in a UI so that they
297            can be routed to the correct event handler.
298        """
299        raise NotImplementedError(
300            not_implemented_message.format(ETSConfig.toolkit)
301        )
302
303    def route_event(self, ui, event):
304        """ Routes a "hooked" event to the corrent handler method.
305        """
306        raise NotImplementedError(
307            not_implemented_message.format(ETSConfig.toolkit)
308        )
309
310    def skip_event(self, event):
311        """ Indicates that an event should continue to be processed by the
312            toolkit.
313        """
314        raise NotImplementedError(
315            not_implemented_message.format(ETSConfig.toolkit)
316        )
317
318    def destroy_control(self, control):
319        """ Destroys a specified GUI toolkit control.
320        """
321        raise NotImplementedError(
322            not_implemented_message.format(ETSConfig.toolkit)
323        )
324
325    def destroy_children(self, control):
326        """ Destroys all of the child controls of a specified GUI toolkit
327            control.
328        """
329        raise NotImplementedError(
330            not_implemented_message.format(ETSConfig.toolkit)
331        )
332
333    def image_size(self, image):
334        """ Returns a ( width, height ) tuple containing the size of a
335            specified toolkit image.
336        """
337        raise NotImplementedError(
338            not_implemented_message.format(ETSConfig.toolkit)
339        )
340
341    def constants(self):
342        """ Returns a dictionary of useful constants.
343
344            Currently, the dictionary should have the following key/value
345            pairs:
346
347            - WindowColor': the standard window background color in the toolkit
348              specific color format.
349        """
350        raise NotImplementedError(
351            not_implemented_message.format(ETSConfig.toolkit)
352        )
353
354    # -------------------------------------------------------------------------
355    #  GUI toolkit dependent trait definitions:
356    # -------------------------------------------------------------------------
357
358    def color_trait(self, *args, **traits):
359        raise NotImplementedError(
360            not_implemented_message.format(ETSConfig.toolkit)
361        )
362
363    def rgb_color_trait(self, *args, **traits):
364        raise NotImplementedError(
365            not_implemented_message.format(ETSConfig.toolkit)
366        )
367
368    def rgba_color_trait(self, *args, **traits):
369        raise NotImplementedError(
370            not_implemented_message.format(ETSConfig.toolkit)
371        )
372
373    def font_trait(self, *args, **traits):
374        raise NotImplementedError(
375            not_implemented_message.format(ETSConfig.toolkit)
376        )
377
378    def kiva_font_trait(self, *args, **traits):
379        raise NotImplementedError(
380            not_implemented_message.format(ETSConfig.toolkit)
381        )
382
383    # -------------------------------------------------------------------------
384    #  'Editor' class methods:
385    # -------------------------------------------------------------------------
386
387    def ui_editor(self):
388        raise NotImplementedError(
389            not_implemented_message.format(ETSConfig.toolkit)
390        )
391
392    # -------------------------------------------------------------------------
393    #  'EditorFactory' factory methods:
394    # -------------------------------------------------------------------------
395
396    def array_editor(self, *args, **traits):
397        raise NotImplementedError(
398            not_implemented_message.format(ETSConfig.toolkit)
399        )
400
401    def boolean_editor(self, *args, **traits):
402        raise NotImplementedError(
403            not_implemented_message.format(ETSConfig.toolkit)
404        )
405
406    def button_editor(self, *args, **traits):
407        raise NotImplementedError(
408            not_implemented_message.format(ETSConfig.toolkit)
409        )
410
411    def check_list_editor(self, *args, **traits):
412        raise NotImplementedError(
413            not_implemented_message.format(ETSConfig.toolkit)
414        )
415
416    def code_editor(self, *args, **traits):
417        raise NotImplementedError(
418            not_implemented_message.format(ETSConfig.toolkit)
419        )
420
421    def color_editor(self, *args, **traits):
422        raise NotImplementedError(
423            not_implemented_message.format(ETSConfig.toolkit)
424        )
425
426    def compound_editor(self, *args, **traits):
427        raise NotImplementedError(
428            not_implemented_message.format(ETSConfig.toolkit)
429        )
430
431    def custom_editor(self, *args, **traits):
432        raise NotImplementedError(
433            not_implemented_message.format(ETSConfig.toolkit)
434        )
435
436    def directory_editor(self, *args, **traits):
437        raise NotImplementedError(
438            not_implemented_message.format(ETSConfig.toolkit)
439        )
440
441    def drop_editor(self, *args, **traits):
442        raise NotImplementedError(
443            not_implemented_message.format(ETSConfig.toolkit)
444        )
445
446    def dnd_editor(self, *args, **traits):
447        raise NotImplementedError(
448            not_implemented_message.format(ETSConfig.toolkit)
449        )
450
451    def enum_editor(self, *args, **traits):
452        raise NotImplementedError(
453            not_implemented_message.format(ETSConfig.toolkit)
454        )
455
456    def file_editor(self, *args, **traits):
457        raise NotImplementedError(
458            not_implemented_message.format(ETSConfig.toolkit)
459        )
460
461    def font_editor(self, *args, **traits):
462        raise NotImplementedError(
463            not_implemented_message.format(ETSConfig.toolkit)
464        )
465
466    def key_binding_editor(self, *args, **traits):
467        raise NotImplementedError(
468            not_implemented_message.format(ETSConfig.toolkit)
469        )
470
471    def history_editor(self, *args, **traits):
472        raise NotImplementedError(
473            not_implemented_message.format(ETSConfig.toolkit)
474        )
475
476    def html_editor(self, *args, **traits):
477        raise NotImplementedError(
478            not_implemented_message.format(ETSConfig.toolkit)
479        )
480
481    def image_editor(self, *args, **traits):
482        raise NotImplementedError(
483            not_implemented_message.format(ETSConfig.toolkit)
484        )
485
486    def image_enum_editor(self, *args, **traits):
487        raise NotImplementedError(
488            not_implemented_message.format(ETSConfig.toolkit)
489        )
490
491    def instance_editor(self, *args, **traits):
492        raise NotImplementedError(
493            not_implemented_message.format(ETSConfig.toolkit)
494        )
495
496    def list_editor(self, *args, **traits):
497        raise NotImplementedError(
498            not_implemented_message.format(ETSConfig.toolkit)
499        )
500
501    def list_str_editor(self, *args, **traits):
502        raise NotImplementedError(
503            not_implemented_message.format(ETSConfig.toolkit)
504        )
505
506    def null_editor(self, *args, **traits):
507        raise NotImplementedError(
508            not_implemented_message.format(ETSConfig.toolkit)
509        )
510
511    def ordered_set_editor(self, *args, **traits):
512        raise NotImplementedError(
513            not_implemented_message.format(ETSConfig.toolkit)
514        )
515
516    def plot_editor(self, *args, **traits):
517        raise NotImplementedError(
518            not_implemented_message.format(ETSConfig.toolkit)
519        )
520
521    def range_editor(self, *args, **traits):
522        raise NotImplementedError(
523            not_implemented_message.format(ETSConfig.toolkit)
524        )
525
526    def rgb_color_editor(self, *args, **traits):
527        raise NotImplementedError(
528            not_implemented_message.format(ETSConfig.toolkit)
529        )
530
531    def rgba_color_editor(self, *args, **traits):
532        raise NotImplementedError(
533            not_implemented_message.format(ETSConfig.toolkit)
534        )
535
536    def shell_editor(self, *args, **traits):
537        raise NotImplementedError(
538            not_implemented_message.format(ETSConfig.toolkit)
539        )
540
541    def table_editor(self, *args, **traits):
542        raise NotImplementedError(
543            not_implemented_message.format(ETSConfig.toolkit)
544        )
545
546    def tabular_editor(self, *args, **traits):
547        raise NotImplementedError(
548            not_implemented_message.format(ETSConfig.toolkit)
549        )
550
551    def text_editor(self, *args, **traits):
552        raise NotImplementedError(
553            not_implemented_message.format(ETSConfig.toolkit)
554        )
555
556    def title_editor(self, *args, **traits):
557        raise NotImplementedError(
558            not_implemented_message.format(ETSConfig.toolkit)
559        )
560
561    def tree_editor(self, *args, **traits):
562        raise NotImplementedError(
563            not_implemented_message.format(ETSConfig.toolkit)
564        )
565
566    def tuple_editor(self, *args, **traits):
567        raise NotImplementedError(
568            not_implemented_message.format(ETSConfig.toolkit)
569        )
570
571    def value_editor(self, *args, **traits):
572        raise NotImplementedError(
573            not_implemented_message.format(ETSConfig.toolkit)
574        )
575