Skip to content

Commit

Permalink
A Variety of Zoom Enhancements
Browse files Browse the repository at this point in the history
Once folks started using zoom, a variety of small enhancement
requests came in. This PR covers all of them, covering several
tickets.

The issues resolved are:

Closes #483.
Zoom implemented on linux; in doing so remove the HOST_SUPPORTS_ZOOM
switch, since all hosts support zoom. To make it testable, ahead
of implementing DisplayInfo on linux, set the defaulted screen size
to 1400x1050, a mid-range 15" laptop.

Closes #433
Correct the error message at zoom time to explain we add
a window-decoration-protection factor but don't show the
confusing dimensions that result.

Closes #473
Order and add separator to the setting menu to be more
rational. Keep "About" at the end.

Closes #457
If you ask for a zoom which outstrips screen parameters, rather than
retain the current zoom look for the largest zoom that will fit those
paramemters. Don't display the confusing-to-users message about how
much space we are reserving for window decoration.
  • Loading branch information
baconpaul committed Feb 4, 2019
1 parent 186cd3e commit 9cbf0f3
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 34 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,4 @@ Makefile
surge-*.make
premake-stamp
/Debug
src/linux/ScalablePiggy*
94 changes: 65 additions & 29 deletions src/common/gui/SurgeGUIEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
#include "UserInteractions.h"
#include "DisplayInfo.h"

#include <iostream>
#include <iomanip>
#include <strstream>

#if TARGET_AUDIOUNIT
#include "aulayer.h"
#endif
Expand Down Expand Up @@ -2425,8 +2429,6 @@ long SurgeGUIEditor::applyParameterOffset(long id)

void SurgeGUIEditor::setZoomFactor(int zf)
{
#if HOST_SUPPORTS_ZOOM

int minZoom = 50;
if (zf < minZoom)
{
Expand All @@ -2451,22 +2453,36 @@ void SurgeGUIEditor::setZoomFactor(int zf)
float baseW = (baseUISize->right - baseUISize->left);
float baseH = (baseUISize->top - baseUISize->bottom);
#endif

// Leave enough room for window decoration with that .9. (You can probably do .95 on mac)
if (zf != 100.0 && (
(baseW * zf / 100.0) > 0.9 * screenDim.getWidth() ||
(baseH * zf / 100.0) > 0.9 * screenDim.getHeight()

/*
** Window decoration takes up some of the screen so don't zoom to full screen dimensions.
** This heuristic seems to work on windows 10 and macos 10.14 weel enough.
** Keep these as integers to be consistent wiht the other zoom factors, and to make
** the error message cleaner.
*/
#ifdef WINDOWS
int maxScreenUsage = 90;
#else
int maxScreenUsage = 95;
#endif

if (zf != 100.0 && zf > 100 && (
(baseW * zf / 100.0) > maxScreenUsage * screenDim.getWidth() / 100.0 ||
(baseH * zf / 100.0) > maxScreenUsage * screenDim.getHeight() / 100.0
)
)
{
int newZF = findLargestFittingZoomBetween(100.0 , zf, 5, maxScreenUsage, baseW, baseH);
zoomFactor = newZF;

std::ostringstream msg;
msg << "You attempted to resize Surge to a size larger than your screen. "
<< "Your screen is " << screenDim.getWidth() << "x" << screenDim.getHeight()
<< " and your zoom of " << zf << "% would make your Surge "
<< baseW * zf / 100.0 << "x" << baseH * zf / 100.0 << "\n\n"
<< "Retaining current zoom of " << zoomFactor << "%.";
msg << "Surge limits zoom levels so as not to grow Surge larger than your available screen. "
<< "Your screen size is " << screenDim.getWidth() << "x" << screenDim.getHeight() << " "
<< "and your target zoom of " << zf << "% would be too large."
<< std::endl << std::endl
<< "Surge is choosing the largest fitting zoom " << zoomFactor << "%.";
Surge::UserInteractions::promptError(msg.str(),
"Screen too small for Zoom");
"Limiting Zoom by Screen Size");
}
else
{
Expand All @@ -2479,12 +2495,6 @@ void SurgeGUIEditor::setZoomFactor(int zf)
int fullPhysicalZoomFactor = (int)(zf * dbs);
CScalableBitmap::setPhysicalZoomFactor(fullPhysicalZoomFactor);

#else
/*
** I don't support zoom, but lets at least keep my internal state consistent in case this gets called
*/
zoomFactor = zf;
#endif
}

void SurgeGUIEditor::showSettingsMenu(CRect &menuRect)
Expand All @@ -2494,13 +2504,6 @@ void SurgeGUIEditor::showSettingsMenu(CRect &menuRect)
int eid = 0;
bool handled = false;

int id_about = eid;
settingsMenu->addEntry("About", eid++);

int id_openmanual = eid;
settingsMenu->addEntry("Surge Manual", eid++);

#if HOST_SUPPORTS_ZOOM
// Zoom submenus
COptionMenu *zoomSubMenu = new COptionMenu(menuRect, 0, 0, 0, 0, VSTGUI::COptionMenu::kNoDrawStyle);

Expand Down Expand Up @@ -2537,8 +2540,15 @@ void SurgeGUIEditor::showSettingsMenu(CRect &menuRect)
zoomSubMenu->addEntry(zcmd); zid++;
}

settingsMenu->addEntry(zoomSubMenu, "Zoom");
#endif // Supports Zoom
settingsMenu->addEntry(zoomSubMenu, "Zoom"); eid++;

settingsMenu->addSeparator(eid++);

int id_openmanual = eid;
settingsMenu->addEntry("Surge Manual", eid++);

int id_about = eid;
settingsMenu->addEntry("About", eid++);

frame->addView(settingsMenu); // add to frame
settingsMenu->setDirty();
Expand Down Expand Up @@ -2579,7 +2589,7 @@ CPoint SurgeGUIEditor::getCurrentMouseLocationCorrectedForVSTGUIBugs()
frame->getCurrentMouseLocation(where);
where = frame->localToFrame(where);

#if ( TARGET_VST2 || TARGET_VST3 ) && HOST_SUPPORTS_ZOOM
#if ( TARGET_VST2 || TARGET_VST3 )
CGraphicsTransform vstfix = frame->getTransform().inverse();
vstfix.transform(where);
vstfix.transform(where);
Expand All @@ -2588,4 +2598,30 @@ CPoint SurgeGUIEditor::getCurrentMouseLocationCorrectedForVSTGUIBugs()
return where;
}

int SurgeGUIEditor::findLargestFittingZoomBetween(int zoomLow, // bottom of range
int zoomHigh, // top of range
int zoomQuanta, // step size
int percentageOfScreenAvailable, // How much to shrink actual screen
float baseW,
float baseH
)
{
// Here is a very crude implementation
int result = zoomHigh;
CRect screenDim = Surge::GUI::getScreenDimensions(getFrame());
float sx = screenDim.getWidth() * percentageOfScreenAvailable / 100.0;
float sy = screenDim.getHeight() * percentageOfScreenAvailable / 100.0;

while(result > zoomLow)
{
if(result * baseW / 100.0 <= sx &&
result * baseH / 100.0 <= sy)
break;
result -= zoomQuanta;
}
if(result < zoomLow)
result = zoomLow;

return result;
}
//------------------------------------------------------------------------------------------------
21 changes: 18 additions & 3 deletions src/common/gui/SurgeGUIEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,24 @@ class SurgeGUIEditor : public EditorType, public VSTGUI::IControlListener, publi
int getZoomFactor() { return zoomFactor; }
void setZoomFactor(int zf);

private:
/**
* findLargestFittingZoomBetween
*
* Finds the largest zoom which will fit your current screen between a lower and upper bound.
* Will never return something smaller than lower or larger than upper. Default is as large as
* possible, quantized in units of zoomQuanta, with the maximum screen usage percentages
* protecting for screen real estate. The function also needs to know the 100% size of the UI
* the baseW and baseH)
*
* for instance findLargestFittingZoomBetween( 100, 200, 5, 90, bw, bh )
*
* would find the largest possible zoom which uses at most 90% of your screen real estate but
* would also guarantee that the result % 5 == 0.
*/
int findLargestFittingZoomBetween(int zoomLow, int zoomHigh, int zoomQuanta, int percentageOfScreenAvailable,
float baseW, float baseH);

private:
std::function< void(SurgeGUIEditor *) > zoom_callback;

Expand Down Expand Up @@ -171,6 +189,3 @@ class SurgeGUIEditor : public EditorType, public VSTGUI::IControlListener, publi
VSTGUI::CVSTGUITimer* _idleTimer = nullptr;
};

#if MAC || WINDOWS
#define HOST_SUPPORTS_ZOOM 1
#endif
4 changes: 2 additions & 2 deletions src/linux/DisplayInfoLinux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ float getDisplayBackingScaleFactor(CFrame *)

CRect getScreenDimensions(CFrame *)
{
Surge::UserInteractions::promptError("getScreenDimensions not implemented yet on linux.",
Surge::UserInteractions::promptError("getScreenDimensions not implemented yet on linux. Returning 1400x1050",
"Software Error");
return CRect(CPoint(0,0), CPoint(1024,768));
return CRect(CPoint(0,0), CPoint(1400,1050)); // a typical mid-range 15" laptop
}

}
Expand Down

0 comments on commit 9cbf0f3

Please sign in to comment.