-
-
Notifications
You must be signed in to change notification settings - Fork 99
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Import ResizeHandle widget for tests, set Demo min size
Signed-off-by: falkTX <[email protected]>
- Loading branch information
Showing
2 changed files
with
210 additions
and
150 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
/* | ||
* DISTRHO Plugin Framework (DPF) | ||
* Copyright (C) 2012-2021 Filipe Coelho <[email protected]> | ||
* Copyright (C) 2012-2022 Filipe Coelho <[email protected]> | ||
* | ||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | ||
* or without fee is hereby granted, provided that the above copyright notice and this | ||
|
@@ -23,6 +23,7 @@ | |
#ifdef DGL_OPENGL | ||
#include "widgets/ExampleTextWidget.hpp" | ||
#endif | ||
#include "widgets/ResizeHandle.hpp" | ||
|
||
#include "demo_res/DemoArtwork.cpp" | ||
#include "images_res/CatPics.cpp" | ||
|
@@ -250,155 +251,6 @@ class LeftSideWidget : public SubWidget | |
#endif | ||
}; | ||
|
||
// -------------------------------------------------------------------------------------------------------------------- | ||
// Resize handle widget | ||
|
||
class ResizeHandle : public TopLevelWidget | ||
{ | ||
Rectangle<uint> area; | ||
Line<double> l1, l2, l3; | ||
uint baseSize; | ||
|
||
// event handling state | ||
bool resizing; | ||
Point<double> lastResizePoint; | ||
Size<double> resizingSize; | ||
|
||
public: | ||
explicit ResizeHandle(TopLevelWidget* const tlw) | ||
: TopLevelWidget(tlw->getWindow()), | ||
baseSize(16), | ||
resizing(false) | ||
{ | ||
resetArea(); | ||
} | ||
|
||
explicit ResizeHandle(Window& window) | ||
: TopLevelWidget(window), | ||
baseSize(16), | ||
resizing(false) | ||
{ | ||
resetArea(); | ||
} | ||
|
||
void setBaseSize(const uint size) | ||
{ | ||
baseSize = std::max(16u, size); | ||
resetArea(); | ||
} | ||
|
||
protected: | ||
void onDisplay() override | ||
{ | ||
const GraphicsContext& context(getGraphicsContext()); | ||
const double offset = getScaleFactor(); | ||
|
||
// draw white lines, 1px wide | ||
Color(1.0f, 1.0f, 1.0f).setFor(context); | ||
l1.draw(context, 1); | ||
l2.draw(context, 1); | ||
l3.draw(context, 1); | ||
|
||
// draw black lines, offset by 1px and 2px wide | ||
Color(0.0f, 0.0f, 0.0f).setFor(context); | ||
Line<double> l1b(l1), l2b(l2), l3b(l3); | ||
l1b.moveBy(offset, offset); | ||
l2b.moveBy(offset, offset); | ||
l3b.moveBy(offset, offset); | ||
l1b.draw(context, 1); | ||
l2b.draw(context, 1); | ||
l3b.draw(context, 1); | ||
} | ||
|
||
bool onMouse(const MouseEvent& ev) override | ||
{ | ||
if (ev.button != 1) | ||
return false; | ||
|
||
if (ev.press && area.contains(ev.pos)) | ||
{ | ||
resizing = true; | ||
resizingSize = Size<double>(getWidth(), getHeight()); | ||
lastResizePoint = ev.pos; | ||
return true; | ||
} | ||
|
||
if (resizing && ! ev.press) | ||
{ | ||
resizing = false; | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
bool onMotion(const MotionEvent& ev) override | ||
{ | ||
if (! resizing) | ||
return false; | ||
|
||
const Size<double> offset(ev.pos.getX() - lastResizePoint.getX(), | ||
ev.pos.getY() - lastResizePoint.getY()); | ||
|
||
resizingSize += offset; | ||
lastResizePoint = ev.pos; | ||
|
||
// TODO min width, min height | ||
const uint minWidth = 16; | ||
const uint minHeight = 16; | ||
|
||
if (resizingSize.getWidth() < minWidth) | ||
resizingSize.setWidth(minWidth); | ||
if (resizingSize.getHeight() < minHeight) | ||
resizingSize.setHeight(minHeight); | ||
|
||
setSize(resizingSize.getWidth(), resizingSize.getHeight()); | ||
return true; | ||
} | ||
|
||
void onResize(const ResizeEvent& ev) override | ||
{ | ||
TopLevelWidget::onResize(ev); | ||
resetArea(); | ||
} | ||
|
||
private: | ||
void resetArea() | ||
{ | ||
const double scaleFactor = getScaleFactor(); | ||
const uint margin = 0.0 * scaleFactor; | ||
const uint size = baseSize * scaleFactor; | ||
|
||
area = Rectangle<uint>(getWidth() - size - margin, | ||
getHeight() - size - margin, | ||
size, size); | ||
|
||
recreateLines(area.getX(), area.getY(), size); | ||
} | ||
|
||
void recreateLines(const uint x, const uint y, const uint size) | ||
{ | ||
uint linesize = size; | ||
uint offset = 0; | ||
|
||
// 1st line, full diagonal size | ||
l1.setStartPos(x + size, y); | ||
l1.setEndPos(x, y + size); | ||
|
||
// 2nd line, bit more to the right and down, cropped | ||
offset += size / 3; | ||
linesize -= size / 3; | ||
l2.setStartPos(x + linesize + offset, y + offset); | ||
l2.setEndPos(x + offset, y + linesize + offset); | ||
|
||
// 3rd line, even more right and down | ||
offset += size / 3; | ||
linesize -= size / 3; | ||
l3.setStartPos(x + linesize + offset, y + offset); | ||
l3.setEndPos(x + offset, y + linesize + offset); | ||
} | ||
}; | ||
|
||
// -------------------------------------------------------------------------------------------------------------------- | ||
// Main Demo Window, having a left-side tab-like widget and main area for current widget | ||
|
||
|
@@ -535,6 +387,7 @@ void createAndShowExampleWidgetStandaloneWindow(Application& app) | |
{ | ||
ExampleWidgetStandaloneWindow swin(app); | ||
const double scaleFactor = swin.getScaleFactor(); | ||
swin.setGeometryConstraints(128 * scaleFactor, 128 * scaleFactor); | ||
swin.setResizable(true); | ||
swin.setSize(600 * scaleFactor, 500 * scaleFactor); | ||
swin.setTitle(ExampleWidgetStandaloneWindow::kExampleWidgetName); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
/* | ||
* Resize handle for DPF | ||
* Copyright (C) 2021-2022 Filipe Coelho <[email protected]> | ||
* | ||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | ||
* or without fee is hereby granted, provided that the above copyright notice and this | ||
* permission notice appear in all copies. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | ||
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | ||
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | ||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | ||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include "../../dgl/Color.hpp" | ||
#include "../../dgl/TopLevelWidget.hpp" | ||
|
||
START_NAMESPACE_DGL | ||
|
||
/** Resize handle for DPF windows, will sit on bottom-right. */ | ||
class ResizeHandle : public TopLevelWidget | ||
{ | ||
public: | ||
/** Constructor for placing this handle on top of a window. */ | ||
explicit ResizeHandle(Window& window) | ||
: TopLevelWidget(window), | ||
handleSize(16), | ||
hasCursor(false), | ||
isResizing(false) | ||
{ | ||
resetArea(); | ||
} | ||
|
||
/** Overloaded constructor, will fetch the window from an existing top-level widget. */ | ||
explicit ResizeHandle(TopLevelWidget* const tlw) | ||
: TopLevelWidget(tlw->getWindow()), | ||
handleSize(16), | ||
hasCursor(false), | ||
isResizing(false) | ||
{ | ||
resetArea(); | ||
} | ||
|
||
/** Set the handle size, minimum 16. | ||
* Scale factor is automatically applied on top of this size as needed */ | ||
void setHandleSize(const uint size) | ||
{ | ||
handleSize = std::max(16u, size); | ||
resetArea(); | ||
} | ||
|
||
protected: | ||
void onDisplay() override | ||
{ | ||
// TODO implement gl3 stuff in DPF | ||
#ifndef DGL_USE_OPENGL3 | ||
const GraphicsContext& context(getGraphicsContext()); | ||
const double lineWidth = 1.0 * getScaleFactor(); | ||
|
||
#if defined(DGL_OPENGL) && !defined(DGL_USE_OPENGL3) | ||
glMatrixMode(GL_MODELVIEW); | ||
#endif | ||
|
||
// draw white lines, 1px wide | ||
Color(1.0f, 1.0f, 1.0f).setFor(context); | ||
l1.draw(context, lineWidth); | ||
l2.draw(context, lineWidth); | ||
l3.draw(context, lineWidth); | ||
|
||
// draw black lines, offset by 1px and 1px wide | ||
Color(0.0f, 0.0f, 0.0f).setFor(context); | ||
Line<double> l1b(l1), l2b(l2), l3b(l3); | ||
l1b.moveBy(lineWidth, lineWidth); | ||
l2b.moveBy(lineWidth, lineWidth); | ||
l3b.moveBy(lineWidth, lineWidth); | ||
l1b.draw(context, lineWidth); | ||
l2b.draw(context, lineWidth); | ||
l3b.draw(context, lineWidth); | ||
#endif | ||
} | ||
|
||
bool onMouse(const MouseEvent& ev) override | ||
{ | ||
if (ev.button != 1) | ||
return false; | ||
|
||
if (ev.press && area.contains(ev.pos)) | ||
{ | ||
isResizing = true; | ||
resizingSize = Size<double>(getWidth(), getHeight()); | ||
lastResizePoint = ev.pos; | ||
return true; | ||
} | ||
|
||
if (isResizing && ! ev.press) | ||
{ | ||
isResizing = false; | ||
recheckCursor(ev.pos); | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
bool onMotion(const MotionEvent& ev) override | ||
{ | ||
if (! isResizing) | ||
{ | ||
recheckCursor(ev.pos); | ||
return false; | ||
} | ||
|
||
const Size<double> offset(ev.pos.getX() - lastResizePoint.getX(), | ||
ev.pos.getY() - lastResizePoint.getY()); | ||
|
||
resizingSize += offset; | ||
lastResizePoint = ev.pos; | ||
|
||
// TODO keepAspectRatio | ||
bool keepAspectRatio; | ||
const Size<uint> minSize(getWindow().getGeometryConstraints(keepAspectRatio)); | ||
const uint minWidth = minSize.getWidth(); | ||
const uint minHeight = minSize.getHeight(); | ||
|
||
if (resizingSize.getWidth() < minWidth) | ||
resizingSize.setWidth(minWidth); | ||
if (resizingSize.getWidth() > 16384) | ||
resizingSize.setWidth(16384); | ||
if (resizingSize.getHeight() < minHeight) | ||
resizingSize.setHeight(minHeight); | ||
if (resizingSize.getHeight() > 16384) | ||
resizingSize.setHeight(16384); | ||
|
||
setSize(resizingSize.getWidth(), resizingSize.getHeight()); | ||
return true; | ||
} | ||
|
||
void onResize(const ResizeEvent& ev) override | ||
{ | ||
TopLevelWidget::onResize(ev); | ||
resetArea(); | ||
} | ||
|
||
private: | ||
Rectangle<uint> area; | ||
Line<double> l1, l2, l3; | ||
uint handleSize; | ||
|
||
// event handling state | ||
bool hasCursor, isResizing; | ||
Point<double> lastResizePoint; | ||
Size<double> resizingSize; | ||
|
||
void recheckCursor(const Point<double>& pos) | ||
{ | ||
const bool shouldHaveCursor = area.contains(pos); | ||
|
||
if (shouldHaveCursor == hasCursor) | ||
return; | ||
|
||
hasCursor = shouldHaveCursor; | ||
setCursor(shouldHaveCursor ? kMouseCursorDiagonal : kMouseCursorArrow); | ||
} | ||
|
||
void resetArea() | ||
{ | ||
const double scaleFactor = getScaleFactor(); | ||
const uint margin = 0.0 * scaleFactor; | ||
const uint size = handleSize * scaleFactor; | ||
|
||
area = Rectangle<uint>(getWidth() - size - margin, | ||
getHeight() - size - margin, | ||
size, size); | ||
|
||
recreateLines(area.getX(), area.getY(), size); | ||
} | ||
|
||
void recreateLines(const uint x, const uint y, const uint size) | ||
{ | ||
uint linesize = size; | ||
uint offset = 0; | ||
|
||
// 1st line, full diagonal size | ||
l1.setStartPos(x + size, y); | ||
l1.setEndPos(x, y + size); | ||
|
||
// 2nd line, bit more to the right and down, cropped | ||
offset += size / 3; | ||
linesize -= size / 3; | ||
l2.setStartPos(x + linesize + offset, y + offset); | ||
l2.setEndPos(x + offset, y + linesize + offset); | ||
|
||
// 3rd line, even more right and down | ||
offset += size / 3; | ||
linesize -= size / 3; | ||
l3.setStartPos(x + linesize + offset, y + offset); | ||
l3.setEndPos(x + offset, y + linesize + offset); | ||
} | ||
|
||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ResizeHandle) | ||
}; | ||
|
||
END_NAMESPACE_DGL |