X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/cacc9daee943655de037c2140dd983a1d0987890..c6e7d14fa96da41236095a18ee8c1e3ad13d3dd0:/src/generic/plot.cpp diff --git a/src/generic/plot.cpp b/src/generic/plot.cpp index 9f91b67505..2ae40ff7ec 100644 --- a/src/generic/plot.cpp +++ b/src/generic/plot.cpp @@ -20,6 +20,8 @@ #pragma hdrstop #endif +#if wxUSE_PLOT + #ifndef WX_PRECOMP #include "wx/object.h" #include "wx/font.h" @@ -60,6 +62,12 @@ static wxBitmap *GetZoomOutBitmap(); static wxBitmap *GetUpBitmap(); static wxBitmap *GetDownBitmap(); +//----------------------------------------------------------------------------- +// consts +//----------------------------------------------------------------------------- + +#define wxPLOT_SCROLL_STEP 30 + //----------------------------------------------------------------------------- // wxPlotEvent //----------------------------------------------------------------------------- @@ -85,6 +93,79 @@ wxPlotCurve::wxPlotCurve( int offsetY, double startY, double endY ) m_endY = endY; } +//----------------------------------------------------------------------------- +// wxPlotOnOffCurve +//----------------------------------------------------------------------------- + +IMPLEMENT_CLASS(wxPlotOnOffCurve, wxObject) + +#include "wx/arrimpl.cpp" +WX_DEFINE_OBJARRAY(wxArrayPlotOnOff); + +wxPlotOnOffCurve::wxPlotOnOffCurve( int offsetY ) +{ + m_offsetY = offsetY; + m_minX = -1; + m_maxX = -1; +} + +void wxPlotOnOffCurve::Add( wxInt32 on, wxInt32 off, void *clientData ) +{ + wxASSERT_MSG( on > 0, wxT("plot index < 0") ); + wxASSERT( on <= off ); + + if (m_minX == -1) + m_minX = on; + if (off > m_maxX) + m_maxX = off; + + wxPlotOnOff *v = new wxPlotOnOff; + v->m_on = on; + v->m_off = off; + v->m_clientData = clientData; + m_marks.Add( v ); +} + +size_t wxPlotOnOffCurve::GetCount() +{ + return m_marks.GetCount(); +} + +wxInt32 wxPlotOnOffCurve::GetOn( size_t index ) +{ + wxPlotOnOff *v = &m_marks.Item( index ); + return v->m_on; +} + +wxInt32 wxPlotOnOffCurve::GetOff( size_t index ) +{ + wxPlotOnOff *v = &m_marks.Item( index ); + return v->m_off; +} + +void* wxPlotOnOffCurve::GetClientData( size_t index ) +{ + wxPlotOnOff *v = &m_marks.Item( index ); + return v->m_clientData; +} + +wxPlotOnOff *wxPlotOnOffCurve::GetAt( size_t index ) +{ + return &m_marks.Item( index ); +} + +void wxPlotOnOffCurve::DrawOnLine( wxDC &dc, wxCoord y, wxCoord start, wxCoord end, void *WXUNUSED(clientData) ) +{ + dc.DrawLine( start, y, start, y-30 ); + dc.DrawLine( start, y-30, end, y-30 ); + dc.DrawLine( end, y-30, end, y ); +} + +void wxPlotOnOffCurve::DrawOffLine( wxDC &dc, wxCoord y, wxCoord start, wxCoord end ) +{ + dc.DrawLine( start, y, end, y ); +} + //----------------------------------------------------------------------------- // wxPlotArea //----------------------------------------------------------------------------- @@ -115,11 +196,11 @@ void wxPlotArea::OnMouse( wxMouseEvent &event ) int view_x; int view_y; m_owner->GetViewStart( &view_x, &view_y ); - view_x *= 10; - view_y *= 10; + view_x *= wxPLOT_SCROLL_STEP; + view_y *= wxPLOT_SCROLL_STEP; - int x = event.GetX(); - int y = event.GetY(); + wxCoord x = event.GetX(); + wxCoord y = event.GetY(); x += view_x; y += view_y; @@ -133,7 +214,7 @@ void wxPlotArea::OnMouse( wxMouseEvent &event ) double end = curve->GetEndY(); wxCoord offset_y = curve->GetOffsetY(); - double dy = (end - curve->GetY( x/m_owner->GetZoom() )) / range; + double dy = (end - curve->GetY( (wxInt32)(x/m_owner->GetZoom()) )) / range; wxCoord curve_y = (wxCoord)(dy * double_client_height) - offset_y - 1; if ((y-curve_y < 4) && (y-curve_y > -4)) @@ -145,7 +226,7 @@ void wxPlotArea::OnMouse( wxMouseEvent &event ) event1.SetPosition( (int)floor(x/m_owner->GetZoom()) ); m_owner->GetEventHandler()->ProcessEvent( event1 ); - if (curve != m_owner->GetCurrent()); + if (curve != m_owner->GetCurrent()) { wxPlotEvent event2( wxEVT_PLOT_SEL_CHANGING, m_owner->GetId() ); event2.SetEventObject( m_owner ); @@ -176,7 +257,7 @@ void wxPlotArea::DrawCurve( wxDC *dc, wxPlotCurve *curve, int from, int to ) int view_x; int view_y; m_owner->GetViewStart( &view_x, &view_y ); - view_x *= 10; + view_x *= wxPLOT_SCROLL_STEP; if (from == -1) from = view_x; @@ -187,7 +268,7 @@ void wxPlotArea::DrawCurve( wxDC *dc, wxPlotCurve *curve, int from, int to ) if (to == -1) to = view_x + client_width; - + double zoom = m_owner->GetZoom(); int start_x = wxMax( from, (int)floor(curve->GetStartX()*zoom) ); @@ -196,6 +277,8 @@ void wxPlotArea::DrawCurve( wxDC *dc, wxPlotCurve *curve, int from, int to ) start_x = wxMax( view_x, start_x ); end_x = wxMin( view_x + client_width, end_x ); + end_x++; + double double_client_height = (double)client_height; double range = curve->GetEndY() - curve->GetStartY(); double end = curve->GetEndY(); @@ -204,7 +287,7 @@ void wxPlotArea::DrawCurve( wxDC *dc, wxPlotCurve *curve, int from, int to ) wxCoord y=0,last_y=0; for (int x = start_x; x < end_x; x++) { - double dy = (end - curve->GetY( x/zoom )) / range; + double dy = (end - curve->GetY( (wxInt32)(x/zoom) )) / range; y = (wxCoord)(dy * double_client_height) - offset_y - 1; if (x != start_x) @@ -214,13 +297,73 @@ void wxPlotArea::DrawCurve( wxDC *dc, wxPlotCurve *curve, int from, int to ) } } +void wxPlotArea::DrawOnOffCurve( wxDC *dc, wxPlotOnOffCurve *curve, int from, int to ) +{ + int view_x; + int view_y; + m_owner->GetViewStart( &view_x, &view_y ); + view_x *= wxPLOT_SCROLL_STEP; + + if (from == -1) + from = view_x; + + int client_width; + int client_height; + GetClientSize( &client_width, &client_height); + + if (to == -1) + to = view_x + client_width; + + double zoom = m_owner->GetZoom(); + + int start_x = wxMax( from, (int)floor(curve->GetStartX()*zoom) ); + int end_x = wxMin( to, (int)floor(curve->GetEndX()*zoom) ); + + start_x = wxMax( view_x, start_x ); + end_x = wxMin( view_x + client_width, end_x ); + + end_x++; + + wxCoord offset_y = curve->GetOffsetY(); + wxCoord last_off = -5; + + if (curve->GetCount() == 0) + return; + + for (size_t index = 0; index < curve->GetCount(); index++) + { + wxPlotOnOff *p = curve->GetAt( index ); + + wxCoord on = (wxCoord)(p->m_on*zoom); + wxCoord off = (wxCoord)(p->m_off*zoom); + + if (end_x < on) + { + curve->DrawOffLine( *dc, client_height-offset_y, last_off, on ); + break; + } + + if (off >= start_x) + { + curve->DrawOffLine( *dc, client_height-offset_y, last_off, on ); + curve->DrawOnLine( *dc, client_height-offset_y, on, off, p->m_clientData ); + } + last_off = off; + } + + wxPlotOnOff *p = curve->GetAt( curve->GetCount()-1 ); + wxCoord off = (wxCoord)(p->m_off*zoom); + if (off < end_x) + curve->DrawOffLine( *dc, client_height-offset_y, off, to ); +} + void wxPlotArea::OnPaint( wxPaintEvent &WXUNUSED(event) ) { int view_x; int view_y; m_owner->GetViewStart( &view_x, &view_y ); - view_x *= 10; - view_y *= 10; + view_x *= wxPLOT_SCROLL_STEP; + view_y *= wxPLOT_SCROLL_STEP; wxPaintDC dc( this ); m_owner->PrepareDC( dc ); @@ -248,7 +391,7 @@ void wxPlotArea::OnPaint( wxPaintEvent &WXUNUSED(event) ) wxNode *node = m_owner->m_curves.First(); while (node) { - wxPlotCurve *curve = (wxPlotCurve*)node->Data(); + wxPlotCurve *curve = (wxPlotCurve*) node->Data(); if (curve == m_owner->GetCurrent()) dc.SetPen( *wxBLACK_PEN ); @@ -259,6 +402,19 @@ void wxPlotArea::OnPaint( wxPaintEvent &WXUNUSED(event) ) node = node->Next(); } + + dc.SetPen( *wxRED_PEN ); + + node = m_owner->m_onOffCurves.First(); + while (node) + { + wxPlotOnOffCurve *curve = (wxPlotOnOffCurve*) node->Data(); + + DrawOnOffCurve( &dc, curve, update_x-1, update_x+update_width+2 ); + + node = node->Next(); + } + upd ++; } } @@ -286,6 +442,7 @@ wxPlotXAxisArea::wxPlotXAxisArea( wxPlotWindow *parent ) m_owner = parent; SetBackgroundColour( *wxWHITE ); + SetFont( *wxSMALL_FONT ); } void wxPlotXAxisArea::OnMouse( wxMouseEvent &event ) @@ -296,11 +453,11 @@ void wxPlotXAxisArea::OnMouse( wxMouseEvent &event ) int view_x; int view_y; m_owner->GetViewStart( &view_x, &view_y ); - view_x *= 10; - view_y *= 10; + view_x *= wxPLOT_SCROLL_STEP; + view_y *= wxPLOT_SCROLL_STEP; - int x = event.GetX(); - int y = event.GetY(); + wxCoord x = event.GetX(); + wxCoord y = event.GetY(); x += view_x; y += view_y; @@ -312,8 +469,8 @@ void wxPlotXAxisArea::OnPaint( wxPaintEvent &WXUNUSED(event) ) int view_x; int view_y; m_owner->GetViewStart( &view_x, &view_y ); - view_x *= 10; - view_y *= 10; + view_x *= wxPLOT_SCROLL_STEP; + view_y *= wxPLOT_SCROLL_STEP; wxPaintDC dc( this ); @@ -374,8 +531,14 @@ void wxPlotXAxisArea::OnPaint( wxPaintEvent &WXUNUSED(event) ) { dc.DrawLine( x, 5, x, 15 ); wxString label; - if (range < 10) - label.Printf( wxT("%.1f"), current ); + if (range < 50) + { + label.Printf( wxT("%f"), current ); + while (label.Last() == wxT('0')) + label.RemoveLast(); + if ((label.Last() == wxT('.')) || (label.Last() == wxT(','))) + label.Append( wxT('0') ); + } else label.Printf( wxT("%d"), (int)floor(current) ); dc.DrawText( label, x-4, 20 ); @@ -406,6 +569,7 @@ wxPlotYAxisArea::wxPlotYAxisArea( wxPlotWindow *parent ) m_owner = parent; SetBackgroundColour( *wxWHITE ); + SetFont( *wxSMALL_FONT ); } void wxPlotYAxisArea::OnMouse( wxMouseEvent &WXUNUSED(event) ) @@ -473,7 +637,16 @@ void wxPlotYAxisArea::OnPaint( wxPaintEvent &WXUNUSED(event) ) { dc.DrawLine( client_width-15, y, client_width-7, y ); wxString label; - label.Printf( wxT("%.1f"), current ); + if (range < 50) + { + label.Printf( wxT("%f"), current ); + while (label.Last() == wxT('0')) + label.RemoveLast(); + if ((label.Last() == wxT('.')) || (label.Last() == wxT(','))) + label.Append( wxT('0') ); + } + else + label.Printf( wxT("%d"), (int)floor(current) ); dc.DrawText( label, 5, y-7 ); } @@ -519,6 +692,9 @@ wxPlotWindow::wxPlotWindow( wxWindow *parent, wxWindowID id, const wxPoint &pos, { m_xUnitsPerValue = 1.0; m_xZoom = 1.0; + + m_enlargeAroundWindowCentre = FALSE; + m_scrollOnThumbRelease = FALSE; m_area = new wxPlotArea( this ); wxBoxSizer *mainsizer = new wxBoxSizer( wxHORIZONTAL ); @@ -646,6 +822,33 @@ wxPlotCurve *wxPlotWindow::GetCurrent() return m_current; } +void wxPlotWindow::Add( wxPlotOnOffCurve *curve ) +{ + m_onOffCurves.Append( curve ); +} + +void wxPlotWindow::Delete( wxPlotOnOffCurve* curve ) +{ + wxNode *node = m_onOffCurves.Find( curve ); + if (!node) return; + + m_onOffCurves.DeleteObject( curve ); +} + +size_t wxPlotWindow::GetOnOffCurveCount() +{ + return m_onOffCurves.GetCount(); +} + +wxPlotOnOffCurve *wxPlotWindow::GetOnOffCurveAt( size_t n ) +{ + wxNode *node = m_onOffCurves.Nth( n ); + if (!node) + return (wxPlotOnOffCurve*) NULL; + + return (wxPlotOnOffCurve*) node->Data(); +} + void wxPlotWindow::Move( wxPlotCurve* curve, int pixels_up ) { m_area->DeleteCurve( curve ); @@ -675,11 +878,29 @@ void wxPlotWindow::Enlarge( wxPlotCurve *curve, double factor ) { m_area->DeleteCurve( curve ); + int client_width; + int client_height; + m_area->GetClientSize( &client_width, &client_height); + double offset = (double)curve->GetOffsetY() / (double)client_height; + double range = curve->GetEndY() - curve->GetStartY(); + offset *= range; + double new_range = range / factor; - double middle = curve->GetEndY() - range/2; - curve->SetStartY( middle - new_range / 2 ); - curve->SetEndY( middle + new_range / 2 ); + double new_offset = offset / factor; + + if (m_enlargeAroundWindowCentre) + { + double middle = curve->GetStartY() - offset + range/2; + + curve->SetStartY( middle - new_range / 2 + new_offset ); + curve->SetEndY( middle + new_range / 2 + new_offset ); + } + else + { + curve->SetStartY( (curve->GetStartY() - offset)/factor + new_offset ); + curve->SetEndY( (curve->GetEndY() - offset)/factor + new_offset ); + } m_area->Refresh( FALSE ); RedrawYAxis(); @@ -710,7 +931,10 @@ void wxPlotWindow::SetZoom( double zoom ) max = curve->GetEndX(); node = node->Next(); } - SetScrollbars( 10, 10, (int)((max*m_xZoom)/10)+1, 0, (int)view_x*zoom/old_zoom, 0 ); + SetScrollbars( wxPLOT_SCROLL_STEP, wxPLOT_SCROLL_STEP, + (int)((max*m_xZoom)/wxPLOT_SCROLL_STEP)+1, 0, + (int)(view_x*zoom/old_zoom), 0, + TRUE ); RedrawXAxis(); m_area->Refresh( TRUE ); @@ -728,7 +952,8 @@ void wxPlotWindow::ResetScrollbar() node = node->Next(); } - SetScrollbars( 10, 10, ((max*m_xZoom)/10)+1, 0 ); + SetScrollbars( wxPLOT_SCROLL_STEP, wxPLOT_SCROLL_STEP, + (int)(((max*m_xZoom)/wxPLOT_SCROLL_STEP)+1), 0 ); } void wxPlotWindow::RedrawXAxis() @@ -778,9 +1003,11 @@ void wxPlotWindow::OnShrink( wxCommandEvent& WXUNUSED(event) ) void wxPlotWindow::OnScroll2( wxScrollWinEvent& event ) { - wxScrolledWindow::OnScroll( event ); - - RedrawXAxis(); + if ((!m_scrollOnThumbRelease) || (event.GetEventType() != wxEVT_SCROLLWIN_THUMBTRACK)) + { + wxScrolledWindow::OnScroll( event ); + RedrawXAxis(); + } } // ---------------------------------------------------------------------------- @@ -798,7 +1025,7 @@ static wxBitmap *GetEnlargeBitmap() s_loaded = TRUE; // set it to TRUE anyhow, we won't try again #if defined(__WXMSW__) || defined(__WXPM__) - s_bitmap = new wxBitmap("plot_enl_bmp", wxBITMAP_TYPE_RESOURCE); + s_bitmap = new wxBitmap("plot_enl_bmp", wxBITMAP_TYPE_RESOURCE); #else s_bitmap = new wxBitmap( plot_enl_xpm ); #endif @@ -874,8 +1101,8 @@ static wxBitmap *GetUpBitmap() s_loaded = TRUE; // set it to TRUE anyhow, we won't try again #if defined(__WXMSW__) || defined(__WXPM__) - s_bitmap = new wxBitmap("plot_up_bmp", wxBITMAP_TYPE_RESOURCE); - #else + s_bitmap = new wxBitmap("plot_up_bmp", wxBITMAP_TYPE_RESOURCE); + #else s_bitmap = new wxBitmap( plot_up_xpm ); #endif } @@ -901,3 +1128,5 @@ static wxBitmap *GetDownBitmap() return s_bitmap; } + +#endif // wxUSE_PLOT