]> git.saurik.com Git - wxWidgets.git/blob - src/generic/plot.cpp
A no-change for scroll events.
[wxWidgets.git] / src / generic / plot.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: plot.cpp
3 // Purpose: wxPlotWindow
4 // Author: Robert Roebling
5 // Modified by:
6 // Created: 12/01/2000
7 // RCS-ID: $Id$
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "plot.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/object.h"
25 #include "wx/font.h"
26 #include "wx/colour.h"
27 #include "wx/settings.h"
28 #include "wx/sizer.h"
29 #include "wx/log.h"
30 #include "wx/intl.h"
31 #include "wx/dcclient.h"
32 #endif
33
34 #include "wx/generic/plot.h"
35
36 #include <math.h>
37
38 //-----------------------------------------------------------------------------
39 // wxPlotCurve
40 //-----------------------------------------------------------------------------
41
42 IMPLEMENT_ABSTRACT_CLASS(wxPlotCurve, wxObject)
43
44 wxPlotCurve::wxPlotCurve( int offsetY, double startY, double endY )
45 {
46 m_offsetY = offsetY;
47 m_startY = startY;
48 m_endY = endY;
49 }
50
51 //-----------------------------------------------------------------------------
52 // wxPlotArea
53 //-----------------------------------------------------------------------------
54
55 IMPLEMENT_DYNAMIC_CLASS(wxPlotArea, wxWindow)
56
57 BEGIN_EVENT_TABLE(wxPlotArea, wxWindow)
58 EVT_PAINT( wxPlotArea::OnPaint)
59 EVT_LEFT_DOWN( wxPlotArea::OnMouse)
60 END_EVENT_TABLE()
61
62 wxPlotArea::wxPlotArea( wxPlotWindow *parent )
63 : wxWindow( parent, -1, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER, "plotarea" )
64 {
65 m_owner = parent;
66
67 SetBackgroundColour( *wxWHITE );
68 }
69
70 void wxPlotArea::OnMouse( wxMouseEvent &event )
71 {
72 int client_width;
73 int client_height;
74 GetClientSize( &client_width, &client_height);
75 int view_x;
76 int view_y;
77 m_owner->GetViewStart( &view_x, &view_y );
78 view_x *= 10;
79 view_y *= 10;
80
81 int x = event.GetX();
82 int y = event.GetY();
83 x += view_x;
84 y += view_y;
85
86 wxNode *node = m_owner->m_curves.First();
87 while (node)
88 {
89 wxPlotCurve *curve = (wxPlotCurve*)node->Data();
90
91 double double_client_height = (double)client_height;
92 double range = curve->GetEndY() - curve->GetStartY();
93 double end = curve->GetEndY();
94 wxCoord offset_y = curve->GetOffsetY();
95
96 double dy = (end - curve->GetY( x )) / range;
97 wxCoord curve_y = (wxCoord)(dy * double_client_height) - offset_y - 1;
98
99 if ((y-curve_y < 4) && (y-curve_y > -4))
100 {
101 m_owner->SetCurrent( curve );
102 return;
103 }
104
105 node = node->Next();
106 }
107 }
108
109 void wxPlotArea::OnPaint( wxPaintEvent &WXUNUSED(event) )
110 {
111 int client_width;
112 int client_height;
113 GetClientSize( &client_width, &client_height);
114 int view_x;
115 int view_y;
116 m_owner->GetViewStart( &view_x, &view_y );
117 view_x *= 10;
118 view_y *= 10;
119
120 wxPaintDC dc( this );
121 m_owner->PrepareDC( dc );
122
123 wxRegionIterator upd( GetUpdateRegion() );
124
125 while (upd)
126 {
127 int update_x = upd.GetX();
128 int update_y = upd.GetY();
129 int update_width = upd.GetWidth();
130
131 update_x += view_x;
132 update_y += view_y;
133
134 /*
135 if (m_owner->m_current)
136 {
137 dc.SetPen( *wxLIGHT_GREY_PEN );
138 int base_line = client_height - m_owner->m_current->GetOffsetY();
139 dc.DrawLine( update_x-1, base_line-1, update_x+update_width+2, base_line-1 );
140 }
141 */
142
143 wxNode *node = m_owner->m_curves.First();
144 while (node)
145 {
146 wxPlotCurve *curve = (wxPlotCurve*)node->Data();
147
148 if (curve == m_owner->GetCurrent())
149 dc.SetPen( *wxBLACK_PEN );
150 else
151 dc.SetPen( *wxLIGHT_GREY_PEN );
152
153 int start_x = wxMax( update_x-1, curve->GetStartX() );
154 int end_x = wxMin( update_x+update_width+2, curve->GetEndX() );
155
156 double double_client_height = (double)client_height;
157 double range = curve->GetEndY() - curve->GetStartY();
158 double end = curve->GetEndY();
159 wxCoord offset_y = curve->GetOffsetY();
160
161 wxCoord y=0,last_y=0;
162 for (int x = start_x; x < end_x; x++)
163 {
164 double dy = (end - curve->GetY( x )) / range;
165 y = (wxCoord)(dy * double_client_height) - offset_y - 1;
166
167 if (x != start_x)
168 dc.DrawLine( x-1, last_y, x, y );
169
170 last_y = y;
171 }
172 node = node->Next();
173 }
174 upd ++;
175 }
176 }
177
178 //-----------------------------------------------------------------------------
179 // wxPlotWindow
180 //-----------------------------------------------------------------------------
181
182 #define ID_ENLARGE_100 1000
183 #define ID_ENLARGE_50 1001
184 #define ID_SHRINK_33 1002
185 #define ID_SHRINK_50 1003
186
187 #define ID_MOVE_UP 1006
188 #define ID_MOVE_DOWN 1007
189
190
191 IMPLEMENT_DYNAMIC_CLASS(wxPlotWindow, wxScrolledWindow)
192
193 BEGIN_EVENT_TABLE(wxPlotWindow, wxScrolledWindow)
194 EVT_PAINT( wxPlotWindow::OnPaint)
195 END_EVENT_TABLE()
196
197 wxPlotWindow::wxPlotWindow( wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, int flag )
198 : wxScrolledWindow( parent, id, pos, size, flag, "plotcanvas" )
199 {
200 m_area = new wxPlotArea( this );
201
202 wxBoxSizer *mainsizer = new wxBoxSizer( wxHORIZONTAL );
203
204 wxBoxSizer *buttonlist = new wxBoxSizer( wxVERTICAL );
205 buttonlist->Add( new wxButton( this, ID_ENLARGE_100, _("+ 100%") ), 0, wxEXPAND|wxALL, 5 );
206 buttonlist->Add( new wxButton( this, ID_ENLARGE_50, _("+ 50%") ), 0, wxEXPAND|wxALL, 5 );
207 buttonlist->Add( new wxButton( this, ID_SHRINK_33, _("- 33%") ), 0, wxEXPAND|wxALL, 5 );
208 buttonlist->Add( new wxButton( this, ID_SHRINK_50, _("- 50%") ), 0, wxEXPAND|wxALL, 5 );
209 buttonlist->Add( 20,20, 0 );
210 buttonlist->Add( new wxButton( this, ID_MOVE_UP, _("Up") ), 0, wxEXPAND|wxALL, 5 );
211 buttonlist->Add( new wxButton( this, ID_MOVE_DOWN, _("Down") ), 0, wxEXPAND|wxALL, 5 );
212 buttonlist->Add( 20,20, 1 );
213
214 mainsizer->Add( buttonlist, 0, wxEXPAND );
215
216 mainsizer->Add( m_area, 1, wxEXPAND|wxLEFT, 50 );
217
218 SetAutoLayout( TRUE );
219 SetSizer( mainsizer );
220
221 SetTargetWindow( m_area );
222
223 SetBackgroundColour( *wxWHITE );
224
225 m_current = (wxPlotCurve*) NULL;
226 }
227
228 wxPlotWindow::~wxPlotWindow()
229 {
230 }
231
232 void wxPlotWindow::Add( wxPlotCurve *curve )
233 {
234 m_curves.Append( curve );
235 if (!m_current) m_current = curve;
236 }
237
238 size_t wxPlotWindow::GetCount()
239 {
240 return m_curves.GetCount();
241 }
242
243 wxPlotCurve *wxPlotWindow::GetAt( size_t n )
244 {
245 wxNode *node = m_curves.Nth( n );
246 if (!node)
247 return (wxPlotCurve*) NULL;
248
249 return (wxPlotCurve*) node->Data();
250 }
251
252 void wxPlotWindow::SetCurrent( wxPlotCurve* current )
253 {
254 m_current = current;
255 m_area->Refresh( FALSE );
256
257 wxPoint pos( m_area->GetPosition() );
258
259 int client_width;
260 int client_height;
261 GetClientSize( &client_width, &client_height);
262 wxRect rect(pos.x-45,0,45,client_height);
263 Refresh(TRUE,&rect);
264 }
265
266 wxPlotCurve *wxPlotWindow::GetCurrent()
267 {
268 return m_current;
269 }
270
271 void wxPlotWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
272 {
273 wxPaintDC dc( this );
274
275 if (!m_current) return;
276
277 int client_width;
278 int client_height;
279 GetClientSize( &client_width, &client_height);
280
281 dc.SetPen( *wxBLACK_PEN );
282
283 wxPoint pos( m_area->GetPosition() );
284
285 double range = m_current->GetEndY() - m_current->GetStartY();
286 double offset = ((double) m_current->GetOffsetY() / (double)client_height ) * range;
287 double start = m_current->GetStartY() - offset;
288 double end = m_current->GetEndY() - offset;
289 int int_log_range = (int)floor( log10( range ) );
290 double step = 1.0;
291 if (int_log_range > 0)
292 {
293 for (int i = 0; i < int_log_range; i++)
294 step *= 10;
295 }
296 if (int_log_range < 0)
297 {
298 for (int i = 0; i < -int_log_range; i++)
299 step /= 10;
300 }
301 double lower = ceil(start / step) * step;
302 double upper = floor(end / step) * step;
303 int steps = (int)ceil((upper-lower)/step);
304 if (steps < 3)
305 {
306 step /= 2;
307 if (lower-step > start) lower -= step;
308 }
309
310 double current = lower;
311 while (current < upper+(step/2))
312 {
313 int y = (int)((m_current->GetEndY()-current) / range * (double)client_height) - 1;
314 y -= m_current->GetOffsetY();
315 if ((y > 10) && (y < client_height-7))
316 {
317 dc.DrawLine( pos.x-15, y, pos.x-7, y );
318 wxString label;
319 label.Printf( "%.1f", current );
320 dc.DrawText( label, pos.x-45, y-7 );
321 }
322
323 current += step;
324 }
325
326 dc.DrawLine( pos.x-15, 5, pos.x-15, client_height-5 );
327 dc.DrawLine( pos.x-19, 9, pos.x-15, 5 );
328 dc.DrawLine( pos.x-10, 10, pos.x-15, 5 );
329
330 }
331