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
|
"""
Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
GNU Radio Companion is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
import pygtk
pygtk.require('2.0')
import gtk
from Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT, DND_TARGETS
class DrawingArea(gtk.DrawingArea):
"""
DrawingArea is the gtk pixel map that graphical elements may draw themselves on.
The drawing area also responds to mouse and key events.
"""
def __init__(self, main_window):
"""
DrawingArea contructor.
Connect event handlers.
@param main_window the main_window containing all flow graphs
"""
self.ctrl_mask = False
self._main_window = main_window
#inject drawing area into main_window
self._main_window.drawing_area = self
gtk.DrawingArea.__init__(self)
self.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT)
self.connect('configure-event', self._handle_window_configure)
self.connect('expose-event', self._handle_window_expose)
self.connect('motion-notify-event', self._handle_mouse_motion)
self.connect('button-press-event', self._handle_mouse_button_press)
self.connect('button-release-event', self._handle_mouse_button_release)
self.add_events(
gtk.gdk.BUTTON_PRESS_MASK | \
gtk.gdk.POINTER_MOTION_MASK | \
gtk.gdk.BUTTON_RELEASE_MASK | \
gtk.gdk.LEAVE_NOTIFY_MASK | \
gtk.gdk.ENTER_NOTIFY_MASK
)
#setup drag and drop
self.drag_dest_set(gtk.DEST_DEFAULT_ALL, DND_TARGETS, gtk.gdk.ACTION_COPY)
self.connect('drag-data-received', self._handle_drag_data_received)
#setup the focus flag
self._focus_flag = False
self.get_focus_flag = lambda: self._focus_flag
self.connect('leave-notify-event', self._handle_focus_event, False)
self.connect('enter-notify-event', self._handle_focus_event, True)
##########################################################################
## Handlers
##########################################################################
def _handle_drag_data_received(self, widget, drag_context, x, y, selection_data, info, time):
"""
Handle a drag and drop by adding a block at the given coordinate.
"""
self._main_window.get_flow_graph().add_new_block(selection_data.data, (x, y))
def _handle_focus_event(self, widget, event, focus_flag):
"""Record the focus state of the flow graph window."""
self._focus_flag = focus_flag
def _handle_mouse_button_press(self, widget, event):
"""
Forward button click information to the flow graph.
"""
self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK
self._main_window.get_flow_graph().handle_mouse_button_press(
left_click=(event.button == 1),
double_click=(event.type == gtk.gdk._2BUTTON_PRESS),
coordinate=(event.x, event.y),
)
def _handle_mouse_button_release(self, widget, event):
"""
Forward button release information to the flow graph.
"""
self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK
self._main_window.get_flow_graph().handle_mouse_button_release(
left_click=(event.button == 1),
coordinate=(event.x, event.y),
)
def _handle_mouse_motion(self, widget, event):
"""
Forward mouse motion information to the flow graph.
"""
self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK
self._main_window.get_flow_graph().handle_mouse_motion(
coordinate=(event.x, event.y),
)
def _handle_window_configure(self, widget, event):
"""
Called when the window is resized.
Create a new pixmap for background buffer.
"""
width, height = self.get_size_request()
self.pixmap = gtk.gdk.Pixmap(self.window, width, height, -1)
def _handle_window_expose(self, widget, event):
"""
Called when window is exposed, or queue_draw is called.
Double buffering: draw to pixmap, then draw pixmap to window.
"""
gc = self.window.new_gc()
self._main_window.get_flow_graph().draw(gc, self.pixmap)
self.window.draw_drawable(gc, self.pixmap, 0, 0, 0, 0, -1, -1)
|