]>
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
);
81 wxPoint pos
= event
.GetPosition();
87 wxNode
*node
= m_owner
->m_curves
.First();
90 wxPlotCurve
*curve
= (wxPlotCurve
*)node
->Data();
92 double double_client_height
= (double)client_height
;
93 double range
= curve
->GetEndY() - curve
->GetStartY();
94 double end
= curve
->GetEndY();
95 wxCoord offset_y
= curve
->GetOffsetY();
97 double dy
= (end
- curve
->GetY( x
)) / range
;
98 wxCoord curve_y
= (wxCoord
)(dy
* double_client_height
) - offset_y
- 1;
100 if ((y
-curve_y
< 4) && (y
-curve_y
> -4))
102 m_owner
->SetCurrent( curve
);
110 void wxPlotArea::DeleteCurve( wxPlotCurve
*curve
, int from
, int to
)
113 m_owner
->PrepareDC( dc
);
114 dc
.SetPen( *wxWHITE_PEN
);
115 DrawCurve( &dc
, curve
, from
, to
);
118 void wxPlotArea::DrawCurve( wxDC
*dc
, wxPlotCurve
*curve
, int from
, int to
)
122 m_owner
->GetViewStart( &view_x
, &view_y
);
130 GetClientSize( &client_width
, &client_height
);
133 to
= view_x
+ client_width
;
135 int start_x
= wxMax( from
, curve
->GetStartX() );
136 int end_x
= wxMin( to
, curve
->GetEndX() );
138 start_x
= wxMax( view_x
, start_x
);
139 end_x
= wxMin( view_x
+ client_width
, end_x
);
141 double double_client_height
= (double)client_height
;
142 double range
= curve
->GetEndY() - curve
->GetStartY();
143 double end
= curve
->GetEndY();
144 wxCoord offset_y
= curve
->GetOffsetY();
146 wxCoord y
=0,last_y
=0;
147 for (int x
= start_x
; x
< end_x
; x
++)
149 double dy
= (end
- curve
->GetY( x
)) / range
;
150 y
= (wxCoord
)(dy
* double_client_height
) - offset_y
- 1;
153 dc
->DrawLine( x
-1, last_y
, x
, y
);
159 void wxPlotArea::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
163 m_owner
->GetViewStart( &view_x
, &view_y
);
167 wxPaintDC
dc( this );
168 m_owner
->PrepareDC( dc
);
170 wxRegionIterator
upd( GetUpdateRegion() );
174 int update_x
= upd
.GetX();
175 int update_y
= upd
.GetY();
176 int update_width
= upd
.GetWidth();
182 if (m_owner->m_current)
184 dc.SetPen( *wxLIGHT_GREY_PEN );
185 int base_line = client_height - m_owner->m_current->GetOffsetY();
186 dc.DrawLine( update_x-1, base_line-1, update_x+update_width+2, base_line-1 );
190 wxNode
*node
= m_owner
->m_curves
.First();
193 wxPlotCurve
*curve
= (wxPlotCurve
*)node
->Data();
195 if (curve
== m_owner
->GetCurrent())
196 dc
.SetPen( *wxBLACK_PEN
);
198 dc
.SetPen( *wxLIGHT_GREY_PEN
);
200 DrawCurve( &dc
, curve
, update_x
-1, update_x
+update_width
+2 );
208 //-----------------------------------------------------------------------------
210 //-----------------------------------------------------------------------------
212 #define ID_ENLARGE_100 1000
213 #define ID_ENLARGE_50 1001
214 #define ID_SHRINK_33 1002
215 #define ID_SHRINK_50 1003
217 #define ID_MOVE_UP 1006
218 #define ID_MOVE_DOWN 1007
221 IMPLEMENT_DYNAMIC_CLASS(wxPlotWindow
, wxScrolledWindow
)
223 BEGIN_EVENT_TABLE(wxPlotWindow
, wxScrolledWindow
)
224 EVT_PAINT( wxPlotWindow::OnPaint
)
225 EVT_BUTTON( ID_MOVE_UP
, wxPlotWindow::OnMoveUp
)
226 EVT_BUTTON( ID_MOVE_DOWN
, wxPlotWindow::OnMoveDown
)
228 EVT_BUTTON( ID_ENLARGE_100
, wxPlotWindow::OnEnlarge100
)
229 EVT_BUTTON( ID_ENLARGE_50
, wxPlotWindow::OnEnlarge50
)
230 EVT_BUTTON( ID_SHRINK_50
, wxPlotWindow::OnShrink50
)
231 EVT_BUTTON( ID_SHRINK_33
, wxPlotWindow::OnShrink33
)
234 wxPlotWindow::wxPlotWindow( wxWindow
*parent
, wxWindowID id
, const wxPoint
&pos
, const wxSize
&size
, int flag
)
235 : wxScrolledWindow( parent
, id
, pos
, size
, flag
, "plotcanvas" )
237 m_area
= new wxPlotArea( this );
239 wxBoxSizer
*mainsizer
= new wxBoxSizer( wxHORIZONTAL
);
241 wxBoxSizer
*buttonlist
= new wxBoxSizer( wxVERTICAL
);
242 buttonlist
->Add( new wxButton( this, ID_ENLARGE_100
, _("+ 100%") ), 0, wxEXPAND
|wxALL
, 5 );
243 buttonlist
->Add( new wxButton( this, ID_ENLARGE_50
, _("+ 50%") ), 0, wxEXPAND
|wxALL
, 5 );
244 buttonlist
->Add( new wxButton( this, ID_SHRINK_33
, _("- 33%") ), 0, wxEXPAND
|wxALL
, 5 );
245 buttonlist
->Add( new wxButton( this, ID_SHRINK_50
, _("- 50%") ), 0, wxEXPAND
|wxALL
, 5 );
246 buttonlist
->Add( 20,20, 0 );
247 buttonlist
->Add( new wxButton( this, ID_MOVE_UP
, _("Up") ), 0, wxEXPAND
|wxALL
, 5 );
248 buttonlist
->Add( new wxButton( this, ID_MOVE_DOWN
, _("Down") ), 0, wxEXPAND
|wxALL
, 5 );
249 buttonlist
->Add( 20,20, 1 );
251 mainsizer
->Add( buttonlist
, 0, wxEXPAND
);
253 mainsizer
->Add( m_area
, 1, wxEXPAND
|wxLEFT
, 50 );
255 SetAutoLayout( TRUE
);
256 SetSizer( mainsizer
);
258 SetTargetWindow( m_area
);
260 SetBackgroundColour( *wxWHITE
);
262 m_current
= (wxPlotCurve
*) NULL
;
265 wxPlotWindow::~wxPlotWindow()
269 void wxPlotWindow::Add( wxPlotCurve
*curve
)
271 m_curves
.Append( curve
);
272 if (!m_current
) m_current
= curve
;
275 size_t wxPlotWindow::GetCount()
277 return m_curves
.GetCount();
280 wxPlotCurve
*wxPlotWindow::GetAt( size_t n
)
282 wxNode
*node
= m_curves
.Nth( n
);
284 return (wxPlotCurve
*) NULL
;
286 return (wxPlotCurve
*) node
->Data();
289 void wxPlotWindow::SetCurrent( wxPlotCurve
* current
)
292 m_area
->Refresh( FALSE
);
297 wxPlotCurve
*wxPlotWindow::GetCurrent()
302 void wxPlotWindow::Move( wxPlotCurve
* curve
, int pixels_up
)
304 m_area
->DeleteCurve( curve
);
306 curve
->SetOffsetY( curve
->GetOffsetY() + pixels_up
);
308 m_area
->Refresh( FALSE
);
313 void wxPlotWindow::OnMoveUp( wxCommandEvent
& WXUNUSED(event
) )
315 if (!m_current
) return;
317 Move( m_current
, 25 );
320 void wxPlotWindow::OnMoveDown( wxCommandEvent
& WXUNUSED(event
) )
322 if (!m_current
) return;
324 Move( m_current
, -25 );
327 void wxPlotWindow::Enlarge( wxPlotCurve
*curve
, double factor
)
329 m_area
->DeleteCurve( curve
);
331 double range
= curve
->GetEndY() - curve
->GetStartY();
332 double new_range
= range
* factor
;
333 double middle
= curve
->GetEndY() - range
/2;
334 curve
->SetStartY( middle
- new_range
/ 2 );
335 curve
->SetEndY( middle
+ new_range
/ 2 );
337 m_area
->Refresh( FALSE
);
342 void wxPlotWindow::OnEnlarge100( wxCommandEvent
& WXUNUSED(event
) )
344 if (!m_current
) return;
346 Enlarge( m_current
, 2.0 );
349 void wxPlotWindow::OnEnlarge50( wxCommandEvent
& WXUNUSED(event
) )
351 if (!m_current
) return;
353 Enlarge( m_current
, 1.5 );
356 void wxPlotWindow::OnShrink50( wxCommandEvent
& WXUNUSED(event
) )
358 if (!m_current
) return;
360 Enlarge( m_current
, 0.5 );
363 void wxPlotWindow::OnShrink33( wxCommandEvent
& WXUNUSED(event
) )
365 if (!m_current
) return;
367 Enlarge( m_current
, 0.6666666 );
370 void wxPlotWindow::RedrawYAxis()
374 GetClientSize( &client_width
, &client_height
);
376 wxPoint
pos( m_area
->GetPosition() );
378 wxRect
rect(pos
.x
-45,0,45,client_height
);
382 void wxPlotWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
384 wxPaintDC
dc( this );
386 if (!m_current
) return;
390 GetClientSize( &client_width
, &client_height
);
392 dc
.SetPen( *wxBLACK_PEN
);
394 wxPoint
pos( m_area
->GetPosition() );
396 double range
= m_current
->GetEndY() - m_current
->GetStartY();
397 double offset
= ((double) m_current
->GetOffsetY() / (double)client_height
) * range
;
398 double start
= m_current
->GetStartY() - offset
;
399 double end
= m_current
->GetEndY() - offset
;
400 int int_log_range
= (int)floor( log10( range
) );
402 if (int_log_range
> 0)
404 for (int i
= 0; i
< int_log_range
; i
++)
407 if (int_log_range
< 0)
409 for (int i
= 0; i
< -int_log_range
; i
++)
412 double lower
= ceil(start
/ step
) * step
;
413 double upper
= floor(end
/ step
) * step
;
415 // if too few values, shrink size
416 int steps
= (int)ceil((upper
-lower
)/step
);
420 if (lower
-step
> start
) lower
-= step
;
421 if (upper
+step
< end
) upper
+= step
;
424 // if still too few, again
425 steps
= (int)ceil((upper
-lower
)/step
);
429 if (lower
-step
> start
) lower
-= step
;
430 if (upper
+step
< end
) upper
+= step
;
433 double current
= lower
;
434 while (current
< upper
+(step
/2))
436 int y
= (int)((m_current
->GetEndY()-current
) / range
* (double)client_height
) - 1;
437 y
-= m_current
->GetOffsetY();
438 if ((y
> 10) && (y
< client_height
-7))
440 dc
.DrawLine( pos
.x
-15, y
, pos
.x
-7, y
);
442 label
.Printf( wxT("%.1f"), current
);
443 dc
.DrawText( label
, pos
.x
-45, y
-7 );
449 dc
.DrawLine( pos
.x
-15, 6, pos
.x
-15, client_height
-5 );
450 dc
.DrawLine( pos
.x
-19, 8, pos
.x
-15, 2 );
451 dc
.DrawLine( pos
.x
-10, 9, pos
.x
-15, 2 );