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