File: buttons_on_canvas.py

package info (click to toggle)
python-enable 4.3.0-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 7,280 kB
  • ctags: 13,899
  • sloc: cpp: 48,447; python: 28,502; ansic: 9,004; makefile: 315; sh: 44
file content (144 lines) | stat: -rw-r--r-- 4,827 bytes parent folder | download | duplicates (2)
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
from __future__ import with_statement

import os.path
import xml.etree.cElementTree as etree

from enable.api import Container, Component, ComponentEditor, BaseTool
from kiva.constants import MODERN
from kiva.fonttools import Font
from traits.api import Instance, Callable, List, Str, HasTraits, Enum
from traitsui.api import View, Item
from enable.savage.svg.document import SVGDocument
from enable.savage.svg.backends.kiva.renderer import Renderer as KivaRenderer


class CanvasButton(Component):
    document = Instance(SVGDocument)
    toggle_document = Instance(SVGDocument)
    label = Str()
    callback = Callable
    callback_args = List(Str)
    state = Enum('up', 'down')

    bounds = [64, 64]

    def __init__(self, filename, callback, callback_args, *args, **kw):
        super(CanvasButton, self).__init__(*args, **kw)

        self.document = self._load_svg_document(filename)

        # set the toggle doc if it wasn't passed in as a keyword arg
        if self.toggle_document is None:
            toggle_filename = os.path.join(os.path.dirname(__file__),
                                           'button_toggle.svg')
            self.toggle_document = self._load_svg_document(toggle_filename)

        self.callback = callback
        self.callback_args = callback_args

    def draw(self, gc, view_bounds, mode):
        if self.state == 'down':
            self._draw_svg_document(gc, self.toggle_document)

        self._draw_svg_document(gc, self.document)

        if len(self.label) > 0:
            self._draw_label(gc)

    def _load_svg_document(self, filename):
        if not os.path.exists(filename):
            raise ValueError
        tree = etree.parse(filename)
        root = tree.getroot()
        return SVGDocument(root, renderer=KivaRenderer)

    def _draw_svg_document(self, gc, document):
        with gc:
            gc.translate_ctm(self.x, self.y+self.height)
            doc_size = document.getSize()
            gc.scale_ctm(self.width/float(doc_size[0]), -self.height/float(doc_size[1]))
            document.render(gc)

    def _draw_label(self, gc):
        with gc:
            font = Font(family=MODERN)
            gc.set_font(font)

            x, y, width, height = gc.get_text_extent(self.label)
            text_x = self.x + (self.width - width)/2.0
            text_y = self.y - height

            gc.show_text(self.label, (text_x, text_y))

    def perform(self):
        self.callback(*self.callback_args)


class ButtonCanvas(Container):
    def draw(self, gc, view_bounds=None, mode="default"):
        for component in self.components:
            component.draw(gc, view_bounds, mode)

    def add_button(self, button):
        button.container = self
        self.components.append(button)

class ButtonSelectionTool(BaseTool):
    """ Listens for double-clicks and tries to open a traits editor on the
        graph node under the mouse.
    """

    def normal_left_down(self, event):
        for component in self.component.components:
            if isinstance(component, CanvasButton) \
                    and component.is_in(event.x, event.y):
                component.state = 'down'
                component.request_redraw()
                component.perform()
                break

    def normal_left_up(self, event):
        for component in self.component.components:
            if isinstance(component, CanvasButton):
                component.state = 'up'
                component.request_redraw()


class ButtonCanvasView(HasTraits):
    canvas = Instance(Container)

    traits_view = View(Item('canvas', editor=ComponentEditor(),
                            show_label=False),
                        width=400,
                        height=400,
                        resizable=True)

    def __init__(self, *args, **kw):
        super(ButtonCanvasView, self).__init__(*args, **kw)
        self.add_buttons()

    def _canvas_default(self):
        """ default setter for _canvas
        """
        container = ButtonCanvas()
        container.tools.append(ButtonSelectionTool(component=container))
        return container

    def add_buttons(self):
        data_dir = os.path.dirname(__file__)
        self.canvas.add_button(CanvasButton(os.path.join(data_dir, 'edit-copy.svg'),
                                            self.do_copy, [],
                                            label="Copy", x=150, y=150,))
        self.canvas.add_button(CanvasButton(os.path.join(data_dir, 'edit-paste.svg'),
                                            self.do_paste, [],
                                            label="Paste", x=250, y=150))

    def do_copy(self):
        print "copying something"

    def do_paste(self):
        print "pasting something"


if __name__ == "__main__":
    ButtonCanvasView().configure_traits()