1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-31 07:59:27 +02:00

Add generic plot widget.

This widget will be used in the new Compressor2 effect but it is
designed for use in other effects as well.

Signed-off-by: Max Maisel <max.maisel@posteo.de>
This commit is contained in:
Max Maisel 2020-02-14 18:41:18 +01:00
parent 2555b68a04
commit bcdc47bc34
5 changed files with 230 additions and 0 deletions

View File

@ -949,6 +949,8 @@ list( APPEND SOURCES PRIVATE
widgets/Overlay.h
widgets/OverlayPanel.cpp
widgets/OverlayPanel.h
widgets/Plot.cpp
widgets/Plot.h
widgets/PopupMenuTable.cpp
widgets/PopupMenuTable.h
widgets/ProgressDialog.cpp

View File

@ -121,6 +121,7 @@ for registering for changes.
#include "widgets/wxTextCtrlWrapper.h"
#include "AllThemeResources.h"
#include "widgets/Plot.h"
#include "widgets/SliderTextCtrl.h"
#if wxUSE_ACCESSIBILITY
@ -777,6 +778,33 @@ void ShuttleGuiBase::AddConstTextBox(
UpdateSizers();
}
Plot* ShuttleGuiBase::AddPlot( const TranslatableString &Prompt,
double x_min, double x_max, double y_min, double y_max,
const TranslatableString& x_label, const TranslatableString& y_label,
int x_format, int y_format, int count)
{
HandleOptionality( Prompt );
AddPrompt( Prompt );
UseUpId();
if( mShuttleMode != eIsCreating )
return wxDynamicCast(wxWindow::FindWindowById(miId, mpDlg), Plot);
Plot* pPlot;
mpWind = pPlot = safenew Plot(GetParent(), miId,
x_min, x_max, y_min, y_max, x_label, y_label,
x_format, y_format, count,
wxDefaultPosition, wxDefaultSize,
GetStyle( SliderTextCtrl::HORIZONTAL )
);
#if wxUSE_ACCESSIBILITY
// so that name can be set on a standard control
mpWind->SetAccessible(safenew WindowAccessible(mpWind));
#endif
mpWind->SetName(wxStripMenuCodes(Prompt.Translation()));
miProp=1;
UpdateSizers();
return pPlot;
}
wxListBox * ShuttleGuiBase::AddListBox(const wxArrayStringEx &choices)
{
UseUpId();

View File

@ -28,6 +28,7 @@
class ChoiceSetting;
class wxArrayStringEx;
class Plot;
class SliderTextCtrl;
@ -348,6 +349,11 @@ public:
void AddConstTextBox(
const TranslatableString &Caption, const TranslatableString & Value );
Plot* AddPlot( const TranslatableString &Prompt,
double x_min, double x_max, double y_min, double y_max,
const TranslatableString& x_label, const TranslatableString& y_label,
int x_format = 1, int y_format = 1, int count = 1 );
//-- Start and end functions. These are used for sizer, or other window containers
// and create the appropriate widget.
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1);

136
src/widgets/Plot.cpp Normal file
View File

@ -0,0 +1,136 @@
/**********************************************************************
Audacity: A Digital Audio Editor
Plot.cpp
Max Maisel
*******************************************************************//**
\class Plot
\brief A customizable generic plot widget.
*//*******************************************************************/
#include "../Audacity.h"
#include "audacity/Types.h"
#include "Plot.h"
#include "Ruler.h"
#include "../AColor.h"
#include "../Theme.h"
#include "../AllThemeResources.h"
#include <wx/brush.h>
#include <wx/dcclient.h>
#include <wx/dcmemory.h>
Plot::Plot(wxWindow *parent, wxWindowID winid,
float x_min, float x_max, float y_min, float y_max,
const TranslatableString& xlabel, const TranslatableString& ylabel,
int xformat, int yformat, int count,
const wxPoint& pos, const wxSize& size, long style)
:
wxPanelWrapper(parent, winid, pos, size, style),
m_xmin(x_min), m_xmax(x_max), m_ymin(y_min), m_ymax(y_max),
m_plots(count)
{
m_xruler = std::unique_ptr<Ruler>(safenew Ruler);
m_xruler->SetOrientation(wxHORIZONTAL);
m_xruler->SetFormat(static_cast<Ruler::RulerFormat>(xformat));
m_xruler->SetUnits(xlabel);
m_xruler->SetFlip(true);
m_yruler = std::unique_ptr<Ruler>(safenew Ruler);
m_yruler->SetOrientation(wxVERTICAL);
m_yruler->SetFormat(static_cast<Ruler::RulerFormat>(yformat));
m_yruler->SetUnits(ylabel);
}
void Plot::OnPaint(wxPaintEvent & evt)
{
wxPaintDC dc(this);
int width, height;
GetSize(&width, &height);
#if defined(__WXMSW__)
dc.Clear();
#endif
// Ruler
int w = 0;
int h = 0;
m_xruler->SetBounds(0, 0, width, height);
m_xruler->SetRange(m_xmin, m_xmax);
m_xruler->GetMaxSize(NULL, &h);
m_yruler->SetBounds(0, 0, width, height);
m_yruler->SetRange(m_ymax, m_ymin);
m_yruler->GetMaxSize(&w, NULL);
m_xruler->SetBounds(w, height - h, width, height);
m_yruler->SetBounds(0, 0, w, height - h);
m_xruler->SetTickColour( theTheme.Colour( clrGraphLabels ));
m_yruler->SetTickColour( theTheme.Colour( clrGraphLabels ));
wxRect border;
border.x = w;
border.y = 0;
border.width = width - w;
border.height = height - h + 1;
dc.SetBrush(*wxWHITE_BRUSH);
dc.SetPen(*wxTRANSPARENT_PEN);
dc.DrawRectangle(border);
m_xruler->DrawGrid(dc, border.height, true, true, border.x, border.y);
m_yruler->DrawGrid(dc, border.width, true, true, border.x, border.y);
for(const auto& plot : m_plots)
{
wxASSERT(plot.xdata.size() == plot.ydata.size());
if(plot.xdata.size() == 0)
continue;
dc.SetPen(*plot.pen);
size_t xsize = plot.xdata.size();
for(size_t i = 1; i < xsize; ++i)
{
AColor::Line(dc,
XToScreen(plot.xdata[i-1], border),
YToScreen(plot.ydata[i-1], border),
XToScreen(plot.xdata[i], border),
YToScreen(plot.ydata[i], border));
}
}
dc.SetBrush(*wxTRANSPARENT_BRUSH);
dc.SetPen(*wxBLACK_PEN);
dc.DrawRectangle(border);
m_xruler->Draw(dc);
m_yruler->Draw(dc);
}
void Plot::OnSize(wxSizeEvent & evt)
{
Refresh(false);
}
int Plot::XToScreen(float x, wxRect& rect)
{
return rect.x + lrint((x-m_xmin)*rect.width/(m_xmax-m_xmin));
}
int Plot::YToScreen(float y, wxRect& rect)
{
return rect.y + rect.height - lrint((y-m_ymin)*rect.height/(m_ymax-m_ymin));
}
BEGIN_EVENT_TABLE(Plot, wxPanelWrapper)
EVT_PAINT(Plot::OnPaint)
EVT_SIZE(Plot::OnSize)
END_EVENT_TABLE()

58
src/widgets/Plot.h Normal file
View File

@ -0,0 +1,58 @@
/**********************************************************************
Audacity: A Digital Audio Editor
Plot.h
Max Maisel
This class is a generic plot.
**********************************************************************/
#ifndef __AUDACITY_PLOT__
#define __AUDACITY_PLOT__
#include "wxPanelWrapper.h" // to inherit
#include "MemoryX.h"
class Ruler;
struct PlotData
{
std::unique_ptr<wxPen> pen;
std::vector<float> xdata;
std::vector<float> ydata;
};
class Plot : public wxPanelWrapper
{
public:
Plot(wxWindow *parent, wxWindowID winid,
float x_min, float x_max, float y_min, float y_max,
const TranslatableString& xlabel, const TranslatableString& ylabel,
int xformat = 1, int yformat = 1, //Ruler::RealFormat
int count = 1, const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL | wxNO_BORDER);
inline PlotData* GetPlotData(int id)
{ return &m_plots[id]; }
private:
void OnPaint(wxPaintEvent & evt);
void OnSize(wxSizeEvent & evt);
float m_xmin, m_xmax;
float m_ymin, m_ymax;
std::vector<PlotData> m_plots;
std::unique_ptr<Ruler> m_xruler, m_yruler;
int XToScreen(float x, wxRect& rect);
int YToScreen(float y, wxRect& rect);
DECLARE_EVENT_TABLE()
};
#endif