]>
git.saurik.com Git - wxWidgets.git/blob - src/generic/plot.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxPlotWindow
4 // Author: Robert Roebling
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "plot.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
24 #include "wx/object.h"
26 #include "wx/colour.h"
27 #include "wx/settings.h"
31 #include "wx/dcclient.h"
34 #include "wx/generic/plot.h"
38 //-----------------------------------------------------------------------------
40 //-----------------------------------------------------------------------------
42 IMPLEMENT_ABSTRACT_CLASS(wxPlotCurve
, wxObject
)
44 wxPlotCurve::wxPlotCurve( int offsetY
, double startY
, double endY
)
51 //-----------------------------------------------------------------------------
53 //-----------------------------------------------------------------------------
55 IMPLEMENT_DYNAMIC_CLASS(wxPlotArea
, wxWindow
)
57 BEGIN_EVENT_TABLE(wxPlotArea
, wxWindow
)
58 EVT_PAINT( wxPlotArea::OnPaint
)
59 EVT_LEFT_DOWN( wxPlotArea::OnMouse
)
62 wxPlotArea::wxPlotArea( wxPlotWindow
*parent
)
63 : wxWindow( parent
, -1, wxDefaultPosition
, wxDefaultSize
, wxSIMPLE_BORDER
, "plotarea" )
67 SetBackgroundColour( *wxWHITE
);
70 void wxPlotArea::OnMouse( wxMouseEvent
&event
)
74 GetClientSize( &client_width
, &client_height
);
77 m_owner
->GetViewStart( &view_x
, &view_y
);
86 wxNode
*node
= m_owner
->m_curves
.First();
89 wxPlotCurve
*curve
= (wxPlotCurve
*)node
->Data();
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();
96 double dy
= (end
- curve
->GetY( x
)) / range
;
97 wxCoord curve_y
= (wxCoord
)(dy
* double_client_height
) - offset_y
- 1;
99 if ((y
-curve_y
< 4) && (y
-curve_y
> -4))
101 m_owner
->SetCurrent( curve
);
109 void wxPlotArea::DeleteCurve( wxPlotCurve
*curve
, int from
, int to
)
112 m_owner
->PrepareDC( dc
);
113 dc
.SetPen( *wxWHITE_PEN
);
114 DrawCurve( &dc
, curve
, from
, to
);
117 void wxPlotArea::DrawCurve( wxDC
*dc
, wxPlotCurve
*curve
, int from
, int to
)
121 m_owner
->GetViewStart( &view_x
, &view_y
);
129 GetClientSize( &client_width
, &client_height
);
132 to
= view_x
+ client_width
;
134 int start_x
= wxMax( from
, curve
->GetStartX() );
135 int end_x
= wxMin( to
, curve
->GetEndX() );
137 start_x
= wxMax( view_x
, start_x
);
138 end_x
= wxMin( view_x
+ client_width
, end_x
);
140 double double_client_height
= (double)client_height
;
141 double range
= curve
->GetEndY() - curve
->GetStartY();
142 double end
= curve
->GetEndY();
143 wxCoord offset_y
= curve
->GetOffsetY();
145 wxCoord y
=0,last_y
=0;
146 for (int x
= start_x
; x
< end_x
; x
++)
148 double dy
= (end
- curve
->GetY( x
)) / range
;
149 y
= (wxCoord
)(dy
* double_client_height
) - offset_y
- 1;
152 dc
->DrawLine( x
-1, last_y
, x
, y
);
158 void wxPlotArea::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
162 m_owner
->GetViewStart( &view_x
, &view_y
);
166 wxPaintDC
dc( this );
167 m_owner
->PrepareDC( dc
);
169 wxRegionIterator
upd( GetUpdateRegion() );
173 int update_x
= upd
.GetX();
174 int update_y
= upd
.GetY();
175 int update_width
= upd
.GetWidth();
181 if (m_owner->m_current)
183 dc.SetPen( *wxLIGHT_GREY_PEN );
184 int base_line = client_height - m_owner->m_current->GetOffsetY();
185 dc.DrawLine( update_x-1, base_line-1, update_x+update_width+2, base_line-1 );
189 wxNode
*node
= m_owner
->m_curves
.First();
192 wxPlotCurve
*curve
= (wxPlotCurve
*)node
->Data();
194 if (curve
== m_owner
->GetCurrent())
195 dc
.SetPen( *wxBLACK_PEN
);
197 dc
.SetPen( *wxLIGHT_GREY_PEN
);
199 DrawCurve( &dc
, curve
, update_x
-1, update_x
+update_width
+2 );
207 //-----------------------------------------------------------------------------
209 //-----------------------------------------------------------------------------
211 #define ID_ENLARGE_100 1000
212 #define ID_ENLARGE_50 1001
213 #define ID_SHRINK_33 1002
214 #define ID_SHRINK_50 1003
216 #define ID_MOVE_UP 1006
217 #define ID_MOVE_DOWN 1007
220 IMPLEMENT_DYNAMIC_CLASS(wxPlotWindow
, wxScrolledWindow
)
222 BEGIN_EVENT_TABLE(wxPlotWindow
, wxScrolledWindow
)
223 EVT_PAINT( wxPlotWindow::OnPaint
)
224 EVT_BUTTON( ID_MOVE_UP
, wxPlotWindow::OnMoveUp
)
225 EVT_BUTTON( ID_MOVE_DOWN
, wxPlotWindow::OnMoveDown
)
227 EVT_BUTTON( ID_ENLARGE_100
, wxPlotWindow::OnEnlarge100
)
228 EVT_BUTTON( ID_ENLARGE_50
, wxPlotWindow::OnEnlarge50
)
229 EVT_BUTTON( ID_SHRINK_50
, wxPlotWindow::OnShrink50
)
230 EVT_BUTTON( ID_SHRINK_33
, wxPlotWindow::OnShrink33
)
233 wxPlotWindow::wxPlotWindow( wxWindow
*parent
, wxWindowID id
, const wxPoint
&pos
, const wxSize
&size
, int flag
)
234 : wxScrolledWindow( parent
, id
, pos
, size
, flag
, "plotcanvas" )
236 m_area
= new wxPlotArea( this );
238 wxBoxSizer
*mainsizer
= new wxBoxSizer( wxHORIZONTAL
);
240 wxBoxSizer
*buttonlist
= new wxBoxSizer( wxVERTICAL
);
241 buttonlist
->Add( new wxButton( this, ID_ENLARGE_100
, _("+ 100%") ), 0, wxEXPAND
|wxALL
, 5 );
242 buttonlist
->Add( new wxButton( this, ID_ENLARGE_50
, _("+ 50%") ), 0, wxEXPAND
|wxALL
, 5 );
243 buttonlist
->Add( new wxButton( this, ID_SHRINK_33
, _("- 33%") ), 0, wxEXPAND
|wxALL
, 5 );
244 buttonlist
->Add( new wxButton( this, ID_SHRINK_50
, _("- 50%") ), 0, wxEXPAND
|wxALL
, 5 );
245 buttonlist
->Add( 20,20, 0 );
246 buttonlist
->Add( new wxButton( this, ID_MOVE_UP
, _("Up") ), 0, wxEXPAND
|wxALL
, 5 );
247 buttonlist
->Add( new wxButton( this, ID_MOVE_DOWN
, _("Down") ), 0, wxEXPAND
|wxALL
, 5 );
248 buttonlist
->Add( 20,20, 1 );
250 mainsizer
->Add( buttonlist
, 0, wxEXPAND
);
252 mainsizer
->Add( m_area
, 1, wxEXPAND
|wxLEFT
, 50 );
254 SetAutoLayout( TRUE
);
255 SetSizer( mainsizer
);
257 SetTargetWindow( m_area
);
259 SetBackgroundColour( *wxWHITE
);
261 m_current
= (wxPlotCurve
*) NULL
;
264 wxPlotWindow::~wxPlotWindow()
268 void wxPlotWindow::Add( wxPlotCurve
*curve
)
270 m_curves
.Append( curve
);
271 if (!m_current
) m_current
= curve
;
274 size_t wxPlotWindow::GetCount()
276 return m_curves
.GetCount();
279 wxPlotCurve
*wxPlotWindow::GetAt( size_t n
)
281 wxNode
*node
= m_curves
.Nth( n
);
283 return (wxPlotCurve
*) NULL
;
285 return (wxPlotCurve
*) node
->Data();
288 void wxPlotWindow::SetCurrent( wxPlotCurve
* current
)
291 m_area
->Refresh( FALSE
);
296 wxPlotCurve
*wxPlotWindow::GetCurrent()
301 void wxPlotWindow::Move( wxPlotCurve
* curve
, int pixels_up
)
303 m_area
->DeleteCurve( curve
);
305 curve
->SetOffsetY( curve
->GetOffsetY() + pixels_up
);
307 m_area
->Refresh( FALSE
);
312 void wxPlotWindow::OnMoveUp( wxCommandEvent
& WXUNUSED(event
) )
314 if (!m_current
) return;
316 Move( m_current
, 25 );
319 void wxPlotWindow::OnMoveDown( wxCommandEvent
& WXUNUSED(event
) )
321 if (!m_current
) return;
323 Move( m_current
, -25 );
326 void wxPlotWindow::Enlarge( wxPlotCurve
*curve
, double factor
)
328 m_area
->DeleteCurve( curve
);
330 double range
= curve
->GetEndY() - curve
->GetStartY();
331 double new_range
= range
* factor
;
332 double middle
= curve
->GetEndY() - range
/2;
333 curve
->SetStartY( middle
- new_range
/ 2 );
334 curve
->SetEndY( middle
+ new_range
/ 2 );
336 m_area
->Refresh( FALSE
);
341 void wxPlotWindow::OnEnlarge100( wxCommandEvent
& WXUNUSED(event
) )
343 if (!m_current
) return;
345 Enlarge( m_current
, 2.0 );
348 void wxPlotWindow::OnEnlarge50( wxCommandEvent
& WXUNUSED(event
) )
350 if (!m_current
) return;
352 Enlarge( m_current
, 1.5 );
355 void wxPlotWindow::OnShrink50( wxCommandEvent
& WXUNUSED(event
) )
357 if (!m_current
) return;
359 Enlarge( m_current
, 0.5 );
362 void wxPlotWindow::OnShrink33( wxCommandEvent
& WXUNUSED(event
) )
364 if (!m_current
) return;
366 Enlarge( m_current
, 0.6666666 );
369 void wxPlotWindow::RedrawYAxis()
373 GetClientSize( &client_width
, &client_height
);
375 wxPoint
pos( m_area
->GetPosition() );
377 wxRect
rect(pos
.x
-45,0,45,client_height
);
381 void wxPlotWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
383 wxPaintDC
dc( this );
385 if (!m_current
) return;
389 GetClientSize( &client_width
, &client_height
);
391 dc
.SetPen( *wxBLACK_PEN
);
393 wxPoint
pos( m_area
->GetPosition() );
395 double range
= m_current
->GetEndY() - m_current
->GetStartY();
396 double offset
= ((double) m_current
->GetOffsetY() / (double)client_height
) * range
;
397 double start
= m_current
->GetStartY() - offset
;
398 double end
= m_current
->GetEndY() - offset
;
399 int int_log_range
= (int)floor( log10( range
) );
401 if (int_log_range
> 0)
403 for (int i
= 0; i
< int_log_range
; i
++)
406 if (int_log_range
< 0)
408 for (int i
= 0; i
< -int_log_range
; i
++)
411 double lower
= ceil(start
/ step
) * step
;
412 double upper
= floor(end
/ step
) * step
;
414 // if too few values, shrink size
415 int steps
= (int)ceil((upper
-lower
)/step
);
419 if (lower
-step
> start
) lower
-= step
;
420 if (upper
+step
< end
) upper
+= step
;
423 // if still too few, again
424 steps
= (int)ceil((upper
-lower
)/step
);
428 if (lower
-step
> start
) lower
-= step
;
429 if (upper
+step
< end
) upper
+= step
;
432 double current
= lower
;
433 while (current
< upper
+(step
/2))
435 int y
= (int)((m_current
->GetEndY()-current
) / range
* (double)client_height
) - 1;
436 y
-= m_current
->GetOffsetY();
437 if ((y
> 10) && (y
< client_height
-7))
439 dc
.DrawLine( pos
.x
-15, y
, pos
.x
-7, y
);
441 label
.Printf( "%.1f", current
);
442 dc
.DrawText( label
, pos
.x
-45, y
-7 );
448 dc
.DrawLine( pos
.x
-15, 6, pos
.x
-15, client_height
-5 );
449 dc
.DrawLine( pos
.x
-19, 8, pos
.x
-15, 2 );
450 dc
.DrawLine( pos
.x
-10, 9, pos
.x
-15, 2 );