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

A Variety of Zoom Enhancements #497

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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