1 /********************************************************************** 2 3 Audacity: A Digital Audio Editor 4 5 ViewInfo.h 6 7 Dominic Mazzoni 8 9 **********************************************************************/ 10 11 #ifndef __AUDACITY_VIEWINFO__ 12 #define __AUDACITY_VIEWINFO__ 13 14 #include <utility> 15 #include <vector> 16 #include <wx/event.h> // inherit wxEvtHandler 17 #include <wx/weakref.h> // member variable 18 #include "SelectedRegion.h" 19 #include <memory> 20 #include "Prefs.h" 21 #include "XMLMethodRegistry.h" 22 #include "ZoomInfo.h" // to inherit 23 24 25 class NotifyingSelectedRegion; 26 27 struct SelectedRegionEvent : public wxEvent 28 { 29 SelectedRegionEvent( wxEventType commandType, 30 NotifyingSelectedRegion *pRegion ); 31 32 wxEvent *Clone() const override; 33 34 wxWeakRef< NotifyingSelectedRegion > pRegion; 35 }; 36 37 // To do: distinguish time changes from frequency changes perhaps? 38 wxDECLARE_EXPORTED_EVENT( SCREEN_GEOMETRY_API, 39 EVT_SELECTED_REGION_CHANGE, SelectedRegionEvent ); 40 41 // This heavyweight wrapper of the SelectedRegion structure emits events 42 // on mutating operations, that other classes can listen for. 43 class SCREEN_GEOMETRY_API NotifyingSelectedRegion : public wxEvtHandler 44 { 45 public: 46 // Expose SelectedRegion's const accessors t0()47 double t0 () const { return mRegion.t0(); } t1()48 double t1 () const { return mRegion.t1(); } f0()49 double f0 () const { return mRegion.f0(); } f1()50 double f1 () const { return mRegion.f1(); } fc()51 double fc () const { return mRegion.fc(); } isPoint()52 bool isPoint() const { return mRegion.isPoint(); } duration()53 double duration() const { return mRegion.duration(); } 54 55 // Writing and reading of persistent fields -- the read is mutating but 56 // does not emit events WriteXMLAttributes(XMLWriter & xmlFile,const char * legacyT0Name,const char * legacyT1Name)57 void WriteXMLAttributes 58 (XMLWriter &xmlFile, 59 const char *legacyT0Name, const char *legacyT1Name) const 60 { mRegion.WriteXMLAttributes(xmlFile, legacyT0Name, legacyT1Name); } 61 62 //! Return some information used for deserialization purposes by ViewInfo 63 static XMLMethodRegistryBase::Mutators<NotifyingSelectedRegion> 64 Mutators(const char *legacyT0Name, const char *legacyT1Name); 65 66 // const-only access allows assignment from this into a SelectedRegion 67 // or otherwise passing it into a function taking const SelectedRegion& 68 operator const SelectedRegion & () const { return mRegion; } 69 70 // These are the event-emitting operations 71 NotifyingSelectedRegion& operator = ( const SelectedRegion &other ); 72 73 // Returns true iff the bounds got swapped 74 bool setTimes(double t0, double t1); 75 76 // Returns true iff the bounds got swapped 77 bool setT0(double t, bool maySwap = true); 78 79 // Returns true iff the bounds got swapped 80 bool setT1(double t, bool maySwap = true); 81 82 void collapseToT0(); 83 84 void collapseToT1(); 85 86 void move(double delta); 87 88 // Returns true iff the bounds got swapped 89 bool setFrequencies(double f0, double f1); 90 91 // Returns true iff the bounds got swapped 92 bool setF0(double f, bool maySwap = true); 93 94 // Returns true iff the bounds got swapped 95 bool setF1(double f, bool maySwap = true); 96 97 private: 98 void Notify( bool delayed = false ); 99 100 SelectedRegion mRegion; 101 }; 102 103 enum : int { 104 kVerticalPadding = 7, /*!< Width of padding below each channel group */ 105 }; 106 107 enum : int { 108 kTrackInfoBtnSize = 18, // widely used dimension, usually height 109 kTrackInfoSliderHeight = 25, 110 kTrackInfoSliderWidth = 84, 111 kTrackInfoSliderAllowance = 5, 112 kTrackInfoSliderExtra = 5, 113 }; 114 115 class PlayRegion; 116 117 struct PlayRegionEvent : public wxEvent 118 { 119 PlayRegionEvent( wxEventType commandType, PlayRegion *pRegion ); 120 wxEvent *Clone() const override; 121 }; 122 123 wxDECLARE_EXPORTED_EVENT( SCREEN_GEOMETRY_API, 124 EVT_PLAY_REGION_CHANGE, PlayRegionEvent ); 125 126 class SCREEN_GEOMETRY_API PlayRegion : public wxEvtHandler 127 { 128 public: 129 PlayRegion() = default; 130 131 PlayRegion( const PlayRegion& ) = delete; 132 PlayRegion &operator= ( const PlayRegion &that ) 133 { 134 mActive = that.mActive; 135 // Guarantee the equivalent un-swapped order of endpoints 136 mStart = that.GetStart(); 137 mEnd = that.GetEnd(); 138 mLastActiveStart = that.GetLastActiveStart(); 139 mLastActiveEnd = that.GetLastActiveEnd(); 140 return *this; 141 } 142 Active()143 bool Active() const { return mActive; } 144 void SetActive( bool active ); 145 Empty()146 bool Empty() const { return GetStart() == GetEnd(); } GetStart()147 double GetStart() const 148 { 149 if ( mEnd < 0 ) 150 return mStart; 151 else 152 return std::min( mStart, mEnd ); 153 } GetEnd()154 double GetEnd() const 155 { 156 if ( mStart < 0 ) 157 return mEnd; 158 else 159 return std::max( mStart, mEnd ); 160 } GetLastActiveStart()161 double GetLastActiveStart() const 162 { 163 if ( mLastActiveEnd < 0 ) 164 return mLastActiveStart; 165 else 166 return std::min( mLastActiveStart, mLastActiveEnd ); 167 } GetLastActiveEnd()168 double GetLastActiveEnd() const 169 { 170 if ( mLastActiveStart < 0 ) 171 return mLastActiveEnd; 172 else 173 return std::max( mLastActiveStart, mLastActiveEnd ); 174 } 175 176 void SetStart( double start ); 177 void SetEnd( double end ); 178 void SetTimes( double start, double end ); 179 // Set current and last active times the same regardless of activation: 180 void SetAllTimes( double start, double end ); 181 182 //! Set to an invalid state 183 void Clear(); 184 //! Test whether in invalid state 185 bool IsClear() const; 186 //! Test whether last active region is in invalid state 187 bool IsLastActiveRegionClear() const; 188 189 void Order(); 190 191 private: 192 void Notify(); 193 194 // Times: 195 static constexpr auto invalidValue = std::numeric_limits<double>::min(); 196 197 double mStart { invalidValue }; 198 double mEnd { invalidValue }; 199 double mLastActiveStart { invalidValue }; 200 double mLastActiveEnd { invalidValue }; 201 202 bool mActive{ false }; 203 }; 204 205 extern SCREEN_GEOMETRY_API const TranslatableString LoopToggleText; 206 207 class SCREEN_GEOMETRY_API ViewInfo final 208 : public wxEvtHandler, public ZoomInfo 209 { 210 public: 211 static ViewInfo &Get( AudacityProject &project ); 212 static const ViewInfo &Get( const AudacityProject &project ); 213 214 ViewInfo(double start, double screenDuration, double pixelsPerSecond); 215 ViewInfo( const ViewInfo & ) PROHIBITED; 216 ViewInfo &operator=( const ViewInfo & ) PROHIBITED; 217 GetHeight()218 int GetHeight() const { return mHeight; } SetHeight(int height)219 void SetHeight( int height ) { mHeight = height; } 220 221 static int UpdateScrollPrefsID(); 222 void UpdatePrefs() override; 223 void UpdateSelectedPrefs( int id ) override; 224 GetBeforeScreenWidth()225 double GetBeforeScreenWidth() const 226 { 227 return h * zoom; 228 } 229 void SetBeforeScreenWidth(wxInt64 beforeWidth, wxInt64 screenWidth, double lowerBoundTime = 0.0); 230 GetTotalWidth()231 double GetTotalWidth() const 232 { return total * zoom; } 233 234 // Current selection 235 236 NotifyingSelectedRegion selectedRegion; 237 PlayRegion playRegion; 238 239 // Scroll info 240 241 double total; // total width in secs 242 // Current horizontal scroll bar positions, in pixels 243 wxInt64 sbarH; 244 wxInt64 sbarScreen; 245 wxInt64 sbarTotal; 246 247 // Internal wxScrollbar positions are only int in range, so multiply 248 // the above values with the following member to get the actual 249 // scroll bar positions as reported by the horizontal wxScrollbar's members 250 // i.e. units are scroll increments per pixel 251 double sbarScale; 252 253 // Vertical scroll step 254 int scrollStep; 255 256 // Other stuff, mainly states (true or false) related to autoscroll and 257 // drawing the waveform. Maybe this should be put somewhere else? 258 259 bool bUpdateTrackIndicator; 260 261 bool bScrollBeyondZero; 262 bool bAdjustSelectionEdges; 263 264 void WriteXMLAttributes(XMLWriter &xmlFile) const; 265 266 private: 267 int mHeight{ 0 }; 268 269 struct ProjectFileIORegistration; 270 }; 271 272 extern SCREEN_GEOMETRY_API BoolSetting ScrollingPreference; 273 #endif 274