Audacity 3.2.0
Public Member Functions | Private Attributes | List of all members
RealtimeEffectListWindow Class Reference
Inheritance diagram for RealtimeEffectListWindow:
[legend]
Collaboration diagram for RealtimeEffectListWindow:
[legend]

Public Member Functions

 RealtimeEffectListWindow (wxWindow *parent, wxWindowID winid=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxScrolledWindowStyle, const wxString &name=wxPanelNameStr)
 
void OnSizeChanged (wxSizeEvent &event)
 
void OnEffectListItemChange (const RealtimeEffectListMessage &msg)
 
void ResetTrack ()
 
void SetTrack (AudacityProject &project, const std::shared_ptr< Track > &track)
 
void EnableEffects (bool enable)
 
void ReloadEffectsList ()
 
void OnAddEffectClicked (const wxCommandEvent &event)
 
void InsertEffectRow (size_t index, const std::shared_ptr< RealtimeEffectState > &pState)
 

Private Attributes

wxWeakRef< AudacityProjectmProject
 
std::shared_ptr< TrackmTrack
 
AButtonmAddEffect {nullptr}
 
wxStaticText * mAddEffectHint {nullptr}
 
wxWindow * mAddEffectTutorialLink {nullptr}
 
wxWindow * mEffectListContainer {nullptr}
 
Observer::Subscription mEffectListItemMovedSubscription
 

Detailed Description

Definition at line 952 of file RealtimeEffectPanel.cpp.

Constructor & Destructor Documentation

◆ RealtimeEffectListWindow()

RealtimeEffectListWindow::RealtimeEffectListWindow ( wxWindow *  parent,
wxWindowID  winid = wxID_ANY,
const wxPoint &  pos = wxDefaultPosition,
const wxSize &  size = wxDefaultSize,
long  style = wxScrolledWindowStyle,
const wxString &  name = wxPanelNameStr 
)
inline

i18n-hint: undo history record first parameter - realtime effect name second parameter - track name

i18n-hint: undo history record first parameter - realtime effect name second parameter - track name

Definition at line 964 of file RealtimeEffectPanel.cpp.

970 : wxScrolledWindow(parent, winid, pos, size, style, name)
971 {
972 Bind(wxEVT_SIZE, &RealtimeEffectListWindow::OnSizeChanged, this);
973#ifdef __WXMSW__
974 //Fixes flickering on redraw
975 wxScrolledWindow::SetDoubleBuffered(true);
976#endif
977 auto rootSizer = std::make_unique<wxBoxSizer>(wxVERTICAL);
978
979 auto effectListContainer = safenew ThemedWindowWrapper<wxPanel>(this, wxID_ANY);
980 effectListContainer->SetBackgroundColorIndex(clrMedium);
981 effectListContainer->SetSizer(safenew wxBoxSizer(wxVERTICAL));
982 effectListContainer->SetDoubleBuffered(true);
983 effectListContainer->Hide();
984 mEffectListContainer = effectListContainer;
985
986 auto addEffect = safenew ThemedAButtonWrapper<AButton>(this, wxID_ANY);
987 addEffect->SetImageIndices(0,
988 bmpHButtonNormal,
989 bmpHButtonHover,
990 bmpHButtonDown,
991 bmpHButtonHover,
992 bmpHButtonDisabled);
993 addEffect->SetTranslatableLabel(XO("Add effect"));
994 addEffect->SetButtonType(AButton::TextButton);
995 addEffect->SetBackgroundColorIndex(clrMedium);
996 addEffect->SetForegroundColorIndex(clrTrackPanelText);
997 addEffect->Bind(wxEVT_BUTTON, &RealtimeEffectListWindow::OnAddEffectClicked, this);
998 mAddEffect = addEffect;
999
1000 auto addEffectHint = safenew ThemedWindowWrapper<wxStaticText>(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
1001 //Workaround: text is set in the OnSizeChange
1002 addEffectHint->SetForegroundColorIndex(clrTrackPanelText);
1003 mAddEffectHint = addEffectHint;
1004
1005 auto addEffectTutorialLink = safenew ThemedWindowWrapper<wxHyperlinkCtrl>(
1006 this, wxID_ANY, _("Watch video"),
1007 "https://www.audacityteam.org/realtime-video", wxDefaultPosition,
1008 wxDefaultSize, wxHL_ALIGN_LEFT | wxHL_CONTEXTMENU);
1009
1010 //i18n-hint: Hyperlink to the effects stack panel tutorial video
1011 addEffectTutorialLink->SetTranslatableLabel(XO("Watch video"));
1012#if wxUSE_ACCESSIBILITY
1013 safenew WindowAccessible(addEffectTutorialLink);
1014#endif
1015
1016 addEffectTutorialLink->Bind(
1017 wxEVT_HYPERLINK, [](wxHyperlinkEvent& event)
1018 { BasicUI::OpenInDefaultBrowser(event.GetURL()); });
1019
1020 mAddEffectTutorialLink = addEffectTutorialLink;
1021
1022 //indicates the insertion position of the item
1023 auto dropHintLine = safenew ThemedWindowWrapper<DropHintLine>(effectListContainer, wxID_ANY);
1024 dropHintLine->SetBackgroundColorIndex(clrDropHintHighlight);
1025 dropHintLine->Hide();
1026
1027 rootSizer->Add(mEffectListContainer, 0, wxEXPAND | wxBOTTOM, 10);
1028 rootSizer->Add(addEffect, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 20);
1029 rootSizer->Add(addEffectHint, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 20);
1030 rootSizer->Add(addEffectTutorialLink, 0, wxLEFT | wxRIGHT | wxEXPAND, 20);
1031
1032 SetSizer(rootSizer.release());
1033 SetMinSize({});
1034
1035 Bind(EVT_MOVABLE_CONTROL_DRAG_STARTED, [dropHintLine](const MovableControlEvent& event)
1036 {
1037 if(auto window = dynamic_cast<wxWindow*>(event.GetEventObject()))
1038 window->Raise();
1039 });
1040 Bind(EVT_MOVABLE_CONTROL_DRAG_POSITION, [this, dropHintLine](const MovableControlEvent& event)
1041 {
1042 constexpr auto DropHintLineHeight { 3 };//px
1043
1044 auto sizer = mEffectListContainer->GetSizer();
1045 assert(sizer != nullptr);
1046
1047 if(event.GetSourceIndex() == event.GetTargetIndex())
1048 {
1049 //do not display hint line if position didn't change
1050 dropHintLine->Hide();
1051 return;
1052 }
1053
1054 if(!dropHintLine->IsShown())
1055 {
1056 dropHintLine->Show();
1057 dropHintLine->Raise();
1058 if(auto window = dynamic_cast<wxWindow*>(event.GetEventObject()))
1059 window->Raise();
1060 }
1061
1062 auto item = sizer->GetItem(event.GetTargetIndex());
1063 dropHintLine->SetSize(item->GetSize().x, DropHintLineHeight);
1064
1065 if(event.GetTargetIndex() > event.GetSourceIndex())
1066 dropHintLine->SetPosition(item->GetRect().GetBottomLeft() - wxPoint(0, DropHintLineHeight));
1067 else
1068 dropHintLine->SetPosition(item->GetRect().GetTopLeft());
1069 });
1070 Bind(EVT_MOVABLE_CONTROL_DRAG_FINISHED, [this, dropHintLine](const MovableControlEvent& event)
1071 {
1072 dropHintLine->Hide();
1073
1074 if(mProject == nullptr)
1075 return;
1076
1077 auto& effectList = RealtimeEffectList::Get(*mTrack);
1078 const auto from = event.GetSourceIndex();
1079 const auto to = event.GetTargetIndex();
1080 if(from != to)
1081 {
1082 auto effectName =
1083 effectList.GetStateAt(from)->GetEffect()->GetName();
1084 bool up = (to < from);
1085 effectList.MoveEffect(from, to);
1086 ProjectHistory::Get(*mProject).PushState(
1087 (up
1092 ? XO("Moved %s up in %s")
1097 : XO("Moved %s down in %s"))
1098 .Format(effectName, mTrack->GetName()),
1099 XO("Change effect order"), UndoPush::CONSOLIDATE);
1100 }
1101 else
1102 {
1103 wxWindowUpdateLocker freeze(this);
1104 Layout();
1105 }
1106 });
1107 SetScrollRate(0, 20);
1108 }
const TranslatableString name
Definition: Distortion.cpp:82
#define XO(s)
Definition: Internat.h:31
#define _(s)
Definition: Internat.h:75
#define safenew
Definition: MemoryX.h:10
@ TextButton
Definition: AButton.h:34
Abstract base class used in importing a file.
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
static ProjectHistory & Get(AudacityProject &project)
static RealtimeEffectList & Get(AudacityProject &project)
std::shared_ptr< Track > mTrack
void OnAddEffectClicked(const wxCommandEvent &event)
void OnSizeChanged(wxSizeEvent &event)
wxWeakRef< AudacityProject > mProject
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
bool OpenInDefaultBrowser(const wxString &url)
Open an URL in default browser.
Definition: BasicUI.cpp:238

References _, CONSOLIDATE, ProjectHistory::Get(), RealtimeEffectList::Get(), mAddEffect, mAddEffectHint, mAddEffectTutorialLink, mEffectListContainer, mProject, mTrack, OnAddEffectClicked(), OnSizeChanged(), BasicUI::OpenInDefaultBrowser(), ProjectHistory::PushState(), safenew, AButton::TextButton, and XO.

Here is the call graph for this function:

Member Function Documentation

◆ EnableEffects()

void RealtimeEffectListWindow::EnableEffects ( bool  enable)
inline

Definition at line 1227 of file RealtimeEffectPanel.cpp.

1228 {
1229 if (mTrack)
1230 RealtimeEffectList::Get(*mTrack).SetActive(enable);
1231 }
void SetActive(bool value)
Done by main thread only, under a lock guard.

References RealtimeEffectList::Get(), mTrack, and RealtimeEffectList::SetActive().

Referenced by RealtimeEffectPanel::RealtimeEffectPanel().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ InsertEffectRow()

void RealtimeEffectListWindow::InsertEffectRow ( size_t  index,
const std::shared_ptr< RealtimeEffectState > &  pState 
)
inline

Definition at line 1289 of file RealtimeEffectPanel.cpp.

1291 {
1292 if(mProject == nullptr)
1293 return;
1294
1295 // See comment in ReloadEffectsList
1296 if(!mEffectListContainer->IsShown())
1297 mEffectListContainer->Show();
1298
1300 row->SetBackgroundColorIndex(clrEffectListItemBackground);
1301 row->SetEffect(*mProject, mTrack, pState);
1302 mEffectListContainer->GetSizer()->Insert(index, row, 0, wxEXPAND);
1303 }

References mEffectListContainer, mProject, mTrack, and safenew.

Referenced by OnEffectListItemChange(), and ReloadEffectsList().

Here is the caller graph for this function:

◆ OnAddEffectClicked()

void RealtimeEffectListWindow::OnAddEffectClicked ( const wxCommandEvent &  event)
inline

i18n-hint: undo history record first parameter - realtime effect name second parameter - track name

Definition at line 1264 of file RealtimeEffectPanel.cpp.

1265 {
1266 if(!mTrack || mProject == nullptr)
1267 return;
1268
1269 const auto effectID = ShowSelectEffectMenu(dynamic_cast<wxWindow*>(event.GetEventObject()));
1270 if(effectID.empty())
1271 return;
1272
1273 if(auto state = AudioIO::Get()->AddState(*mProject, &*mTrack, effectID))
1274 {
1275 auto effect = state->GetEffect();
1276 assert(effect); // postcondition of AddState
1277 const auto effectName = effect->GetName();
1278 ProjectHistory::Get(*mProject).PushState(
1283 XO("Added %s to %s").Format(effectName, mTrack->GetName()),
1284 //i18n-hint: undo history record
1285 XO("Add %s").Format(effectName));
1286 }
1287 }
static AudioIO * Get()
Definition: AudioIO.cpp:133
PluginID ShowSelectEffectMenu(wxWindow *parent, RealtimeEffectControl *currentEffectControl=nullptr)

References AudioIO::Get(), ProjectHistory::Get(), mProject, mTrack, ProjectHistory::PushState(), anonymous_namespace{RealtimeEffectPanel.cpp}::ShowSelectEffectMenu(), and XO.

Referenced by RealtimeEffectListWindow().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ OnEffectListItemChange()

void RealtimeEffectListWindow::OnEffectListItemChange ( const RealtimeEffectListMessage msg)
inline

Definition at line 1126 of file RealtimeEffectPanel.cpp.

1127 {
1128 auto sizer = mEffectListContainer->GetSizer();
1129 const auto insertItem = [this, &msg](){
1130 auto& effects = RealtimeEffectList::Get(*mTrack);
1131 InsertEffectRow(msg.srcIndex, effects.GetStateAt(msg.srcIndex));
1132 mAddEffectHint->Hide();
1133 mAddEffectTutorialLink->Hide();
1134 };
1135 const auto removeItem = [&](){
1137 // Don't need to auto-save changed settings of effect that is deleted
1138 // Undo history push will do it anyway
1139 ui.Hide();
1140
1141 auto window = sizer->GetItem(msg.srcIndex)->GetWindow();
1142 sizer->Remove(msg.srcIndex);
1143 wxTheApp->CallAfter([ref = wxWeakRef { window }] {
1144 if(ref) ref->Destroy();
1145 });
1146
1147 if(sizer->IsEmpty())
1148 {
1149 if(mEffectListContainer->IsDescendant(FindFocus()))
1150 mAddEffect->SetFocus();
1151
1152 mEffectListContainer->Hide();
1153 mAddEffectHint->Show();
1154 mAddEffectTutorialLink->Show();
1155 }
1156 };
1157
1158 wxWindowUpdateLocker freeze(this);
1160 {
1161 const auto sizer = mEffectListContainer->GetSizer();
1162
1163 const auto movedItem = sizer->GetItem(msg.srcIndex);
1164
1165 const auto proportion = movedItem->GetProportion();
1166 const auto flag = movedItem->GetFlag();
1167 const auto border = movedItem->GetBorder();
1168 const auto window = movedItem->GetWindow();
1169
1170 if(msg.srcIndex < msg.dstIndex)
1171 window->MoveAfterInTabOrder(sizer->GetItem(msg.dstIndex)->GetWindow());
1172 else
1173 window->MoveBeforeInTabOrder(sizer->GetItem(msg.dstIndex)->GetWindow());
1174
1175 sizer->Remove(msg.srcIndex);
1176 sizer->Insert(msg.dstIndex, window, proportion, flag, border);
1177 }
1179 {
1180 insertItem();
1181 }
1183 {
1184 removeItem();
1185 }
1187 {
1188 insertItem();
1189 }
1191 {
1192 removeItem();
1193 }
1194 SendSizeEventToParent();
1195 }
static std::once_flag flag
void InsertEffectRow(size_t index, const std::shared_ptr< RealtimeEffectState > &pState)
static RealtimeEffectStateUI & Get(RealtimeEffectState &state)
@ Remove
Effect item was removed from the list at srcIndex position. affectedState is removed state.
@ DidReplace
Effect item was replaced with a new item at srcIndex position. affectedState is an old state.
@ Move
Item position has changed, from srcIndex to dstIndex. affectedState is the moved state.
@ Insert
New effect item was added to the list at srcIndex position. affectedState is a new state.
@ WillReplace
Effect item will be replaced with a new item at srcIndex position. affectedState is the state to be r...
std::shared_ptr< RealtimeEffectState > affectedState

References RealtimeEffectListMessage::affectedState, RealtimeEffectListMessage::DidReplace, RealtimeEffectListMessage::dstIndex, flag, RealtimeEffectList::Get(), RealtimeEffectStateUI::Get(), RealtimeEffectListMessage::Insert, InsertEffectRow(), mAddEffect, mAddEffectHint, mAddEffectTutorialLink, mEffectListContainer, RealtimeEffectListMessage::Move, mTrack, RealtimeEffectListMessage::Remove, RealtimeEffectListMessage::srcIndex, RealtimeEffectListMessage::type, and RealtimeEffectListMessage::WillReplace.

Referenced by SetTrack().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ OnSizeChanged()

void RealtimeEffectListWindow::OnSizeChanged ( wxSizeEvent &  event)
inline

Definition at line 1110 of file RealtimeEffectPanel.cpp.

1111 {
1112 if(auto sizerItem = GetSizer()->GetItem(mAddEffectHint))
1113 {
1114 //We need to wrap the text whenever panel width changes and adjust widget height
1115 //so that text is fully visible, but there is no height-for-width layout algorithm
1116 //in wxWidgets yet, so for now we just do it manually
1117
1118 //Restore original text, because 'Wrap' will replace it with wrapped one
1119 mAddEffectHint->SetLabel(_("Realtime effects are non-destructive and can be changed at any time."));
1120 mAddEffectHint->Wrap(GetClientSize().x - sizerItem->GetBorder() * 2);
1121 mAddEffectHint->InvalidateBestSize();
1122 }
1123 event.Skip();
1124 }

References _, and mAddEffectHint.

Referenced by RealtimeEffectListWindow().

Here is the caller graph for this function:

◆ ReloadEffectsList()

void RealtimeEffectListWindow::ReloadEffectsList ( )
inline

Definition at line 1233 of file RealtimeEffectPanel.cpp.

1234 {
1235 wxWindowUpdateLocker freeze(this);
1236
1237 const auto hadFocus = mEffectListContainer->IsDescendant(FindFocus());
1238 //delete items that were added to the sizer
1239 mEffectListContainer->Hide();
1240 mEffectListContainer->GetSizer()->Clear(true);
1241
1242
1243 if(!mTrack || RealtimeEffectList::Get(*mTrack).GetStatesCount() == 0)
1244 mEffectListContainer->Hide();
1245
1246 auto isEmpty{true};
1247 if(mTrack)
1248 {
1249 auto& effects = RealtimeEffectList::Get(*mTrack);
1250 isEmpty = effects.GetStatesCount() == 0;
1251 for(size_t i = 0, count = effects.GetStatesCount(); i < count; ++i)
1252 InsertEffectRow(i, effects.GetStateAt(i));
1253 }
1255 //Workaround for GTK: Underlying GTK widget does not update
1256 //its size when wxWindow size is set to zero
1257 mEffectListContainer->Show(!isEmpty);
1258 mAddEffectHint->Show(isEmpty);
1259 mAddEffectTutorialLink->Show(isEmpty);
1260
1261 SendSizeEventToParent();
1262 }
void SetEnabled(bool state)
Definition: AButton.h:104
size_t GetStatesCount() const noexcept

References RealtimeEffectList::Get(), RealtimeEffectList::GetStatesCount(), InsertEffectRow(), mAddEffect, mAddEffectHint, mAddEffectTutorialLink, mEffectListContainer, mTrack, and AButton::SetEnabled().

Referenced by ResetTrack(), and SetTrack().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ResetTrack()

void RealtimeEffectListWindow::ResetTrack ( )
inline

Definition at line 1197 of file RealtimeEffectPanel.cpp.

1198 {
1200
1201 mTrack.reset();
1202 mProject = nullptr;
1204 }
void Reset() noexcept
Breaks the connection (constant time)
Definition: Observer.cpp:101
Observer::Subscription mEffectListItemMovedSubscription

References mEffectListItemMovedSubscription, mProject, mTrack, ReloadEffectsList(), and Observer::Subscription::Reset().

Referenced by RealtimeEffectPanel::ResetTrack().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetTrack()

void RealtimeEffectListWindow::SetTrack ( AudacityProject project,
const std::shared_ptr< Track > &  track 
)
inline

Definition at line 1206 of file RealtimeEffectPanel.cpp.

1207 {
1208 if (mTrack == track)
1209 return;
1210
1212
1213 mTrack = track;
1214 mProject = &project;
1216
1217 if (track)
1218 {
1219 auto& effects = RealtimeEffectList::Get(*mTrack);
1220 mEffectListItemMovedSubscription = effects.Subscribe(
1222
1224 }
1225 }
void OnEffectListItemChange(const RealtimeEffectListMessage &msg)

References RealtimeEffectList::Get(), mEffectListItemMovedSubscription, mProject, mTrack, OnEffectListItemChange(), ReloadEffectsList(), Observer::Subscription::Reset(), and anonymous_namespace{RealtimeEffectPanel.cpp}::UpdateRealtimeEffectUIData().

Referenced by RealtimeEffectPanel::SetTrack().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ mAddEffect

AButton* RealtimeEffectListWindow::mAddEffect {nullptr}
private

◆ mAddEffectHint

wxStaticText* RealtimeEffectListWindow::mAddEffectHint {nullptr}
private

◆ mAddEffectTutorialLink

wxWindow* RealtimeEffectListWindow::mAddEffectTutorialLink {nullptr}
private

◆ mEffectListContainer

wxWindow* RealtimeEffectListWindow::mEffectListContainer {nullptr}
private

◆ mEffectListItemMovedSubscription

Observer::Subscription RealtimeEffectListWindow::mEffectListItemMovedSubscription
private

Definition at line 961 of file RealtimeEffectPanel.cpp.

Referenced by ResetTrack(), and SetTrack().

◆ mProject

wxWeakRef<AudacityProject> RealtimeEffectListWindow::mProject
private

◆ mTrack

std::shared_ptr<Track> RealtimeEffectListWindow::mTrack
private

The documentation for this class was generated from the following file: