Audacity 3.2.0
Classes | Functions | Variables
ProjectWindow.h File Reference
#include <memory>
#include "ProjectWindowBase.h"
#include "Prefs.h"
#include "Viewport.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

struct  ProjectWindowDestroyedMessage
 Message sent when the project window is closed. More...
 
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 111 of file ProjectWindow.cpp.

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

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

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

Here is the caller graph for this function:

◆ GetNextWindowPlacement()

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

Definition at line 158 of file ProjectWindow.cpp.

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

References CornersOnScreen(), AllProjects::empty(), details::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 162 of file ProjectManager.cpp.

163{
164 auto pProject = window.FindProject();
165 if (!pProject)
166 return;
167 auto &project = *pProject;
168 auto &viewport = Viewport::Get(project);
169
170 auto statusBar = window.CreateProjectStatusBar();
171
172 auto &viewInfo = ViewInfo::Get( project );
173
174 // LLL: Read this!!!
175 //
176 // Until the time (and cpu) required to refresh the track panel is
177 // reduced, leave the following window creations in the order specified.
178 // This will place the refresh of the track panel last, allowing all
179 // the others to get done quickly.
180 //
181 // Near as I can tell, this is only a problem under Windows.
182 //
183
184 //
185 // Create the ToolDock
186 //
189
190 //
191 // Create the TrackPanel and the scrollbars
192 //
193
194 auto topPanel = window.GetTopPanel();
195
196 {
197 auto ubs = std::make_unique<wxBoxSizer>(wxVERTICAL);
198 ubs->Add( ToolManager::Get( project ).GetTopDock(), 0, wxEXPAND | wxALIGN_TOP );
199 topPanel->SetSizer(ubs.release());
200 }
201
202 wxBoxSizer *bs;
203 {
204 auto ubs = std::make_unique<wxBoxSizer>(wxVERTICAL);
205 bs = ubs.get();
206 bs->Add(topPanel, 0, wxEXPAND | wxALIGN_TOP);
207 bs->Add(window.GetContainerWindow(), 1, wxEXPAND);
208 bs->Add( ToolManager::Get( project ).GetBotDock(), 0, wxEXPAND );
209 window.SetAutoLayout(true);
210 window.SetSizer(ubs.release());
211 }
212 bs->Layout();
213
214 auto &trackPanel = TrackPanel::Get( project );
215
216 // LLL: When Audacity starts or becomes active after returning from
217 // another application, the first window that can accept focus
218 // will be given the focus even if we try to SetFocus(). By
219 // making the TrackPanel that first window, we resolve several
220 // keyboard focus problems.
221 window.GetContainerWindow()->MoveAfterInTabOrder(topPanel);
222
223 const auto trackListWindow = window.GetTrackListWindow();
224
225 //
226 // Create the horizontal ruler
227 //
229
230 bs = static_cast<wxBoxSizer*>(trackListWindow->GetSizer());
231
232 auto vsBar = &window.GetVerticalScrollBar();
233 auto hsBar = &window.GetHorizontalScrollBar();
234
235 {
236 // Top horizontal grouping
237 auto hs = std::make_unique<wxBoxSizer>(wxHORIZONTAL);
238
239 // Track panel
240 hs->Add(&trackPanel, 1, wxEXPAND | wxALIGN_LEFT | wxALIGN_TOP);
241
242 {
243 // Vertical grouping
244 auto vs = std::make_unique<wxBoxSizer>(wxVERTICAL);
245
246 // Vertical scroll bar
247 vs->Add(vsBar, 1, wxEXPAND | wxALIGN_TOP);
248 hs->Add(vs.release(), 0, wxEXPAND | wxALIGN_TOP);
249 }
250
251 bs->Add(&ruler, 0, wxEXPAND | wxALIGN_TOP);
252 bs->Add(hs.release(), 1, wxEXPAND | wxALIGN_LEFT | wxALIGN_TOP);
253 }
254
255 {
256 // Bottom horizontal grouping
257 auto hs = std::make_unique<wxBoxSizer>(wxHORIZONTAL);
258
259 // Bottom scrollbar
260 hs->Add(viewInfo.GetLeftOffset() - 1, 0);
261 hs->Add(hsBar, 1, wxALIGN_BOTTOM);
262 hs->Add(vsBar->GetSize().GetWidth(), 0);
263 bs->Add(hs.release(), 0, wxEXPAND | wxALIGN_LEFT);
264 }
265
266 // Lay it out
267 trackListWindow->SetAutoLayout(true);
268 trackListWindow->Layout();
269
270 wxASSERT( trackPanel.GetProject() == &project );
271
272 // MM: Give track panel the focus to ensure keyboard commands work
273 trackPanel.SetFocus();
274
275 viewport.UpdateScrollbarsForTracks();
276 ruler.SetLeftOffset(viewInfo.GetLeftOffset()); // bevel on AdornedRuler
277
278 //
279 // Set the Icon
280 //
281
282 // loads either the XPM or the windows resource, depending on the platform
283#if !defined(__WXMAC__) && !defined(__WXX11__)
284 {
285#if defined(__WXMSW__)
286 wxIcon ic{ wxICON(AudacityLogo) };
287#elif defined(__WXGTK__)
288 wxIcon ic{wxICON(AudacityLogoAlpha)};
289#else
290 wxIcon ic{};
291 ic.CopyFromBitmap(theTheme.Bitmap(bmpAudacityLogo48x48));
292#endif
293 window.SetIcon(ic);
294 }
295#endif
296
297 window.UpdateStatusWidths();
298 auto msg = XO("Welcome to Audacity version %s")
299 .Format( AUDACITY_VERSION_STRING );
301}
XO("Cut/Copy/Paste")
StatusBarField MainStatusBarField()
ID of the second field in the status bar. This field is expandable.
const auto project
THEME_API Theme theTheme
Definition: Theme.cpp:82
static AdornedRulerPanel & Get(AudacityProject &project)
static ProjectManager & Get(AudacityProject &project)
void SetStatusText(const TranslatableString &text, const StatusBarField &field)
std::shared_ptr< AudacityProject > FindProject()
wxScrollBar & GetHorizontalScrollBar()
wxScrollBar & GetVerticalScrollBar()
wxPanel * GetTopPanel() noexcept
Top panel contains project-related controls and tools.
wxWindow * GetTrackListWindow() noexcept
Track list window is the parent container for TrackPanel.
wxSplitterWindow * GetContainerWindow() noexcept
Container is a parent window for both effects panel and track list windows.
wxStatusBar * CreateProjectStatusBar()
void UpdateStatusWidths()
wxBitmap & Bitmap(int iIndex)
static ToolManager & Get(AudacityProject &project)
void CreateWindows()
void LayoutToolBars()
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:234
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
static Viewport & Get(AudacityProject &project)
Definition: Viewport.cpp:33

References ThemeBase::Bitmap(), ProjectWindow::CreateProjectStatusBar(), ToolManager::CreateWindows(), ProjectWindowBase::FindProject(), ViewInfo::Get(), Viewport::Get(), AdornedRulerPanel::Get(), ProjectManager::Get(), ToolManager::Get(), TrackPanel::Get(), ProjectWindow::GetContainerWindow(), ProjectWindow::GetHorizontalScrollBar(), ProjectWindow::GetTopPanel(), ProjectWindow::GetTrackListWindow(), ProjectWindow::GetVerticalScrollBar(), ToolManager::LayoutToolBars(), MainStatusBarField(), project, anonymous_namespace{TimeTrackVRulerControls.cpp}::ruler(), 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