1 /**********************************************************************
2 
3    Audacity - A Digital Audio Editor
4    Copyright 1999-2018 Audacity Team
5    License: wxwidgets
6 
7    James Crook
8 
9 ******************************************************************//**
10 
11 \file SetLabelCommand.cpp
12 \brief Definitions for SetLabelCommand
13 
14 \class SetLabelCommand
15 \brief Command that sets label information
16 
17 *//*******************************************************************/
18 
19 
20 #include "SetLabelCommand.h"
21 
22 #include "LoadCommands.h"
23 #include "ViewInfo.h"
24 #include "../WaveTrack.h"
25 #include "../LabelTrack.h"
26 #include "../ProjectHistory.h"
27 #include "../Shuttle.h"
28 #include "../ShuttleGui.h"
29 #include "CommandContext.h"
30 #include "../tracks/labeltrack/ui/LabelTrackView.h"
31 
32 const ComponentInterfaceSymbol SetLabelCommand::Symbol
33 { XO("Set Label") };
34 
35 namespace{ BuiltinCommandsModule::Registration< SetLabelCommand > reg; }
36 
SetLabelCommand()37 SetLabelCommand::SetLabelCommand()
38 {
39 }
40 
41 
DefineParams(ShuttleParams & S)42 bool SetLabelCommand::DefineParams( ShuttleParams & S ){
43    S.Define(    mLabelIndex,                            wxT("Label"), 0, 0, 100 );
44    S.OptionalY( bHasText       ).Define(  mText,        wxT("Text"),       wxT("empty") );
45    S.OptionalY( bHasT0         ).Define(  mT0,          wxT("Start"),      0.0, 0.0, 100000.0);
46    S.OptionalY( bHasT1         ).Define(  mT1,          wxT("End"),        0.0, 0.0, 100000.0);
47    S.OptionalN( bHasSelected   ).Define(  mbSelected,   wxT("Selected"),   false );
48    return true;
49 };
50 
PopulateOrExchange(ShuttleGui & S)51 void SetLabelCommand::PopulateOrExchange(ShuttleGui & S)
52 {
53    S.AddSpace(0, 5);
54 
55    S.StartMultiColumn(2, wxALIGN_CENTER);
56    {
57       S.TieNumericTextBox( XXO("Label Index"), mLabelIndex );
58    }
59    S.EndMultiColumn();
60    S.StartMultiColumn(3, wxALIGN_CENTER);
61    {
62       S.Optional( bHasText      ).TieTextBox(         XXO("Text:"),     mText );
63       S.Optional( bHasT0        ).TieNumericTextBox(  XXO("Start:"),    mT0 );
64       S.Optional( bHasT1        ).TieNumericTextBox(  XXO("End:"),      mT1 );
65       S.Optional( bHasSelected  ).TieCheckBox(        XXO("Selected"),  mbSelected );
66    }
67    S.EndMultiColumn();
68 }
69 
Apply(const CommandContext & context)70 bool SetLabelCommand::Apply(const CommandContext & context)
71 {
72    // \todo we have similar code for finding the nth Label, Clip, Track etc.
73    // this code could be put in subroutines/reduced.
74 
75    //wxString mode = GetString(wxT("Type"));
76    AudacityProject * p = &context.project;
77    auto &tracks = TrackList::Get( *p );
78    auto &selectedRegion = ViewInfo::Get( *p ).selectedRegion;
79    const LabelStruct * pLabel = nullptr;
80    LabelTrack *labelTrack = nullptr;
81    auto ii = mLabelIndex;
82    if ( mLabelIndex >= 0 ) {
83       for (auto lt : tracks.Any<LabelTrack>()) {
84          const auto &labels = lt->GetLabels();
85          const auto nLabels = labels.size();
86          if( ii >= (int)nLabels )
87             ii -= nLabels;
88          else {
89             labelTrack = lt;
90             pLabel = &labels[ ii ];
91             break;
92          }
93       }
94    }
95 
96    if ( !pLabel )
97    {
98       context.Error(wxT("LabelIndex was invalid."));
99       return false;
100    }
101    auto newLabel = *pLabel;
102    if( bHasText )
103       newLabel.title = mText;
104    if( bHasT0 )
105       newLabel.selectedRegion.setT0(mT0, false);
106    if( bHasT1 )
107       newLabel.selectedRegion.setT1(mT1, false);
108    if( bHasT0 || bHasT1 )
109       newLabel.selectedRegion.ensureOrdering();
110    labelTrack->SetLabel( ii, newLabel );
111 
112    // Only one label can be selected.
113    if( bHasSelected ) {
114       auto &view = LabelTrackView::Get( *labelTrack );
115       if( mbSelected )
116       {
117          view.SetNavigationIndex( ii );
118          double t0 = pLabel->selectedRegion.t0();
119          double t1 = pLabel->selectedRegion.t1();
120          selectedRegion.setTimes( t0, t1);
121       }
122       else if( view.GetNavigationIndex( context.project ) == ii )
123          view.SetNavigationIndex( -1 );
124    }
125 
126    labelTrack->SortLabels();
127 
128    ProjectHistory::Get(context.project).PushState(
129       XO("Edited Label"), XO("Label"));
130 
131    return true;
132 }
133