Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ISSUE-50: Add zoom in/out shortcuts #315

Merged
merged 7 commits into from
Jan 2, 2022

Conversation

danailbd
Copy link
Contributor

@danailbd danailbd commented Nov 28, 2020

Description of Change(s)

Introduces keyboard shortcuts for zooming in/out the score. It mainly reuses the existing zoom change mechanics. The default shortcuts are as follows:

MacOS

  • Zoom in - Cmd+=
  • Zoom out - Cmd+-

Widndows

  • Zoom in - Ctrl+=
  • Zoom out - Ctrl+-

Fixes Issue(s)

  • partly fixes issue 50 - TODO add link when PR is ready

TODO

  • Add tests?

@cameronwhite
Copy link
Member

Great to see this being worked on! Feel free to let me know when I should take a look over the changes, or if you have any questions about how to approach things

Copy link
Contributor Author

@danailbd danailbd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @cameronwhite thanks for the heads up! : )

I think I have the basic idea in place. I've done probably the most basic approach for achieving these zoom in/out shortcuts (which do seems relatively small as a change). I haven't added wheel zoom though.

Overall, I don't really enjoy enlarging the already significant powertabeditor class. I guess the zoom logic deserves a dedicated class, especially if the wheel zoom is added. On the other hand I didn't what to overengeneer this simple functionality.

I'd be happy to hear your thoughts on the current changes. I've added a couple of questions


void PowerTabEditor::zoomOutScore()
{
const int ZOOM_CHANGE_COEFITIENT = 25;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a good idea where this constant should live :/ I don't want to pollute the substantial powertabeditor class.
This constant is related to the "Zoom in shortcuts", something that we don't have a dedicated place for...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd probably put that inside the ViewOptions class, maybe with just an increaseZoom / decreaseZoom method? If the predefined zoom levels (currently stored in playbackwidget.ui for populating the combobox widget) were instead stored in ViewOptions, the increase / decrease methods could also step through the predefined zoom levels rather than a fixed percentage

@@ -17,6 +17,14 @@

#include "viewoptions.h"

static constexpr double MIN_ZOOM = 25;
static constexpr double MAX_ZOOM = 300;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel these should live in a more general place so that the playback widget could also appreciate them. Any suggestions?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these could be fine as static constants on the ViewOptions class, and then the UI widgets can refer to those constants as needed.

@cameronwhite
Copy link
Member

I agree on not adding further bloat to the main PowerTabEditor class 👍 . I think it's fine to put most of the additional logic or constants in the ViewOptions class

@danailbd danailbd marked this pull request as ready for review February 13, 2021 14:01
/// Increases to the next possible zoom level.
bool increaseZoom();
/// Increases to the previous possible zoom level.
bool decreaseZoom();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to make them Booleans in case we decide to add an "error" sound upon hitting a bound

public:
static constexpr double MIN_ZOOM = 25;
static constexpr double MAX_ZOOM = 300;
static constexpr std::array<unsigned short, 14> ZOOM_LEVELS = { 25, 50, 70, 80, 90, 100, 110, 125, 150, 175, 200, 225, 250, 300 };
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wanted these to be scoped. Wasn't sure whether to use namespace or the class though

@danailbd
Copy link
Contributor Author

danailbd commented Feb 13, 2021

@cameronwhite I moved as much logic to ViewOptions as I could, but the PowerTabEditor class still has to serve as the mediator that applies the updated zoom - at least I assumed it should as the the PowerTabEditor holds the Score.

One side note - how about adding setting for the default "zoom level"? That would save me a few actions when opening a document. I suppose there are others having a similar feeling for this behaviour

@cameronwhite
Copy link
Member

That looks good! Having the zoom constants in class scope is fine

Adding a preference to remember the last zoom level sounds reasonable!

Copy link
Contributor Author

@danailbd danailbd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @cameronwhite, here's a suggestion on the saving the zoom level as a setting. Overall, I'm keeping the last "set" zoom level (LastZoomLevel) and apply it to all newly opened documents (either preexisting or fresh new).
Another way would be to have it configurable in the preferences.

{
myDocumentList.emplace_back(new Document());
myCurrentIndex = static_cast<int>(myDocumentList.size()) - 1;

auto settings = settings_manager.getReadHandle();
myDocumentList.back()->getViewOptions().setZoom(settings->get(Settings::LastZoomLevel));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not so sure about applying the setting here - for a "default" document we should be ok. On the other hand, at some point in the future we might find it useful to serialise the zoom level with a file...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point, at least, I'm thinking it probably won't be likely that we want to save the zoom level with a file, since that's specific to a user's machine / monitor?
More likely might be saving per-document zoom settings locally, but I think the current behaviour is good for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I misused the idea of serialising. I was thinking precisely for a per-document zoom setting locally

@@ -140,6 +140,7 @@ void ScoreArea::renderDocument(const Document &document)
}

myScene.addItem(myCaretPainter);
refreshZoom();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want the document's zoom applied. Most likely there's a better way to integrate it in the rendering itself (in the Caret). I'd prefer to avoid breaking something with this oftenly used functionality.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed because the document might now have a zoom level other than 100% after it's first created / rendered?

I think that's fine to call here - it just sets the overall transform for the scene, so it could probably even be done at the start of this method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, the document didn't got rescaled with the initial value. I'll give it a try moving it to the 🔝

public:
ViewOptions();

const std::optional<int> &getFilter() const { return myFilter; }
void setFilter(int filter) { myFilter = filter; }
void clearFilter() { myFilter.reset(); }

double getZoom() const { return myZoom; }
void setZoom(double percent) { myZoom = percent; }
int getZoom() const { return myZoom; }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cameronwhite was there a particular reason for the zoom to be a double? I believe a short would suit it better. What do you think? (I know I've changed it to int here. A simple way to avoid a settings converter)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I had any particular reason for double - changing to int would be fine!
I usually avoid lower capacity types like short unless there's a real need for it.

@danailbd
Copy link
Contributor Author

@cameronwhite what do you think about the predefined behaviour of QKeySequence::ZoomIn on Windows? - https://stackoverflow.com/a/40688325
On macOS it works with or without the shift key, which I'd prefer to be the behaviour on Windows as well. On the positive side, the key combination is configurable through the shortcuts, but for a new user the proper zoom in key combination might not be that obvious, nor would be the possibility of changing it. We're so used to using "Ctrl+=" for zooming in...

Copy link
Member

@cameronwhite cameronwhite left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Saving the zoom level by default makes the most sense IMO, versus adding a new configurable preference.

For QKeySequence I'd directly specify your own shortcuts, then, if it isn't the expected behaviour (we have ifdef's in a few places for macOS-specific variants of other shortcuts)

{
myDocumentList.emplace_back(new Document());
myCurrentIndex = static_cast<int>(myDocumentList.size()) - 1;

auto settings = settings_manager.getReadHandle();
myDocumentList.back()->getViewOptions().setZoom(settings->get(Settings::LastZoomLevel));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point, at least, I'm thinking it probably won't be likely that we want to save the zoom level with a file, since that's specific to a user's machine / monitor?
More likely might be saving per-document zoom settings locally, but I think the current behaviour is good for now.

@@ -140,6 +140,7 @@ void ScoreArea::renderDocument(const Document &document)
}

myScene.addItem(myCaretPainter);
refreshZoom();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed because the document might now have a zoom level other than 100% after it's first created / rendered?

I think that's fine to call here - it just sets the overall transform for the scene, so it could probably even be done at the start of this method.

public:
ViewOptions();

const std::optional<int> &getFilter() const { return myFilter; }
void setFilter(int filter) { myFilter = filter; }
void clearFilter() { myFilter.reset(); }

double getZoom() const { return myZoom; }
void setZoom(double percent) { myZoom = percent; }
int getZoom() const { return myZoom; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I had any particular reason for double - changing to int would be fine!
I usually avoid lower capacity types like short unless there's a real need for it.

@cameronwhite cameronwhite merged commit 03b0ca5 into powertab:master Jan 2, 2022
@cameronwhite
Copy link
Member

I've merged this in and fixed up the last couple suggestions from the code review
Thanks for your work on this!!

This was referenced Jan 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants