/
ca_graph.py
144 lines (109 loc) · 4.97 KB
/
ca_graph.py
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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This program 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 3 of the License, or
# (at your option) any later version.
#
# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Copyright (C) 2011 Yaacov Zamir <kobi.zamir@gmail.com>
# Author: Yaacov Zamir (2011) <kobi.zamir@gmail.com>
from gi.repository import Gtk, Gdk
from ca_graph_file import CaGraphFile, CaGraphStyle
class CaGraph(Gtk.DrawingArea, CaGraphFile):
''' Gtk3 cairo charting class '''
def __init__(self):
''' init event handlers and default parameters '''
Gtk.DrawingArea.__init__(self)
CaGraphFile.__init__(self)
self.pan = False
self.pointer_x = 0
self.pointer_y = 0
# events
self.connect("draw", self.draw)
self.connect("motion_notify_event", self.motion_notify)
self.connect("scroll_event", self.scroll)
self.connect("leave_notify_event", self.button_release)
self.connect("button_press_event", self.button_press)
self.connect("button_release_event", self.button_release)
self.set_events(Gdk.EventMask.EXPOSURE_MASK
| Gdk.EventMask.LEAVE_NOTIFY_MASK
| Gdk.EventMask.SCROLL_MASK
| Gdk.EventMask.BUTTON_PRESS_MASK
| Gdk.EventMask.BUTTON_RELEASE_MASK
| Gdk.EventMask.POINTER_MOTION_MASK
| Gdk.EventMask.POINTER_MOTION_HINT_MASK)
def button_press(self, widget, event):
# if this is double click auto set ranges
if event.type == Gdk.EventType._2BUTTON_PRESS:
self.auto_set_range()
self.redraw()
return
self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.HAND1))
self.pointer_x = event.x
self.pointer_y = event.y
self.pan = True
def button_release(self, widget, event):
self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.ARROW))
self.pan = False
def motion_notify(self, widget, event):
style = self.graph_style
if self.pan:
for axis in self.axiss:
#if axis.axis_style.side in ['bottom', 'top']:
if axis.type == 'xaxis':
diff = (axis.px_to_data(self.pointer_x) - \
axis.px_to_data(event.x))
else:
diff = (axis.px_to_data(self.pointer_y) - \
axis.px_to_data(event.y))
axis.min = axis.min + diff
axis.max = axis.max + diff
self.pointer_x = event.x
self.pointer_y = event.y
if self.pan or \
style.draw_pointer or style.draw_pointer_y:
self.redraw()
return False
def scroll(self, widget, event):
for axis in self.axiss:
diff = (axis.max - axis.min) / 10.0
if event.direction == Gdk.ScrollDirection.DOWN:
diff *= -1
axis.min = axis.min - diff
axis.max = axis.max + diff
self.redraw()
def draw(self, widget, cr):
''' handle widget draw event '''
# get widgetcontext
self.context = cr
rect = self.get_allocation()
# get width and height
self.graph_style.width = rect.width
self.graph_style.height = rect.height
self.draw_graph()
self.context.set_line_width(self.graph_style.pointer_width)
self.context.set_source_rgba(*self.graph_style.pointer_color)
# draw pointer line
if self.graph_style.draw_pointer:
if self.check_xy(self.pointer_x, self.pointer_y):
self.context.move_to(self.pointer_x, self.graph_style.margin)
self.context.line_to(self.pointer_x, rect.height - self.graph_style.margin)
self.context.stroke()
# draw horizontal pointer line
if self.graph_style.draw_pointer_y:
if self.check_xy(self.pointer_x, self.pointer_y):
self.context.move_to(self.graph_style.margin, self.pointer_y)
self.context.line_to(rect.width - self.graph_style.margin, self.pointer_y)
self.context.stroke()
return False
def redraw(self):
''' invalidate widget window '''
self.queue_draw()