X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/981b25083e41288f142e717f917e709347c34a02..9b1801c19c82340be79810c8b7617b05caa0cd59:/src/generic/plot.cpp diff --git a/src/generic/plot.cpp b/src/generic/plot.cpp index ca02719c09..cf2dfddf96 100644 --- a/src/generic/plot.cpp +++ b/src/generic/plot.cpp @@ -33,15 +33,19 @@ #include "wx/generic/plot.h" +#include + //----------------------------------------------------------------------------- // wxPlotCurve //----------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPlotCurve, wxObject) -wxPlotCurve::wxPlotCurve( int offsetY ) +wxPlotCurve::wxPlotCurve( int offsetY, double startY, double endY ) { m_offsetY = offsetY; + m_startY = startY; + m_endY = endY; } //----------------------------------------------------------------------------- @@ -84,10 +88,14 @@ void wxPlotArea::OnMouse( wxMouseEvent &event ) { wxPlotCurve *curve = (wxPlotCurve*)node->Data(); - wxCoord offset_y = client_height - curve->GetOffsetY(); - - double dy = curve->GetY( x ); - int curve_y = (wxCoord)(-dy * 100) + offset_y - 1; + double double_client_height = (double)client_height; + double range = curve->GetEndY() - curve->GetStartY(); + double end = curve->GetEndY(); + wxCoord offset_y = curve->GetOffsetY(); + + double dy = (end - curve->GetY( x )) / range; + wxCoord curve_y = (wxCoord)(dy * double_client_height) - offset_y - 1; + if ((y-curve_y < 4) && (y-curve_y > -4)) { m_owner->SetCurrent( curve ); @@ -98,11 +106,57 @@ void wxPlotArea::OnMouse( wxMouseEvent &event ) } } -void wxPlotArea::OnPaint( wxPaintEvent &WXUNUSED(event) ) +void wxPlotArea::DeleteCurve( wxPlotCurve *curve, int from, int to ) +{ + wxClientDC dc(this); + m_owner->PrepareDC( dc ); + dc.SetPen( *wxWHITE_PEN ); + DrawCurve( &dc, curve, from, to ); +} + +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; + + 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; + + int start_x = wxMax( from, curve->GetStartX() ); + int end_x = wxMin( to, curve->GetEndX() ); + + start_x = wxMax( view_x, start_x ); + end_x = wxMin( view_x + client_width, end_x ); + + double double_client_height = (double)client_height; + double range = curve->GetEndY() - curve->GetStartY(); + double end = curve->GetEndY(); + wxCoord offset_y = curve->GetOffsetY(); + + wxCoord y=0,last_y=0; + for (int x = start_x; x < end_x; x++) + { + double dy = (end - curve->GetY( x )) / range; + y = (wxCoord)(dy * double_client_height) - offset_y - 1; + + if (x != start_x) + dc->DrawLine( x-1, last_y, x, y ); + + last_y = y; + } +} + +void wxPlotArea::OnPaint( wxPaintEvent &WXUNUSED(event) ) +{ int view_x; int view_y; m_owner->GetViewStart( &view_x, &view_y ); @@ -123,12 +177,14 @@ void wxPlotArea::OnPaint( wxPaintEvent &WXUNUSED(event) ) update_x += view_x; update_y += view_y; +/* if (m_owner->m_current) { dc.SetPen( *wxLIGHT_GREY_PEN ); int base_line = client_height - m_owner->m_current->GetOffsetY(); dc.DrawLine( update_x-1, base_line-1, update_x+update_width+2, base_line-1 ); } +*/ wxNode *node = m_owner->m_curves.First(); while (node) @@ -139,22 +195,9 @@ void wxPlotArea::OnPaint( wxPaintEvent &WXUNUSED(event) ) dc.SetPen( *wxBLACK_PEN ); else dc.SetPen( *wxLIGHT_GREY_PEN ); - wxCoord offset_y = client_height - curve->GetOffsetY(); + + DrawCurve( &dc, curve, update_x-1, update_x+update_width+2 ); - int start_x = wxMax( update_x-1, curve->GetStartX() ); - int end_x = wxMin( update_x+update_width+2, curve->GetEndX() ); - - wxCoord y=0,last_y=0; - for (int x = start_x; x < end_x; x++) - { - double dy = curve->GetY( x ); - y = (wxCoord)(-dy * 100) + offset_y - 1; - - if (x != start_x) - dc.DrawLine( x-1, last_y, x, y ); - - last_y = y; - } node = node->Next(); } upd ++; @@ -177,7 +220,14 @@ void wxPlotArea::OnPaint( wxPaintEvent &WXUNUSED(event) ) IMPLEMENT_DYNAMIC_CLASS(wxPlotWindow, wxScrolledWindow) BEGIN_EVENT_TABLE(wxPlotWindow, wxScrolledWindow) - EVT_PAINT( wxPlotWindow::OnPaint) + EVT_PAINT( wxPlotWindow::OnPaint) + EVT_BUTTON( ID_MOVE_UP, wxPlotWindow::OnMoveUp) + EVT_BUTTON( ID_MOVE_DOWN, wxPlotWindow::OnMoveDown) + + EVT_BUTTON( ID_ENLARGE_100, wxPlotWindow::OnEnlarge100) + EVT_BUTTON( ID_ENLARGE_50, wxPlotWindow::OnEnlarge50) + EVT_BUTTON( ID_SHRINK_50, wxPlotWindow::OnShrink50) + EVT_BUTTON( ID_SHRINK_33, wxPlotWindow::OnShrink33) END_EVENT_TABLE() wxPlotWindow::wxPlotWindow( wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, int flag ) @@ -238,15 +288,9 @@ wxPlotCurve *wxPlotWindow::GetAt( size_t n ) void wxPlotWindow::SetCurrent( wxPlotCurve* current ) { m_current = current; - m_area->Refresh( TRUE ); + m_area->Refresh( FALSE ); - wxPoint pos( m_area->GetPosition() ); - - int client_width; - int client_height; - GetClientSize( &client_width, &client_height); - wxRect rect(pos.x-40,0,40,client_height); - Refresh(TRUE,&rect); + RedrawYAxis(); } wxPlotCurve *wxPlotWindow::GetCurrent() @@ -254,6 +298,86 @@ wxPlotCurve *wxPlotWindow::GetCurrent() return m_current; } +void wxPlotWindow::Move( wxPlotCurve* curve, int pixels_up ) +{ + m_area->DeleteCurve( curve ); + + curve->SetOffsetY( curve->GetOffsetY() + pixels_up ); + + m_area->Refresh( FALSE ); + + RedrawYAxis(); +} + +void wxPlotWindow::OnMoveUp( wxCommandEvent& WXUNUSED(event) ) +{ + if (!m_current) return; + + Move( m_current, 25 ); +} + +void wxPlotWindow::OnMoveDown( wxCommandEvent& WXUNUSED(event) ) +{ + if (!m_current) return; + + Move( m_current, -25 ); +} + +void wxPlotWindow::Enlarge( wxPlotCurve *curve, double factor ) +{ + m_area->DeleteCurve( curve ); + + double range = curve->GetEndY() - curve->GetStartY(); + double new_range = range * factor; + double middle = curve->GetEndY() - range/2; + curve->SetStartY( middle - new_range / 2 ); + curve->SetEndY( middle + new_range / 2 ); + + m_area->Refresh( FALSE ); + + RedrawYAxis(); +} + +void wxPlotWindow::OnEnlarge100( wxCommandEvent& WXUNUSED(event) ) +{ + if (!m_current) return; + + Enlarge( m_current, 2.0 ); +} + +void wxPlotWindow::OnEnlarge50( wxCommandEvent& WXUNUSED(event) ) +{ + if (!m_current) return; + + Enlarge( m_current, 1.5 ); +} + +void wxPlotWindow::OnShrink50( wxCommandEvent& WXUNUSED(event) ) +{ + if (!m_current) return; + + Enlarge( m_current, 0.5 ); +} + +void wxPlotWindow::OnShrink33( wxCommandEvent& WXUNUSED(event) ) +{ + if (!m_current) return; + + Enlarge( m_current, 0.6666666 ); +} + +void wxPlotWindow::RedrawYAxis() +{ + int client_width; + int client_height; + GetClientSize( &client_width, &client_height); + + wxPoint pos( m_area->GetPosition() ); + + wxRect rect(pos.x-45,0,45,client_height); + Refresh(TRUE,&rect); +} + void wxPlotWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) { wxPaintDC dc( this ); @@ -268,11 +392,62 @@ void wxPlotWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) wxPoint pos( m_area->GetPosition() ); - dc.DrawLine( pos.x-15, 5, pos.x-15, client_height-5 ); - dc.DrawLine( pos.x-19, 9, pos.x-15, 5 ); - dc.DrawLine( pos.x-10, 10, pos.x-15, 5 ); + double range = m_current->GetEndY() - m_current->GetStartY(); + double offset = ((double) m_current->GetOffsetY() / (double)client_height ) * range; + double start = m_current->GetStartY() - offset; + double end = m_current->GetEndY() - offset; + int int_log_range = (int)floor( log10( range ) ); + double step = 1.0; + if (int_log_range > 0) + { + for (int i = 0; i < int_log_range; i++) + step *= 10; + } + if (int_log_range < 0) + { + for (int i = 0; i < -int_log_range; i++) + step /= 10; + } + double lower = ceil(start / step) * step; + double upper = floor(end / step) * step; + + // if too few values, shrink size + int steps = (int)ceil((upper-lower)/step); + if (steps < 4) + { + step /= 2; + if (lower-step > start) lower -= step; + if (upper+step < end) upper += step; + } + + // if still too few, again + steps = (int)ceil((upper-lower)/step); + if (steps < 4) + { + step /= 2; + if (lower-step > start) lower -= step; + if (upper+step < end) upper += step; + } + + double current = lower; + while (current < upper+(step/2)) + { + int y = (int)((m_current->GetEndY()-current) / range * (double)client_height) - 1; + y -= m_current->GetOffsetY(); + if ((y > 10) && (y < client_height-7)) + { + dc.DrawLine( pos.x-15, y, pos.x-7, y ); + wxString label; + label.Printf( wxT("%.1f"), current ); + dc.DrawText( label, pos.x-45, y-7 ); + } + + current += step; + } + + dc.DrawLine( pos.x-15, 6, pos.x-15, client_height-5 ); + dc.DrawLine( pos.x-19, 8, pos.x-15, 2 ); + dc.DrawLine( pos.x-10, 9, pos.x-15, 2 ); - int y = client_height - m_current->GetOffsetY() - 1; - dc.DrawLine( pos.x-15, y, pos.x-7, y ); }