Skip to content
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ target_sources(${PROJECT_NAME}
src/gui/SliderWithLabel.h
src/gui/ComboBoxWithLabel.h
src/gui/HoverHandler.h
src/gui/ControlComponent.h
src/gui/ToggleWithLabel.h

src/media/MediaDisplayComponent.cpp
src/media/AudioDisplayComponent.cpp
Expand Down
8 changes: 7 additions & 1 deletion src/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,13 @@ class GuiAppApplication : public JUCEApplication, public FocusChangeListener
windowIdentifier(name.replaceCharacters(" :", "__"))
{
setUsingNativeTitleBar(true);
setContentOwned(new MainComponent(), true);
MainComponent* mainComp = new MainComponent();
setContentOwned(mainComp, true);
setResizable(true, true);

setConstrainer(&constrainer);
mainComp->updateWindowConstraints();

// Try to restore saved position and size
restoreWindowPosition();

Expand Down Expand Up @@ -359,6 +363,8 @@ class GuiAppApplication : public JUCEApplication, public FocusChangeListener

String windowIdentifier;

ComponentBoundsConstrainer constrainer;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(HARPWindow)
};

Expand Down
124 changes: 101 additions & 23 deletions src/MainComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,29 @@ MainComponent::MainComponent()

initializeMenuBar();

mainModelTab.addChangeListener(this);

addAndMakeVisible(mainModelTab);
addAndMakeVisible(statusAreaWidget);
addAndMakeVisible(mediaClipboardWidget);

showStatusArea = Settings::getBoolValue("view.showStatusArea", true);
showMediaClipboard = Settings::getBoolValue("view.showMediaClipboard", false);

sharedTokens->initializeAPIKeys();
requiredWindowWidth = minimumWindowWidth;
requiredWindowHeight = minimumWindowHeight;
setSize(requiredWindowWidth, requiredWindowHeight);

setSize(800, 2000);
sharedTokens->initializeAPIKeys();

statusMessage->setMessage("Welcome to HARP!");
}

MainComponent::~MainComponent() { deinitializeMenuBar(); }
MainComponent::~MainComponent()
{
deinitializeMenuBar();
mainModelTab.removeChangeListener(this);
}

void MainComponent::paint(Graphics& g)
{
Expand All @@ -48,7 +56,7 @@ void MainComponent::resized()

if (showStatusArea)
{
mainPanel.items.add(FlexItem(statusAreaWidget).withHeight(100));
mainPanel.items.add(FlexItem(statusAreaWidget).withHeight(statusAreaHeight));
}
else
{
Expand All @@ -59,7 +67,7 @@ void MainComponent::resized()

if (showMediaClipboard)
{
fullWindow.items.add(FlexItem(mediaClipboardWidget).withFlex(0.4));
fullWindow.items.add(FlexItem(mediaClipboardWidget).withFlex(mediaClipboardFlex));
}
else
{
Expand All @@ -69,6 +77,65 @@ void MainComponent::resized()
fullWindow.performLayout(fullArea);
}

void MainComponent::updateWindowConstraints()
{
if (auto* window = findParentComponentOfClass<DocumentWindow>())
{
// Compute percentage of total window width given to main panel
const float mainPanelRatio = showMediaClipboard ? (1.0f / mediaClipboardScale) : 1.0f;

// Determine minimum width needed to display controls plus padding
const int requiredMainPanelWidth =
jmax(minimumMainPanelWidth,
mainModelTab.getMinimumRequiredControlWidth() + minimumMainPanelHorPadding);
// Determine current width of main panel
const int mainPanelWidth = jmax(requiredMainPanelWidth, mainModelTab.getWidth());
// Determine minimum height needed to display all model contents plus status widget
const int requiredMainPanelHeight =
mainModelTab.getMinimumRequiredHeightForWidth(mainPanelWidth)
+ (showStatusArea ? statusAreaHeight : 0);

// Determine effective minimum width of entire window
const int newRequiredWindowWidth = jmax(
minimumWindowWidth, (int) std::ceil((float) requiredMainPanelWidth / mainPanelRatio));
// Determine effective minimum height of entire window
const int newRequiredWindowHeight =
jmax(minimumWindowHeight, requiredMainPanelHeight + minimumMainPanelVertPadding);

auto* currentDisplay =
Desktop::getInstance().getDisplays().getDisplayForRect(window->getScreenBounds());

const auto userArea =
currentDisplay != nullptr
? currentDisplay->userArea
: Rectangle<int>(0, 0, newRequiredWindowWidth, newRequiredWindowHeight);

ComponentBoundsConstrainer* constrainer = window->getConstrainer();

constrainer->setMinimumSize(jmin(newRequiredWindowWidth, userArea.getWidth()),
jmin(newRequiredWindowHeight, userArea.getHeight()));
constrainer->setMaximumSize(userArea.getWidth(), userArea.getHeight());
constrainer->setMinimumOnscreenAmounts(40, 40, 40, 40);

const bool constraintsDecreased = newRequiredWindowWidth < requiredWindowWidth
|| newRequiredWindowHeight < requiredWindowHeight;

requiredWindowWidth = newRequiredWindowWidth;
requiredWindowHeight = newRequiredWindowHeight;

auto bounds = window->getBounds();

window->setBoundsConstrained(bounds);

if (constraintsDecreased)
{
// Small hack allowing immediate shrinking when constraints decrease
window->setBounds(bounds.withWidth(bounds.getWidth() + 1));
window->setBounds(bounds);
}
}
}

/* --File-- */

/**
Expand Down Expand Up @@ -110,9 +177,13 @@ void MainComponent::viewStatusAreaCallback()
{
// Determine which display contains HARP
auto* currentDisplay =
Desktop::getInstance().getDisplays().getDisplayForRect(getScreenBounds());
Desktop::getInstance().getDisplays().getDisplayForRect(window->getScreenBounds());

// Get current bounds of top-level window
Rectangle<int> windowBounds = window->getBounds();

int currentDisplayHeight;
// Default display height to height of current window
int currentDisplayHeight = windowBounds.getHeight();

if (currentDisplay != nullptr)
{
Expand All @@ -126,20 +197,18 @@ void MainComponent::viewStatusAreaCallback()
}
}

// Get current bounds of top-level window
Rectangle<int> windowBounds = window->getBounds();

if (showStatusArea)
{
// Scale bounds to extend window by height of status area
windowBounds.setHeight(jmin(currentDisplayHeight, windowBounds.getHeight() + 100));
windowBounds.setHeight(
jmin(currentDisplayHeight, windowBounds.getHeight() + statusAreaHeight));
}
else
{
if (! window->isFullScreen())
{
// Scale bounds to reduce window to main height
windowBounds.setHeight(windowBounds.getHeight() - 100);
windowBounds.setHeight(windowBounds.getHeight() - statusAreaHeight);
}
}

Expand All @@ -153,7 +222,7 @@ void MainComponent::viewStatusAreaCallback()
// Send status message to add check to file menu
commandManager.commandStatusChanged();

resized();
updateWindowConstraints();
}

void MainComponent::viewMediaClipboardCallback()
Expand All @@ -166,9 +235,13 @@ void MainComponent::viewMediaClipboardCallback()
{
// Determine which display contains HARP
auto* currentDisplay =
Desktop::getInstance().getDisplays().getDisplayForRect(getScreenBounds());
Desktop::getInstance().getDisplays().getDisplayForRect(window->getScreenBounds());

// Get current bounds of top-level window
Rectangle<int> windowBounds = window->getBounds();

int currentDisplayWidth;
// Default display width to width of current window
int currentDisplayWidth = windowBounds.getWidth();

if (currentDisplay != nullptr)
{
Expand All @@ -182,23 +255,20 @@ void MainComponent::viewMediaClipboardCallback()
}
}

//int totalDesktopWidth = Desktop::getInstance().getDisplays().getDisplayForRect(getBounds())->totalArea.getWidth();

// Get current bounds of top-level window
Rectangle<int> windowBounds = window->getBounds();

if (showMediaClipboard)
{
// Scale bounds to extend window by 40% of main width
windowBounds.setWidth(
jmin(currentDisplayWidth, static_cast<int>(1.4 * windowBounds.getWidth())));
jmin(currentDisplayWidth,
static_cast<int>(mediaClipboardScale * windowBounds.getWidth())));
}
else
{
if (! window->isFullScreen())
{
// Scale bounds to reduce window to main width
windowBounds.setWidth(static_cast<int>(windowBounds.getWidth() / 1.4));
windowBounds.setWidth(
static_cast<int>(windowBounds.getWidth() / mediaClipboardScale));
}
}

Expand All @@ -212,7 +282,7 @@ void MainComponent::viewMediaClipboardCallback()
// Send status message to add check to file menu
commandManager.commandStatusChanged();

resized();
updateWindowConstraints();
}

/* --Help-- */
Expand Down Expand Up @@ -281,3 +351,11 @@ void MainComponent::focusCallback()
}
}
*/

void MainComponent::changeListenerCallback(ChangeBroadcaster* source)
{
if (source == &mainModelTab)
{
updateWindowConstraints();
}
}
25 changes: 24 additions & 1 deletion src/MainComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@

using namespace juce;

class MainComponent : public Component, public MenuBarModel, public ApplicationCommandTarget
class MainComponent : public Component,
public MenuBarModel,
public ApplicationCommandTarget,
private ChangeListener

{
public:
Expand Down Expand Up @@ -70,6 +73,8 @@ class MainComponent : public Component, public MenuBarModel, public ApplicationC
void paint(Graphics& g) override;
void resized() override;

void updateWindowConstraints();

private:
/* File Menu */

Expand All @@ -87,9 +92,27 @@ class MainComponent : public Component, public MenuBarModel, public ApplicationC

// Miscellaneous
//void focusCallback();
void changeListenerCallback(ChangeBroadcaster* source);

/* Interface */

const int statusAreaHeight = 100;
const float mediaClipboardFlex = 0.4f;
const float mediaClipboardScale = 1.4f;

// Minimum size to ensure all controls remain visible and functional:
// - WelcomeWindow popup is 480x500, needs padding
// - Dropdown labels need adequate width
// - Control Area needs space for sliders/toggles/textboxes
const int minimumWindowWidth = 700;
const int minimumWindowHeight = 500;
const int minimumMainPanelWidth = 320;
const int minimumMainPanelHorPadding = 32;
const int minimumMainPanelVertPadding = 32;

int requiredWindowWidth;
int requiredWindowHeight;

bool showStatusArea;
bool showMediaClipboard;

Expand Down
Loading
Loading