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