Merged Rolf Schmidt's illysam branch
[hooke.git] / hooke / ui / gui / panels / plot.py
1 #!/usr/bin/env python\r
2 \r
3 '''\r
4 plot.py\r
5 \r
6 Plot panel for Hooke.\r
7 \r
8 Copyright 2009 by Dr. Rolf Schmidt (Concordia University, Canada)\r
9 \r
10 This program is released under the GNU General Public License version 2.\r
11 '''\r
12 \r
13 from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas\r
14 \r
15 from matplotlib.backends.backend_wx import NavigationToolbar2Wx\r
16 \r
17 from matplotlib.figure import Figure\r
18 \r
19 import wx\r
20 \r
21 #there are many comments in here from the demo app\r
22 #they should come in handy to expand the functionality in the future\r
23 \r
24 class HookeCustomToolbar(NavigationToolbar2Wx):\r
25 \r
26     def __init__(self, plotCanvas):\r
27         NavigationToolbar2Wx.__init__(self, plotCanvas)\r
28         # add new toolbar buttons\r
29         #glyph_file = 'resources' + os.sep + 'pipette.png'\r
30         #glyph = wx.Image(glyph_file, wx.BITMAP_TYPE_ANY).ConvertToBitmap()\r
31 \r
32         #self.AddCheckTool(ON_CUSTOM_PICK, glyph, shortHelp='Select a data point', longHelp='Select a data point')\r
33         #wx.EVT_TOOL(self, ON_CUSTOM_PICK, self.OnSelectPoint)\r
34 \r
35         # remove the unwanted button\r
36 #        POSITION_OF_CONFIGURE_SUBPLOTS_BTN = 6\r
37 #        self.DeleteToolByPos(POSITION_OF_CONFIGURE_SUBPLOTS_BTN)\r
38 \r
39     #def OnSelectPoint(self, event):\r
40         #self.Parent.Parent.Parent.pick_active = True\r
41 \r
42 \r
43 #class LineBuilder:\r
44     #def __init__(self, line):\r
45         #self.line = line\r
46         #self.xs = list(line.get_xdata())\r
47         #self.ys = list(line.get_ydata())\r
48         #self.cid = line.figure.canvas.mpl_connect('button_press_event', self)\r
49 \r
50     #def __call__(self, event):\r
51         #print 'click', event\r
52         #if event.inaxes != self.line.axes:\r
53             #return\r
54         #self.xs.append(event.xdata)\r
55         #self.ys.append(event.ydata)\r
56         #self.line.set_data(self.xs, self.ys)\r
57         #self.line.figure.canvas.draw()\r
58 \r
59 \r
60 class PlotPanel(wx.Panel):\r
61 \r
62     def __init__(self, parent, ID):\r
63         wx.Panel.__init__(self, parent, ID, style=wx.WANTS_CHARS|wx.NO_BORDER, size=(160, 200))\r
64 \r
65         self.figure = Figure()\r
66         self.canvas = FigureCanvas(self, -1, self.figure)\r
67         self.SetColor(wx.NamedColor('WHITE'))\r
68 \r
69         self.sizer = wx.BoxSizer(wx.VERTICAL)\r
70         self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)\r
71         self.SetSizer(self.sizer)\r
72         self.Fit()\r
73 \r
74         self.display_coordinates = False\r
75 \r
76         self.figure.canvas.mpl_connect('button_press_event', self.OnClick)\r
77         self.figure.canvas.mpl_connect('axes_enter_event', self.OnEnterAxes)\r
78         self.figure.canvas.mpl_connect('axes_leave_event', self.OnLeaveAxes)\r
79         self.figure.canvas.mpl_connect('motion_notify_event', self.OnMouseMove)\r
80         self.add_toolbar()  # comment this out for no toolbar\r
81 \r
82     def add_toolbar(self):\r
83         self.toolbar = HookeCustomToolbar(self.canvas)\r
84         self.toolbar.Realize()\r
85         if wx.Platform == '__WXMAC__':\r
86             # Mac platform (OSX 10.3, MacPython) does not seem to cope with\r
87             # having a toolbar in a sizer. This work-around gets the buttons\r
88             # back, but at the expense of having the toolbar at the top\r
89             self.SetToolBar(self.toolbar)\r
90         else:\r
91             # On Windows platform, default window size is incorrect, so set\r
92             # toolbar width to figure width.\r
93             tw, th = self.toolbar.GetSizeTuple()\r
94             fw, fh = self.canvas.GetSizeTuple()\r
95             # By adding toolbar in sizer, we are able to put it at the bottom\r
96             # of the frame - so appearance is closer to GTK version.\r
97             # As noted above, doesn't work for Mac.\r
98             self.toolbar.SetSize(wx.Size(fw, th))\r
99             self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)\r
100         # update the axes menu on the toolbar\r
101         self.toolbar.update()\r
102 \r
103     def get_figure(self):\r
104         return self.figure\r
105 \r
106     def SetColor(self, rgbtuple):\r
107         '''\r
108         Set figure and canvas colours to be the same\r
109         '''\r
110         if not rgbtuple:\r
111             rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get()\r
112         col = [c / 255.0 for c in rgbtuple]\r
113         self.figure.set_facecolor(col)\r
114         self.figure.set_edgecolor(col)\r
115         self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple))\r
116 \r
117     def SetStatusText(self, text, field=1):\r
118         self.Parent.Parent.statusbar.SetStatusText(text, field)\r
119 \r
120     def OnClick(self, event):\r
121         #self.SetStatusText(str(event.xdata))\r
122         #print 'button=%d, x=%d, y=%d, xdata=%f, ydata=%f'%(event.button, event.x, event.y, event.xdata, event.ydata)\r
123         pass\r
124 \r
125     def OnEnterAxes(self, event):\r
126         self.display_coordinates = True\r
127 \r
128     def OnLeaveAxes(self, event):\r
129         self.display_coordinates = False\r
130         self.SetStatusText('')\r
131 \r
132     def OnMouseMove(self, event):\r
133         if event.guiEvent.m_shiftDown:\r
134             self.toolbar.set_cursor(2)\r
135             #print 'hand: ' + str(wx.CURSOR_HAND)\r
136             #print 'cross: ' + str(wx.CURSOR_CROSS)\r
137             #print 'ibeam: ' + str(wx.CURSOR_IBEAM)\r
138             #print 'wait: ' + str(wx.CURSOR_WAIT)\r
139             #print 'hourglass: ' + str(wx.HOURGLASS_CURSOR)\r
140         else:\r
141             self.toolbar.set_cursor(1)\r
142 \r
143             #axes = self.figure.axes[0]\r
144             #line, = axes.plot([event.x - 20 , event.x + 20], [event.y - 20, event.y + 20])\r
145 \r
146             #line.figure.canvas.draw()\r
147         if self.display_coordinates:\r
148             coordinateString = ''.join(['x: ', str(event.xdata), ' y: ', str(event.ydata)])\r
149             #TODO: pretty format\r
150             self.SetStatusText(coordinateString)\r
151 \r
152     def OnPaint(self, event):\r
153         self.canvas.draw()\r