mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-17 16:40:07 +02:00
Much code moved out of LabelTrack.cpp, freeing 3 files from cycles...
They are: LabelTrack Snap TimeShiftHandle The code, about 2000 lines, moved mostly into LabelTrackView, with some into LabelTextHandle and LabelGlyphHandle. With this commit, Track and its four subclasses are all free from the big s.c.c, which has 29 remaining files, according to scripts/graph.pl. But in truth there are still linkage dependencies not shown in the graph, because overrides of Track::DoGetView and Track::DoGetControls are still in scattered places, and they are needed to populate the virtual function tables of those classes. Thus dependency on LabelTrack still really implies dependency on LabelTrackView and likewise for the other three Track subclasses.
This commit is contained in:
commit
a7cc55e9e7
@ -36,6 +36,7 @@
|
|||||||
#include "Project.h"
|
#include "Project.h"
|
||||||
#include "ProjectWindow.h"
|
#include "ProjectWindow.h"
|
||||||
#include "ViewInfo.h"
|
#include "ViewInfo.h"
|
||||||
|
#include "tracks/labeltrack/ui/LabelTrackView.h"
|
||||||
#include "widgets/AudacityMessageBox.h"
|
#include "widgets/AudacityMessageBox.h"
|
||||||
#include "widgets/ErrorDialog.h"
|
#include "widgets/ErrorDialog.h"
|
||||||
#include "widgets/Grid.h"
|
#include "widgets/Grid.h"
|
||||||
@ -420,8 +421,8 @@ bool LabelDialog::TransferDataFromWindow()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Add the label to it
|
// Add the label to it
|
||||||
lt->AddLabel(rd.selectedRegion, rd.title, -2);
|
lt->AddLabel(rd.selectedRegion, rd.title);
|
||||||
lt->Unselect();
|
LabelTrackView::Get( *lt ).SetSelectedIndex( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -723,7 +724,7 @@ void LabelDialog::OnExport(wxCommandEvent & WXUNUSED(event))
|
|||||||
for (i = 0; i < cnt; i++) {
|
for (i = 0; i < cnt; i++) {
|
||||||
RowData &rd = mData[i];
|
RowData &rd = mData[i];
|
||||||
|
|
||||||
lt->AddLabel(rd.selectedRegion, rd.title,-2);
|
lt->AddLabel(rd.selectedRegion, rd.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export them and clean
|
// Export them and clean
|
||||||
|
2179
src/LabelTrack.cpp
2179
src/LabelTrack.cpp
File diff suppressed because it is too large
Load Diff
201
src/LabelTrack.h
201
src/LabelTrack.h
@ -17,20 +17,11 @@
|
|||||||
#include "Track.h"
|
#include "Track.h"
|
||||||
|
|
||||||
|
|
||||||
class wxFont;
|
|
||||||
class wxKeyEvent;
|
|
||||||
class wxMouseEvent;
|
|
||||||
class wxTextFile;
|
class wxTextFile;
|
||||||
class wxWindow;
|
|
||||||
class wxIcon;
|
|
||||||
class wxBitmap;
|
|
||||||
class TrackList;
|
|
||||||
|
|
||||||
class AudacityProject;
|
class AudacityProject;
|
||||||
class DirManager;
|
class DirManager;
|
||||||
class TimeWarper;
|
class TimeWarper;
|
||||||
class ZoomInfo;
|
|
||||||
|
|
||||||
|
|
||||||
struct LabelTrackHit;
|
struct LabelTrackHit;
|
||||||
struct TrackPanelDrawingContext;
|
struct TrackPanelDrawingContext;
|
||||||
@ -38,18 +29,12 @@ struct TrackPanelDrawingContext;
|
|||||||
class LabelStruct
|
class LabelStruct
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
LabelStruct() = default;
|
||||||
// Copies region
|
// Copies region
|
||||||
LabelStruct(const SelectedRegion& region, const wxString &aTitle);
|
LabelStruct(const SelectedRegion& region, const wxString &aTitle);
|
||||||
// Copies region but then overwrites other times
|
// Copies region but then overwrites other times
|
||||||
LabelStruct(const SelectedRegion& region, double t0, double t1,
|
LabelStruct(const SelectedRegion& region, double t0, double t1,
|
||||||
const wxString &aTitle);
|
const wxString &aTitle);
|
||||||
void DrawLines( wxDC & dc, const wxRect & r) const;
|
|
||||||
void DrawGlyphs
|
|
||||||
( wxDC & dc, const wxRect & r, int GlyphLeft, int GlyphRight) const;
|
|
||||||
void DrawText( wxDC & dc, const wxRect & r) const;
|
|
||||||
void DrawTextBox( wxDC & dc, const wxRect & r) const;
|
|
||||||
void DrawHighlight( wxDC & dc, int xPos1, int xPos2, int charHeight) const;
|
|
||||||
void getXPos( wxDC & dc, int * xPos1, int cursorPos) const;
|
|
||||||
const SelectedRegion &getSelectedRegion() const { return selectedRegion; }
|
const SelectedRegion &getSelectedRegion() const { return selectedRegion; }
|
||||||
double getDuration() const { return selectedRegion.duration(); }
|
double getDuration() const { return selectedRegion.duration(); }
|
||||||
double getT0() const { return selectedRegion.t0(); }
|
double getT0() const { return selectedRegion.t0(); }
|
||||||
@ -84,54 +69,33 @@ public:
|
|||||||
public:
|
public:
|
||||||
SelectedRegion selectedRegion;
|
SelectedRegion selectedRegion;
|
||||||
wxString title; /// Text of the label.
|
wxString title; /// Text of the label.
|
||||||
mutable int width; /// width of the text in pixels.
|
mutable int width{}; /// width of the text in pixels.
|
||||||
|
|
||||||
// Working storage for on-screen layout.
|
// Working storage for on-screen layout.
|
||||||
mutable int x; /// Pixel position of left hand glyph
|
mutable int x{}; /// Pixel position of left hand glyph
|
||||||
mutable int x1; /// Pixel position of right hand glyph
|
mutable int x1{}; /// Pixel position of right hand glyph
|
||||||
mutable int xText; /// Pixel position of left hand side of text box
|
mutable int xText{}; /// Pixel position of left hand side of text box
|
||||||
mutable int y; /// Pixel position of label.
|
mutable int y{}; /// Pixel position of label.
|
||||||
|
|
||||||
bool updated; /// flag to tell if the label times were updated
|
bool updated{}; /// flag to tell if the label times were updated
|
||||||
};
|
};
|
||||||
|
|
||||||
using LabelArray = std::vector<LabelStruct>;
|
using LabelArray = std::vector<LabelStruct>;
|
||||||
|
|
||||||
const int NUM_GLYPH_CONFIGS = 3;
|
class AUDACITY_DLL_API LabelTrack final
|
||||||
const int NUM_GLYPH_HIGHLIGHTS = 4;
|
: public Track
|
||||||
const int MAX_NUM_ROWS =80;
|
, public wxEvtHandler
|
||||||
|
|
||||||
class AUDACITY_DLL_API LabelTrack final : public Track
|
|
||||||
{
|
{
|
||||||
friend class LabelTrackView;
|
|
||||||
friend class LabelStruct;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void DoEditLabels(
|
|
||||||
AudacityProject &project, LabelTrack *lt = nullptr, int index = -1);
|
|
||||||
static int DialogForLabelName(
|
|
||||||
AudacityProject &project, const SelectedRegion& region,
|
|
||||||
const wxString& initialValue, wxString& value);
|
|
||||||
|
|
||||||
bool IsTextSelected() const;
|
|
||||||
|
|
||||||
void CreateCustomGlyphs();
|
|
||||||
LabelTrack(const std::shared_ptr<DirManager> &projDirManager);
|
LabelTrack(const std::shared_ptr<DirManager> &projDirManager);
|
||||||
LabelTrack(const LabelTrack &orig);
|
LabelTrack(const LabelTrack &orig);
|
||||||
|
|
||||||
virtual ~ LabelTrack();
|
virtual ~ LabelTrack();
|
||||||
|
|
||||||
|
void SetLabel( size_t iLabel, const LabelStruct &newLabel );
|
||||||
|
|
||||||
void SetOffset(double dOffset) override;
|
void SetOffset(double dOffset) override;
|
||||||
|
|
||||||
static const int DefaultFontSize = 12;
|
|
||||||
|
|
||||||
static wxFont GetFont(const wxString &faceName, int size = DefaultFontSize);
|
|
||||||
static void ResetFont();
|
|
||||||
|
|
||||||
void Draw( TrackPanelDrawingContext &context, const wxRect & r ) const;
|
|
||||||
|
|
||||||
int getSelectedIndex() const { return mSelIndex; }
|
|
||||||
|
|
||||||
double GetOffset() const override;
|
double GetOffset() const override;
|
||||||
double GetStartTime() const override;
|
double GetStartTime() const override;
|
||||||
double GetEndTime() const override;
|
double GetEndTime() const override;
|
||||||
@ -142,8 +106,6 @@ private:
|
|||||||
Track::Holder Clone() const override;
|
Track::Holder Clone() const override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void SetSelected(bool s) override;
|
|
||||||
|
|
||||||
bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override;
|
bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override;
|
||||||
XMLTagHandler *HandleXMLChild(const wxChar *tag) override;
|
XMLTagHandler *HandleXMLChild(const wxChar *tag) override;
|
||||||
void WriteXML(XMLWriter &xmlFile) const override;
|
void WriteXML(XMLWriter &xmlFile) const override;
|
||||||
@ -161,76 +123,21 @@ public:
|
|||||||
|
|
||||||
void Silence(double t0, double t1) override;
|
void Silence(double t0, double t1) override;
|
||||||
void InsertSilence(double t, double len) override;
|
void InsertSilence(double t, double len) override;
|
||||||
void OverGlyph(LabelTrackHit &hit, int x, int y) const;
|
|
||||||
static wxBitmap & GetGlyph( int i);
|
|
||||||
|
|
||||||
|
|
||||||
struct Flags {
|
|
||||||
int mInitialCursorPos, mCurrentCursorPos, mSelIndex;
|
|
||||||
bool mRightDragging, mDrawCursor;
|
|
||||||
};
|
|
||||||
void ResetFlags();
|
|
||||||
Flags SaveFlags() const
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
mInitialCursorPos, mCurrentCursorPos, mSelIndex,
|
|
||||||
mRightDragging, mDrawCursor
|
|
||||||
};
|
|
||||||
}
|
|
||||||
void RestoreFlags( const Flags& flags );
|
|
||||||
|
|
||||||
int OverATextBox(int xx, int yy) const;
|
|
||||||
bool OverTextBox(const LabelStruct *pLabel, int x, int y) const;
|
|
||||||
bool CutSelectedText();
|
|
||||||
bool CopySelectedText();
|
|
||||||
bool PasteSelectedText(double sel0, double sel1);
|
|
||||||
static bool IsTextClipSupported();
|
|
||||||
|
|
||||||
void HandleGlyphClick
|
|
||||||
(LabelTrackHit &hit,
|
|
||||||
const wxMouseEvent & evt, const wxRect & r, const ZoomInfo &zoomInfo,
|
|
||||||
SelectedRegion *newSel);
|
|
||||||
void HandleTextClick
|
|
||||||
(const wxMouseEvent & evt, const wxRect & r, const ZoomInfo &zoomInfo,
|
|
||||||
SelectedRegion *newSel);
|
|
||||||
bool HandleGlyphDragRelease
|
|
||||||
(LabelTrackHit &hit,
|
|
||||||
const wxMouseEvent & evt, wxRect & r, const ZoomInfo &zoomInfo,
|
|
||||||
SelectedRegion *newSel);
|
|
||||||
void HandleTextDragRelease(const wxMouseEvent & evt);
|
|
||||||
|
|
||||||
void Import(wxTextFile & f);
|
void Import(wxTextFile & f);
|
||||||
void Export(wxTextFile & f) const;
|
void Export(wxTextFile & f) const;
|
||||||
|
|
||||||
void Unselect();
|
|
||||||
|
|
||||||
// Whether any label box is selected -- not, whether the track is selected.
|
|
||||||
bool HasSelection() const;
|
|
||||||
|
|
||||||
int GetNumLabels() const;
|
int GetNumLabels() const;
|
||||||
const LabelStruct *GetLabel(int index) const;
|
const LabelStruct *GetLabel(int index) const;
|
||||||
const LabelArray &GetLabels() const { return mLabels; }
|
const LabelArray &GetLabels() const { return mLabels; }
|
||||||
|
|
||||||
|
void OnLabelAdded( const wxString &title, int pos );
|
||||||
//This returns the index of the label we just added.
|
//This returns the index of the label we just added.
|
||||||
int AddLabel(const SelectedRegion ®ion, const wxString &title = {},
|
int AddLabel(const SelectedRegion ®ion, const wxString &title);
|
||||||
int restoreFocus = -1);
|
|
||||||
//And this tells us the index, if there is a label already there.
|
|
||||||
int GetLabelIndex(double t, double t1);
|
|
||||||
|
|
||||||
//This deletes the label at given index.
|
//This deletes the label at given index.
|
||||||
void DeleteLabel(int index);
|
void DeleteLabel(int index);
|
||||||
|
|
||||||
//get current cursor position,
|
|
||||||
// relative to the left edge of the track panel
|
|
||||||
bool CalcCursorX(int * x) const;
|
|
||||||
|
|
||||||
void CalcHighlightXs(int *x1, int *x2) const;
|
|
||||||
|
|
||||||
void MayAdjustLabel
|
|
||||||
( LabelTrackHit &hit,
|
|
||||||
int iLabel, int iEdge, bool bAllowSwapping, double fNewTime);
|
|
||||||
void MayMoveLabel( int iLabel, int iEdge, double fNewTime);
|
|
||||||
|
|
||||||
// This pastes labels without shifting existing ones
|
// This pastes labels without shifting existing ones
|
||||||
bool PasteOver(double t, const Track *src);
|
bool PasteOver(double t, const Track *src);
|
||||||
|
|
||||||
@ -251,57 +158,61 @@ public:
|
|||||||
int FindPrevLabel(const SelectedRegion& currentSelection);
|
int FindPrevLabel(const SelectedRegion& currentSelection);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void SortLabels(LabelTrackHit *pHit = nullptr);
|
void SortLabels();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TrackKind GetKind() const override { return TrackKind::Label; }
|
TrackKind GetKind() const override { return TrackKind::Label; }
|
||||||
|
|
||||||
void ShowContextMenu();
|
|
||||||
void OnContextMenu(wxCommandEvent & evt);
|
|
||||||
|
|
||||||
int mSelIndex; /// Keeps track of the currently selected label
|
|
||||||
int mxMouseDisplacement; /// Displacement of mouse cursor from the centre being dragged.
|
|
||||||
LabelArray mLabels;
|
LabelArray mLabels;
|
||||||
|
|
||||||
static int mIconHeight;
|
|
||||||
static int mIconWidth;
|
|
||||||
static int mTextHeight;
|
|
||||||
static bool mbGlyphsReady;
|
|
||||||
static wxBitmap mBoundaryGlyphs[NUM_GLYPH_CONFIGS * NUM_GLYPH_HIGHLIGHTS];
|
|
||||||
|
|
||||||
static int mFontHeight;
|
|
||||||
int mCurrentCursorPos; /// current cursor position
|
|
||||||
int mInitialCursorPos; /// initial cursor position
|
|
||||||
|
|
||||||
bool mRightDragging; /// flag to tell if it's a valid dragging
|
|
||||||
bool mDrawCursor; /// flag to tell if drawing the
|
|
||||||
/// cursor or not
|
|
||||||
int mRestoreFocus; /// Restore focus to this track
|
|
||||||
/// when done editing
|
|
||||||
|
|
||||||
// Set in copied label tracks
|
// Set in copied label tracks
|
||||||
double mClipLen;
|
double mClipLen;
|
||||||
|
|
||||||
int miLastLabel; // used by FindNextLabel and FindPrevLabel
|
int miLastLabel; // used by FindNextLabel and FindPrevLabel
|
||||||
|
|
||||||
void ComputeLayout(const wxRect & r, const ZoomInfo &zoomInfo) const;
|
|
||||||
void ComputeTextPosition(const wxRect & r, int index) const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
int FindCurrentCursorPosition(int xPos);
|
|
||||||
void SetCurrentCursorPosition(int xPos);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void calculateFontHeight(wxDC & dc) const;
|
|
||||||
void RemoveSelectedText();
|
|
||||||
|
|
||||||
static wxFont msFont;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::shared_ptr<TrackView> DoGetView() override;
|
std::shared_ptr<TrackView> DoGetView() override;
|
||||||
std::shared_ptr<TrackControls> DoGetControls() override;
|
std::shared_ptr<TrackControls> DoGetControls() override;
|
||||||
|
|
||||||
friend class GetInfoCommand; // to get labels.
|
|
||||||
friend class SetLabelCommand; // to set labels.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LabelTrackEvent : TrackListEvent
|
||||||
|
{
|
||||||
|
explicit
|
||||||
|
LabelTrackEvent(
|
||||||
|
wxEventType commandType, const std::shared_ptr<LabelTrack> &pTrack,
|
||||||
|
const wxString &title,
|
||||||
|
int formerPosition,
|
||||||
|
int presentPosition
|
||||||
|
)
|
||||||
|
: TrackListEvent{ commandType, pTrack }
|
||||||
|
, mTitle{ title }
|
||||||
|
, mFormerPosition{ formerPosition }
|
||||||
|
, mPresentPosition{ presentPosition }
|
||||||
|
{}
|
||||||
|
|
||||||
|
LabelTrackEvent( const LabelTrackEvent& ) = default;
|
||||||
|
wxEvent *Clone() const override {
|
||||||
|
// wxWidgets will own the event object
|
||||||
|
return safenew LabelTrackEvent(*this); }
|
||||||
|
|
||||||
|
wxString mTitle;
|
||||||
|
|
||||||
|
// invalid for addition event
|
||||||
|
int mFormerPosition{ -1 };
|
||||||
|
|
||||||
|
// invalid for deletion event
|
||||||
|
int mPresentPosition{ -1 };
|
||||||
|
};
|
||||||
|
|
||||||
|
// Posted when a label is added.
|
||||||
|
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
|
||||||
|
EVT_LABELTRACK_ADDITION, LabelTrackEvent);
|
||||||
|
|
||||||
|
// Posted when a label is deleted.
|
||||||
|
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
|
||||||
|
EVT_LABELTRACK_DELETION, LabelTrackEvent);
|
||||||
|
|
||||||
|
// Posted when a label is repositioned in the sequence of labels.
|
||||||
|
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
|
||||||
|
EVT_LABELTRACK_PERMUTED, LabelTrackEvent);
|
||||||
#endif
|
#endif
|
||||||
|
@ -114,8 +114,7 @@ void ProjectAudioManager::OnAudioIOStopRecording()
|
|||||||
pTrack->AddLabel(
|
pTrack->AddLabel(
|
||||||
SelectedRegion{ interval.first,
|
SelectedRegion{ interval.first,
|
||||||
interval.first + interval.second },
|
interval.first + interval.second },
|
||||||
wxString::Format(wxT("%ld"), counter++),
|
wxString::Format(wxT("%ld"), counter++));
|
||||||
-2 );
|
|
||||||
ShowWarningDialog(&window, wxT("DropoutDetected"), _("\
|
ShowWarningDialog(&window, wxT("DropoutDetected"), _("\
|
||||||
Recorded audio was lost at the labeled locations. Possible causes:\n\
|
Recorded audio was lost at the labeled locations. Possible causes:\n\
|
||||||
\n\
|
\n\
|
||||||
|
@ -334,7 +334,7 @@ private:
|
|||||||
|
|
||||||
bool GetSelected() const { return mSelected; }
|
bool GetSelected() const { return mSelected; }
|
||||||
|
|
||||||
virtual void SetSelected(bool s);
|
void SetSelected(bool s);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -1081,7 +1081,9 @@ struct TrackListEvent : public wxCommandEvent
|
|||||||
|
|
||||||
TrackListEvent( const TrackListEvent& ) = default;
|
TrackListEvent( const TrackListEvent& ) = default;
|
||||||
|
|
||||||
wxEvent *Clone() const override { return new TrackListEvent(*this); }
|
wxEvent *Clone() const override {
|
||||||
|
// wxWidgets will own the event object
|
||||||
|
return safenew TrackListEvent(*this); }
|
||||||
|
|
||||||
std::weak_ptr<Track> mpTrack;
|
std::weak_ptr<Track> mpTrack;
|
||||||
int mCode;
|
int mCode;
|
||||||
|
@ -88,7 +88,7 @@ audio tracks.
|
|||||||
#include "widgets/Ruler.h"
|
#include "widgets/Ruler.h"
|
||||||
#include "AllThemeResources.h"
|
#include "AllThemeResources.h"
|
||||||
#include "TrackPanelDrawingContext.h"
|
#include "TrackPanelDrawingContext.h"
|
||||||
#include "tracks/ui/TrackView.h"
|
#include "tracks/labeltrack/ui/LabelTrackView.h"
|
||||||
|
|
||||||
|
|
||||||
#undef PROFILE_WAVEFORM
|
#undef PROFILE_WAVEFORM
|
||||||
@ -414,7 +414,7 @@ void TrackArt::DrawTrack(TrackPanelDrawingContext &context,
|
|||||||
},
|
},
|
||||||
#endif // USE_MIDI
|
#endif // USE_MIDI
|
||||||
[&](const LabelTrack *lt) {
|
[&](const LabelTrack *lt) {
|
||||||
lt->Draw( context, rect );
|
LabelTrackView::Get( *lt ).Draw( context, rect );
|
||||||
},
|
},
|
||||||
[&](const TimeTrack *tt) {
|
[&](const TimeTrack *tt) {
|
||||||
DrawTimeTrack( context, tt, rect );
|
DrawTimeTrack( context, tt, rect );
|
||||||
|
@ -610,8 +610,7 @@ bool GetInfoCommand::SendLabels(const CommandContext &context)
|
|||||||
context.StartArray();
|
context.StartArray();
|
||||||
context.AddItem( (double)i ); // Track number.
|
context.AddItem( (double)i ); // Track number.
|
||||||
context.StartArray();
|
context.StartArray();
|
||||||
for (int nn = 0; nn< (int)labelTrack->mLabels.size(); nn++) {
|
for ( const auto &label : labelTrack->GetLabels() ) {
|
||||||
const auto &label = labelTrack->mLabels[nn];
|
|
||||||
context.StartArray();
|
context.StartArray();
|
||||||
context.AddItem( label.getT0() ); // start
|
context.AddItem( label.getT0() ); // start
|
||||||
context.AddItem( label.getT1() ); // end
|
context.AddItem( label.getT1() ); // end
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "../Shuttle.h"
|
#include "../Shuttle.h"
|
||||||
#include "../ShuttleGui.h"
|
#include "../ShuttleGui.h"
|
||||||
#include "CommandContext.h"
|
#include "CommandContext.h"
|
||||||
|
#include "../tracks/labeltrack/ui/LabelTrackView.h"
|
||||||
|
|
||||||
SetLabelCommand::SetLabelCommand()
|
SetLabelCommand::SetLabelCommand()
|
||||||
{
|
{
|
||||||
@ -68,49 +69,51 @@ bool SetLabelCommand::Apply(const CommandContext & context)
|
|||||||
AudacityProject * p = &context.project;
|
AudacityProject * p = &context.project;
|
||||||
auto &tracks = TrackList::Get( *p );
|
auto &tracks = TrackList::Get( *p );
|
||||||
auto &selectedRegion = ViewInfo::Get( *p ).selectedRegion;
|
auto &selectedRegion = ViewInfo::Get( *p ).selectedRegion;
|
||||||
LabelStruct * pLabel = NULL;
|
const LabelStruct * pLabel = nullptr;
|
||||||
int i=0;
|
LabelTrack *labelTrack = nullptr;
|
||||||
int nn=0;
|
auto ii = mLabelIndex;
|
||||||
|
if ( mLabelIndex >= 0 ) {
|
||||||
LabelTrack *labelTrack {};
|
for (auto lt : tracks.Any<LabelTrack>()) {
|
||||||
for (auto lt : tracks.Any<LabelTrack>()) {
|
const auto &labels = lt->GetLabels();
|
||||||
if( i > mLabelIndex )
|
const auto nLabels = labels.size();
|
||||||
break;
|
if( ii >= nLabels )
|
||||||
labelTrack = lt;
|
ii -= nLabels;
|
||||||
for (nn = 0;
|
else {
|
||||||
(nn< (int)labelTrack->mLabels.size()) && i<=mLabelIndex;
|
labelTrack = lt;
|
||||||
nn++) {
|
pLabel = &labels[ ii ];
|
||||||
i++;
|
break;
|
||||||
pLabel = &labelTrack->mLabels[nn];
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (i< mLabelIndex) || (pLabel == NULL))
|
if ( !pLabel )
|
||||||
{
|
{
|
||||||
context.Error(wxT("LabelIndex was invalid."));
|
context.Error(wxT("LabelIndex was invalid."));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
auto newLabel = *pLabel;
|
||||||
if( bHasText )
|
if( bHasText )
|
||||||
pLabel->title = mText;
|
newLabel.title = mText;
|
||||||
if( bHasT0 )
|
if( bHasT0 )
|
||||||
pLabel->selectedRegion.setT0(mT0, false);
|
newLabel.selectedRegion.setT0(mT0, false);
|
||||||
if( bHasT1 )
|
if( bHasT1 )
|
||||||
pLabel->selectedRegion.setT1(mT1, false);
|
newLabel.selectedRegion.setT1(mT1, false);
|
||||||
if( bHasT0 || bHasT1 )
|
if( bHasT0 || bHasT1 )
|
||||||
pLabel->selectedRegion.ensureOrdering();
|
newLabel.selectedRegion.ensureOrdering();
|
||||||
pLabel->updated = true;
|
labelTrack->SetLabel( ii, newLabel );
|
||||||
|
|
||||||
// Only one label can be selected.
|
// Only one label can be selected.
|
||||||
if( bHasSelected ){
|
if( bHasSelected ) {
|
||||||
|
auto &view = LabelTrackView::Get( *labelTrack );
|
||||||
if( mbSelected )
|
if( mbSelected )
|
||||||
{
|
{
|
||||||
labelTrack->mSelIndex = nn-1;
|
view.SetSelectedIndex( ii );
|
||||||
double t0 = pLabel->selectedRegion.t0();
|
double t0 = pLabel->selectedRegion.t0();
|
||||||
double t1 = pLabel->selectedRegion.t1();
|
double t1 = pLabel->selectedRegion.t1();
|
||||||
selectedRegion.setTimes( t0, t1);
|
selectedRegion.setTimes( t0, t1);
|
||||||
}
|
}
|
||||||
else if( labelTrack->mSelIndex == (nn-1) )
|
else if( view.GetSelectedIndex() == ii )
|
||||||
labelTrack->mSelIndex = -1;
|
view.SetSelectedIndex( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
labelTrack->SortLabels();
|
labelTrack->SortLabels();
|
||||||
|
@ -37,6 +37,8 @@ public:
|
|||||||
bool Apply(const CommandContext & context) override;
|
bool Apply(const CommandContext & context) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// zero-based index of the desired label, within the concatenation of the
|
||||||
|
// arrays of labels of all label tracks
|
||||||
int mLabelIndex;
|
int mLabelIndex;
|
||||||
wxString mText;
|
wxString mText;
|
||||||
double mT0;
|
double mT0;
|
||||||
|
@ -216,8 +216,7 @@ bool EffectFindClipping::ProcessOne(LabelTrack * lt,
|
|||||||
if (stoprun >= mStop) {
|
if (stoprun >= mStop) {
|
||||||
lt->AddLabel(SelectedRegion(startTime,
|
lt->AddLabel(SelectedRegion(startTime,
|
||||||
wt->LongSamplesToTime(start + s - mStop)),
|
wt->LongSamplesToTime(start + s - mStop)),
|
||||||
wxString::Format(wxT("%lld of %lld"), startrun.as_long_long(), (samps - mStop).as_long_long()),
|
wxString::Format(wxT("%lld of %lld"), startrun.as_long_long(), (samps - mStop).as_long_long()));
|
||||||
-2);
|
|
||||||
startrun = 0;
|
startrun = 0;
|
||||||
stoprun = 0;
|
stoprun = 0;
|
||||||
samps = 0;
|
samps = 0;
|
||||||
|
@ -1406,7 +1406,7 @@ bool NyquistEffect::ProcessOne()
|
|||||||
// let Nyquist analyzers define more complicated selections
|
// let Nyquist analyzers define more complicated selections
|
||||||
nyx_get_label(l, &t0, &t1, &str);
|
nyx_get_label(l, &t0, &t1, &str);
|
||||||
|
|
||||||
ltrack->AddLabel(SelectedRegion(t0 + mT0, t1 + mT0), UTF8CTOWX(str), -2);
|
ltrack->AddLabel(SelectedRegion(t0 + mT0, t1 + mT0), UTF8CTOWX(str));
|
||||||
}
|
}
|
||||||
return (GetType() != EffectTypeProcess || mIsPrompt);
|
return (GetType() != EffectTypeProcess || mIsPrompt);
|
||||||
}
|
}
|
||||||
|
@ -759,7 +759,7 @@ void VampEffect::AddFeatures(LabelTrack *ltrack,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ltrack->AddLabel(SelectedRegion(ltime0, ltime1), label, -2);
|
ltrack->AddLabel(SelectedRegion(ltime0, ltime1), label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "../prefs/PrefsDialog.h"
|
#include "../prefs/PrefsDialog.h"
|
||||||
#include "../prefs/SpectrogramSettings.h"
|
#include "../prefs/SpectrogramSettings.h"
|
||||||
#include "../prefs/WaveformSettings.h"
|
#include "../prefs/WaveformSettings.h"
|
||||||
|
#include "../tracks/labeltrack/ui/LabelTrackView.h"
|
||||||
#include "../widgets/AudacityMessageBox.h"
|
#include "../widgets/AudacityMessageBox.h"
|
||||||
|
|
||||||
// private helper classes and functions
|
// private helper classes and functions
|
||||||
@ -46,10 +47,11 @@ bool DoPasteText(AudacityProject &project)
|
|||||||
for (auto pLabelTrack : tracks.Any<LabelTrack>())
|
for (auto pLabelTrack : tracks.Any<LabelTrack>())
|
||||||
{
|
{
|
||||||
// Does this track have an active label?
|
// Does this track have an active label?
|
||||||
if (pLabelTrack->HasSelection()) {
|
if (LabelTrackView::Get( *pLabelTrack ).HasSelection()) {
|
||||||
|
|
||||||
// Yes, so try pasting into it
|
// Yes, so try pasting into it
|
||||||
if (pLabelTrack->PasteSelectedText(selectedRegion.t0(),
|
auto &view = LabelTrackView::Get( *pLabelTrack );
|
||||||
|
if (view.PasteSelectedText(selectedRegion.t0(),
|
||||||
selectedRegion.t1()))
|
selectedRegion.t1()))
|
||||||
{
|
{
|
||||||
ProjectHistory::Get( project )
|
ProjectHistory::Get( project )
|
||||||
@ -57,7 +59,7 @@ bool DoPasteText(AudacityProject &project)
|
|||||||
|
|
||||||
// Make sure caret is in view
|
// Make sure caret is in view
|
||||||
int x;
|
int x;
|
||||||
if (pLabelTrack->CalcCursorX(&x)) {
|
if (view.CalcCursorX(&x)) {
|
||||||
trackPanel.ScrollIntoView(x);
|
trackPanel.ScrollIntoView(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +303,8 @@ void OnCut(const CommandContext &context)
|
|||||||
// in the middle of editing the label text and select "Cut".
|
// in the middle of editing the label text and select "Cut".
|
||||||
|
|
||||||
for (auto lt : tracks.Selected< LabelTrack >()) {
|
for (auto lt : tracks.Selected< LabelTrack >()) {
|
||||||
if (lt->CutSelectedText()) {
|
auto &view = LabelTrackView::Get( *lt );
|
||||||
|
if (view.CutSelectedText()) {
|
||||||
trackPanel.Refresh(false);
|
trackPanel.Refresh(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -408,7 +411,8 @@ void OnCopy(const CommandContext &context)
|
|||||||
auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
|
auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
|
||||||
|
|
||||||
for (auto lt : tracks.Selected< LabelTrack >()) {
|
for (auto lt : tracks.Selected< LabelTrack >()) {
|
||||||
if (lt->CopySelectedText()) {
|
auto &view = LabelTrackView::Get( *lt );
|
||||||
|
if (view.CopySelectedText()) {
|
||||||
//trackPanel.Refresh(false);
|
//trackPanel.Refresh(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1095,7 +1099,9 @@ const ReservedCommandFlag
|
|||||||
CutCopyAvailableFlag{
|
CutCopyAvailableFlag{
|
||||||
[](const AudacityProject &project){
|
[](const AudacityProject &project){
|
||||||
auto range = TrackList::Get( project ).Any<const LabelTrack>()
|
auto range = TrackList::Get( project ).Any<const LabelTrack>()
|
||||||
+ &LabelTrack::IsTextSelected;
|
+ [](const LabelTrack *pTrack){
|
||||||
|
return LabelTrackView::Get( *pTrack ).IsTextSelected();
|
||||||
|
};
|
||||||
if ( !range.empty() )
|
if ( !range.empty() )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "../WaveTrack.h"
|
#include "../WaveTrack.h"
|
||||||
#include "../commands/CommandContext.h"
|
#include "../commands/CommandContext.h"
|
||||||
#include "../commands/CommandManager.h"
|
#include "../commands/CommandManager.h"
|
||||||
|
#include "../tracks/labeltrack/ui/LabelTrackView.h"
|
||||||
|
|
||||||
// private helper classes and functions
|
// private helper classes and functions
|
||||||
namespace {
|
namespace {
|
||||||
@ -31,7 +32,7 @@ int DoAddLabel(
|
|||||||
bool useDialog;
|
bool useDialog;
|
||||||
gPrefs->Read(wxT("/GUI/DialogForNameNewLabel"), &useDialog, false);
|
gPrefs->Read(wxT("/GUI/DialogForNameNewLabel"), &useDialog, false);
|
||||||
if (useDialog) {
|
if (useDialog) {
|
||||||
if (LabelTrack::DialogForLabelName(
|
if (LabelTrackView::DialogForLabelName(
|
||||||
project, region, wxEmptyString, title) == wxID_CANCEL)
|
project, region, wxEmptyString, title) == wxID_CANCEL)
|
||||||
return -1; // index
|
return -1; // index
|
||||||
}
|
}
|
||||||
@ -57,22 +58,22 @@ int DoAddLabel(
|
|||||||
// SelectNone();
|
// SelectNone();
|
||||||
lt->SetSelected(true);
|
lt->SetSelected(true);
|
||||||
|
|
||||||
int focusTrackNumber;
|
int index;
|
||||||
if (useDialog) {
|
if (useDialog) {
|
||||||
focusTrackNumber = -2;
|
index = lt->AddLabel(region, title);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
focusTrackNumber = -1;
|
int focusTrackNumber = -1;
|
||||||
if (pFocusedTrack && preserveFocus) {
|
if (pFocusedTrack && preserveFocus) {
|
||||||
// Must remember the track to re-focus after finishing a label edit.
|
// Must remember the track to re-focus after finishing a label edit.
|
||||||
// do NOT identify it by a pointer, which might dangle! Identify
|
// do NOT identify it by a pointer, which might dangle! Identify
|
||||||
// by position.
|
// by position.
|
||||||
focusTrackNumber = pFocusedTrack->GetIndex();
|
focusTrackNumber = pFocusedTrack->GetIndex();
|
||||||
}
|
}
|
||||||
|
index =
|
||||||
|
LabelTrackView::Get( *lt ).AddLabel(region, title, focusTrackNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = lt->AddLabel(region, title, focusTrackNumber);
|
|
||||||
|
|
||||||
ProjectHistory::Get( project ).PushState(_("Added label"), _("Label"));
|
ProjectHistory::Get( project ).PushState(_("Added label"), _("Label"));
|
||||||
|
|
||||||
window.RedrawProject();
|
window.RedrawProject();
|
||||||
@ -256,7 +257,7 @@ struct Handler : CommandHandlerObject {
|
|||||||
void OnEditLabels(const CommandContext &context)
|
void OnEditLabels(const CommandContext &context)
|
||||||
{
|
{
|
||||||
auto &project = context.project;
|
auto &project = context.project;
|
||||||
LabelTrack::DoEditLabels(project);
|
LabelTrackView::DoEditLabels(project);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnAddLabel(const CommandContext &context)
|
void OnAddLabel(const CommandContext &context)
|
||||||
@ -318,12 +319,13 @@ void OnPasteNewLabel(const CommandContext &context)
|
|||||||
// Unselect the last label, so we'll have just one active label when
|
// Unselect the last label, so we'll have just one active label when
|
||||||
// we're done
|
// we're done
|
||||||
if (plt)
|
if (plt)
|
||||||
plt->Unselect();
|
LabelTrackView::Get( *plt ).SetSelectedIndex( -1 );
|
||||||
|
|
||||||
// Add a NEW label, paste into it
|
// Add a NEW label, paste into it
|
||||||
// Paul L: copy whatever defines the selected region, not just times
|
// Paul L: copy whatever defines the selected region, not just times
|
||||||
lt->AddLabel(selectedRegion);
|
auto &view = LabelTrackView::Get( *lt );
|
||||||
if (lt->PasteSelectedText(selectedRegion.t0(),
|
view.AddLabel(selectedRegion);
|
||||||
|
if (view.PasteSelectedText(selectedRegion.t0(),
|
||||||
selectedRegion.t1()))
|
selectedRegion.t1()))
|
||||||
bPastedSomething = true;
|
bPastedSomething = true;
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ Paul Licameli split from TrackPanel.cpp
|
|||||||
#include "../../../Audacity.h"
|
#include "../../../Audacity.h"
|
||||||
#include "LabelDefaultClickHandle.h"
|
#include "LabelDefaultClickHandle.h"
|
||||||
|
|
||||||
|
#include "LabelTrackView.h"
|
||||||
#include "../../ui/TrackView.h"
|
#include "../../ui/TrackView.h"
|
||||||
#include "../../../HitTestResult.h"
|
#include "../../../HitTestResult.h"
|
||||||
#include "../../../LabelTrack.h"
|
#include "../../../LabelTrack.h"
|
||||||
@ -26,7 +27,9 @@ LabelDefaultClickHandle::~LabelDefaultClickHandle()
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct LabelDefaultClickHandle::LabelState {
|
struct LabelDefaultClickHandle::LabelState {
|
||||||
std::vector< std::pair< std::weak_ptr<LabelTrack>, LabelTrack::Flags > > mPairs;
|
std::vector<
|
||||||
|
std::pair< std::weak_ptr<LabelTrack>, LabelTrackView::Flags >
|
||||||
|
> mPairs;
|
||||||
};
|
};
|
||||||
|
|
||||||
void LabelDefaultClickHandle::SaveState( AudacityProject *pProject )
|
void LabelDefaultClickHandle::SaveState( AudacityProject *pProject )
|
||||||
@ -35,17 +38,21 @@ void LabelDefaultClickHandle::SaveState( AudacityProject *pProject )
|
|||||||
auto &pairs = mLabelState->mPairs;
|
auto &pairs = mLabelState->mPairs;
|
||||||
auto &tracks = TrackList::Get( *pProject );
|
auto &tracks = TrackList::Get( *pProject );
|
||||||
|
|
||||||
for (auto lt : tracks.Any<LabelTrack>())
|
for (auto lt : tracks.Any<LabelTrack>()) {
|
||||||
|
auto &view = LabelTrackView::Get( *lt );
|
||||||
pairs.push_back( std::make_pair(
|
pairs.push_back( std::make_pair(
|
||||||
lt->SharedPointer<LabelTrack>(), lt->SaveFlags() ) );
|
lt->SharedPointer<LabelTrack>(), view.SaveFlags() ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LabelDefaultClickHandle::RestoreState( AudacityProject *pProject )
|
void LabelDefaultClickHandle::RestoreState( AudacityProject *pProject )
|
||||||
{
|
{
|
||||||
if ( mLabelState ) {
|
if ( mLabelState ) {
|
||||||
for ( const auto &pair : mLabelState->mPairs )
|
for ( const auto &pair : mLabelState->mPairs )
|
||||||
if (auto pLt = TrackList::Get( *pProject ).Lock(pair.first))
|
if (auto pLt = TrackList::Get( *pProject ).Lock(pair.first)) {
|
||||||
pLt->RestoreFlags( pair.second );
|
auto &view = LabelTrackView::Get( *pLt );
|
||||||
|
view.RestoreFlags( pair.second );
|
||||||
|
}
|
||||||
mLabelState.reset();
|
mLabelState.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,8 +71,9 @@ UIHandle::Result LabelDefaultClickHandle::Click
|
|||||||
const auto pLT = evt.pCell.get();
|
const auto pLT = evt.pCell.get();
|
||||||
for (auto lt : TrackList::Get( *pProject ).Any<LabelTrack>()) {
|
for (auto lt : TrackList::Get( *pProject ).Any<LabelTrack>()) {
|
||||||
if (pLT != &TrackView::Get( *lt )) {
|
if (pLT != &TrackView::Get( *lt )) {
|
||||||
lt->ResetFlags();
|
auto &view = LabelTrackView::Get( *lt );
|
||||||
lt->Unselect();
|
view.ResetFlags();
|
||||||
|
view.SetSelectedIndex( -1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ Paul Licameli split from TrackPanel.cpp
|
|||||||
#include "../../../Audacity.h"
|
#include "../../../Audacity.h"
|
||||||
#include "LabelGlyphHandle.h"
|
#include "LabelGlyphHandle.h"
|
||||||
|
|
||||||
|
#include "LabelTrackView.h"
|
||||||
#include "../../../HitTestResult.h"
|
#include "../../../HitTestResult.h"
|
||||||
#include "../../../LabelTrack.h"
|
#include "../../../LabelTrack.h"
|
||||||
#include "../../../ProjectHistory.h"
|
#include "../../../ProjectHistory.h"
|
||||||
@ -22,10 +23,46 @@ Paul Licameli split from TrackPanel.cpp
|
|||||||
#include <wx/cursor.h>
|
#include <wx/cursor.h>
|
||||||
#include <wx/translation.h>
|
#include <wx/translation.h>
|
||||||
|
|
||||||
|
LabelTrackHit::LabelTrackHit( const std::shared_ptr<LabelTrack> &pLT )
|
||||||
|
: mpLT{ pLT }
|
||||||
|
{
|
||||||
|
pLT->Bind(
|
||||||
|
EVT_LABELTRACK_PERMUTED, &LabelTrackHit::OnLabelPermuted, this );
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelTrackHit::~LabelTrackHit()
|
||||||
|
{
|
||||||
|
// Must do this because this sink isn't wxEvtHandler
|
||||||
|
mpLT->Unbind(
|
||||||
|
EVT_LABELTRACK_PERMUTED, &LabelTrackHit::OnLabelPermuted, this );
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabelTrackHit::OnLabelPermuted( LabelTrackEvent &e )
|
||||||
|
{
|
||||||
|
e.Skip();
|
||||||
|
if ( e.mpTrack.lock() != mpLT )
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto former = e.mFormerPosition;
|
||||||
|
auto present = e.mPresentPosition;
|
||||||
|
|
||||||
|
auto update = [=]( int &index ){
|
||||||
|
if ( index == former )
|
||||||
|
index = present;
|
||||||
|
else if ( former < index && index <= present )
|
||||||
|
-- index;
|
||||||
|
else if ( former > index && index >= present )
|
||||||
|
++ index;
|
||||||
|
};
|
||||||
|
|
||||||
|
update( mMouseOverLabelLeft );
|
||||||
|
update( mMouseOverLabelRight );
|
||||||
|
}
|
||||||
|
|
||||||
LabelGlyphHandle::LabelGlyphHandle
|
LabelGlyphHandle::LabelGlyphHandle
|
||||||
(const std::shared_ptr<LabelTrack> &pLT,
|
(const std::shared_ptr<LabelTrack> &pLT,
|
||||||
const wxRect &rect, const LabelTrackHit &hit)
|
const wxRect &rect, const std::shared_ptr<LabelTrackHit> &pHit)
|
||||||
: mHit{ hit }
|
: mpHit{ pHit }
|
||||||
, mpLT{ pLT }
|
, mpLT{ pLT }
|
||||||
, mRect{ rect }
|
, mRect{ rect }
|
||||||
{
|
{
|
||||||
@ -39,7 +76,7 @@ void LabelGlyphHandle::Enter(bool)
|
|||||||
UIHandle::Result LabelGlyphHandle::NeedChangeHighlight
|
UIHandle::Result LabelGlyphHandle::NeedChangeHighlight
|
||||||
(const LabelGlyphHandle &oldState, const LabelGlyphHandle &newState)
|
(const LabelGlyphHandle &oldState, const LabelGlyphHandle &newState)
|
||||||
{
|
{
|
||||||
if (oldState.mHit.mEdge != newState.mHit.mEdge)
|
if (oldState.mpHit->mEdge != newState.mpHit->mEdge)
|
||||||
// pointer moves between the circle and the chevron
|
// pointer moves between the circle and the chevron
|
||||||
return RefreshCode::RefreshCell;
|
return RefreshCode::RefreshCell;
|
||||||
return 0;
|
return 0;
|
||||||
@ -61,14 +98,18 @@ UIHandlePtr LabelGlyphHandle::HitTest
|
|||||||
const wxMouseState &state,
|
const wxMouseState &state,
|
||||||
const std::shared_ptr<LabelTrack> &pLT, const wxRect &rect)
|
const std::shared_ptr<LabelTrack> &pLT, const wxRect &rect)
|
||||||
{
|
{
|
||||||
LabelTrackHit hit{};
|
// Allocate on heap because there are pointers to it when it is bound as
|
||||||
pLT->OverGlyph(hit, state.m_x, state.m_y);
|
// an event sink, therefore it's not copyable; make it shared so
|
||||||
|
// LabelGlyphHandle can be copyable:
|
||||||
|
auto pHit = std::make_shared<LabelTrackHit>( pLT );
|
||||||
|
|
||||||
|
LabelTrackView::OverGlyph(*pLT, *pHit, state.m_x, state.m_y);
|
||||||
|
|
||||||
// IF edge!=0 THEN we've set the cursor and we're done.
|
// IF edge!=0 THEN we've set the cursor and we're done.
|
||||||
// signal this by setting the tip.
|
// signal this by setting the tip.
|
||||||
if ( hit.mEdge & 3 )
|
if ( pHit->mEdge & 3 )
|
||||||
{
|
{
|
||||||
auto result = std::make_shared<LabelGlyphHandle>( pLT, rect, hit );
|
auto result = std::make_shared<LabelGlyphHandle>( pLT, rect, pHit );
|
||||||
result = AssignUIHandlePtr(holder, result);
|
result = AssignUIHandlePtr(holder, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -80,6 +121,64 @@ LabelGlyphHandle::~LabelGlyphHandle()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LabelGlyphHandle::HandleGlyphClick
|
||||||
|
(LabelTrackHit &hit, const wxMouseEvent & evt,
|
||||||
|
const wxRect & r, const ZoomInfo &zoomInfo,
|
||||||
|
SelectedRegion *WXUNUSED(newSel))
|
||||||
|
{
|
||||||
|
if (evt.ButtonDown())
|
||||||
|
{
|
||||||
|
//OverGlyph sets mMouseOverLabel to be the chosen label.
|
||||||
|
const auto pTrack = mpLT;
|
||||||
|
LabelTrackView::OverGlyph(*pTrack, hit, evt.m_x, evt.m_y);
|
||||||
|
hit.mIsAdjustingLabel = evt.Button(wxMOUSE_BTN_LEFT) &&
|
||||||
|
( hit.mEdge & 3 ) != 0;
|
||||||
|
|
||||||
|
if (hit.mIsAdjustingLabel)
|
||||||
|
{
|
||||||
|
float t = 0.0;
|
||||||
|
// We move if we hit the centre, we adjust one edge if we hit a chevron.
|
||||||
|
// This is if we are moving just one edge.
|
||||||
|
hit.mbIsMoving = (hit.mEdge & 4)!=0;
|
||||||
|
// When we start dragging the label(s) we don't want them to jump.
|
||||||
|
// so we calculate the displacement of the mouse from the drag center
|
||||||
|
// and use that in subsequent dragging calculations. The mouse stays
|
||||||
|
// at the same relative displacement throughout dragging.
|
||||||
|
|
||||||
|
// However, if two label's edges are being dragged
|
||||||
|
// then the displacement is relative to the initial average
|
||||||
|
// position of them, and in that case there can be a jump of at most
|
||||||
|
// a few pixels to bring the two label boundaries to exactly the same
|
||||||
|
// position when we start dragging.
|
||||||
|
|
||||||
|
// Dragging of three label edges at the same time is not supported (yet).
|
||||||
|
|
||||||
|
const auto &mLabels = pTrack->GetLabels();
|
||||||
|
if( ( hit.mMouseOverLabelRight >= 0 ) &&
|
||||||
|
( hit.mMouseOverLabelLeft >= 0 )
|
||||||
|
)
|
||||||
|
{
|
||||||
|
t = (mLabels[ hit.mMouseOverLabelRight ].getT1() +
|
||||||
|
mLabels[ hit.mMouseOverLabelLeft ].getT0()) / 2.0f;
|
||||||
|
// If we're moving two edges, then it's a move (label size preserved)
|
||||||
|
// if both edges are the same label, and it's an adjust (label sizes change)
|
||||||
|
// if we're on a boundary between two different labels.
|
||||||
|
hit.mbIsMoving =
|
||||||
|
( hit.mMouseOverLabelLeft == hit.mMouseOverLabelRight );
|
||||||
|
}
|
||||||
|
else if( hit.mMouseOverLabelRight >=0)
|
||||||
|
{
|
||||||
|
t = mLabels[ hit.mMouseOverLabelRight ].getT1();
|
||||||
|
}
|
||||||
|
else if( hit.mMouseOverLabelLeft >=0)
|
||||||
|
{
|
||||||
|
t = mLabels[ hit.mMouseOverLabelLeft ].getT0();
|
||||||
|
}
|
||||||
|
mxMouseDisplacement = zoomInfo.TimeToPosition(t, r.x) - evt.m_x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UIHandle::Result LabelGlyphHandle::Click
|
UIHandle::Result LabelGlyphHandle::Click
|
||||||
(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
|
(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
|
||||||
{
|
{
|
||||||
@ -88,10 +187,10 @@ UIHandle::Result LabelGlyphHandle::Click
|
|||||||
const wxMouseEvent &event = evt.event;
|
const wxMouseEvent &event = evt.event;
|
||||||
|
|
||||||
auto &viewInfo = ViewInfo::Get( *pProject );
|
auto &viewInfo = ViewInfo::Get( *pProject );
|
||||||
mpLT->HandleGlyphClick
|
HandleGlyphClick(
|
||||||
(mHit, event, mRect, viewInfo, &viewInfo.selectedRegion);
|
*mpHit, event, mRect, viewInfo, &viewInfo.selectedRegion);
|
||||||
|
|
||||||
if (! mHit.mIsAdjustingLabel )
|
if (! mpHit->mIsAdjustingLabel )
|
||||||
{
|
{
|
||||||
// The positive hit test should have ensured otherwise
|
// The positive hit test should have ensured otherwise
|
||||||
//wxASSERT(false);
|
//wxASSERT(false);
|
||||||
@ -111,6 +210,143 @@ UIHandle::Result LabelGlyphHandle::Click
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If the index is for a real label, adjust its left or right boundary.
|
||||||
|
/// @iLabel - index of label, -1 for none.
|
||||||
|
/// @iEdge - which edge is requested to move, -1 for left +1 for right.
|
||||||
|
/// @bAllowSwapping - if we can switch which edge is being dragged.
|
||||||
|
/// fNewTime - the NEW time for this edge of the label.
|
||||||
|
void LabelGlyphHandle::MayAdjustLabel
|
||||||
|
( LabelTrackHit &hit, int iLabel, int iEdge, bool bAllowSwapping, double fNewTime)
|
||||||
|
{
|
||||||
|
if( iLabel < 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto pTrack = mpLT;
|
||||||
|
const auto &mLabels = pTrack->GetLabels();
|
||||||
|
auto labelStruct = mLabels[ iLabel ];
|
||||||
|
|
||||||
|
// Adjust the requested edge.
|
||||||
|
bool flipped = labelStruct.AdjustEdge( iEdge, fNewTime );
|
||||||
|
// If the edges did not swap, then we are done.
|
||||||
|
if( ! flipped ) {
|
||||||
|
pTrack->SetLabel( iLabel, labelStruct );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If swapping's not allowed we must also move the edge
|
||||||
|
// we didn't move. Then we're done.
|
||||||
|
if( !bAllowSwapping )
|
||||||
|
{
|
||||||
|
labelStruct.AdjustEdge( -iEdge, fNewTime );
|
||||||
|
pTrack->SetLabel( iLabel, labelStruct );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pTrack->SetLabel( iLabel, labelStruct );
|
||||||
|
|
||||||
|
// Swap our record of what we are dragging.
|
||||||
|
std::swap( hit.mMouseOverLabelLeft, hit.mMouseOverLabelRight );
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the index is for a real label, adjust its left and right boundary.
|
||||||
|
void LabelGlyphHandle::MayMoveLabel( int iLabel, int iEdge, double fNewTime)
|
||||||
|
{
|
||||||
|
if( iLabel < 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto pTrack = mpLT;
|
||||||
|
const auto &mLabels = pTrack->GetLabels();
|
||||||
|
auto labelStruct = mLabels[ iLabel ];
|
||||||
|
labelStruct.MoveLabel( iEdge, fNewTime );
|
||||||
|
pTrack->SetLabel( iLabel, labelStruct );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constrain function, as in processing/arduino.
|
||||||
|
// returned value will be between min and max (inclusive).
|
||||||
|
static int Constrain( int value, int min, int max )
|
||||||
|
{
|
||||||
|
wxASSERT( min <= max );
|
||||||
|
int result=value;
|
||||||
|
if( result < min )
|
||||||
|
result=min;
|
||||||
|
if( result > max )
|
||||||
|
result=max;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LabelGlyphHandle::HandleGlyphDragRelease
|
||||||
|
(LabelTrackHit &hit, const wxMouseEvent & evt,
|
||||||
|
wxRect & r, const ZoomInfo &zoomInfo,
|
||||||
|
SelectedRegion *newSel)
|
||||||
|
{
|
||||||
|
const auto pTrack = mpLT;
|
||||||
|
const auto &mLabels = pTrack->GetLabels();
|
||||||
|
if(evt.LeftUp())
|
||||||
|
{
|
||||||
|
bool lupd = false, rupd = false;
|
||||||
|
if( hit.mMouseOverLabelLeft >= 0 ) {
|
||||||
|
auto labelStruct = mLabels[ hit.mMouseOverLabelLeft ];
|
||||||
|
lupd = labelStruct.updated;
|
||||||
|
labelStruct.updated = false;
|
||||||
|
pTrack->SetLabel( hit.mMouseOverLabelLeft, labelStruct );
|
||||||
|
}
|
||||||
|
if( hit.mMouseOverLabelRight >= 0 ) {
|
||||||
|
auto labelStruct = mLabels[ hit.mMouseOverLabelRight ];
|
||||||
|
rupd = labelStruct.updated;
|
||||||
|
labelStruct.updated = false;
|
||||||
|
pTrack->SetLabel( hit.mMouseOverLabelRight, labelStruct );
|
||||||
|
}
|
||||||
|
|
||||||
|
hit.mIsAdjustingLabel = false;
|
||||||
|
hit.mMouseOverLabelLeft = -1;
|
||||||
|
hit.mMouseOverLabelRight = -1;
|
||||||
|
return lupd || rupd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(evt.Dragging())
|
||||||
|
{
|
||||||
|
//If we are currently adjusting a label,
|
||||||
|
//just reset its value and redraw.
|
||||||
|
// LL: Constrain to inside track rectangle for now. Should be changed
|
||||||
|
// to allow scrolling while dragging labels
|
||||||
|
int x = Constrain( evt.m_x + mxMouseDisplacement - r.x, 0, r.width);
|
||||||
|
|
||||||
|
// If exactly one edge is selected we allow swapping
|
||||||
|
bool bAllowSwapping =
|
||||||
|
( hit.mMouseOverLabelLeft >=0 ) !=
|
||||||
|
( hit.mMouseOverLabelRight >= 0);
|
||||||
|
// If we're on the 'dot' and nowe're moving,
|
||||||
|
// Though shift-down inverts that.
|
||||||
|
// and if both edges the same, then we're always moving the label.
|
||||||
|
bool bLabelMoving = hit.mbIsMoving;
|
||||||
|
bLabelMoving ^= evt.ShiftDown();
|
||||||
|
bLabelMoving |= ( hit.mMouseOverLabelLeft == hit.mMouseOverLabelRight );
|
||||||
|
double fNewX = zoomInfo.PositionToTime(x, 0);
|
||||||
|
if( bLabelMoving )
|
||||||
|
{
|
||||||
|
MayMoveLabel( hit.mMouseOverLabelLeft, -1, fNewX );
|
||||||
|
MayMoveLabel( hit.mMouseOverLabelRight, +1, fNewX );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MayAdjustLabel( hit, hit.mMouseOverLabelLeft, -1, bAllowSwapping, fNewX );
|
||||||
|
MayAdjustLabel( hit, hit.mMouseOverLabelRight, +1, bAllowSwapping, fNewX );
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &view = LabelTrackView::Get( *pTrack );
|
||||||
|
if( view.HasSelection() )
|
||||||
|
{
|
||||||
|
auto selIndex = view.GetSelectedIndex();
|
||||||
|
//Set the selection region to be equal to
|
||||||
|
//the NEW size of the label.
|
||||||
|
*newSel = mLabels[ selIndex ].selectedRegion;
|
||||||
|
}
|
||||||
|
pTrack->SortLabels();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
UIHandle::Result LabelGlyphHandle::Drag
|
UIHandle::Result LabelGlyphHandle::Drag
|
||||||
(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
|
(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
|
||||||
{
|
{
|
||||||
@ -118,8 +354,8 @@ UIHandle::Result LabelGlyphHandle::Drag
|
|||||||
|
|
||||||
const wxMouseEvent &event = evt.event;
|
const wxMouseEvent &event = evt.event;
|
||||||
auto &viewInfo = ViewInfo::Get( *pProject );
|
auto &viewInfo = ViewInfo::Get( *pProject );
|
||||||
mpLT->HandleGlyphDragRelease
|
HandleGlyphDragRelease(
|
||||||
(mHit, event, mRect, viewInfo, &viewInfo.selectedRegion);
|
*mpHit, event, mRect, viewInfo, &viewInfo.selectedRegion);
|
||||||
|
|
||||||
// Refresh all so that the change of selection is redrawn in all tracks
|
// Refresh all so that the change of selection is redrawn in all tracks
|
||||||
return result | RefreshCode::RefreshAll | RefreshCode::DrawOverlays;
|
return result | RefreshCode::RefreshAll | RefreshCode::DrawOverlays;
|
||||||
@ -128,7 +364,7 @@ UIHandle::Result LabelGlyphHandle::Drag
|
|||||||
HitTestPreview LabelGlyphHandle::Preview
|
HitTestPreview LabelGlyphHandle::Preview
|
||||||
(const TrackPanelMouseState &, const AudacityProject *)
|
(const TrackPanelMouseState &, const AudacityProject *)
|
||||||
{
|
{
|
||||||
return HitPreview( (mHit.mEdge & 4 )!=0);
|
return HitPreview( (mpHit->mEdge & 4 )!=0);
|
||||||
}
|
}
|
||||||
|
|
||||||
UIHandle::Result LabelGlyphHandle::Release
|
UIHandle::Result LabelGlyphHandle::Release
|
||||||
@ -139,8 +375,8 @@ UIHandle::Result LabelGlyphHandle::Release
|
|||||||
|
|
||||||
const wxMouseEvent &event = evt.event;
|
const wxMouseEvent &event = evt.event;
|
||||||
auto &viewInfo = ViewInfo::Get( *pProject );
|
auto &viewInfo = ViewInfo::Get( *pProject );
|
||||||
if (mpLT->HandleGlyphDragRelease
|
if (HandleGlyphDragRelease(
|
||||||
(mHit, event, mRect, viewInfo, &viewInfo.selectedRegion)) {
|
*mpHit, event, mRect, viewInfo, &viewInfo.selectedRegion)) {
|
||||||
ProjectHistory::Get( *pProject ).PushState(_("Modified Label"),
|
ProjectHistory::Get( *pProject ).PushState(_("Modified Label"),
|
||||||
_("Label Edit"),
|
_("Label Edit"),
|
||||||
UndoPush::CONSOLIDATE);
|
UndoPush::CONSOLIDATE);
|
||||||
|
@ -15,6 +15,9 @@ Paul Licameli split from TrackPanel.cpp
|
|||||||
|
|
||||||
class wxMouseState;
|
class wxMouseState;
|
||||||
class LabelTrack;
|
class LabelTrack;
|
||||||
|
class LabelTrackEvent;
|
||||||
|
class SelectedRegion;
|
||||||
|
class ZoomInfo;
|
||||||
|
|
||||||
/// mEdge:
|
/// mEdge:
|
||||||
/// 0 if not over a glyph,
|
/// 0 if not over a glyph,
|
||||||
@ -26,12 +29,20 @@ class LabelTrack;
|
|||||||
/// mMouseLabelLeft - index of any left label hit
|
/// mMouseLabelLeft - index of any left label hit
|
||||||
/// mMouseLabelRight - index of any right label hit
|
/// mMouseLabelRight - index of any right label hit
|
||||||
///
|
///
|
||||||
struct LabelTrackHit {
|
struct LabelTrackHit
|
||||||
|
{
|
||||||
|
LabelTrackHit( const std::shared_ptr<LabelTrack> &pLT );
|
||||||
|
~LabelTrackHit();
|
||||||
|
|
||||||
int mEdge{};
|
int mEdge{};
|
||||||
int mMouseOverLabelLeft{ -1 }; /// Keeps track of which left label the mouse is currently over.
|
int mMouseOverLabelLeft{ -1 }; /// Keeps track of which left label the mouse is currently over.
|
||||||
int mMouseOverLabelRight{ -1 }; /// Keeps track of which right label the mouse is currently over.
|
int mMouseOverLabelRight{ -1 }; /// Keeps track of which right label the mouse is currently over.
|
||||||
bool mbIsMoving {};
|
bool mbIsMoving {};
|
||||||
bool mIsAdjustingLabel {};
|
bool mIsAdjustingLabel {};
|
||||||
|
|
||||||
|
std::shared_ptr<LabelTrack> mpLT {};
|
||||||
|
|
||||||
|
void OnLabelPermuted( LabelTrackEvent &e );
|
||||||
};
|
};
|
||||||
|
|
||||||
class LabelGlyphHandle final : public LabelDefaultClickHandle
|
class LabelGlyphHandle final : public LabelDefaultClickHandle
|
||||||
@ -41,7 +52,7 @@ class LabelGlyphHandle final : public LabelDefaultClickHandle
|
|||||||
public:
|
public:
|
||||||
explicit LabelGlyphHandle
|
explicit LabelGlyphHandle
|
||||||
(const std::shared_ptr<LabelTrack> &pLT,
|
(const std::shared_ptr<LabelTrack> &pLT,
|
||||||
const wxRect &rect, const LabelTrackHit &hit);
|
const wxRect &rect, const std::shared_ptr<LabelTrackHit> &pHit);
|
||||||
|
|
||||||
LabelGlyphHandle &operator=(const LabelGlyphHandle&) = default;
|
LabelGlyphHandle &operator=(const LabelGlyphHandle&) = default;
|
||||||
|
|
||||||
@ -72,14 +83,31 @@ public:
|
|||||||
|
|
||||||
bool StopsOnKeystroke() override { return true; }
|
bool StopsOnKeystroke() override { return true; }
|
||||||
|
|
||||||
LabelTrackHit mHit{};
|
std::shared_ptr<LabelTrackHit> mpHit{};
|
||||||
|
|
||||||
static UIHandle::Result NeedChangeHighlight
|
static UIHandle::Result NeedChangeHighlight
|
||||||
(const LabelGlyphHandle &oldState, const LabelGlyphHandle &newState);
|
(const LabelGlyphHandle &oldState, const LabelGlyphHandle &newState);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void HandleGlyphClick
|
||||||
|
(LabelTrackHit &hit,
|
||||||
|
const wxMouseEvent & evt, const wxRect & r, const ZoomInfo &zoomInfo,
|
||||||
|
SelectedRegion *newSel);
|
||||||
|
bool HandleGlyphDragRelease
|
||||||
|
(LabelTrackHit &hit,
|
||||||
|
const wxMouseEvent & evt, wxRect & r, const ZoomInfo &zoomInfo,
|
||||||
|
SelectedRegion *newSel);
|
||||||
|
|
||||||
|
void MayAdjustLabel
|
||||||
|
( LabelTrackHit &hit,
|
||||||
|
int iLabel, int iEdge, bool bAllowSwapping, double fNewTime);
|
||||||
|
void MayMoveLabel( int iLabel, int iEdge, double fNewTime);
|
||||||
|
|
||||||
std::shared_ptr<LabelTrack> mpLT {};
|
std::shared_ptr<LabelTrack> mpLT {};
|
||||||
wxRect mRect {};
|
wxRect mRect {};
|
||||||
|
|
||||||
|
/// Displacement of mouse cursor from the centre being dragged.
|
||||||
|
int mxMouseDisplacement;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,6 +11,7 @@ Paul Licameli split from TrackPanel.cpp
|
|||||||
#include "../../../Audacity.h"
|
#include "../../../Audacity.h"
|
||||||
#include "LabelTextHandle.h"
|
#include "LabelTextHandle.h"
|
||||||
|
|
||||||
|
#include "LabelTrackView.h"
|
||||||
#include "../../../Experimental.h"
|
#include "../../../Experimental.h"
|
||||||
|
|
||||||
#include "../../../HitTestResult.h"
|
#include "../../../HitTestResult.h"
|
||||||
@ -23,6 +24,8 @@ Paul Licameli split from TrackPanel.cpp
|
|||||||
#include "../../../ViewInfo.h"
|
#include "../../../ViewInfo.h"
|
||||||
#include "../../../images/Cursors.h"
|
#include "../../../images/Cursors.h"
|
||||||
|
|
||||||
|
#include <wx/clipbrd.h>
|
||||||
|
|
||||||
LabelTextHandle::LabelTextHandle
|
LabelTextHandle::LabelTextHandle
|
||||||
( const std::shared_ptr<LabelTrack> &pLT, int labelNum )
|
( const std::shared_ptr<LabelTrack> &pLT, int labelNum )
|
||||||
: mpLT{ pLT }
|
: mpLT{ pLT }
|
||||||
@ -54,7 +57,8 @@ UIHandlePtr LabelTextHandle::HitTest
|
|||||||
// If Control is down, let the select handle be hit instead
|
// If Control is down, let the select handle be hit instead
|
||||||
int labelNum;
|
int labelNum;
|
||||||
if (!state.ControlDown() &&
|
if (!state.ControlDown() &&
|
||||||
(labelNum = pLT->OverATextBox(state.m_x, state.m_y) ) >= 0) {
|
(labelNum =
|
||||||
|
LabelTrackView::OverATextBox(*pLT, state.m_x, state.m_y) ) >= 0) {
|
||||||
auto result = std::make_shared<LabelTextHandle>( pLT, labelNum );
|
auto result = std::make_shared<LabelTextHandle>( pLT, labelNum );
|
||||||
result = AssignUIHandlePtr(holder, result);
|
result = AssignUIHandlePtr(holder, result);
|
||||||
return result;
|
return result;
|
||||||
@ -67,6 +71,80 @@ LabelTextHandle::~LabelTextHandle()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LabelTextHandle::HandleTextClick(const wxMouseEvent & evt,
|
||||||
|
const wxRect & r, const ZoomInfo &zoomInfo,
|
||||||
|
SelectedRegion *newSel)
|
||||||
|
{
|
||||||
|
auto pTrack = mpLT.lock();
|
||||||
|
if (!pTrack)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto &view = LabelTrackView::Get( *pTrack );
|
||||||
|
static_cast<void>(r);//compiler food.
|
||||||
|
static_cast<void>(zoomInfo);//compiler food.
|
||||||
|
if (evt.ButtonDown())
|
||||||
|
{
|
||||||
|
const auto selIndex = LabelTrackView::OverATextBox( *pTrack, evt.m_x, evt.m_y );
|
||||||
|
view.SetSelectedIndex( selIndex );
|
||||||
|
if ( selIndex != -1 ) {
|
||||||
|
const auto &mLabels = pTrack->GetLabels();
|
||||||
|
const auto &labelStruct = mLabels[ selIndex ];
|
||||||
|
*newSel = labelStruct.selectedRegion;
|
||||||
|
|
||||||
|
if (evt.LeftDown()) {
|
||||||
|
// Find the NEW drag end
|
||||||
|
auto position = view.FindCursorPosition( evt.m_x );
|
||||||
|
|
||||||
|
// Anchor shift-drag at the farther end of the previous highlight
|
||||||
|
// that is farther from the click, on Mac, for consistency with
|
||||||
|
// its text editors, but on the others, re-use the previous
|
||||||
|
// anchor.
|
||||||
|
auto initial = view.GetInitialCursorPosition();
|
||||||
|
if (evt.ShiftDown()) {
|
||||||
|
#ifdef __WXMAC__
|
||||||
|
// Set the drag anchor at the end of the previous selection
|
||||||
|
// that is farther from the NEW drag end
|
||||||
|
const auto current = view.GetCurrentCursorPosition();
|
||||||
|
if ( abs( position - current ) > abs( position - initial ) )
|
||||||
|
initial = current;
|
||||||
|
#else
|
||||||
|
// initial position remains as before
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
initial = position;
|
||||||
|
|
||||||
|
view.SetTextHighlight( initial, position );
|
||||||
|
mRightDragging = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// Actually this might be right or middle down
|
||||||
|
mRightDragging = true;
|
||||||
|
|
||||||
|
// Middle click on GTK: paste from primary selection
|
||||||
|
#if defined(__WXGTK__) && (HAVE_GTK)
|
||||||
|
if (evt.MiddleDown()) {
|
||||||
|
// Check for a click outside of the selected label's text box; in this
|
||||||
|
// case PasteSelectedText() will start a NEW label at the click
|
||||||
|
// location
|
||||||
|
if (!LabelTrackView::OverTextBox(&labelStruct, evt.m_x, evt.m_y))
|
||||||
|
view.SetSelectedIndex( -1 );
|
||||||
|
double t = zoomInfo.PositionToTime(evt.m_x, r.x);
|
||||||
|
*newSel = SelectedRegion(t, t);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if defined(__WXGTK__) && (HAVE_GTK)
|
||||||
|
if (evt.MiddleDown()) {
|
||||||
|
// Paste text, making a NEW label if none is selected.
|
||||||
|
wxTheClipboard->UsePrimarySelection(true);
|
||||||
|
view.PasteSelectedText(newSel->t0(), newSel->t1());
|
||||||
|
wxTheClipboard->UsePrimarySelection(false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UIHandle::Result LabelTextHandle::Click
|
UIHandle::Result LabelTextHandle::Click
|
||||||
(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
|
(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
|
||||||
{
|
{
|
||||||
@ -85,8 +163,7 @@ UIHandle::Result LabelTextHandle::Click
|
|||||||
auto &viewInfo = ViewInfo::Get( *pProject );
|
auto &viewInfo = ViewInfo::Get( *pProject );
|
||||||
|
|
||||||
mSelectedRegion = viewInfo.selectedRegion;
|
mSelectedRegion = viewInfo.selectedRegion;
|
||||||
pLT->HandleTextClick( event, evt.rect, viewInfo, &viewInfo.selectedRegion );
|
HandleTextClick( event, evt.rect, viewInfo, &viewInfo.selectedRegion );
|
||||||
wxASSERT(pLT->HasSelection());
|
|
||||||
|
|
||||||
{
|
{
|
||||||
// IF the user clicked a label, THEN select all other tracks by Label
|
// IF the user clicked a label, THEN select all other tracks by Label
|
||||||
@ -115,6 +192,58 @@ UIHandle::Result LabelTextHandle::Click
|
|||||||
return result | RefreshCode::RefreshCell | RefreshCode::UpdateSelection;
|
return result | RefreshCode::RefreshCell | RefreshCode::UpdateSelection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LabelTextHandle::HandleTextDragRelease(const wxMouseEvent & evt)
|
||||||
|
{
|
||||||
|
auto pTrack = mpLT.lock();
|
||||||
|
if (!pTrack)
|
||||||
|
return;
|
||||||
|
auto &view = LabelTrackView::Get( *pTrack );
|
||||||
|
|
||||||
|
if(evt.LeftUp())
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
// AWD: Due to wxWidgets bug #7491 (fix not ported to 2.8 branch) we
|
||||||
|
// should never write the primary selection. We can enable this block
|
||||||
|
// when we move to the 3.0 branch (or if a fixed 2.8 version is released
|
||||||
|
// and we can do a runtime version check)
|
||||||
|
#if defined (__WXGTK__) && defined (HAVE_GTK)
|
||||||
|
// On GTK, if we just dragged out a text selection, set the primary
|
||||||
|
// selection
|
||||||
|
if (mInitialCursorPos != mCurrentCursorPos) {
|
||||||
|
wxTheClipboard->UsePrimarySelection(true);
|
||||||
|
CopySelectedText();
|
||||||
|
wxTheClipboard->UsePrimarySelection(false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(evt.Dragging())
|
||||||
|
{
|
||||||
|
if (!mRightDragging)
|
||||||
|
// Update drag end
|
||||||
|
view.SetCurrentCursorPosition(
|
||||||
|
view.FindCursorPosition( evt.m_x ) );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evt.RightUp()) {
|
||||||
|
const auto selIndex = view.GetSelectedIndex();
|
||||||
|
if ( selIndex != -1 &&
|
||||||
|
LabelTrackView::OverTextBox(
|
||||||
|
pTrack->GetLabel( selIndex ), evt.m_x, evt.m_y ) ) {
|
||||||
|
// popup menu for editing
|
||||||
|
// TODO: handle context menus via CellularPanel?
|
||||||
|
view.ShowContextMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
UIHandle::Result LabelTextHandle::Drag
|
UIHandle::Result LabelTextHandle::Drag
|
||||||
(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
|
(const TrackPanelMouseEvent &evt, AudacityProject *pProject)
|
||||||
{
|
{
|
||||||
@ -124,7 +253,7 @@ UIHandle::Result LabelTextHandle::Drag
|
|||||||
const wxMouseEvent &event = evt.event;
|
const wxMouseEvent &event = evt.event;
|
||||||
auto pLT = TrackList::Get( *pProject ).Lock(mpLT);
|
auto pLT = TrackList::Get( *pProject ).Lock(mpLT);
|
||||||
if(pLT)
|
if(pLT)
|
||||||
pLT->HandleTextDragRelease(event);
|
HandleTextDragRelease(event);
|
||||||
|
|
||||||
// locate the initial mouse position
|
// locate the initial mouse position
|
||||||
if (event.LeftIsDown()) {
|
if (event.LeftIsDown()) {
|
||||||
@ -132,10 +261,11 @@ UIHandle::Result LabelTextHandle::Drag
|
|||||||
mLabelTrackStartXPos = event.m_x;
|
mLabelTrackStartXPos = event.m_x;
|
||||||
mLabelTrackStartYPos = event.m_y;
|
mLabelTrackStartYPos = event.m_y;
|
||||||
|
|
||||||
|
auto pView = pLT ? &LabelTrackView::Get( *pLT ) : nullptr;
|
||||||
if (pLT &&
|
if (pLT &&
|
||||||
(pLT->getSelectedIndex() != -1) &&
|
(pView->GetSelectedIndex() != -1) &&
|
||||||
pLT->OverTextBox(
|
LabelTrackView::OverTextBox(
|
||||||
pLT->GetLabel(pLT->getSelectedIndex()),
|
pLT->GetLabel(pView->GetSelectedIndex()),
|
||||||
mLabelTrackStartXPos,
|
mLabelTrackStartXPos,
|
||||||
mLabelTrackStartYPos))
|
mLabelTrackStartYPos))
|
||||||
mLabelTrackStartYPos = -1;
|
mLabelTrackStartYPos = -1;
|
||||||
@ -172,7 +302,7 @@ UIHandle::Result LabelTextHandle::Release
|
|||||||
const wxMouseEvent &event = evt.event;
|
const wxMouseEvent &event = evt.event;
|
||||||
auto pLT = TrackList::Get( *pProject ).Lock(mpLT);
|
auto pLT = TrackList::Get( *pProject ).Lock(mpLT);
|
||||||
if (pLT)
|
if (pLT)
|
||||||
pLT->HandleTextDragRelease(event);
|
HandleTextDragRelease(event);
|
||||||
|
|
||||||
// handle mouse left button up
|
// handle mouse left button up
|
||||||
if (event.LeftUp())
|
if (event.LeftUp())
|
||||||
|
@ -17,6 +17,7 @@ Paul Licameli split from TrackPanel.cpp
|
|||||||
class wxMouseState;
|
class wxMouseState;
|
||||||
class LabelTrack;
|
class LabelTrack;
|
||||||
class SelectionStateChanger;
|
class SelectionStateChanger;
|
||||||
|
class ZoomInfo;
|
||||||
|
|
||||||
class LabelTextHandle final : public LabelDefaultClickHandle
|
class LabelTextHandle final : public LabelDefaultClickHandle
|
||||||
{
|
{
|
||||||
@ -55,12 +56,20 @@ public:
|
|||||||
Result Cancel(AudacityProject *pProject) override;
|
Result Cancel(AudacityProject *pProject) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void HandleTextClick
|
||||||
|
(const wxMouseEvent & evt, const wxRect & r, const ZoomInfo &zoomInfo,
|
||||||
|
SelectedRegion *newSel);
|
||||||
|
void HandleTextDragRelease(const wxMouseEvent & evt);
|
||||||
|
|
||||||
std::weak_ptr<LabelTrack> mpLT {};
|
std::weak_ptr<LabelTrack> mpLT {};
|
||||||
int mLabelNum{ -1 };
|
int mLabelNum{ -1 };
|
||||||
int mLabelTrackStartXPos { -1 };
|
int mLabelTrackStartXPos { -1 };
|
||||||
int mLabelTrackStartYPos { -1 };
|
int mLabelTrackStartYPos { -1 };
|
||||||
SelectedRegion mSelectedRegion{};
|
SelectedRegion mSelectedRegion{};
|
||||||
std::shared_ptr<SelectionStateChanger> mChanger;
|
std::shared_ptr<SelectionStateChanger> mChanger;
|
||||||
|
|
||||||
|
/// flag to tell if it's a valid dragging
|
||||||
|
bool mRightDragging{ false };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,6 +11,7 @@ Paul Licameli split from TrackPanel.cpp
|
|||||||
#include "../../../Audacity.h"
|
#include "../../../Audacity.h"
|
||||||
#include "LabelTrackControls.h"
|
#include "LabelTrackControls.h"
|
||||||
|
|
||||||
|
#include "LabelTrackView.h"
|
||||||
#include "../../../HitTestResult.h"
|
#include "../../../HitTestResult.h"
|
||||||
#include "../../../LabelTrack.h"
|
#include "../../../LabelTrack.h"
|
||||||
#include "../../../widgets/PopupMenuTable.h"
|
#include "../../../widgets/PopupMenuTable.h"
|
||||||
@ -103,10 +104,10 @@ void LabelTrackMenuTable::OnSetFont(wxCommandEvent &)
|
|||||||
// Correct for empty facename, or bad preference file:
|
// Correct for empty facename, or bad preference file:
|
||||||
// get the name of a really existing font, to highlight by default
|
// get the name of a really existing font, to highlight by default
|
||||||
// in the list box
|
// in the list box
|
||||||
facename = LabelTrack::GetFont(facename).GetFaceName();
|
facename = LabelTrackView::GetFont(facename).GetFaceName();
|
||||||
|
|
||||||
long fontsize = gPrefs->Read(wxT("/GUI/LabelFontSize"),
|
long fontsize = gPrefs->Read(wxT("/GUI/LabelFontSize"),
|
||||||
LabelTrack::DefaultFontSize);
|
LabelTrackView::DefaultFontSize);
|
||||||
|
|
||||||
/* i18n-hint: (noun) This is the font for the label track.*/
|
/* i18n-hint: (noun) This is the font for the label track.*/
|
||||||
wxDialogWrapper dlg(mpData->pParent, wxID_ANY, wxString(_("Label Track Font")));
|
wxDialogWrapper dlg(mpData->pParent, wxID_ANY, wxString(_("Label Track Font")));
|
||||||
@ -160,7 +161,7 @@ void LabelTrackMenuTable::OnSetFont(wxCommandEvent &)
|
|||||||
gPrefs->Write(wxT("/GUI/LabelFontSize"), sc->GetValue());
|
gPrefs->Write(wxT("/GUI/LabelFontSize"), sc->GetValue());
|
||||||
gPrefs->Flush();
|
gPrefs->Flush();
|
||||||
|
|
||||||
LabelTrack::ResetFont();
|
LabelTrackView::ResetFont();
|
||||||
|
|
||||||
mpData->result = RefreshCode::RefreshAll;
|
mpData->result = RefreshCode::RefreshAll;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -15,8 +15,23 @@ Paul Licameli split from class LabelTrack
|
|||||||
|
|
||||||
class LabelGlyphHandle;
|
class LabelGlyphHandle;
|
||||||
class LabelTextHandle;
|
class LabelTextHandle;
|
||||||
|
class LabelDefaultClickHandle;
|
||||||
|
class LabelStruct;
|
||||||
class LabelTrack;
|
class LabelTrack;
|
||||||
|
struct LabelTrackEvent;
|
||||||
|
struct LabelTrackHit;
|
||||||
class SelectedRegion;
|
class SelectedRegion;
|
||||||
|
struct TrackPanelDrawingContext;
|
||||||
|
class ZoomInfo;
|
||||||
|
|
||||||
|
class wxBitmap;
|
||||||
|
class wxCommandEvent;
|
||||||
|
class wxDC;
|
||||||
|
class wxMouseEvent;
|
||||||
|
|
||||||
|
constexpr int NUM_GLYPH_CONFIGS = 3;
|
||||||
|
constexpr int NUM_GLYPH_HIGHLIGHTS = 4;
|
||||||
|
constexpr int MAX_NUM_ROWS =80;
|
||||||
|
|
||||||
class wxKeyEvent;
|
class wxKeyEvent;
|
||||||
|
|
||||||
@ -25,7 +40,11 @@ class LabelTrackView final : public CommonTrackView
|
|||||||
LabelTrackView( const LabelTrackView& ) = delete;
|
LabelTrackView( const LabelTrackView& ) = delete;
|
||||||
LabelTrackView &operator=( const LabelTrackView& ) = delete;
|
LabelTrackView &operator=( const LabelTrackView& ) = delete;
|
||||||
|
|
||||||
|
void Reparent( const std::shared_ptr<Track> &parent ) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum : int { DefaultFontSize = 12 };
|
||||||
|
|
||||||
explicit
|
explicit
|
||||||
LabelTrackView( const std::shared_ptr<Track> &pTrack );
|
LabelTrackView( const std::shared_ptr<Track> &pTrack );
|
||||||
~LabelTrackView() override;
|
~LabelTrackView() override;
|
||||||
@ -37,7 +56,15 @@ public:
|
|||||||
bool DoKeyDown(SelectedRegion &sel, wxKeyEvent & event);
|
bool DoKeyDown(SelectedRegion &sel, wxKeyEvent & event);
|
||||||
bool DoChar(SelectedRegion &sel, wxKeyEvent & event);
|
bool DoChar(SelectedRegion &sel, wxKeyEvent & event);
|
||||||
|
|
||||||
|
//This returns the index of the label we just added.
|
||||||
|
int AddLabel(const SelectedRegion ®ion,
|
||||||
|
const wxString &title = {},
|
||||||
|
int restoreFocus = -1);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void BindTo( LabelTrack *pParent );
|
||||||
|
void UnbindFrom( LabelTrack *pParent );
|
||||||
|
|
||||||
std::vector<UIHandlePtr> DetailedHitTest
|
std::vector<UIHandlePtr> DetailedHitTest
|
||||||
(const TrackPanelMouseState &state,
|
(const TrackPanelMouseState &state,
|
||||||
const AudacityProject *pProject, int currentTool, bool bMultiTool)
|
const AudacityProject *pProject, int currentTool, bool bMultiTool)
|
||||||
@ -54,11 +81,137 @@ private:
|
|||||||
|
|
||||||
std::shared_ptr<TrackVRulerControls> DoGetVRulerControls() override;
|
std::shared_ptr<TrackVRulerControls> DoGetVRulerControls() override;
|
||||||
|
|
||||||
|
// Preserve some view state too for undo/redo purposes
|
||||||
|
void Copy( const TrackView &other ) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void DoEditLabels(
|
||||||
|
AudacityProject &project, LabelTrack *lt = nullptr, int index = -1);
|
||||||
|
|
||||||
|
static int DialogForLabelName(
|
||||||
|
AudacityProject &project, const SelectedRegion& region,
|
||||||
|
const wxString& initialValue, wxString& value);
|
||||||
|
|
||||||
|
bool IsTextSelected() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CreateCustomGlyphs();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static wxFont GetFont(const wxString &faceName, int size = DefaultFontSize);
|
||||||
|
static void ResetFont();
|
||||||
|
|
||||||
|
void Draw( TrackPanelDrawingContext &context, const wxRect & r ) const;
|
||||||
|
|
||||||
|
int GetSelectedIndex() const;
|
||||||
|
void SetSelectedIndex( int index );
|
||||||
|
|
||||||
|
bool CutSelectedText();
|
||||||
|
bool CopySelectedText();
|
||||||
|
bool PasteSelectedText(double sel0, double sel1);
|
||||||
|
|
||||||
|
static void OverGlyph(
|
||||||
|
const LabelTrack &track, LabelTrackHit &hit, int x, int y );
|
||||||
|
|
||||||
|
private:
|
||||||
|
static wxBitmap & GetGlyph( int i);
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct Flags {
|
||||||
|
int mInitialCursorPos, mCurrentCursorPos, mSelIndex;
|
||||||
|
bool mDrawCursor;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ResetFlags();
|
||||||
|
Flags SaveFlags() const
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
mInitialCursorPos, mCurrentCursorPos, mSelIndex,
|
||||||
|
mDrawCursor
|
||||||
|
};
|
||||||
|
}
|
||||||
|
void RestoreFlags( const Flags& flags );
|
||||||
|
|
||||||
|
static int OverATextBox( const LabelTrack &track, int xx, int yy );
|
||||||
|
|
||||||
|
static bool OverTextBox( const LabelStruct *pLabel, int x, int y );
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool IsTextClipSupported();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void AddedLabel( const wxString &title, int pos );
|
||||||
|
void DeletedLabel( int index );
|
||||||
|
|
||||||
|
private:
|
||||||
|
//And this tells us the index, if there is a label already there.
|
||||||
|
int GetLabelIndex(double t, double t1);
|
||||||
|
|
||||||
|
public:
|
||||||
|
//get current cursor position,
|
||||||
|
// relative to the left edge of the track panel
|
||||||
|
bool CalcCursorX(int * x) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CalcHighlightXs(int *x1, int *x2) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void ShowContextMenu();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void OnContextMenu(wxCommandEvent & evt);
|
||||||
|
|
||||||
|
mutable int mSelIndex{-1}; /// Keeps track of the currently selected label
|
||||||
|
|
||||||
|
static int mIconHeight;
|
||||||
|
static int mIconWidth;
|
||||||
|
static int mTextHeight;
|
||||||
|
|
||||||
|
static bool mbGlyphsReady;
|
||||||
|
static wxBitmap mBoundaryGlyphs[NUM_GLYPH_CONFIGS * NUM_GLYPH_HIGHLIGHTS];
|
||||||
|
|
||||||
|
static int mFontHeight;
|
||||||
|
int mCurrentCursorPos; /// current cursor position
|
||||||
|
int mInitialCursorPos; /// initial cursor position
|
||||||
|
|
||||||
|
bool mDrawCursor; /// flag to tell if drawing the
|
||||||
|
/// cursor or not
|
||||||
|
int mRestoreFocus{-2}; /// Restore focus to this track
|
||||||
|
/// when done editing
|
||||||
|
|
||||||
|
void ComputeTextPosition(const wxRect & r, int index) const;
|
||||||
|
void ComputeLayout(const wxRect & r, const ZoomInfo &zoomInfo) const;
|
||||||
|
static void DrawLines( wxDC & dc, const LabelStruct &ls, const wxRect & r);
|
||||||
|
static void DrawGlyphs( wxDC & dc, const LabelStruct &ls, const wxRect & r,
|
||||||
|
int GlyphLeft, int GlyphRight);
|
||||||
|
static void DrawText( wxDC & dc, const LabelStruct &ls, const wxRect & r);
|
||||||
|
static void DrawTextBox( wxDC & dc, const LabelStruct &ls, const wxRect & r);
|
||||||
|
static void DrawHighlight(
|
||||||
|
wxDC & dc, const LabelStruct &ls, int xPos1, int xPos2, int charHeight);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// convert pixel coordinate to character position in text box
|
||||||
|
int FindCursorPosition(wxCoord xPos);
|
||||||
|
int GetCurrentCursorPosition() const { return mCurrentCursorPos; }
|
||||||
|
void SetCurrentCursorPosition(int pos);
|
||||||
|
int GetInitialCursorPosition() const { return mInitialCursorPos; }
|
||||||
|
void SetTextHighlight( int initialPosition, int currentPosition );
|
||||||
|
|
||||||
|
static void calculateFontHeight(wxDC & dc);
|
||||||
|
bool HasSelection() const;
|
||||||
|
void RemoveSelectedText();
|
||||||
|
|
||||||
|
void OnLabelAdded( LabelTrackEvent& );
|
||||||
|
void OnLabelDeleted( LabelTrackEvent& );
|
||||||
|
void OnLabelPermuted( LabelTrackEvent& );
|
||||||
|
|
||||||
std::shared_ptr<LabelTrack> FindLabelTrack();
|
std::shared_ptr<LabelTrack> FindLabelTrack();
|
||||||
std::shared_ptr<const LabelTrack> FindLabelTrack() const;
|
std::shared_ptr<const LabelTrack> FindLabelTrack() const;
|
||||||
|
|
||||||
std::weak_ptr<LabelGlyphHandle> mGlyphHandle;
|
std::weak_ptr<LabelGlyphHandle> mGlyphHandle;
|
||||||
std::weak_ptr<LabelTextHandle> mTextHandle;
|
std::weak_ptr<LabelTextHandle> mTextHandle;
|
||||||
|
|
||||||
|
static wxFont msFont;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -63,7 +63,7 @@ public:
|
|||||||
|
|
||||||
std::shared_ptr<Track> DoFindTrack() override;
|
std::shared_ptr<Track> DoFindTrack() override;
|
||||||
|
|
||||||
void Reparent( const std::shared_ptr<Track> &parent );
|
virtual void Reparent( const std::shared_ptr<Track> &parent );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::weak_ptr< Track > mwTrack;
|
std::weak_ptr< Track > mwTrack;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user