Audacity 3.2.0
Classes | Functions | Variables
ProjectWindow.h File Reference
#include <memory>
#include "ProjectWindowBase.h"
#include "TrackPanelListener.h"
#include "Prefs.h"
#include "Observer.h"
Include dependency graph for ProjectWindow.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

class  ProjectWindow
 A top-level window associated with a project, and handling scrollbars and zooming. More...
 
struct  ProjectWindow::PlaybackScrollerMessage
 
class  ProjectWindow::PlaybackScroller
 

Functions

void InitProjectWindow (ProjectWindow &window)
 
void GetDefaultWindowRect (wxRect *defRect)
 
void GetNextWindowPlacement (wxRect *nextRect, bool *pMaximized, bool *pIconized)
 

Variables

AUDACITY_DLL_API BoolSetting ProjectWindowMaximized
 
AUDACITY_DLL_API BoolSetting ProjectWindowIconized
 
AUDACITY_DLL_API IntSetting ProjectWindowX
 
AUDACITY_DLL_API IntSetting ProjectWindowY
 
AUDACITY_DLL_API IntSetting ProjectWindowWidth
 
AUDACITY_DLL_API IntSetting ProjectWindowHeight
 
AUDACITY_DLL_API IntSetting ProjectWindowNormalX
 
AUDACITY_DLL_API IntSetting ProjectWindowNormalY
 
AUDACITY_DLL_API IntSetting ProjectWindowNormalWidth
 
AUDACITY_DLL_API IntSetting ProjectWindowNormalHeight
 

Function Documentation

◆ GetDefaultWindowRect()

void GetDefaultWindowRect ( wxRect *  defRect)

Definition at line 116 of file ProjectWindow.cpp.

117{
118 *defRect = wxGetClientDisplayRect();
119
120 int width = DEFAULT_WINDOW_WIDTH;
121 int height = DEFAULT_WINDOW_HEIGHT;
122
123 //These conditional values assist in improving placement and size
124 //of NEW windows on different platforms.
125#ifdef __WXGTK__
126 height += 20;
127#endif
128
129#ifdef __WXMSW__
130 height += 40;
131#endif
132
133#ifdef __WXMAC__
134 height += 55;
135#endif
136
137 // Use screen size where it is smaller than the values we would like.
138 // Otherwise use the values we would like, and centred.
139 if (width < defRect->width)
140 {
141 defRect->x = (defRect->width - width)/2;
142 defRect->width = width;
143 }
144
145 if (height < defRect->height)
146 {
147 defRect->y = (defRect->height - height)/2;
148 // Bug 1119 workaround
149 // Small adjustment for very small Mac screens.
150 // If there is only a tiny space at the top
151 // then instead of vertical centre, align to bottom.
152 const int pixelsFormenu = 60;
153 if( defRect->y < pixelsFormenu )
154 defRect->y *=2;
155 defRect->height = height;
156 }
157}

References anonymous_namespace{ProjectWindow.cpp}::DEFAULT_WINDOW_HEIGHT, and anonymous_namespace{ProjectWindow.cpp}::DEFAULT_WINDOW_WIDTH.

Referenced by GetNextWindowPlacement(), ProjectWindow::Reset(), and ProjectManager::SaveWindowSize().

Here is the caller graph for this function:

◆ GetNextWindowPlacement()

void GetNextWindowPlacement ( wxRect *  nextRect,
bool *  pMaximized,
bool *  pIconized 
)

Definition at line 163 of file ProjectWindow.cpp.

164{
165 int inc = 25;
166
167 wxRect defaultRect;
168 GetDefaultWindowRect(&defaultRect);
169
170 *pMaximized = ProjectWindowMaximized.Read();
171 *pIconized = ProjectWindowIconized.Read();
172
173 wxRect windowRect;
174 windowRect.x = ProjectWindowX.ReadWithDefault(defaultRect.x);
175 windowRect.y = ProjectWindowY.ReadWithDefault(defaultRect.y);
176 windowRect.width = ProjectWindowWidth.ReadWithDefault(defaultRect.width);
177 windowRect.height = ProjectWindowHeight.ReadWithDefault(defaultRect.height);
178
179 wxRect normalRect;
180 normalRect.x = ProjectWindowNormalX.ReadWithDefault(defaultRect.x);
181 normalRect.y = ProjectWindowNormalY.ReadWithDefault(defaultRect.y);
182 normalRect.width = ProjectWindowNormalWidth.ReadWithDefault(defaultRect.width);
183 normalRect.height = ProjectWindowNormalHeight.ReadWithDefault(defaultRect.height);
184
185 // Workaround 2.1.1 and earlier bug on OSX...affects only normalRect, but let's just
186 // validate for all rects and plats
187 if (normalRect.width == 0 || normalRect.height == 0) {
188 normalRect = defaultRect;
189 }
190 if (windowRect.width == 0 || windowRect.height == 0) {
191 windowRect = defaultRect;
192 }
193
194
195 wxRect screenRect( wxGetClientDisplayRect());
196#if defined(__WXMAC__)
197
198 // On OSX, the top of the window should never be less than the menu height,
199 // so something is amiss if it is
200 if (normalRect.y < screenRect.y) {
201 normalRect = defaultRect;
202 }
203 if (windowRect.y < screenRect.y) {
204 windowRect = defaultRect;
205 }
206#endif
207
208 // IF projects empty, THEN it's the first window.
209 // It lands where the config says it should, and can straddle screen.
210 if (AllProjects{}.empty()) {
211 if (*pMaximized || *pIconized) {
212 *nextRect = normalRect;
213 }
214 else {
215 *nextRect = windowRect;
216 }
217 // Resize, for example if one monitor that was on is now off.
218 if (!CornersOnScreen( wxRect(*nextRect).Deflate( 32, 32 ))) {
219 *nextRect = defaultRect;
220 }
221 if (!IsWindowAccessible(nextRect)) {
222 *nextRect = defaultRect;
223 }
224 // Do not trim the first project window down.
225 // All corners are on screen (or almost so), and
226 // the rect may straddle screens.
227 return;
228 }
229
230
231 // ELSE a subsequent NEW window. It will NOT straddle screens.
232
233 // We don't mind being 32 pixels off the screen in any direction.
234 // Make sure initial sizes (pretty much) fit within the display bounds
235 // We used to trim the sizes which could result in ridiculously small windows.
236 // contributing to bug 1243.
237 // Now instead if the window significantly doesn't fit the screen, we use the default
238 // window instead, which we know does.
239 if (ScreenContaining( wxRect(normalRect).Deflate( 32, 32 ))<0) {
240 normalRect = defaultRect;
241 }
242 if (ScreenContaining( wxRect(windowRect).Deflate( 32, 32 ) )<0) {
243 windowRect = defaultRect;
244 }
245
246 bool validWindowSize = false;
247 ProjectWindow * validProject = NULL;
248 for ( auto iter = AllProjects{}.rbegin(), end = AllProjects{}.rend();
249 iter != end; ++iter
250 ) {
251 auto pProject = *iter;
252 if (!GetProjectFrame( *pProject ).IsIconized()) {
253 validWindowSize = true;
254 validProject = &ProjectWindow::Get( *pProject );
255 break;
256 }
257 }
258 if (validWindowSize) {
259 *nextRect = validProject->GetRect();
260 *pMaximized = validProject->IsMaximized();
261 *pIconized = validProject->IsIconized();
262 // Do not straddle screens.
263 if (ScreenContaining( wxRect(*nextRect).Deflate( 32, 32 ) )<0) {
264 *nextRect = defaultRect;
265 }
266 }
267 else {
268 *nextRect = normalRect;
269 }
270
271 //Placement depends on the increments
272 nextRect->x += inc;
273 nextRect->y += inc;
274
275 // defaultrect is a rectangle on the first screen. It's the right fallback to
276 // use most of the time if things are not working out right with sizing.
277 // windowRect is a saved rectangle size.
278 // normalRect seems to be a substitute for windowRect when iconized or maximised.
279
280 // Windows can say that we are off screen when actually we are not.
281 // On Windows 10 I am seeing miscalculation by about 6 pixels.
282 // To fix this we allow some sloppiness on the edge being counted as off screen.
283 // This matters most when restoring very carefully sized windows that are maximised
284 // in one dimension (height or width) but not both.
285 const int edgeSlop = 10;
286
287 // Next four lines are getting the rectangle for the screen that contains the
288 // top left corner of nextRect (and defaulting to rect of screen 0 otherwise).
289 wxPoint p = nextRect->GetLeftTop();
290 int scr = std::max( 0, wxDisplay::GetFromPoint( p ));
291 wxDisplay d( scr );
292 screenRect = d.GetClientArea();
293
294 // Now we (possibly) start trimming our rectangle down.
295 // Have we hit the right side of the screen?
296 wxPoint bottomRight = nextRect->GetBottomRight();
297 if (bottomRight.x > (screenRect.GetRight()+edgeSlop)) {
298 int newWidth = screenRect.GetWidth() - nextRect->GetLeft();
299 if (newWidth < defaultRect.GetWidth()) {
300 nextRect->x = windowRect.x;
301 nextRect->y = windowRect.y;
302 nextRect->width = windowRect.width;
303 }
304 else {
305 nextRect->width = newWidth;
306 }
307 }
308
309 // Have we hit the bottom of the screen?
310 bottomRight = nextRect->GetBottomRight();
311 if (bottomRight.y > (screenRect.GetBottom()+edgeSlop)) {
312 nextRect->y -= inc;
313 bottomRight = nextRect->GetBottomRight();
314 if (bottomRight.y > (screenRect.GetBottom()+edgeSlop)) {
315 nextRect->SetBottom(screenRect.GetBottom());
316 }
317 }
318
319 // After all that we could have a window that does not have a visible
320 // top bar. [It is unlikely, but something might have gone wrong]
321 // If so, use the safe fallback size.
322 if (!IsWindowAccessible(nextRect)) {
323 *nextRect = defaultRect;
324 }
325}
IntSetting ProjectWindowY
bool CornersOnScreen(wxRect &r)
IntSetting ProjectWindowX
void GetDefaultWindowRect(wxRect *defRect)
IntSetting ProjectWindowWidth
BoolSetting ProjectWindowIconized
bool IsWindowAccessible(wxRect *requestedRect)
BoolSetting ProjectWindowMaximized
IntSetting ProjectWindowNormalHeight
IntSetting ProjectWindowHeight
IntSetting ProjectWindowNormalX
int ScreenContaining(wxRect &r)
IntSetting ProjectWindowNormalWidth
IntSetting ProjectWindowNormalY
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
const_reverse_iterator rend() const
Definition: Project.cpp:37
const_reverse_iterator rbegin() const
Definition: Project.cpp:32
bool empty() const
Definition: Project.h:46
A top-level window associated with a project, and handling scrollbars and zooming.
Definition: ProjectWindow.h:36
static ProjectWindow & Get(AudacityProject &project)
bool IsIconized() const override
bool ReadWithDefault(T *pVar, const T &defaultValue) const
overload of ReadWithDefault returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:206
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:200
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159

References CornersOnScreen(), AllProjects::empty(), PackedArray::end(), ProjectWindow::Get(), GetDefaultWindowRect(), GetProjectFrame(), ProjectWindow::IsIconized(), IsWindowAccessible(), ProjectWindowHeight, ProjectWindowIconized, ProjectWindowMaximized, ProjectWindowNormalHeight, ProjectWindowNormalWidth, ProjectWindowNormalX, ProjectWindowNormalY, ProjectWindowWidth, ProjectWindowX, ProjectWindowY, AllProjects::rbegin(), Setting< T >::Read(), Setting< T >::ReadWithDefault(), AllProjects::rend(), and ScreenContaining().

Referenced by AudacityApp::InitPart2(), and ProjectManager::New().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ InitProjectWindow()

void InitProjectWindow ( ProjectWindow window)

Definition at line 176 of file ProjectManager.cpp.

177{
178 auto &project = window.GetProject();
179
180#ifdef EXPERIMENTAL_DA2
181 SetBackgroundColour(theTheme.Colour( clrMedium ));
182#endif
183 // Note that the first field of the status bar is a dummy, and its width is set
184 // to zero latter in the code. This field is needed for wxWidgets 2.8.12 because
185 // if you move to the menu bar, the first field of the menu bar is cleared, which
186 // is undesirable behaviour.
187 // In addition, the help strings of menu items are by default sent to the first
188 // field. Currently there are no such help strings, but it they were introduced, then
189 // there would need to be an event handler to send them to the appropriate field.
190 auto statusBar = window.CreateStatusBar(4);
191#if wxUSE_ACCESSIBILITY
192 // so that name can be set on a standard control
193 statusBar->SetAccessible(safenew WindowAccessible(statusBar));
194#endif
195 statusBar->SetName(wxT("status_line")); // not localized
196
197 auto &viewInfo = ViewInfo::Get( project );
198
199 // LLL: Read this!!!
200 //
201 // Until the time (and cpu) required to refresh the track panel is
202 // reduced, leave the following window creations in the order specified.
203 // This will place the refresh of the track panel last, allowing all
204 // the others to get done quickly.
205 //
206 // Near as I can tell, this is only a problem under Windows.
207 //
208
209 //
210 // Create the ToolDock
211 //
212 ToolManager::Get( project ).CreateWindows();
213 ToolManager::Get( project ).LayoutToolBars();
214
215 //
216 // Create the TrackPanel and the scrollbars
217 //
218
219 auto topPanel = window.GetTopPanel();
220
221 {
222 auto ubs = std::make_unique<wxBoxSizer>(wxVERTICAL);
223 ubs->Add( ToolManager::Get( project ).GetTopDock(), 0, wxEXPAND | wxALIGN_TOP );
224 topPanel->SetSizer(ubs.release());
225 }
226
227 wxBoxSizer *bs;
228 {
229 auto ubs = std::make_unique<wxBoxSizer>(wxVERTICAL);
230 bs = ubs.get();
231 bs->Add(topPanel, 0, wxEXPAND | wxALIGN_TOP);
232 bs->Add(window.GetContainerWindow(), 1, wxEXPAND);
233 bs->Add( ToolManager::Get( project ).GetBotDock(), 0, wxEXPAND );
234 window.SetAutoLayout(true);
235 window.SetSizer(ubs.release());
236 }
237 bs->Layout();
238
239 auto &trackPanel = TrackPanel::Get( project );
240
241 // LLL: When Audacity starts or becomes active after returning from
242 // another application, the first window that can accept focus
243 // will be given the focus even if we try to SetFocus(). By
244 // making the TrackPanel that first window, we resolve several
245 // keyboard focus problems.
246 window.GetContainerWindow()->MoveAfterInTabOrder(topPanel);
247
248 const auto trackListWindow = window.GetTrackListWindow();
249
250 //
251 // Create the horizontal ruler
252 //
253 auto &ruler = AdornedRulerPanel::Get( project );
254
255 bs = static_cast<wxBoxSizer*>(trackListWindow->GetSizer());
256
257 auto vsBar = &window.GetVerticalScrollBar();
258 auto hsBar = &window.GetHorizontalScrollBar();
259
260 {
261 // Top horizontal grouping
262 auto hs = std::make_unique<wxBoxSizer>(wxHORIZONTAL);
263
264 // Track panel
265 hs->Add(&trackPanel, 1, wxEXPAND | wxALIGN_LEFT | wxALIGN_TOP);
266
267 {
268 // Vertical grouping
269 auto vs = std::make_unique<wxBoxSizer>(wxVERTICAL);
270
271 // Vertical scroll bar
272 vs->Add(vsBar, 1, wxEXPAND | wxALIGN_TOP);
273 hs->Add(vs.release(), 0, wxEXPAND | wxALIGN_TOP);
274 }
275
276 bs->Add(&ruler, 0, wxEXPAND | wxALIGN_TOP);
277 bs->Add(hs.release(), 1, wxEXPAND | wxALIGN_LEFT | wxALIGN_TOP);
278 }
279
280 {
281 // Bottom horizontal grouping
282 auto hs = std::make_unique<wxBoxSizer>(wxHORIZONTAL);
283
284 // Bottom scrollbar
285 hs->Add(viewInfo.GetLeftOffset() - 1, 0);
286 hs->Add(hsBar, 1, wxALIGN_BOTTOM);
287 hs->Add(vsBar->GetSize().GetWidth(), 0);
288 bs->Add(hs.release(), 0, wxEXPAND | wxALIGN_LEFT);
289 }
290
291 // Lay it out
292 trackListWindow->SetAutoLayout(true);
293 trackListWindow->Layout();
294
295 wxASSERT( trackPanel.GetProject() == &project );
296
297 // MM: Give track panel the focus to ensure keyboard commands work
298 trackPanel.SetFocus();
299
300 window.FixScrollbars();
301 ruler.SetLeftOffset(viewInfo.GetLeftOffset()); // bevel on AdornedRuler
302
303 //
304 // Set the Icon
305 //
306
307 // loads either the XPM or the windows resource, depending on the platform
308#if !defined(__WXMAC__) && !defined(__WXX11__)
309 {
310#if defined(__WXMSW__)
311 wxIcon ic{ wxICON(AudacityLogo) };
312#elif defined(__WXGTK__)
313 wxIcon ic{wxICON(AudacityLogoAlpha)};
314#else
315 wxIcon ic{};
316 ic.CopyFromBitmap(theTheme.Bitmap(bmpAudacityLogo48x48));
317#endif
318 window.SetIcon(ic);
319 }
320#endif
321
322 window.UpdateStatusWidths();
323 auto msg = XO("Welcome to Audacity version %s")
324 .Format( AUDACITY_VERSION_STRING );
326
327#ifdef EXPERIMENTAL_DA2
328 ClearBackground();// For wxGTK.
329#endif
330}
#define XO(s)
Definition: Internat.h:31
#define safenew
Definition: MemoryX.h:10
@ mainStatusBarField
Definition: ProjectStatus.h:26
THEME_API Theme theTheme
Definition: Theme.cpp:82
static AdornedRulerPanel & Get(AudacityProject &project)
static ProjectManager & Get(AudacityProject &project)
void SetStatusText(const TranslatableString &text, int number)
AudacityProject & GetProject()
wxScrollBar & GetHorizontalScrollBar()
wxScrollBar & GetVerticalScrollBar()
wxWindow * GetContainerWindow() noexcept
Container is a parent window for both effects panel and track list windows.
wxPanel * GetTopPanel() noexcept
Top panel contains project-related controls and tools.
wxWindow * GetTrackListWindow() noexcept
Track list window is the parent container for TrackPanel.
void UpdateStatusWidths()
wxColour & Colour(int iIndex)
wxBitmap & Bitmap(int iIndex)
static ToolManager & Get(AudacityProject &project)
void CreateWindows()
void LayoutToolBars()
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:230
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...

References ThemeBase::Bitmap(), ThemeBase::Colour(), ToolManager::CreateWindows(), ProjectWindow::FixScrollbars(), ViewInfo::Get(), AdornedRulerPanel::Get(), ProjectManager::Get(), ToolManager::Get(), TrackPanel::Get(), ProjectWindow::GetContainerWindow(), ProjectWindow::GetHorizontalScrollBar(), ProjectWindowBase::GetProject(), ProjectWindow::GetTopPanel(), ProjectWindow::GetTrackListWindow(), ProjectWindow::GetVerticalScrollBar(), ToolManager::LayoutToolBars(), mainStatusBarField, anonymous_namespace{TimeTrackVRulerControls.cpp}::ruler(), safenew, ProjectManager::SetStatusText(), theTheme, ProjectWindow::UpdateStatusWidths(), and XO.

Referenced by ProjectManager::New().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ ProjectWindowHeight

AUDACITY_DLL_API IntSetting ProjectWindowHeight
extern

◆ ProjectWindowIconized

AUDACITY_DLL_API BoolSetting ProjectWindowIconized
extern

◆ ProjectWindowMaximized

AUDACITY_DLL_API BoolSetting ProjectWindowMaximized
extern

◆ ProjectWindowNormalHeight

AUDACITY_DLL_API IntSetting ProjectWindowNormalHeight
extern

◆ ProjectWindowNormalWidth

AUDACITY_DLL_API IntSetting ProjectWindowNormalWidth
extern

◆ ProjectWindowNormalX

AUDACITY_DLL_API IntSetting ProjectWindowNormalX
extern

◆ ProjectWindowNormalY

AUDACITY_DLL_API IntSetting ProjectWindowNormalY
extern

◆ ProjectWindowWidth

AUDACITY_DLL_API IntSetting ProjectWindowWidth
extern

◆ ProjectWindowX

AUDACITY_DLL_API IntSetting ProjectWindowX
extern

◆ ProjectWindowY

AUDACITY_DLL_API IntSetting ProjectWindowY
extern