mirror of
https://github.com/cookiengineer/audacity
synced 2025-08-04 06:09:28 +02:00
This change is believed to be a direct refactoring that does not change functionality. It paves the way for more complex kinds of selection, such as selections involving frequency as well as time. It also reduces risk of left and right edges being swapped in future code using SelectedRegion, as the default is to swap on assignment if needed.
275 lines
9.2 KiB
C++
275 lines
9.2 KiB
C++
/**********************************************************************
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
LabelTrack.h
|
|
|
|
Dominic Mazzoni
|
|
James Crook
|
|
Jun Wan
|
|
|
|
**********************************************************************/
|
|
|
|
#ifndef _LABELTRACK_
|
|
#define _LABELTRACK_
|
|
|
|
#include "SelectedRegion.h"
|
|
#include "Track.h"
|
|
|
|
#include <wx/brush.h>
|
|
#include <wx/event.h>
|
|
#include <wx/font.h>
|
|
#include <wx/pen.h>
|
|
#include <wx/dynarray.h>
|
|
#include <wx/string.h>
|
|
#include <wx/clipbrd.h>
|
|
|
|
|
|
class wxKeyEvent;
|
|
class wxMouseEvent;
|
|
class wxTextFile;
|
|
class wxWindow;
|
|
class wxIcon;
|
|
class wxBitmap;
|
|
class TrackList;
|
|
|
|
class AudacityProject;
|
|
class DirManager;
|
|
class TimeWarper;
|
|
|
|
|
|
class LabelStruct
|
|
{
|
|
// disallow copy
|
|
private:
|
|
LabelStruct(const LabelStruct&);
|
|
LabelStruct& operator= (const LabelStruct&);
|
|
public:
|
|
// Copies region
|
|
LabelStruct(const SelectedRegion& region, const wxString &aTitle);
|
|
// Copies region but then overwrites other times
|
|
LabelStruct(const SelectedRegion& region, double t0, double t1,
|
|
const wxString &aTitle);
|
|
void DrawLines( wxDC & dc, const wxRect & r);
|
|
void DrawGlyphs( wxDC & dc, const wxRect & r, int GlyphLeft, int GlyphRight);
|
|
void DrawText( wxDC & dc, const wxRect & r);
|
|
void DrawTextBox( wxDC & dc, const wxRect & r);
|
|
void DrawHighlight( wxDC & dc, int xPos1, int xPos2, int charHeight);
|
|
void getXPos( wxDC & dc, int * xPos1, int cursorPos);
|
|
double getDuration() const { return selectedRegion.duration(); }
|
|
double getT0() const { return selectedRegion.t0(); }
|
|
double getT1() const { return selectedRegion.t1(); }
|
|
// Returns true iff the label got inverted:
|
|
bool AdjustEdge( int iEdge, double fNewTime);
|
|
void MoveLabel( int iEdge, double fNewTime);
|
|
|
|
/// Relationships between selection region and labels
|
|
enum TimeRelations
|
|
{
|
|
BEFORE_LABEL,
|
|
AFTER_LABEL,
|
|
SURROUNDS_LABEL,
|
|
WITHIN_LABEL,
|
|
BEGINS_IN_LABEL,
|
|
ENDS_IN_LABEL
|
|
};
|
|
|
|
/// Returns relationship between a region described and this label; if
|
|
/// parent is set, it will consider point labels at the very beginning
|
|
/// and end of parent to be within a region that borders them (this makes
|
|
/// it possible to delete capture all labels with a Select All).
|
|
TimeRelations RegionRelation(double reg_t0, double reg_t1,
|
|
LabelTrack *parent = NULL);
|
|
|
|
public:
|
|
SelectedRegion selectedRegion;
|
|
wxString title; /// Text of the label.
|
|
int width; /// width of the text in pixels.
|
|
|
|
// Working storage for on-screen layout.
|
|
int x; /// Pixel position of left hand glyph
|
|
int x1; /// Pixel position of right hand glyph
|
|
int xText; /// Pixel position of left hand side of text box
|
|
int y; /// Pixel position of label.
|
|
|
|
bool highlighted; /// if the text is highlighted
|
|
bool changeInitialMouseXPos; /// flag to change initial mouse X pos
|
|
bool updated; /// flag to tell if the label times were updated
|
|
};
|
|
|
|
//You can't stick AUDACITY_DLL_API in front of the WX_DEFINE_ARRAY() macro, you
|
|
//have to use the below macro instead to avoid a warning
|
|
WX_DEFINE_USER_EXPORTED_ARRAY(LabelStruct *, LabelArray, class AUDACITY_DLL_API);
|
|
|
|
const int NUM_GLYPH_CONFIGS = 3;
|
|
const int NUM_GLYPH_HIGHLIGHTS = 4;
|
|
const int MAX_NUM_ROWS =80;
|
|
|
|
|
|
class AUDACITY_DLL_API LabelTrack : public Track
|
|
{
|
|
friend class LabelStruct;
|
|
|
|
public:
|
|
bool IsGoodLabelFirstKey(int keyCode);
|
|
bool IsGoodLabelEditKey(int keyCode);
|
|
bool IsTextSelected();
|
|
|
|
void CreateCustomGlyphs();
|
|
LabelTrack(DirManager * projDirManager);
|
|
LabelTrack(const LabelTrack &orig);
|
|
|
|
virtual ~ LabelTrack();
|
|
virtual void SetOffset(double dOffset);
|
|
|
|
static void ResetFont();
|
|
|
|
void Draw(wxDC & dc, const wxRect & r, double h, double pps,
|
|
double sel0, double sel1);
|
|
|
|
int getSelectedIndex() const { return mSelIndex; }
|
|
|
|
virtual int GetKind() const { return Label; }
|
|
|
|
virtual double GetStartTime();
|
|
virtual double GetEndTime();
|
|
|
|
virtual Track *Duplicate() { return new LabelTrack(*this); }
|
|
|
|
virtual bool HandleXMLTag(const wxChar *tag, const wxChar **attrs);
|
|
virtual XMLTagHandler *HandleXMLChild(const wxChar *tag);
|
|
virtual void WriteXML(XMLWriter &xmlFile);
|
|
|
|
#if LEGACY_PROJECT_FILE_SUPPORT
|
|
virtual bool Load(wxTextFile * in, DirManager * dirManager);
|
|
virtual bool Save(wxTextFile * out, bool overwrite);
|
|
#endif
|
|
|
|
virtual bool Cut (double t0, double t1, Track ** dest);
|
|
// JKC Do not add the const modifier to Copy(), Clear()
|
|
// or Paste() because then it
|
|
// is no longer recognised as a virtual function matching the
|
|
// one in Track.
|
|
virtual bool Copy (double t0, double t1, Track ** dest);// const;
|
|
virtual bool Clear(double t0, double t1);
|
|
virtual bool Paste(double t, Track * src);
|
|
bool Repeat(double t0, double t1, int n);
|
|
|
|
virtual bool Silence(double t0, double t1);
|
|
virtual bool InsertSilence(double t, double len);
|
|
int OverGlyph(int x, int y);
|
|
static wxBitmap & GetGlyph( int i);
|
|
|
|
|
|
void ResetFlags();
|
|
bool OverTextBox(const LabelStruct *pLabel, int x, int y);
|
|
bool CutSelectedText();
|
|
bool CopySelectedText();
|
|
bool PasteSelectedText(double sel0, double sel1);
|
|
static bool IsTextClipSupported();
|
|
|
|
// methods to set flags
|
|
void SetDragXPos(const int d) { mDragXPos = d; };
|
|
void SetInBox(bool inTextBox) { mInBox = inTextBox; };
|
|
void SetResetCursorPos(bool resetFlag) { mResetCursorPos = resetFlag; };
|
|
void SetWrongDragging(bool rightFlag) { mRightDragging = rightFlag; };
|
|
void SetDrawCursor(bool drawCursorFlag) { mDrawCursor = drawCursorFlag; };
|
|
|
|
bool HandleMouse(const wxMouseEvent & evt, wxRect & r, double h, double pps,
|
|
SelectedRegion *newSel);
|
|
|
|
bool CaptureKey(wxKeyEvent & event);
|
|
bool OnKeyDown(SelectedRegion &sel, wxKeyEvent & event);
|
|
bool OnChar(SelectedRegion &sel, wxKeyEvent & event);
|
|
|
|
void Import(wxTextFile & f);
|
|
void Export(wxTextFile & f);
|
|
|
|
void Unselect();
|
|
|
|
bool IsSelected() const;
|
|
|
|
int GetNumLabels() const;
|
|
const LabelStruct *GetLabel(int index) const;
|
|
|
|
//This returns the index of the label we just added.
|
|
int AddLabel(const SelectedRegion ®ion, const wxString &title = wxT(""));
|
|
//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.
|
|
void DeleteLabel(int index);
|
|
|
|
//get current cursor position
|
|
bool CalcCursorX(wxWindow * parent, int * x);
|
|
int getCurrentCursorPosition() const { return mCurrentCursorPos; };
|
|
|
|
void MayAdjustLabel( int iLabel, int iEdge, bool bAllowSwapping, double fNewTime);
|
|
void MayMoveLabel( int iLabel, int iEdge, double fNewTime);
|
|
|
|
// This pastes labels without shifting existing ones
|
|
bool PasteOver(double t, Track *src);
|
|
bool SplitCut(double b, double e, Track **dest);
|
|
bool SplitDelete(double b, double e);
|
|
void ShiftLabelsOnInsert(double length, double pt);
|
|
void ChangeLabelsOnReverse(double b, double e);
|
|
void ScaleLabels(double b, double e, double change);
|
|
double AdjustTimeStampOnScale(double t, double b, double e, double change);
|
|
void WarpLabels(const TimeWarper &warper);
|
|
|
|
// Returns tab-separated text of all labels completely within given region
|
|
wxString GetTextOfLabels(double t0, double t1);
|
|
|
|
public:
|
|
void SortLabels();
|
|
//These two are used by a TrackPanel KLUDGE, which is why they are public.
|
|
bool mbHitCenter;
|
|
//The edge variable tells us what state the icon is in.
|
|
//mOldEdge is useful for telling us when there has been a state change.
|
|
int mOldEdge;
|
|
private:
|
|
|
|
int mSelIndex; /// Keeps track of the currently selected label
|
|
int mMouseOverLabelLeft; /// Keeps track of which left label the mouse is currently over.
|
|
int mMouseOverLabelRight; /// Keeps track of which right label the mouse is currently over.
|
|
int mxMouseDisplacement; /// Displacement of mouse cursor from the centre being dragged.
|
|
LabelArray mLabels;
|
|
|
|
static int mIconHeight;
|
|
static int mIconWidth;
|
|
static int mTextHeight;
|
|
static bool mbGlyphsReady;
|
|
static wxBitmap mBoundaryGlyphs[NUM_GLYPH_CONFIGS * NUM_GLYPH_HIGHLIGHTS];
|
|
|
|
int xUsed[MAX_NUM_ROWS];
|
|
|
|
static int mFontHeight;
|
|
int mXPos1; /// left X pos of highlighted area
|
|
int mXPos2; /// right X pos of highlighted area
|
|
int mCurrentCursorPos; /// current cursor position
|
|
int mInitialCursorPos; /// initial cursor position
|
|
double mMouseXPos; /// mouse X pos
|
|
int mDragXPos; /// end X pos of dragging
|
|
bool mInBox; /// flag to tell if the mouse is in text box
|
|
bool mResetCursorPos; /// flag to reset cursor position(used in the dragging the glygh)
|
|
bool mRightDragging; /// flag to tell if it's a valid dragging
|
|
bool mDrawCursor; /// flag to tell if drawing the cursor or not
|
|
|
|
// Set in copied label tracks
|
|
double mClipLen;
|
|
|
|
void ComputeLayout(const wxRect & r, double h, double pps);
|
|
void ComputeTextPosition(const wxRect & r, int index);
|
|
void SetCurrentCursorPosition(wxDC & dc, int xPos);
|
|
|
|
void calculateFontHeight(wxDC & dc);
|
|
void RemoveSelectedText();
|
|
|
|
bool mIsAdjustingLabel;
|
|
bool mbIsMoving;
|
|
|
|
static wxFont msFont;
|
|
};
|
|
|
|
#endif
|