]> git.saurik.com Git - wxWidgets.git/blob - src/generic/plot.cpp
Implemented MSW's paint region clipping, but
[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 #if wxUSE_PLOT
24
25 #ifndef WX_PRECOMP
26 #include "wx/object.h"
27 #include "wx/font.h"
28 #include "wx/colour.h"
29 #include "wx/settings.h"
30 #include "wx/sizer.h"
31 #include "wx/log.h"
32 #include "wx/intl.h"
33 #include "wx/dcclient.h"
34 #endif
35
36 #include "wx/generic/plot.h"
37 #include "wx/bmpbuttn.h"
38
39 #include <math.h>
40
41 // ----------------------------------------------------------------------------
42 // XPMs
43 // ----------------------------------------------------------------------------
44
45 #if !defined(__WXMSW__) && !defined(__WXPM__)
46 #include "wx/generic/plot_enl.xpm"
47 #include "wx/generic/plot_shr.xpm"
48 #include "wx/generic/plot_zin.xpm"
49 #include "wx/generic/plot_zot.xpm"
50 #include "wx/generic/plot_up.xpm"
51 #include "wx/generic/plot_dwn.xpm"
52 #endif
53
54 // ----------------------------------------------------------------------------
55 // accessor functions for the bitmaps (may return NULL, check for it!)
56 // ----------------------------------------------------------------------------
57
58 static wxBitmap *GetEnlargeBitmap();
59 static wxBitmap *GetShrinkBitmap();
60 static wxBitmap *GetZoomInBitmap();
61 static wxBitmap *GetZoomOutBitmap();
62 static wxBitmap *GetUpBitmap();
63 static wxBitmap *GetDownBitmap();
64
65 //-----------------------------------------------------------------------------
66 // consts
67 //-----------------------------------------------------------------------------
68
69 #define wxPLOT_SCROLL_STEP 30
70
71 //-----------------------------------------------------------------------------
72 // wxPlotEvent
73 //-----------------------------------------------------------------------------
74
75 wxPlotEvent::wxPlotEvent( wxEventType commandType, int id )
76 : wxNotifyEvent( commandType, id )
77 {
78 m_curve = (wxPlotCurve*) NULL;
79 m_zoom = 1.0;
80 m_position = 0;
81 }
82
83 //-----------------------------------------------------------------------------
84 // wxPlotCurve
85 //-----------------------------------------------------------------------------
86
87 IMPLEMENT_ABSTRACT_CLASS(wxPlotCurve, wxObject)
88
89 wxPlotCurve::wxPlotCurve( int offsetY, double startY, double endY )
90 {
91 m_offsetY = offsetY;
92 m_startY = startY;
93 m_endY = endY;
94 }
95
96 //-----------------------------------------------------------------------------
97 // wxPlotArea
98 //-----------------------------------------------------------------------------
99
100 IMPLEMENT_DYNAMIC_CLASS(wxPlotArea, wxWindow)
101
102 BEGIN_EVENT_TABLE(wxPlotArea, wxWindow)
103 EVT_PAINT( wxPlotArea::OnPaint)
104 EVT_LEFT_DOWN( wxPlotArea::OnMouse)
105 EVT_LEFT_DCLICK( wxPlotArea::OnMouse)
106 END_EVENT_TABLE()
107
108 wxPlotArea::wxPlotArea( wxPlotWindow *parent )
109 : wxWindow( parent, -1, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER, "plotarea" )
110 {
111 m_owner = parent;
112
113 m_zooming = FALSE;
114
115 SetBackgroundColour( *wxWHITE );
116 }
117
118 void wxPlotArea::OnMouse( wxMouseEvent &event )
119 {
120 int client_width;
121 int client_height;
122 GetClientSize( &client_width, &client_height);
123 int view_x;
124 int view_y;
125 m_owner->GetViewStart( &view_x, &view_y );
126 view_x *= wxPLOT_SCROLL_STEP;
127 view_y *= wxPLOT_SCROLL_STEP;
128
129 wxCoord x = event.GetX();
130 wxCoord y = event.GetY();
131 x += view_x;
132 y += view_y;
133
134 wxNode *node = m_owner->m_curves.First();
135 while (node)
136 {
137 wxPlotCurve *curve = (wxPlotCurve*)node->Data();
138
139 double double_client_height = (double)client_height;
140 double range = curve->GetEndY() - curve->GetStartY();
141 double end = curve->GetEndY();
142 wxCoord offset_y = curve->GetOffsetY();
143
144 double dy = (end - curve->GetY( (wxInt32)(x/m_owner->GetZoom()) )) / range;
145 wxCoord curve_y = (wxCoord)(dy * double_client_height) - offset_y - 1;
146
147 if ((y-curve_y < 4) && (y-curve_y > -4))
148 {
149 wxPlotEvent event1( event.ButtonDClick() ? wxEVT_PLOT_DOUBLECLICKED : wxEVT_PLOT_CLICKED, m_owner->GetId() );
150 event1.SetEventObject( m_owner );
151 event1.SetZoom( m_owner->GetZoom() );
152 event1.SetCurve( curve );
153 event1.SetPosition( (int)floor(x/m_owner->GetZoom()) );
154 m_owner->GetEventHandler()->ProcessEvent( event1 );
155
156 if (curve != m_owner->GetCurrent());
157 {
158 wxPlotEvent event2( wxEVT_PLOT_SEL_CHANGING, m_owner->GetId() );
159 event2.SetEventObject( m_owner );
160 event2.SetZoom( m_owner->GetZoom() );
161 event2.SetCurve( curve );
162 if (!m_owner->GetEventHandler()->ProcessEvent( event2 ) || event2.IsAllowed())
163 {
164 m_owner->SetCurrent( curve );
165 }
166 }
167 return;
168 }
169
170 node = node->Next();
171 }
172 }
173
174 void wxPlotArea::DeleteCurve( wxPlotCurve *curve, int from, int to )
175 {
176 wxClientDC dc(this);
177 m_owner->PrepareDC( dc );
178 dc.SetPen( *wxWHITE_PEN );
179 DrawCurve( &dc, curve, from, to );
180 }
181
182 void wxPlotArea::DrawCurve( wxDC *dc, wxPlotCurve *curve, int from, int to )
183 {
184 int view_x;
185 int view_y;
186 m_owner->GetViewStart( &view_x, &view_y );
187 view_x *= wxPLOT_SCROLL_STEP;
188
189 if (from == -1)
190 from = view_x;
191
192 int client_width;
193 int client_height;
194 GetClientSize( &client_width, &client_height);
195
196 if (to == -1)
197 to = view_x + client_width;
198
199 double zoom = m_owner->GetZoom();
200
201 int start_x = wxMax( from, (int)floor(curve->GetStartX()*zoom) );
202 int end_x = wxMin( to, (int)floor(curve->GetEndX()*zoom) );
203
204 start_x = wxMax( view_x, start_x );
205 end_x = wxMin( view_x + client_width, end_x );
206
207 end_x++;
208
209 double double_client_height = (double)client_height;
210 double range = curve->GetEndY() - curve->GetStartY();
211 double end = curve->GetEndY();
212 wxCoord offset_y = curve->GetOffsetY();
213
214 wxCoord y=0,last_y=0;
215 for (int x = start_x; x < end_x; x++)
216 {
217 double dy = (end - curve->GetY( (wxInt32)(x/zoom) )) / range;
218 y = (wxCoord)(dy * double_client_height) - offset_y - 1;
219
220 if (x != start_x)
221 dc->DrawLine( x-1, last_y, x, y );
222
223 last_y = y;
224 }
225 }
226
227 void wxPlotArea::OnPaint( wxPaintEvent &WXUNUSED(event) )
228 {
229 int view_x;
230 int view_y;
231 m_owner->GetViewStart( &view_x, &view_y );
232 view_x *= wxPLOT_SCROLL_STEP;
233 view_y *= wxPLOT_SCROLL_STEP;
234
235 wxPaintDC dc( this );
236 m_owner->PrepareDC( dc );
237
238 wxRegionIterator upd( GetUpdateRegion() );
239
240 while (upd)
241 {
242 int update_x = upd.GetX();
243 int update_y = upd.GetY();
244 int update_width = upd.GetWidth();
245
246 update_x += view_x;
247 update_y += view_y;
248
249 /*
250 if (m_owner->m_current)
251 {
252 dc.SetPen( *wxLIGHT_GREY_PEN );
253 int base_line = client_height - m_owner->m_current->GetOffsetY();
254 dc.DrawLine( update_x-1, base_line-1, update_x+update_width+2, base_line-1 );
255 }
256 */
257
258 wxNode *node = m_owner->m_curves.First();
259 while (node)
260 {
261 wxPlotCurve *curve = (wxPlotCurve*)node->Data();
262
263 if (curve == m_owner->GetCurrent())
264 dc.SetPen( *wxBLACK_PEN );
265 else
266 dc.SetPen( *wxGREY_PEN );
267
268 DrawCurve( &dc, curve, update_x-1, update_x+update_width+2 );
269
270 node = node->Next();
271 }
272 upd ++;
273 }
274 }
275
276 void wxPlotArea::ScrollWindow( int dx, int dy, const wxRect *rect )
277 {
278 wxWindow::ScrollWindow( dx, dy, rect );
279 // m_owner->m_xaxis->ScrollWindow( dx, 0 );
280 }
281
282 //-----------------------------------------------------------------------------
283 // wxPlotXAxisArea
284 //-----------------------------------------------------------------------------
285
286 IMPLEMENT_DYNAMIC_CLASS(wxPlotXAxisArea, wxWindow)
287
288 BEGIN_EVENT_TABLE(wxPlotXAxisArea, wxWindow)
289 EVT_PAINT( wxPlotXAxisArea::OnPaint)
290 EVT_LEFT_DOWN( wxPlotXAxisArea::OnMouse)
291 END_EVENT_TABLE()
292
293 wxPlotXAxisArea::wxPlotXAxisArea( wxPlotWindow *parent )
294 : wxWindow( parent, -1, wxDefaultPosition, wxSize(-1,40), 0, "plotxaxisarea" )
295 {
296 m_owner = parent;
297
298 SetBackgroundColour( *wxWHITE );
299 SetFont( *wxSMALL_FONT );
300 }
301
302 void wxPlotXAxisArea::OnMouse( wxMouseEvent &event )
303 {
304 int client_width;
305 int client_height;
306 GetClientSize( &client_width, &client_height);
307 int view_x;
308 int view_y;
309 m_owner->GetViewStart( &view_x, &view_y );
310 view_x *= wxPLOT_SCROLL_STEP;
311 view_y *= wxPLOT_SCROLL_STEP;
312
313 wxCoord x = event.GetX();
314 wxCoord y = event.GetY();
315 x += view_x;
316 y += view_y;
317
318 /* do something here */
319 }
320
321 void wxPlotXAxisArea::OnPaint( wxPaintEvent &WXUNUSED(event) )
322 {
323 int view_x;
324 int view_y;
325 m_owner->GetViewStart( &view_x, &view_y );
326 view_x *= wxPLOT_SCROLL_STEP;
327 view_y *= wxPLOT_SCROLL_STEP;
328
329 wxPaintDC dc( this );
330
331 int client_width;
332 int client_height;
333 GetClientSize( &client_width, &client_height);
334
335 double zoom = m_owner->GetZoom();
336
337 double ups = m_owner->GetUnitsPerValue() / zoom;
338
339 double start = view_x * ups;
340 double end = (view_x + client_width) * ups;
341 double range = end - start;
342
343 int int_log_range = (int)floor( log10( range ) );
344 double step = 1.0;
345 if (int_log_range > 0)
346 {
347 for (int i = 0; i < int_log_range; i++)
348 step *= 10;
349 }
350 if (int_log_range < 0)
351 {
352 for (int i = 0; i < -int_log_range; i++)
353 step /= 10;
354 }
355 double lower = ceil(start / step) * step;
356 double upper = floor(end / step) * step;
357
358 // if too few values, shrink size
359 if ((range/step) < 4)
360 {
361 step /= 2;
362 if (lower-step > start) lower -= step;
363 if (upper+step < end) upper += step;
364 }
365
366 // if still too few, again
367 if ((range/step) < 4)
368 {
369 step /= 2;
370 if (lower-step > start) lower -= step;
371 if (upper+step < end) upper += step;
372 }
373
374 dc.SetBrush( *wxWHITE_BRUSH );
375 dc.SetPen( *wxTRANSPARENT_PEN );
376 dc.DrawRectangle( 4, 5, client_width-14, 10 );
377 dc.DrawRectangle( 0, 20, client_width, 20 );
378 dc.SetPen( *wxBLACK_PEN );
379
380 double current = lower;
381 while (current < upper+(step/2))
382 {
383 int x = (int)ceil((current-start) / range * (double)client_width) - 1;
384 if ((x > 4) && (x < client_width-25))
385 {
386 dc.DrawLine( x, 5, x, 15 );
387 wxString label;
388 if (range < 50)
389 {
390 label.Printf( wxT("%f"), current );
391 while (label.Last() == wxT('0'))
392 label.RemoveLast();
393 if ((label.Last() == wxT('.')) || (label.Last() == wxT(',')))
394 label.Append( wxT('0') );
395 }
396 else
397 label.Printf( wxT("%d"), (int)floor(current) );
398 dc.DrawText( label, x-4, 20 );
399 }
400
401 current += step;
402 }
403
404 dc.DrawLine( 0, 15, client_width-8, 15 );
405 dc.DrawLine( client_width-4, 15, client_width-10, 10 );
406 dc.DrawLine( client_width-4, 15, client_width-10, 20 );
407 }
408
409 //-----------------------------------------------------------------------------
410 // wxPlotYAxisArea
411 //-----------------------------------------------------------------------------
412
413 IMPLEMENT_DYNAMIC_CLASS(wxPlotYAxisArea, wxWindow)
414
415 BEGIN_EVENT_TABLE(wxPlotYAxisArea, wxWindow)
416 EVT_PAINT( wxPlotYAxisArea::OnPaint)
417 EVT_LEFT_DOWN( wxPlotYAxisArea::OnMouse)
418 END_EVENT_TABLE()
419
420 wxPlotYAxisArea::wxPlotYAxisArea( wxPlotWindow *parent )
421 : wxWindow( parent, -1, wxDefaultPosition, wxSize(60,-1), 0, "plotyaxisarea" )
422 {
423 m_owner = parent;
424
425 SetBackgroundColour( *wxWHITE );
426 SetFont( *wxSMALL_FONT );
427 }
428
429 void wxPlotYAxisArea::OnMouse( wxMouseEvent &WXUNUSED(event) )
430 {
431 /* do something here */
432 }
433
434 void wxPlotYAxisArea::OnPaint( wxPaintEvent &WXUNUSED(event) )
435 {
436 wxPaintDC dc( this );
437
438 wxPlotCurve *curve = m_owner->GetCurrent();
439
440 if (!curve) return;
441
442 int client_width;
443 int client_height;
444 GetClientSize( &client_width, &client_height);
445
446
447 double range = curve->GetEndY() - curve->GetStartY();
448 double offset = ((double) curve->GetOffsetY() / (double)client_height ) * range;
449 double start = curve->GetStartY() - offset;
450 double end = curve->GetEndY() - offset;
451
452 int int_log_range = (int)floor( log10( range ) );
453 double step = 1.0;
454 if (int_log_range > 0)
455 {
456 for (int i = 0; i < int_log_range; i++)
457 step *= 10;
458 }
459 if (int_log_range < 0)
460 {
461 for (int i = 0; i < -int_log_range; i++)
462 step /= 10;
463 }
464 double lower = ceil(start / step) * step;
465 double upper = floor(end / step) * step;
466
467 // if too few values, shrink size
468 if ((range/step) < 4)
469 {
470 step /= 2;
471 if (lower-step > start) lower -= step;
472 if (upper+step < end) upper += step;
473 }
474
475 // if still too few, again
476 if ((range/step) < 4)
477 {
478 step /= 2;
479 if (lower-step > start) lower -= step;
480 if (upper+step < end) upper += step;
481 }
482
483 dc.SetPen( *wxBLACK_PEN );
484
485 double current = lower;
486 while (current < upper+(step/2))
487 {
488 int y = (int)((curve->GetEndY()-current) / range * (double)client_height) - 1;
489 y -= curve->GetOffsetY();
490 if ((y > 10) && (y < client_height-7))
491 {
492 dc.DrawLine( client_width-15, y, client_width-7, y );
493 wxString label;
494 if (range < 50)
495 {
496 label.Printf( wxT("%f"), current );
497 while (label.Last() == wxT('0'))
498 label.RemoveLast();
499 if ((label.Last() == wxT('.')) || (label.Last() == wxT(',')))
500 label.Append( wxT('0') );
501 }
502 else
503 label.Printf( wxT("%d"), (int)floor(current) );
504 dc.DrawText( label, 5, y-7 );
505 }
506
507 current += step;
508 }
509
510 dc.DrawLine( client_width-15, 6, client_width-15, client_height );
511 dc.DrawLine( client_width-15, 2, client_width-20, 8 );
512 dc.DrawLine( client_width-15, 2, client_width-10, 8 );
513 }
514
515 //-----------------------------------------------------------------------------
516 // wxPlotWindow
517 //-----------------------------------------------------------------------------
518
519 #define ID_ENLARGE 1000
520 #define ID_SHRINK 1002
521
522 #define ID_MOVE_UP 1006
523 #define ID_MOVE_DOWN 1007
524
525 #define ID_ZOOM_IN 1010
526 #define ID_ZOOM_OUT 1011
527
528
529 IMPLEMENT_DYNAMIC_CLASS(wxPlotWindow, wxScrolledWindow)
530
531 BEGIN_EVENT_TABLE(wxPlotWindow, wxScrolledWindow)
532 EVT_BUTTON( ID_MOVE_UP, wxPlotWindow::OnMoveUp)
533 EVT_BUTTON( ID_MOVE_DOWN, wxPlotWindow::OnMoveDown)
534
535 EVT_BUTTON( ID_ENLARGE, wxPlotWindow::OnEnlarge)
536 EVT_BUTTON( ID_SHRINK, wxPlotWindow::OnShrink)
537
538 EVT_BUTTON( ID_ZOOM_IN, wxPlotWindow::OnZoomIn)
539 EVT_BUTTON( ID_ZOOM_OUT, wxPlotWindow::OnZoomOut)
540
541 EVT_SCROLLWIN( wxPlotWindow::OnScroll2)
542 END_EVENT_TABLE()
543
544 wxPlotWindow::wxPlotWindow( wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, int flag )
545 : wxScrolledWindow( parent, id, pos, size, flag, "plotcanvas" )
546 {
547 m_xUnitsPerValue = 1.0;
548 m_xZoom = 1.0;
549
550 m_enlargeAroundWindowCentre = FALSE;
551 m_scrollOnThumbRelease = FALSE;
552
553 m_area = new wxPlotArea( this );
554 wxBoxSizer *mainsizer = new wxBoxSizer( wxHORIZONTAL );
555
556 if ((GetWindowStyleFlag() & wxPLOT_BUTTON_ALL) != 0)
557 {
558 wxBoxSizer *buttonlist = new wxBoxSizer( wxVERTICAL );
559 if ((GetWindowStyleFlag() & wxPLOT_BUTTON_ENLARGE) != 0)
560 {
561 buttonlist->Add( new wxBitmapButton( this, ID_ENLARGE, *GetEnlargeBitmap() ), 0, wxEXPAND|wxALL, 2 );
562 buttonlist->Add( new wxBitmapButton( this, ID_SHRINK, *GetShrinkBitmap() ), 0, wxEXPAND|wxALL, 2 );
563 buttonlist->Add( 20,10, 0 );
564 }
565 if ((GetWindowStyleFlag() & wxPLOT_BUTTON_MOVE) != 0)
566 {
567 buttonlist->Add( new wxBitmapButton( this, ID_MOVE_UP, *GetUpBitmap() ), 0, wxEXPAND|wxALL, 2 );
568 buttonlist->Add( new wxBitmapButton( this, ID_MOVE_DOWN, *GetDownBitmap() ), 0, wxEXPAND|wxALL, 2 );
569 buttonlist->Add( 20,10, 0 );
570 }
571 if ((GetWindowStyleFlag() & wxPLOT_BUTTON_ZOOM) != 0)
572 {
573 buttonlist->Add( new wxBitmapButton( this, ID_ZOOM_IN, *GetZoomInBitmap() ), 0, wxEXPAND|wxALL, 2 );
574 buttonlist->Add( new wxBitmapButton( this, ID_ZOOM_OUT, *GetZoomOutBitmap() ), 0, wxEXPAND|wxALL, 2 );
575 }
576 mainsizer->Add( buttonlist, 0, wxEXPAND|wxALL, 4 );
577 }
578
579 wxBoxSizer *plotsizer = new wxBoxSizer( wxHORIZONTAL );
580
581 if ((GetWindowStyleFlag() & wxPLOT_Y_AXIS) != 0)
582 {
583 m_yaxis = new wxPlotYAxisArea( this );
584
585 wxBoxSizer *vert1 = new wxBoxSizer( wxVERTICAL );
586 plotsizer->Add( vert1, 0, wxEXPAND );
587 vert1->Add( m_yaxis, 1 );
588 if ((GetWindowStyleFlag() & wxPLOT_X_AXIS) != 0)
589 vert1->Add( 60, 40 );
590 }
591 else
592 {
593 m_yaxis = (wxPlotYAxisArea*) NULL;
594 }
595
596 if ((GetWindowStyleFlag() & wxPLOT_X_AXIS) != 0)
597 {
598 m_xaxis = new wxPlotXAxisArea( this );
599
600 wxBoxSizer *vert2 = new wxBoxSizer( wxVERTICAL );
601 plotsizer->Add( vert2, 1, wxEXPAND );
602 vert2->Add( m_area, 1, wxEXPAND );
603 vert2->Add( m_xaxis, 0, wxEXPAND );
604 }
605 else
606 {
607 plotsizer->Add( m_area, 1, wxEXPAND );
608 m_xaxis = (wxPlotXAxisArea*) NULL;
609 }
610
611 mainsizer->Add( plotsizer, 1, wxEXPAND );
612
613 SetAutoLayout( TRUE );
614 SetSizer( mainsizer );
615
616 SetTargetWindow( m_area );
617
618 SetBackgroundColour( *wxWHITE );
619
620 m_current = (wxPlotCurve*) NULL;
621 }
622
623 wxPlotWindow::~wxPlotWindow()
624 {
625 }
626
627 void wxPlotWindow::Add( wxPlotCurve *curve )
628 {
629 m_curves.Append( curve );
630 if (!m_current) m_current = curve;
631
632 ResetScrollbar();
633 }
634
635 size_t wxPlotWindow::GetCount()
636 {
637 return m_curves.GetCount();
638 }
639
640 wxPlotCurve *wxPlotWindow::GetAt( size_t n )
641 {
642 wxNode *node = m_curves.Nth( n );
643 if (!node)
644 return (wxPlotCurve*) NULL;
645
646 return (wxPlotCurve*) node->Data();
647 }
648
649 void wxPlotWindow::SetCurrent( wxPlotCurve* current )
650 {
651 m_current = current;
652 m_area->Refresh( FALSE );
653
654 RedrawYAxis();
655
656 wxPlotEvent event( wxEVT_PLOT_SEL_CHANGED, GetId() );
657 event.SetEventObject( this );
658 event.SetZoom( GetZoom() );
659 event.SetCurve( m_current );
660 GetEventHandler()->ProcessEvent( event );
661 }
662
663 void wxPlotWindow::Delete( wxPlotCurve* curve )
664 {
665 wxNode *node = m_curves.Find( curve );
666 if (!node) return;
667
668 m_curves.DeleteObject( curve );
669
670 m_area->DeleteCurve( curve );
671 m_area->Refresh( FALSE );
672 }
673
674 wxPlotCurve *wxPlotWindow::GetCurrent()
675 {
676 return m_current;
677 }
678
679 void wxPlotWindow::Move( wxPlotCurve* curve, int pixels_up )
680 {
681 m_area->DeleteCurve( curve );
682
683 curve->SetOffsetY( curve->GetOffsetY() + pixels_up );
684
685 m_area->Refresh( FALSE );
686
687 RedrawYAxis();
688 }
689
690 void wxPlotWindow::OnMoveUp( wxCommandEvent& WXUNUSED(event) )
691 {
692 if (!m_current) return;
693
694 Move( m_current, 25 );
695 }
696
697 void wxPlotWindow::OnMoveDown( wxCommandEvent& WXUNUSED(event) )
698 {
699 if (!m_current) return;
700
701 Move( m_current, -25 );
702 }
703
704 void wxPlotWindow::Enlarge( wxPlotCurve *curve, double factor )
705 {
706 m_area->DeleteCurve( curve );
707
708 int client_width;
709 int client_height;
710 m_area->GetClientSize( &client_width, &client_height);
711 double offset = (double)curve->GetOffsetY() / (double)client_height;
712
713 double range = curve->GetEndY() - curve->GetStartY();
714 offset *= range;
715
716 double new_range = range / factor;
717 double new_offset = offset / factor;
718
719 if (m_enlargeAroundWindowCentre)
720 {
721 double middle = curve->GetStartY() - offset + range/2;
722
723 curve->SetStartY( middle - new_range / 2 + new_offset );
724 curve->SetEndY( middle + new_range / 2 + new_offset );
725 }
726 else
727 {
728 curve->SetStartY( (curve->GetStartY() - offset)/factor + new_offset );
729 curve->SetEndY( (curve->GetEndY() - offset)/factor + new_offset );
730 }
731
732 m_area->Refresh( FALSE );
733 RedrawYAxis();
734 }
735
736 void wxPlotWindow::SetUnitsPerValue( double upv )
737 {
738 m_xUnitsPerValue = upv;
739
740 RedrawXAxis();
741 }
742
743 void wxPlotWindow::SetZoom( double zoom )
744 {
745 double old_zoom = m_xZoom;
746 m_xZoom = zoom;
747
748 int view_x = 0;
749 int view_y = 0;
750 GetViewStart( &view_x, &view_y );
751
752 wxInt32 max = 0;
753 wxNode *node = m_curves.First();
754 while (node)
755 {
756 wxPlotCurve *curve = (wxPlotCurve*) node->Data();
757 if (curve->GetEndX() > max)
758 max = curve->GetEndX();
759 node = node->Next();
760 }
761 SetScrollbars( wxPLOT_SCROLL_STEP, wxPLOT_SCROLL_STEP,
762 (int)((max*m_xZoom)/wxPLOT_SCROLL_STEP)+1, 0,
763 (int)(view_x*zoom/old_zoom), 0,
764 TRUE );
765
766 RedrawXAxis();
767 m_area->Refresh( TRUE );
768 }
769
770 void wxPlotWindow::ResetScrollbar()
771 {
772 wxInt32 max = 0;
773 wxNode *node = m_curves.First();
774 while (node)
775 {
776 wxPlotCurve *curve = (wxPlotCurve*) node->Data();
777 if (curve->GetEndX() > max)
778 max = curve->GetEndX();
779 node = node->Next();
780 }
781
782 SetScrollbars( wxPLOT_SCROLL_STEP, wxPLOT_SCROLL_STEP,
783 (int)(((max*m_xZoom)/wxPLOT_SCROLL_STEP)+1), 0 );
784 }
785
786 void wxPlotWindow::RedrawXAxis()
787 {
788 if (m_xaxis)
789 m_xaxis->Refresh( FALSE );
790 }
791
792 void wxPlotWindow::RedrawYAxis()
793 {
794 if (m_yaxis)
795 m_yaxis->Refresh( TRUE );
796 }
797
798 void wxPlotWindow::RedrawEverything()
799 {
800 if (m_xaxis)
801 m_xaxis->Refresh( TRUE );
802 if (m_yaxis)
803 m_yaxis->Refresh( TRUE );
804 m_area->Refresh( TRUE );
805 }
806
807 void wxPlotWindow::OnZoomIn( wxCommandEvent& WXUNUSED(event) )
808 {
809 SetZoom( m_xZoom * 1.5 );
810 }
811
812 void wxPlotWindow::OnZoomOut( wxCommandEvent& WXUNUSED(event) )
813 {
814 SetZoom( m_xZoom * 0.6666 );
815 }
816
817 void wxPlotWindow::OnEnlarge( wxCommandEvent& WXUNUSED(event) )
818 {
819 if (!m_current) return;
820
821 Enlarge( m_current, 1.5 );
822 }
823
824 void wxPlotWindow::OnShrink( wxCommandEvent& WXUNUSED(event) )
825 {
826 if (!m_current) return;
827
828 Enlarge( m_current, 0.6666666 );
829 }
830
831 void wxPlotWindow::OnScroll2( wxScrollWinEvent& event )
832 {
833 if ((!m_scrollOnThumbRelease) || (event.GetEventType() != wxEVT_SCROLLWIN_THUMBTRACK))
834 {
835 wxScrolledWindow::OnScroll( event );
836 RedrawXAxis();
837 }
838 }
839
840 // ----------------------------------------------------------------------------
841 // global functions
842 // ----------------------------------------------------------------------------
843
844 // FIXME MT-UNSAFE
845 static wxBitmap *GetEnlargeBitmap()
846 {
847 static wxBitmap* s_bitmap = (wxBitmap *) NULL;
848 static bool s_loaded = FALSE;
849
850 if ( !s_loaded )
851 {
852 s_loaded = TRUE; // set it to TRUE anyhow, we won't try again
853
854 #if defined(__WXMSW__) || defined(__WXPM__)
855 s_bitmap = new wxBitmap("plot_enl_bmp", wxBITMAP_TYPE_RESOURCE);
856 #else
857 s_bitmap = new wxBitmap( plot_enl_xpm );
858 #endif
859 }
860
861 return s_bitmap;
862 }
863
864 static wxBitmap *GetShrinkBitmap()
865 {
866 static wxBitmap* s_bitmap = (wxBitmap *) NULL;
867 static bool s_loaded = FALSE;
868
869 if ( !s_loaded )
870 {
871 s_loaded = TRUE; // set it to TRUE anyhow, we won't try again
872
873 #if defined(__WXMSW__) || defined(__WXPM__)
874 s_bitmap = new wxBitmap("plot_shr_bmp", wxBITMAP_TYPE_RESOURCE);
875 #else
876 s_bitmap = new wxBitmap( plot_shr_xpm );
877 #endif
878 }
879
880 return s_bitmap;
881 }
882
883 static wxBitmap *GetZoomInBitmap()
884 {
885 static wxBitmap* s_bitmap = (wxBitmap *) NULL;
886 static bool s_loaded = FALSE;
887
888 if ( !s_loaded )
889 {
890 s_loaded = TRUE; // set it to TRUE anyhow, we won't try again
891
892 #if defined(__WXMSW__) || defined(__WXPM__)
893 s_bitmap = new wxBitmap("plot_zin_bmp", wxBITMAP_TYPE_RESOURCE);
894 #else
895 s_bitmap = new wxBitmap( plot_zin_xpm );
896 #endif
897 }
898
899 return s_bitmap;
900 }
901
902 static wxBitmap *GetZoomOutBitmap()
903 {
904 static wxBitmap* s_bitmap = (wxBitmap *) NULL;
905 static bool s_loaded = FALSE;
906
907 if ( !s_loaded )
908 {
909 s_loaded = TRUE; // set it to TRUE anyhow, we won't try again
910
911 #if defined(__WXMSW__) || defined(__WXPM__)
912 s_bitmap = new wxBitmap("plot_zot_bmp", wxBITMAP_TYPE_RESOURCE);
913 #else
914 s_bitmap = new wxBitmap( plot_zot_xpm );
915 #endif
916 }
917
918 return s_bitmap;
919 }
920
921 static wxBitmap *GetUpBitmap()
922 {
923 static wxBitmap* s_bitmap = (wxBitmap *) NULL;
924 static bool s_loaded = FALSE;
925
926 if ( !s_loaded )
927 {
928 s_loaded = TRUE; // set it to TRUE anyhow, we won't try again
929
930 #if defined(__WXMSW__) || defined(__WXPM__)
931 s_bitmap = new wxBitmap("plot_up_bmp", wxBITMAP_TYPE_RESOURCE);
932 #else
933 s_bitmap = new wxBitmap( plot_up_xpm );
934 #endif
935 }
936
937 return s_bitmap;
938 }
939
940 static wxBitmap *GetDownBitmap()
941 {
942 static wxBitmap* s_bitmap = (wxBitmap *) NULL;
943 static bool s_loaded = FALSE;
944
945 if ( !s_loaded )
946 {
947 s_loaded = TRUE; // set it to TRUE anyhow, we won't try again
948
949 #if defined(__WXMSW__) || defined(__WXPM__)
950 s_bitmap = new wxBitmap("plot_dwn_bmp", wxBITMAP_TYPE_RESOURCE);
951 #else
952 s_bitmap = new wxBitmap( plot_dwn_xpm );
953 #endif
954 }
955
956 return s_bitmap;
957 }
958
959 #endif // wxUSE_PLOT