Audacity 3.2.0
ExportMixerPanel.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 ExportMixerPanel.cpp
6
7 Dominic Mazzoni
8
9**********************************************************************/
10
11
12#include "ExportMixerPanel.h"
13
14#include <wx/dcclient.h>
15#include <wx/dcmemory.h>
16
17#include "MixerOptions.h"
18#include "AColor.h"
19
20BEGIN_EVENT_TABLE(ExportMixerPanel, wxPanelWrapper)
22 EVT_MOUSE_EVENTS(ExportMixerPanel::OnMouseEvent)
24
25ExportMixerPanel::ExportMixerPanel( wxWindow *parent, wxWindowID id,
26 MixerOptions::Downmix *mixerSpec,
27 wxArrayString trackNames,
28 const wxPoint& pos, const wxSize& size):
29 wxPanelWrapper(parent, id, pos, size)
30 , mMixerSpec{mixerSpec}
31 , mChannelRects{ mMixerSpec->GetMaxNumChannels() }
32 , mTrackRects{ mMixerSpec->GetNumTracks() }
33{
34 mBitmap = NULL;
35 mWidth = 0;
36 mHeight = 0;
37 mSelectedTrack = mSelectedChannel = -1;
38
39 mTrackNames = trackNames;
40}
41
43{
44}
45
46//set the font on memDC such that text can fit in specified width and height
47void ExportMixerPanel::SetFont(wxMemoryDC &memDC, const wxString &text, int width,
48 int height )
49{
50 int l = 0, u = 13, m, w, h;
51 wxFont font = memDC.GetFont();
52 while( l < u - 1 )
53 {
54 m = ( l + u ) / 2;
55 font.SetPointSize( m );
56 memDC.SetFont( font );
57 memDC.GetTextExtent( text, &w, &h );
58
59 if( w < width && h < height )
60 l = m;
61 else
62 u = m;
63 }
64 font.SetPointSize( l );
65 memDC.SetFont( font );
66}
67
68void ExportMixerPanel::OnPaint(wxPaintEvent & WXUNUSED(event))
69{
70 wxPaintDC dc( this );
71
72 int width, height;
73 GetSize( &width, &height );
74
75 if( !mBitmap || mWidth != width || mHeight != height )
76 {
77 mWidth = width;
78 mHeight = height;
79 mBitmap = std::make_unique<wxBitmap>( mWidth, mHeight,24 );
80 }
81
82 wxColour bkgnd = GetBackgroundColour();
83 wxBrush bkgndBrush( bkgnd, wxBRUSHSTYLE_SOLID );
84
85 wxMemoryDC memDC;
86 memDC.SelectObject( *mBitmap );
87
88 //draw background
89 wxRect bkgndRect;
90 bkgndRect.x = 0;
91 bkgndRect.y = 0;
92 bkgndRect.width = mWidth;
93 bkgndRect.height = mHeight;
94
95 memDC.SetBrush( *wxWHITE_BRUSH );
96 memDC.SetPen( *wxBLACK_PEN );
97 memDC.DrawRectangle( bkgndRect );
98
99 //box dimensions
100 mBoxWidth = mWidth / 6;
101
102 mTrackHeight = ( mHeight * 3 ) / ( mMixerSpec->GetNumTracks() * 4 );
103 if( mTrackHeight > 30 )
104 mTrackHeight = 30;
105
106 mChannelHeight = ( mHeight * 3 ) / ( mMixerSpec->GetNumChannels() * 4 );
107 if( mChannelHeight > 30 )
108 mChannelHeight = 30;
109
110 static double PI = 2 * acos( 0.0 );
111 double angle = atan( ( 3.0 * mHeight ) / mWidth );
112 double radius = mHeight / ( 2.0 * sin( PI - 2.0 * angle ) );
113 double totAngle = ( asin( mHeight / ( 2.0 * radius ) ) * 2.0 );
114
115 //draw tracks
116 memDC.SetBrush( AColor::envelopeBrush );
117 angle = totAngle / ( mMixerSpec->GetNumTracks() + 1 );
118
119 int max = 0, w, h;
120 for( unsigned int i = 1; i < mMixerSpec->GetNumTracks(); i++ )
121 if( mTrackNames[ i ].length() > mTrackNames[ max ].length() )
122 max = i;
123
124 SetFont( memDC, mTrackNames[ max ], mBoxWidth, mTrackHeight );
125
126 for( unsigned int i = 0; i < mMixerSpec->GetNumTracks(); i++ )
127 {
128 mTrackRects[ i ].x = (int)( mBoxWidth * 2 + radius - radius *
129 cos( totAngle / 2.0 - angle * ( i + 1 ) ) - mBoxWidth + 0.5 );
130 mTrackRects[ i ].y = (int)( mHeight * 0.5 - radius *
131 sin( totAngle * 0.5 - angle * ( i + 1.0 ) ) -
132 0.5 * mTrackHeight + 0.5 );
133
134 mTrackRects[ i ].width = mBoxWidth;
135 mTrackRects[ i ].height = mTrackHeight;
136
137 memDC.SetPen( mSelectedTrack == (int)i ? *wxRED_PEN : *wxBLACK_PEN );
138 memDC.DrawRectangle( mTrackRects[ i ] );
139
140 memDC.GetTextExtent( mTrackNames[ i ], &w, &h );
141 memDC.DrawText( mTrackNames[ i ],
142 mTrackRects[ i ].x + ( mBoxWidth - w ) / 2,
143 mTrackRects[ i ].y + ( mTrackHeight - h ) / 2 );
144 }
145
146 //draw channels
147 memDC.SetBrush( AColor::playRegionBrush[ 0 ] );
148 angle = ( asin( mHeight / ( 2.0 * radius ) ) * 2.0 ) /
149 ( mMixerSpec->GetNumChannels() + 1 );
150
151 SetFont( memDC, wxT( "Channel: XX" ), mBoxWidth, mChannelHeight );
152 memDC.GetTextExtent( wxT( "Channel: XX" ), &w, &h );
153
154 for( unsigned int i = 0; i < mMixerSpec->GetNumChannels(); i++ )
155 {
156 mChannelRects[ i ].x = (int)( mBoxWidth * 4 - radius + radius *
157 cos( totAngle * 0.5 - angle * ( i + 1 ) ) + 0.5 );
158 mChannelRects[ i ].y = (int)( mHeight * 0.5 - radius *
159 sin( totAngle * 0.5 - angle * ( i + 1 ) ) -
160 0.5 * mChannelHeight + 0.5 );
161
162 mChannelRects[ i ].width = mBoxWidth;
163 mChannelRects[ i ].height = mChannelHeight;
164
165 memDC.SetPen( mSelectedChannel == (int)i ? *wxRED_PEN : *wxBLACK_PEN );
166 memDC.DrawRectangle( mChannelRects[ i ] );
167
168 memDC.DrawText( wxString::Format( _( "Channel: %2d" ), i + 1 ),
169 mChannelRects[ i ].x + ( mBoxWidth - w ) / 2,
170 mChannelRects[ i ].y + ( mChannelHeight - h ) / 2 );
171 }
172
173 //draw links
174 memDC.SetPen( wxPen( *wxBLACK, mHeight / 200 ) );
175 for( unsigned int i = 0; i < mMixerSpec->GetNumTracks(); i++ )
176 for( unsigned int j = 0; j < mMixerSpec->GetNumChannels(); j++ )
177 if( mMixerSpec->mMap[ i ][ j ] )
178 AColor::Line(memDC, mTrackRects[ i ].x + mBoxWidth,
179 mTrackRects[ i ].y + mTrackHeight / 2, mChannelRects[ j ].x,
180 mChannelRects[ j ].y + mChannelHeight / 2 );
181
182 dc.Blit( 0, 0, mWidth, mHeight, &memDC, 0, 0, wxCOPY, FALSE );
183}
184
185double ExportMixerPanel::Distance( wxPoint &a, wxPoint &b )
186{
187 return sqrt( pow( a.x - b.x, 2.0 ) + pow( a.y - b.y, 2.0 ) );
188}
189
190//checks if p is on the line connecting la, lb with tolerance
191bool ExportMixerPanel::IsOnLine( wxPoint p, wxPoint la, wxPoint lb )
192{
193 return Distance( p, la ) + Distance( p, lb ) - Distance( la, lb ) < 0.1;
194}
195
196void ExportMixerPanel::OnMouseEvent(wxMouseEvent & event)
197{
198 if( event.ButtonDown() )
199 {
200 bool reset = true;
201 //check tracks
202 for( unsigned int i = 0; i < mMixerSpec->GetNumTracks(); i++ )
203 if( mTrackRects[ i ].Contains( event.m_x, event.m_y ) )
204 {
205 reset = false;
206 if( mSelectedTrack == (int)i )
207 mSelectedTrack = -1;
208 else
209 {
210 mSelectedTrack = i;
211 if( mSelectedChannel != -1 )
214 }
215 goto found;
216 }
217
218 //check channels
219 for( unsigned int i = 0; i < mMixerSpec->GetNumChannels(); i++ )
220 if( mChannelRects[ i ].Contains( event.m_x, event.m_y ) )
221 {
222 reset = false;
223 if( mSelectedChannel == (int)i )
224 mSelectedChannel = -1;
225 else
226 {
228 if( mSelectedTrack != -1 )
231 }
232 goto found;
233 }
234
235 //check links
236 for( unsigned int i = 0; i < mMixerSpec->GetNumTracks(); i++ )
237 for( unsigned int j = 0; j < mMixerSpec->GetNumChannels(); j++ )
238 if( mMixerSpec->mMap[ i ][ j ] && IsOnLine( wxPoint( event.m_x,
239 event.m_y ), wxPoint( mTrackRects[ i ].x + mBoxWidth,
240 mTrackRects[ i ].y + mTrackHeight / 2 ),
241 wxPoint( mChannelRects[ j ].x, mChannelRects[ j ].y +
242 mChannelHeight / 2 ) ) )
243 mMixerSpec->mMap[ i ][ j ] = false;
244
245found:
246 if( reset )
248 Refresh( false );
249 }
250}
wxT("CloseDown"))
END_EVENT_TABLE()
#define PI
Definition: Biquad.cpp:18
#define _(s)
Definition: Internat.h:73
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:185
static wxBrush playRegionBrush[1]
Definition: AColor.h:108
static wxBrush envelopeBrush
Definition: AColor.h:117
Panel that displays mixing for advanced mixing option.
void OnMouseEvent(wxMouseEvent &event)
MixerOptions::Downmix * mMixerSpec
void SetFont(wxMemoryDC &memDC, const wxString &text, int width, int height)
std::unique_ptr< wxBitmap > mBitmap
bool IsOnLine(wxPoint p, wxPoint la, wxPoint lb)
void OnPaint(wxPaintEvent &event)
double Distance(wxPoint &a, wxPoint &b)
ArrayOf< wxRect > mChannelRects
ArrayOf< wxRect > mTrackRects
virtual ~ExportMixerPanel()
wxArrayString mTrackNames
ArraysOf< bool > mMap
Definition: MixerOptions.h:38
unsigned GetNumTracks() const
Definition: MixerOptions.h:50
unsigned GetNumChannels() const
Definition: MixerOptions.h:47
__finl float_x4 __vecc sqrt(const float_x4 &a)