]> git.saurik.com Git - wxWidgets.git/blame - src/generic/plot.cpp
deTABified
[wxWidgets.git] / src / generic / plot.cpp
CommitLineData
981b2508
RR
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
9b33fe02
VZ
23#if wxUSE_PLOT
24
981b2508
RR
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"
279ababf 37#include "wx/bmpbuttn.h"
981b2508 38
846e1424
RR
39#include <math.h>
40
279ababf
RR
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
58static wxBitmap *GetEnlargeBitmap();
59static wxBitmap *GetShrinkBitmap();
60static wxBitmap *GetZoomInBitmap();
61static wxBitmap *GetZoomOutBitmap();
62static wxBitmap *GetUpBitmap();
63static wxBitmap *GetDownBitmap();
64
530a7383
RR
65//-----------------------------------------------------------------------------
66// consts
67//-----------------------------------------------------------------------------
68
69#define wxPLOT_SCROLL_STEP 30
70
279ababf
RR
71//-----------------------------------------------------------------------------
72// wxPlotEvent
73//-----------------------------------------------------------------------------
74
75wxPlotEvent::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
981b2508
RR
83//-----------------------------------------------------------------------------
84// wxPlotCurve
85//-----------------------------------------------------------------------------
86
87IMPLEMENT_ABSTRACT_CLASS(wxPlotCurve, wxObject)
88
846e1424 89wxPlotCurve::wxPlotCurve( int offsetY, double startY, double endY )
981b2508
RR
90{
91 m_offsetY = offsetY;
846e1424
RR
92 m_startY = startY;
93 m_endY = endY;
981b2508
RR
94}
95
96//-----------------------------------------------------------------------------
97// wxPlotArea
98//-----------------------------------------------------------------------------
99
100IMPLEMENT_DYNAMIC_CLASS(wxPlotArea, wxWindow)
101
102BEGIN_EVENT_TABLE(wxPlotArea, wxWindow)
103 EVT_PAINT( wxPlotArea::OnPaint)
104 EVT_LEFT_DOWN( wxPlotArea::OnMouse)
279ababf 105 EVT_LEFT_DCLICK( wxPlotArea::OnMouse)
981b2508
RR
106END_EVENT_TABLE()
107
108wxPlotArea::wxPlotArea( wxPlotWindow *parent )
109 : wxWindow( parent, -1, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER, "plotarea" )
110{
111 m_owner = parent;
279ababf
RR
112
113 m_zooming = FALSE;
981b2508
RR
114
115 SetBackgroundColour( *wxWHITE );
116}
117
118void 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 );
530a7383
RR
126 view_x *= wxPLOT_SCROLL_STEP;
127 view_y *= wxPLOT_SCROLL_STEP;
279ababf
RR
128
129 int x = event.GetX();
130 int y = event.GetY();
981b2508
RR
131 x += view_x;
132 y += view_y;
279ababf 133
981b2508
RR
134 wxNode *node = m_owner->m_curves.First();
135 while (node)
136 {
137 wxPlotCurve *curve = (wxPlotCurve*)node->Data();
279ababf 138
846e1424
RR
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();
279ababf
RR
143
144 double dy = (end - curve->GetY( x/m_owner->GetZoom() )) / range;
846e1424 145 wxCoord curve_y = (wxCoord)(dy * double_client_height) - offset_y - 1;
279ababf 146
981b2508
RR
147 if ((y-curve_y < 4) && (y-curve_y > -4))
148 {
279ababf
RR
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 }
981b2508
RR
167 return;
168 }
279ababf 169
981b2508
RR
170 node = node->Next();
171 }
172}
173
d3a809c7
RR
174void 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
182void wxPlotArea::DrawCurve( wxDC *dc, wxPlotCurve *curve, int from, int to )
981b2508 183{
d3a809c7
RR
184 int view_x;
185 int view_y;
186 m_owner->GetViewStart( &view_x, &view_y );
530a7383 187 view_x *= wxPLOT_SCROLL_STEP;
279ababf 188
d3a809c7
RR
189 if (from == -1)
190 from = view_x;
191
981b2508
RR
192 int client_width;
193 int client_height;
194 GetClientSize( &client_width, &client_height);
279ababf 195
d3a809c7
RR
196 if (to == -1)
197 to = view_x + client_width;
530a7383
RR
198
199 to += 2; // no idea why this is needed
06b466c7 200
279ababf
RR
201 double zoom = m_owner->GetZoom();
202
203 int start_x = wxMax( from, (int)floor(curve->GetStartX()*zoom) );
204 int end_x = wxMin( to, (int)floor(curve->GetEndX()*zoom) );
d3a809c7
RR
205
206 start_x = wxMax( view_x, start_x );
207 end_x = wxMin( view_x + client_width, end_x );
279ababf 208
d3a809c7
RR
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();
279ababf 213
d3a809c7
RR
214 wxCoord y=0,last_y=0;
215 for (int x = start_x; x < end_x; x++)
216 {
279ababf 217 double dy = (end - curve->GetY( x/zoom )) / range;
d3a809c7 218 y = (wxCoord)(dy * double_client_height) - offset_y - 1;
279ababf 219
d3a809c7
RR
220 if (x != start_x)
221 dc->DrawLine( x-1, last_y, x, y );
279ababf 222
d3a809c7
RR
223 last_y = y;
224 }
225}
226
227void wxPlotArea::OnPaint( wxPaintEvent &WXUNUSED(event) )
228{
981b2508
RR
229 int view_x;
230 int view_y;
231 m_owner->GetViewStart( &view_x, &view_y );
530a7383
RR
232 view_x *= wxPLOT_SCROLL_STEP;
233 view_y *= wxPLOT_SCROLL_STEP;
981b2508
RR
234
235 wxPaintDC dc( this );
236 m_owner->PrepareDC( dc );
237
238 wxRegionIterator upd( GetUpdateRegion() );
279ababf 239
981b2508
RR
240 while (upd)
241 {
242 int update_x = upd.GetX();
243 int update_y = upd.GetY();
244 int update_width = upd.GetWidth();
279ababf 245
981b2508
RR
246 update_x += view_x;
247 update_y += view_y;
279ababf 248
846e1424 249/*
981b2508
RR
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 }
846e1424 256*/
279ababf 257
981b2508
RR
258 wxNode *node = m_owner->m_curves.First();
259 while (node)
260 {
261 wxPlotCurve *curve = (wxPlotCurve*)node->Data();
279ababf 262
981b2508
RR
263 if (curve == m_owner->GetCurrent())
264 dc.SetPen( *wxBLACK_PEN );
265 else
279ababf
RR
266 dc.SetPen( *wxGREY_PEN );
267
d3a809c7 268 DrawCurve( &dc, curve, update_x-1, update_x+update_width+2 );
981b2508 269
981b2508
RR
270 node = node->Next();
271 }
272 upd ++;
273 }
274}
275
279ababf
RR
276void 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
286IMPLEMENT_DYNAMIC_CLASS(wxPlotXAxisArea, wxWindow)
287
288BEGIN_EVENT_TABLE(wxPlotXAxisArea, wxWindow)
289 EVT_PAINT( wxPlotXAxisArea::OnPaint)
290 EVT_LEFT_DOWN( wxPlotXAxisArea::OnMouse)
291END_EVENT_TABLE()
292
293wxPlotXAxisArea::wxPlotXAxisArea( wxPlotWindow *parent )
294 : wxWindow( parent, -1, wxDefaultPosition, wxSize(-1,40), 0, "plotxaxisarea" )
295{
296 m_owner = parent;
297
298 SetBackgroundColour( *wxWHITE );
530a7383 299 SetFont( *wxSMALL_FONT );
279ababf
RR
300}
301
302void 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 );
530a7383
RR
310 view_x *= wxPLOT_SCROLL_STEP;
311 view_y *= wxPLOT_SCROLL_STEP;
279ababf
RR
312
313 int x = event.GetX();
314 int y = event.GetY();
315 x += view_x;
316 y += view_y;
317
318 /* do something here */
319}
320
321void wxPlotXAxisArea::OnPaint( wxPaintEvent &WXUNUSED(event) )
322{
323 int view_x;
324 int view_y;
325 m_owner->GetViewStart( &view_x, &view_y );
530a7383
RR
326 view_x *= wxPLOT_SCROLL_STEP;
327 view_y *= wxPLOT_SCROLL_STEP;
279ababf
RR
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;
530a7383
RR
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 }
279ababf
RR
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
413IMPLEMENT_DYNAMIC_CLASS(wxPlotYAxisArea, wxWindow)
414
415BEGIN_EVENT_TABLE(wxPlotYAxisArea, wxWindow)
416 EVT_PAINT( wxPlotYAxisArea::OnPaint)
417 EVT_LEFT_DOWN( wxPlotYAxisArea::OnMouse)
418END_EVENT_TABLE()
419
420wxPlotYAxisArea::wxPlotYAxisArea( wxPlotWindow *parent )
421 : wxWindow( parent, -1, wxDefaultPosition, wxSize(60,-1), 0, "plotyaxisarea" )
422{
423 m_owner = parent;
424
425 SetBackgroundColour( *wxWHITE );
530a7383 426 SetFont( *wxSMALL_FONT );
279ababf
RR
427}
428
429void wxPlotYAxisArea::OnMouse( wxMouseEvent &WXUNUSED(event) )
430{
431 /* do something here */
432}
433
434void 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;
530a7383
RR
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) );
279ababf
RR
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
981b2508
RR
515//-----------------------------------------------------------------------------
516// wxPlotWindow
517//-----------------------------------------------------------------------------
518
279ababf
RR
519#define ID_ENLARGE 1000
520#define ID_SHRINK 1002
981b2508
RR
521
522#define ID_MOVE_UP 1006
523#define ID_MOVE_DOWN 1007
524
279ababf
RR
525#define ID_ZOOM_IN 1010
526#define ID_ZOOM_OUT 1011
527
981b2508
RR
528
529IMPLEMENT_DYNAMIC_CLASS(wxPlotWindow, wxScrolledWindow)
530
531BEGIN_EVENT_TABLE(wxPlotWindow, wxScrolledWindow)
d3a809c7
RR
532 EVT_BUTTON( ID_MOVE_UP, wxPlotWindow::OnMoveUp)
533 EVT_BUTTON( ID_MOVE_DOWN, wxPlotWindow::OnMoveDown)
279ababf
RR
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)
981b2508
RR
542END_EVENT_TABLE()
543
544wxPlotWindow::wxPlotWindow( wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, int flag )
545 : wxScrolledWindow( parent, id, pos, size, flag, "plotcanvas" )
546{
279ababf
RR
547 m_xUnitsPerValue = 1.0;
548 m_xZoom = 1.0;
530a7383
RR
549
550 m_enlargeAroundWindowCentre = FALSE;
551 m_scrollOnThumbRelease = FALSE;
06b466c7 552
279ababf 553 m_area = new wxPlotArea( this );
981b2508 554 wxBoxSizer *mainsizer = new wxBoxSizer( wxHORIZONTAL );
279ababf
RR
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 }
06b466c7 610
279ababf
RR
611 mainsizer->Add( plotsizer, 1, wxEXPAND );
612
981b2508
RR
613 SetAutoLayout( TRUE );
614 SetSizer( mainsizer );
615
616 SetTargetWindow( m_area );
617
618 SetBackgroundColour( *wxWHITE );
279ababf 619
981b2508
RR
620 m_current = (wxPlotCurve*) NULL;
621}
622
623wxPlotWindow::~wxPlotWindow()
624{
625}
626
627void wxPlotWindow::Add( wxPlotCurve *curve )
628{
629 m_curves.Append( curve );
630 if (!m_current) m_current = curve;
279ababf
RR
631
632 ResetScrollbar();
981b2508
RR
633}
634
635size_t wxPlotWindow::GetCount()
636{
637 return m_curves.GetCount();
638}
639
640wxPlotCurve *wxPlotWindow::GetAt( size_t n )
641{
642 wxNode *node = m_curves.Nth( n );
643 if (!node)
644 return (wxPlotCurve*) NULL;
279ababf 645
981b2508
RR
646 return (wxPlotCurve*) node->Data();
647}
648
649void wxPlotWindow::SetCurrent( wxPlotCurve* current )
650{
651 m_current = current;
846e1424 652 m_area->Refresh( FALSE );
279ababf 653
d3a809c7 654 RedrawYAxis();
279ababf
RR
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 );
d3a809c7
RR
661}
662
a5a0dd06
RR
663void 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
d3a809c7
RR
674wxPlotCurve *wxPlotWindow::GetCurrent()
675{
676 return m_current;
677}
678
679void wxPlotWindow::Move( wxPlotCurve* curve, int pixels_up )
680{
681 m_area->DeleteCurve( curve );
279ababf 682
d3a809c7 683 curve->SetOffsetY( curve->GetOffsetY() + pixels_up );
279ababf 684
d3a809c7 685 m_area->Refresh( FALSE );
279ababf 686
d3a809c7
RR
687 RedrawYAxis();
688}
689
690void wxPlotWindow::OnMoveUp( wxCommandEvent& WXUNUSED(event) )
691{
692 if (!m_current) return;
279ababf 693
d3a809c7
RR
694 Move( m_current, 25 );
695}
696
697void wxPlotWindow::OnMoveDown( wxCommandEvent& WXUNUSED(event) )
698{
699 if (!m_current) return;
279ababf 700
d3a809c7
RR
701 Move( m_current, -25 );
702}
703
704void wxPlotWindow::Enlarge( wxPlotCurve *curve, double factor )
705{
706 m_area->DeleteCurve( curve );
279ababf 707
530a7383
RR
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
d3a809c7 713 double range = curve->GetEndY() - curve->GetStartY();
530a7383
RR
714 offset *= range;
715
279ababf 716 double new_range = range / factor;
530a7383
RR
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 }
279ababf 731
d3a809c7 732 m_area->Refresh( FALSE );
d3a809c7
RR
733 RedrawYAxis();
734}
735
279ababf 736void wxPlotWindow::SetUnitsPerValue( double upv )
d3a809c7 737{
279ababf
RR
738 m_xUnitsPerValue = upv;
739
740 RedrawXAxis();
d3a809c7
RR
741}
742
279ababf 743void wxPlotWindow::SetZoom( double zoom )
d3a809c7 744{
279ababf
RR
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 }
530a7383
RR
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 );
06b466c7 765
279ababf
RR
766 RedrawXAxis();
767 m_area->Refresh( TRUE );
d3a809c7
RR
768}
769
279ababf 770void wxPlotWindow::ResetScrollbar()
d3a809c7 771{
279ababf
RR
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
530a7383
RR
782 SetScrollbars( wxPLOT_SCROLL_STEP, wxPLOT_SCROLL_STEP,
783 ((max*m_xZoom)/wxPLOT_SCROLL_STEP)+1, 0 );
d3a809c7
RR
784}
785
279ababf 786void wxPlotWindow::RedrawXAxis()
d3a809c7 787{
279ababf
RR
788 if (m_xaxis)
789 m_xaxis->Refresh( FALSE );
d3a809c7
RR
790}
791
792void wxPlotWindow::RedrawYAxis()
793{
279ababf
RR
794 if (m_yaxis)
795 m_yaxis->Refresh( TRUE );
796}
06b466c7 797
279ababf
RR
798void 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}
06b466c7 806
279ababf
RR
807void wxPlotWindow::OnZoomIn( wxCommandEvent& WXUNUSED(event) )
808{
809 SetZoom( m_xZoom * 1.5 );
981b2508
RR
810}
811
279ababf 812void wxPlotWindow::OnZoomOut( wxCommandEvent& WXUNUSED(event) )
981b2508 813{
279ababf
RR
814 SetZoom( m_xZoom * 0.6666 );
815}
06b466c7 816
279ababf
RR
817void wxPlotWindow::OnEnlarge( wxCommandEvent& WXUNUSED(event) )
818{
981b2508 819 if (!m_current) return;
279ababf
RR
820
821 Enlarge( m_current, 1.5 );
822}
06b466c7 823
279ababf
RR
824void wxPlotWindow::OnShrink( wxCommandEvent& WXUNUSED(event) )
825{
826 if (!m_current) return;
827
828 Enlarge( m_current, 0.6666666 );
829}
981b2508 830
279ababf
RR
831void wxPlotWindow::OnScroll2( wxScrollWinEvent& event )
832{
530a7383
RR
833 if ((!m_scrollOnThumbRelease) || (event.GetEventType() != wxEVT_SCROLLWIN_THUMBTRACK))
834 {
835 wxScrolledWindow::OnScroll( event );
836 RedrawXAxis();
837 }
279ababf 838}
06b466c7 839
279ababf
RR
840// ----------------------------------------------------------------------------
841// global functions
842// ----------------------------------------------------------------------------
06b466c7 843
279ababf
RR
844// FIXME MT-UNSAFE
845static wxBitmap *GetEnlargeBitmap()
846{
847 static wxBitmap* s_bitmap = (wxBitmap *) NULL;
848 static bool s_loaded = FALSE;
849
850 if ( !s_loaded )
846e1424 851 {
279ababf
RR
852 s_loaded = TRUE; // set it to TRUE anyhow, we won't try again
853
854 #if defined(__WXMSW__) || defined(__WXPM__)
1265b12a 855 s_bitmap = new wxBitmap("plot_enl_bmp", wxBITMAP_TYPE_RESOURCE);
279ababf
RR
856 #else
857 s_bitmap = new wxBitmap( plot_enl_xpm );
858 #endif
846e1424 859 }
279ababf
RR
860
861 return s_bitmap;
862}
863
864static wxBitmap *GetShrinkBitmap()
865{
866 static wxBitmap* s_bitmap = (wxBitmap *) NULL;
867 static bool s_loaded = FALSE;
868
869 if ( !s_loaded )
846e1424 870 {
279ababf
RR
871 s_loaded = TRUE; // set it to TRUE anyhow, we won't try again
872
873 #if defined(__WXMSW__) || defined(__WXPM__)
cacc9dae 874 s_bitmap = new wxBitmap("plot_shr_bmp", wxBITMAP_TYPE_RESOURCE);
279ababf
RR
875 #else
876 s_bitmap = new wxBitmap( plot_shr_xpm );
877 #endif
846e1424 878 }
06b466c7 879
279ababf
RR
880 return s_bitmap;
881}
882
883static wxBitmap *GetZoomInBitmap()
884{
885 static wxBitmap* s_bitmap = (wxBitmap *) NULL;
886 static bool s_loaded = FALSE;
887
888 if ( !s_loaded )
d3a809c7 889 {
279ababf
RR
890 s_loaded = TRUE; // set it to TRUE anyhow, we won't try again
891
892 #if defined(__WXMSW__) || defined(__WXPM__)
cacc9dae 893 s_bitmap = new wxBitmap("plot_zin_bmp", wxBITMAP_TYPE_RESOURCE);
279ababf
RR
894 #else
895 s_bitmap = new wxBitmap( plot_zin_xpm );
896 #endif
d3a809c7 897 }
06b466c7 898
279ababf
RR
899 return s_bitmap;
900}
901
902static wxBitmap *GetZoomOutBitmap()
903{
904 static wxBitmap* s_bitmap = (wxBitmap *) NULL;
905 static bool s_loaded = FALSE;
906
907 if ( !s_loaded )
846e1424 908 {
279ababf
RR
909 s_loaded = TRUE; // set it to TRUE anyhow, we won't try again
910
911 #if defined(__WXMSW__) || defined(__WXPM__)
cacc9dae 912 s_bitmap = new wxBitmap("plot_zot_bmp", wxBITMAP_TYPE_RESOURCE);
279ababf
RR
913 #else
914 s_bitmap = new wxBitmap( plot_zot_xpm );
915 #endif
846e1424 916 }
06b466c7 917
279ababf
RR
918 return s_bitmap;
919}
920
921static wxBitmap *GetUpBitmap()
922{
923 static wxBitmap* s_bitmap = (wxBitmap *) NULL;
924 static bool s_loaded = FALSE;
925
926 if ( !s_loaded )
846e1424 927 {
279ababf 928 s_loaded = TRUE; // set it to TRUE anyhow, we won't try again
846e1424 929
279ababf 930 #if defined(__WXMSW__) || defined(__WXPM__)
1265b12a
JS
931 s_bitmap = new wxBitmap("plot_up_bmp", wxBITMAP_TYPE_RESOURCE);
932 #else
279ababf
RR
933 s_bitmap = new wxBitmap( plot_up_xpm );
934 #endif
846e1424 935 }
06b466c7 936
279ababf 937 return s_bitmap;
981b2508
RR
938}
939
279ababf
RR
940static 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__)
cacc9dae 950 s_bitmap = new wxBitmap("plot_dwn_bmp", wxBITMAP_TYPE_RESOURCE);
279ababf
RR
951 #else
952 s_bitmap = new wxBitmap( plot_dwn_xpm );
953 #endif
954 }
955
956 return s_bitmap;
957}
9b33fe02
VZ
958
959#endif // wxUSE_PLOT