commit c6e9bec69384bbb47fd6dffe30abb601d07804b8
parent 272e1bbfbd9d70e3852fcd666716c72310e3ac23
Author: falkTX <falktx@falktx.com>
Date: Thu, 6 May 2021 17:29:14 +0100
Start adding back widget stuff, almost at drawing step
Signed-off-by: falkTX <falktx@falktx.com>
Diffstat:
22 files changed, 747 insertions(+), 328 deletions(-)
diff --git a/dgl/Application.hpp b/dgl/Application.hpp
@@ -38,7 +38,7 @@ public:
Constructor.
*/
// NOTE: the default value is not yet passed, so we catch where we use this
- Application(bool isStandalone /* = true */);
+ Application(bool isStandalone = true);
/**
Destructor.
diff --git a/dgl/Cairo.hpp b/dgl/Cairo.hpp
@@ -17,13 +17,14 @@
#ifndef DGL_CAIRO_HPP_INCLUDED
#define DGL_CAIRO_HPP_INCLUDED
-#include "Base.hpp"
+#include "SubWidget.hpp"
+#include "TopLevelWidget.hpp"
#include <cairo/cairo.h>
START_NAMESPACE_DGL
-// -----------------------------------------------------------------------
+// --------------------------------------------------------------------------------------------------------------------
/**
Cairo Graphics context.
@@ -33,7 +34,49 @@ struct CairoGraphicsContext : GraphicsContext
cairo_t* handle;
};
-// -----------------------------------------------------------------------
+/**
+ Cairo SubWidget, handy class that takes graphics context during onDisplay and passes it in a new function.
+ */
+class CairoSubWidget : public SubWidget
+{
+public:
+ CairoSubWidget(Widget* widgetToGroupTo)
+ : SubWidget(widgetToGroupTo) {}
+
+protected:
+ void onDisplay() override
+ {
+ const CairoGraphicsContext& context((const CairoGraphicsContext&)getGraphicsContext());
+ onCairoDisplay(context);
+ }
+
+ virtual void onCairoDisplay(const CairoGraphicsContext& context) = 0;
+
+ DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CairoSubWidget);
+};
+
+/**
+ Cairo TopLevelWidget, handy class that takes graphics context during onDisplay and passes it in a new function.
+ */
+class CairoTopLevelWidget : public TopLevelWidget
+{
+public:
+ CairoTopLevelWidget(Window& windowToMapTo)
+ : TopLevelWidget(windowToMapTo) {}
+
+protected:
+ void onDisplay() override
+ {
+ const CairoGraphicsContext& context((const CairoGraphicsContext&)getGraphicsContext());
+ onCairoDisplay(context);
+ }
+
+ virtual void onCairoDisplay(const CairoGraphicsContext& context) = 0;
+
+ DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CairoTopLevelWidget);
+};
+
+// --------------------------------------------------------------------------------------------------------------------
END_NAMESPACE_DGL
diff --git a/dgl/StandaloneWindow.hpp b/dgl/StandaloneWindow.hpp
@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
- * Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
+ * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
*
* 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
@@ -17,7 +17,6 @@
#ifndef DGL_STANDALONE_WINDOW_HPP_INCLUDED
#define DGL_STANDALONE_WINDOW_HPP_INCLUDED
-#include "Application.hpp"
#include "TopLevelWidget.hpp"
#include "Window.hpp"
@@ -25,33 +24,54 @@ START_NAMESPACE_DGL
// -----------------------------------------------------------------------
-class StandaloneWindow : public Application,
- public Window
+class StandaloneWindow : public Window,
+ public TopLevelWidget
{
public:
/**
Constructor.
*/
- StandaloneWindow();
+ StandaloneWindow(Application& app)
+ : Window(app),
+ TopLevelWidget((Window&)*this) {}
/**
- Show window and execute application.
+ Overloaded functions to ensure they apply to the Window class.
*/
- void exec();
+ bool isVisible() const noexcept { return Window::isVisible(); }
+ void setVisible(bool yesNo) { Window::setVisible(yesNo); }
+ void hide() { Window::hide(); }
+ void show() { Window::show(); }
+ uint getWidth() const noexcept { return Window::getWidth(); }
+ uint getHeight() const noexcept { return Window::getHeight(); }
+ const Size<uint> getSize() const noexcept { return Window::getSize(); }
-private:
- TopLevelWidget* fWidget;
+ /**
+ Overloaded functions to ensure size changes apply on both TopLevelWidget and Window classes.
+ */
+ void setWidth(uint width)
+ {
+ TopLevelWidget::setWidth(width);
+ Window::setWidth(width);
+ }
- /** @internal */
- void onReshape(uint width, uint height) override;
+ void setHeight(uint height)
+ {
+ TopLevelWidget::setHeight(height);
+ Window::setHeight(height);
+ }
-#if 0
- /** @internal */
- void _addWidget(TopLevelWidget* widget) override;
+ void setSize(uint width, uint height)
+ {
+ TopLevelWidget::setSize(width, height);
+ Window::setSize(width, height);
+ }
- /** @internal */
- void _removeWidget(TopLevelWidget* widget) override;
-#endif
+ void setSize(const Size<uint>& size)
+ {
+ TopLevelWidget::setSize(size);
+ Window::setSize(size);
+ }
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(StandaloneWindow)
};
diff --git a/dgl/TopLevelWidget.hpp b/dgl/TopLevelWidget.hpp
@@ -52,18 +52,10 @@ public:
protected:
/**
- A function called before any draw operations begin (in the current event-loop cycle).
- Can be used to setup any resources for needed drawing.
- The default implementation simply paints the full Widget contents black.
+ A function called to draw the widget contents.
+ Reimplemented from Widget::onDisplay.
*/
- virtual void onDisplayBefore();
-
- /**
- A function called after all draw operations have ended (in the current event-loop cycle).
- Can be used to clear any resources setup during onDisplayBefore().
- The default implementation does nothing.
- */
- virtual void onDisplayAfter();
+ void onDisplay() override;
/**
A function called when the widget is resized.
diff --git a/dgl/Widget.hpp b/dgl/Widget.hpp
@@ -30,11 +30,11 @@
START_NAMESPACE_DGL
-// class Application;
+class Application;
// class NanoWidget;
// class Window;
// class StandaloneWindow;
-// class SubWidget;
+class SubWidget;
class TopLevelWidget;
using namespace Events;
@@ -46,26 +46,31 @@ using namespace Events;
This is the base Widget class, from which all widgets are built.
- All widgets have a parent Window where they'll be drawn.
- This parent is never changed during the widget lifetime.
+ All widgets have a parent widget where they'll be drawn, this can be the top-level widget or a group widget.
+ This parent is never changed during a widget's lifetime.
- Widgets receive events in relative coordinates.
- (0, 0) means its top-left position.
+ Widgets receive events in relative coordinates. (0, 0) means its top-left position.
- Windows paint widgets in the order they are constructed.
- Early widgets are drawn first, at the bottom, then newer ones on top.
- Events are sent in the inverse order so that the top-most widget gets
+ The top-level widget will draw subwidgets in the order they are constructed.
+ Early subwidgets are drawn first, at the bottom, then newer ones on top.
+ Events are sent in the inverse order so that the top-most widgets get
a chance to catch the event and stop its propagation.
- All widget event callbacks do nothing by default.
+ All widget event callbacks do nothing by default and onDisplay MUST be reimplemented by subclasses.
+
+ @note It is not possible to subclass this Widget class directly, you must use SubWidget or TopLevelWidget instead.
*/
class Widget
{
/**
- Constructor, reserved for DGL ..
- use TopLevelWidget or SubWidget instead
+ Private constructor, reserved for SubWidget class.
+ */
+ explicit Widget(Widget* widgetToGroupTo);
+
+ /**
+ Private constructor, reserved for TopLevelWidget class.
*/
- explicit Widget(TopLevelWidget& topLevelWidget);
+ explicit Widget(TopLevelWidget* topLevelWidget);
public:
/**
@@ -109,7 +114,7 @@ public:
/**
Get size.
*/
- const Size<uint>& getSize() const noexcept;
+ const Size<uint> getSize() const noexcept;
/**
Set width.
@@ -132,17 +137,6 @@ public:
void setSize(const Size<uint>& size) noexcept;
/**
- Get top-level widget, as passed in the constructor.
- */
- TopLevelWidget& getTopLevelWidget() const noexcept;
-
- /**
- Tell this widget's window to repaint itself.
- FIXME better description, partial redraw
- */
- void repaint() noexcept;
-
- /**
Get the Id associated with this widget.
@see setId
*/
@@ -154,9 +148,35 @@ public:
*/
void setId(uint id) noexcept;
+ /**
+ Get the application associated with this widget's window.
+ This is the same as calling `getTopLevelWidget()->getApp()`.
+ */
+ Application& getApp() const noexcept;
+
+ /**
+ Get the graphics context associated with this widget.
+ GraphicsContext is an empty struct and needs to be casted into a different type in order to be usable,
+ for example GraphicsContext.
+ @see CairoSubWidget, CairoTopLevelWidget
+ */
+ const GraphicsContext& getGraphicsContext() const noexcept;
+
+ /**
+ Get top-level widget, as passed directly in the constructor
+ or going up the chain of group widgets until it finds the top-level widget.
+ */
+ TopLevelWidget* getTopLevelWidget() const noexcept;
+
+ /**
+ Tell this widget's window to repaint itself.
+ FIXME better description, partial redraw
+ */
+ void repaint() noexcept;
+
protected:
/**
- A function called to draw the view contents with OpenGL.
+ A function called to draw the widget contents.
*/
virtual void onDisplay() = 0;
@@ -208,6 +228,7 @@ private:
// friend class NanoWidget;
// friend class Window;
// friend class StandaloneWindow;
+ friend class SubWidget;
friend class TopLevelWidget;
// #ifdef DISTRHO_DEFINES_H_INCLUDED
// friend class DISTRHO_NAMESPACE::UI;
diff --git a/dgl/Window.hpp b/dgl/Window.hpp
@@ -22,6 +22,7 @@
START_NAMESPACE_DGL
class Application;
+class TopLevelWidget;
// -----------------------------------------------------------------------
@@ -152,6 +153,11 @@ public:
void setTitle(const char* title);
/**
+ Get the application associated with this window.
+ */
+ Application& getApp() const noexcept;
+
+ /**
Get the "native" window handle.
Returned value depends on the platform:
- HaikuOS: This is a pointer to a `BView`.
@@ -161,10 +167,18 @@ public:
*/
uintptr_t getNativeWindowHandle() const noexcept;
+protected:
+ /**
+ A function called when the window is resized.
+ If there is a top-level widget associated with this window, its size will be set right after this function.
+ */
+ virtual void onReshape(uint width, uint height);
+
private:
struct PrivateData;
PrivateData* const pData;
friend class Application;
+ friend class TopLevelWidget;
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Window);
};
@@ -251,11 +265,6 @@ END_NAMESPACE_DGL
double getScaling() const noexcept;
-#if 0
- // should this be removed?
- Application& getApp() const noexcept;
-#endif
-
const GraphicsContext& getGraphicsContext() const noexcept;
void addIdleCallback(IdleCallback* const callback);
diff --git a/dgl/src/Cairo.cpp b/dgl/src/Cairo.cpp
@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
- * Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com>
+ * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
*
* 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
@@ -14,8 +14,8 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include "../Geometry.hpp"
#include "../Cairo.hpp"
+#include "WidgetPrivateData.hpp"
START_NAMESPACE_DGL
@@ -63,49 +63,28 @@ void Rectangle<T>::_draw(const bool outline)
}
// -----------------------------------------------------------------------
-// Possible template data types
-
-template class Point<double>;
-template class Point<float>;
-template class Point<int>;
-template class Point<uint>;
-template class Point<short>;
-template class Point<ushort>;
-
-template class Size<double>;
-template class Size<float>;
-template class Size<int>;
-template class Size<uint>;
-template class Size<short>;
-template class Size<ushort>;
-
-template class Line<double>;
-template class Line<float>;
-template class Line<int>;
-template class Line<uint>;
-template class Line<short>;
-template class Line<ushort>;
-
-template class Circle<double>;
-template class Circle<float>;
-template class Circle<int>;
-template class Circle<uint>;
-template class Circle<short>;
-template class Circle<ushort>;
-
-template class Triangle<double>;
-template class Triangle<float>;
-template class Triangle<int>;
-template class Triangle<uint>;
-template class Triangle<short>;
-template class Triangle<ushort>;
-
-template class Rectangle<double>;
-template class Rectangle<float>;
-template class Rectangle<int>;
-template class Rectangle<uint>;
-template class Rectangle<short>;
-template class Rectangle<ushort>;
+
+void Widget::PrivateData::display(const uint width,
+ const uint height,
+ const double scaling,
+ const bool renderingSubWidget)
+{
+ if ((skipDisplay && ! renderingSubWidget) || size.isInvalid() || ! visible)
+ return;
+
+ cairo_t* cr = static_cast<const CairoGraphicsContext&>(parent.getGraphicsContext()).cairo;
+ cairo_matrix_t matrix;
+ cairo_get_matrix(cr, &matrix);
+ cairo_translate(cr, absolutePos.getX(), absolutePos.getY());
+ // TODO: scaling and cropping
+
+ // display widget
+ self->onDisplay();
+
+ cairo_set_matrix(cr, &matrix);
+
+ displaySubWidgets(width, height, scaling);
+}
// -----------------------------------------------------------------------
diff --git a/dgl/src/OpenGL.cpp b/dgl/src/OpenGL.cpp
@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
- * Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com>
+ * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
*
* 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
@@ -14,8 +14,8 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include "../Geometry.hpp"
#include "../OpenGL.hpp"
+#include "WidgetPrivateData.hpp"
START_NAMESPACE_DGL
@@ -108,49 +108,65 @@ void Rectangle<T>::_draw(const bool outline)
}
// -----------------------------------------------------------------------
-// Possible template data types
-
-template class Point<double>;
-template class Point<float>;
-template class Point<int>;
-template class Point<uint>;
-template class Point<short>;
-template class Point<ushort>;
-
-template class Size<double>;
-template class Size<float>;
-template class Size<int>;
-template class Size<uint>;
-template class Size<short>;
-template class Size<ushort>;
-
-template class Line<double>;
-template class Line<float>;
-template class Line<int>;
-template class Line<uint>;
-template class Line<short>;
-template class Line<ushort>;
-
-template class Circle<double>;
-template class Circle<float>;
-template class Circle<int>;
-template class Circle<uint>;
-template class Circle<short>;
-template class Circle<ushort>;
-
-template class Triangle<double>;
-template class Triangle<float>;
-template class Triangle<int>;
-template class Triangle<uint>;
-template class Triangle<short>;
-template class Triangle<ushort>;
-
-template class Rectangle<double>;
-template class Rectangle<float>;
-template class Rectangle<int>;
-template class Rectangle<uint>;
-template class Rectangle<short>;
-template class Rectangle<ushort>;
+
+void Widget::PrivateData::display(const uint width,
+ const uint height,
+ const double scaling,
+ const bool renderingSubWidget)
+{
+ if (/*(skipDisplay && ! renderingSubWidget) ||*/ size.isInvalid() || ! visible)
+ return;
+
+// bool needsDisableScissor = false;
+
+ // reset color
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+
+// if (needsFullViewport || (absolutePos.isZero() && size == Size<uint>(width, height)))
+ {
+ // full viewport size
+ glViewport(0,
+ -(height * scaling - height),
+ width * scaling,
+ height * scaling);
+ }
+// else if (needsScaling)
+// {
+// // limit viewport to widget bounds
+// glViewport(absolutePos.getX(),
+// height - self->getHeight() - absolutePos.getY(),
+// self->getWidth(),
+// self->getHeight());
+// }
+// else
+// {
+// // only set viewport pos
+// glViewport(absolutePos.getX() * scaling,
+// -std::round((height * scaling - height) + (absolutePos.getY() * scaling)),
+// std::round(width * scaling),
+// std::round(height * scaling));
+//
+// // then cut the outer bounds
+// glScissor(absolutePos.getX() * scaling,
+// height - std::round((self->getHeight() + absolutePos.getY()) * scaling),
+// std::round(self->getWidth() * scaling),
+// std::round(self->getHeight() * scaling));
+//
+// glEnable(GL_SCISSOR_TEST);
+// needsDisableScissor = true;
+// }
+
+ // display widget
+ self->onDisplay();
+
+// if (needsDisableScissor)
+// {
+// glDisable(GL_SCISSOR_TEST);
+// needsDisableScissor = false;
+// }
+
+ displaySubWidgets(width, height, scaling);
+}
// -----------------------------------------------------------------------
diff --git a/dgl/src/StandaloneWindow.cpp b/dgl/src/StandaloneWindow.cpp
@@ -15,16 +15,15 @@
*/
#include "../StandaloneWindow.hpp"
-#include "WidgetPrivateData.hpp"
+#include "../TopLevelWidget.hpp"
START_NAMESPACE_DGL
// -----------------------------------------------------------------------
-StandaloneWindow::StandaloneWindow()
- : Application(true),
- Window((Application&)*this),
- fWidget(nullptr) {}
+StandaloneWindow::StandaloneWindow(Application& app)
+ : Window(app),
+ TopLevelWidget(this) {}
void StandaloneWindow::exec()
{
diff --git a/dgl/src/SubWidget.cpp b/dgl/src/SubWidget.cpp
@@ -15,9 +15,15 @@
*/
#include "SubWidgetPrivateData.hpp"
+#include "../TopLevelWidget.hpp"
+
+START_NAMESPACE_DGL
+
+// --------------------------------------------------------------------------------------------------------------------
SubWidget::SubWidget(Widget* const widgetToGroupTo)
- : pData(new PrivateData(this, widgetToGroupTo)) {}
+ : Widget(widgetToGroupTo),
+ pData(new PrivateData(this, widgetToGroupTo)) {}
SubWidget::~SubWidget()
{
@@ -79,9 +85,14 @@ void SubWidget::setAbsolutePos(const Point<int>& pos) noexcept
pData->absolutePos = pos;
onPositionChanged(ev);
- getTopLevelWidget().repaint();
+ // repaint the whole thing
+ pData->parent->repaint();
}
void SubWidget::onPositionChanged(const PositionChangedEvent&)
{
}
+
+// --------------------------------------------------------------------------------------------------------------------
+
+END_NAMESPACE_DGL
diff --git a/dgl/src/SubWidgetPrivateData.hpp b/dgl/src/SubWidgetPrivateData.hpp
@@ -18,31 +18,25 @@
#define DGL_SUBWIDGET_PRIVATE_DATA_HPP_INCLUDED
#include "../SubWidget.hpp"
-#include "../WidgetPrivateData.hpp"
-
-#include <vector>
START_NAMESPACE_DGL
-// -----------------------------------------------------------------------
+// --------------------------------------------------------------------------------------------------------------------
struct SubWidget::PrivateData {
SubWidget* const self;
- Widget* const groupWidget;
+ Widget* const parent;
Point<int> absolutePos;
- PrivateData(SubWidget* const s, Widget* const g)
+ PrivateData(SubWidget* const s, Widget* const p)
: self(s),
- groupWidget(g),
- absolutePos()
- {
- groupWidget->pData->subWidgets.push_back(self);
- }
+ parent(p),
+ absolutePos() {}
- DISTRHO_DECLARE_NON_COPY_STRUCT(PrivateData)
+ DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData)
};
-// -----------------------------------------------------------------------
+// --------------------------------------------------------------------------------------------------------------------
END_NAMESPACE_DGL
diff --git a/dgl/src/TopLevelWidget.cpp b/dgl/src/TopLevelWidget.cpp
@@ -15,14 +15,14 @@
*/
#include "TopLevelWidgetPrivateData.hpp"
-#include "pugl.hpp"
+// #include "pugl.hpp"
START_NAMESPACE_DGL
// -----------------------------------------------------------------------
TopLevelWidget::TopLevelWidget(Window& windowToMapTo)
- : Widget(*this),
+ : Widget(this),
pData(new PrivateData(this, windowToMapTo)) {}
TopLevelWidget::~TopLevelWidget()
@@ -30,16 +30,14 @@ TopLevelWidget::~TopLevelWidget()
delete pData;
}
-void TopLevelWidget::onDisplayBefore()
-{
-}
-
-void TopLevelWidget::onDisplayAfter()
+void TopLevelWidget::onDisplay()
{
+ pData->display();
}
void TopLevelWidget::onResize(const ResizeEvent& ev)
{
+ pData->resize(ev.size.getWidth(), ev.size.getHeight());
Widget::onResize(ev);
}
diff --git a/dgl/src/TopLevelWidgetPrivateData.cpp b/dgl/src/TopLevelWidgetPrivateData.cpp
@@ -15,16 +15,17 @@
*/
#include "TopLevelWidgetPrivateData.hpp"
-#include "../Window.hpp"
-// #include "pugl.hpp"
+#include "WidgetPrivateData.hpp"
+#include "WindowPrivateData.hpp"
+#include "pugl.hpp"
START_NAMESPACE_DGL
#define FOR_EACH_WIDGET(it) \
- for (std::list<Widget*>::iterator it = fWidgets.begin(); it != fWidgets.end(); ++it)
+ for (std::list<Widget*>::iterator it = widgets.begin(); it != widgets.end(); ++it)
#define FOR_EACH_WIDGET_INV(rit) \
- for (std::list<Widget*>::reverse_iterator rit = fWidgets.rbegin(); rit != fWidgets.rend(); ++rit)
+ for (std::list<Widget*>::reverse_iterator rit = widgets.rbegin(); rit != widgets.rend(); ++rit)
// -----------------------------------------------------------------------
@@ -35,17 +36,20 @@ TopLevelWidget::PrivateData::PrivateData(TopLevelWidget* const s, Window& w)
void TopLevelWidget::PrivateData::display()
{
+ puglFallbackOnDisplay(window.pData->view);
+
if (widgets.size() == 0)
return;
const Size<uint> size(window.getSize());
-// const int width = rect.width;
-// const int height = rect.height;
+ const uint width = size.getWidth();
+ const uint height = size.getHeight();
+ const double scaling = window.pData->autoScaling;
FOR_EACH_WIDGET(it)
{
Widget* const widget(*it);
- widget->pData->display(width, height, fAutoScaling, false);
+ widget->pData->display(width, height, scaling, false);
}
}
@@ -53,14 +57,14 @@ void TopLevelWidget::PrivateData::resize(const uint width, const uint height)
{
if (widgets.size() == 0)
return;
-
+/*
FOR_EACH_WIDGET(it)
{
Widget* const widget(*it);
if (widget->pData->needsFullViewport)
widget->setSize(width, height);
- }
+ }*/
}
// -----------------------------------------------------------------------
diff --git a/dgl/src/Widget.cpp b/dgl/src/Widget.cpp
@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
- * Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com>
+ * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
*
* 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
@@ -21,8 +21,11 @@ START_NAMESPACE_DGL
// -----------------------------------------------------------------------
// Widget
-Widget::Widget(TopLevelWidget& tlw)
- : pData(new PrivateData(this, tlw)) {}
+Widget::Widget(Widget* const widgetToGroupTo)
+ : pData(new PrivateData(this, widgetToGroupTo)) {}
+
+Widget::Widget(TopLevelWidget* const topLevelWidget)
+ : pData(new PrivateData(this, topLevelWidget)) {}
Widget::~Widget()
{
@@ -40,7 +43,7 @@ void Widget::setVisible(bool yesNo)
return;
pData->visible = yesNo;
- pData->topLevelWidget.repaint();
+ repaint();
}
void Widget::show()
@@ -63,7 +66,7 @@ uint Widget::getHeight() const noexcept
return pData->size.getHeight();
}
-const Size<uint>& Widget::getSize() const noexcept
+const Size<uint> Widget::getSize() const noexcept
{
return pData->size;
}
@@ -80,7 +83,7 @@ void Widget::setWidth(uint width) noexcept
pData->size.setWidth(width);
onResize(ev);
- pData->topLevelWidget.repaint();
+ pData->repaint();
}
void Widget::setHeight(uint height) noexcept
@@ -95,7 +98,7 @@ void Widget::setHeight(uint height) noexcept
pData->size.setHeight(height);
onResize(ev);
- pData->topLevelWidget.repaint();
+ pData->repaint();
}
void Widget::setSize(uint width, uint height) noexcept
@@ -115,17 +118,15 @@ void Widget::setSize(const Size<uint>& size) noexcept
pData->size = size;
onResize(ev);
- pData->topLevelWidget.repaint();
+ pData->repaint();
}
-#if 0
-Application& Widget::getParentApp() const noexcept
+Application& Widget::getApp() const noexcept
{
- return pData->parent.getApp();
+ return pData->topLevelWidget->getApp();
}
-#endif
-TopLevelWidget& Widget::getTopLevelWidget() const noexcept
+TopLevelWidget* Widget::getTopLevelWidget() const noexcept
{
return pData->topLevelWidget;
}
diff --git a/dgl/src/WidgetPrivateData.cpp b/dgl/src/WidgetPrivateData.cpp
@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
- * Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com>
+ * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
*
* 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
@@ -15,6 +15,7 @@
*/
#include "WidgetPrivateData.hpp"
+#include "../TopLevelWidget.hpp"
#ifdef DGL_CAIRO
# include "../Cairo.hpp"
@@ -27,79 +28,67 @@ START_NAMESPACE_DGL
// -----------------------------------------------------------------------
-void Widget::PrivateData::display(const uint width,
- const uint height,
- const double scaling,
- const bool renderingSubWidget)
+Widget::PrivateData::PrivateData(Widget* const s, TopLevelWidget* const tlw)
+ : self(s),
+ topLevelWidget(tlw),
+ groupWidget(nullptr),
+ id(0),
+ needsScaling(false),
+ visible(true),
+ size(0, 0),
+ subWidgets()
{
- if ((skipDisplay && ! renderingSubWidget) || size.isInvalid() || ! visible)
- return;
+}
-#ifdef DGL_OPENGL
- bool needsDisableScissor = false;
+Widget::PrivateData::PrivateData(Widget* const s, Widget* const g)
+ : self(s),
+ topLevelWidget(findTopLevelWidget(g)),
+ groupWidget(g),
+ id(0),
+ needsScaling(false),
+ visible(true),
+ size(0, 0),
+ subWidgets()
+{
+ groupWidget->pData->subWidgets.push_back(self);
+}
- // reset color
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+Widget::PrivateData::~PrivateData()
+{
+ if (groupWidget != nullptr)
+ groupWidget->pData->subWidgets.remove(self);
- if (needsFullViewport || (absolutePos.isZero() && size == Size<uint>(width, height)))
- {
- // full viewport size
- glViewport(0,
- -(height * scaling - height),
- width * scaling,
- height * scaling);
- }
- else if (needsScaling)
- {
- // limit viewport to widget bounds
- glViewport(absolutePos.getX(),
- height - self->getHeight() - absolutePos.getY(),
- self->getWidth(),
- self->getHeight());
- }
- else
- {
- // only set viewport pos
- glViewport(absolutePos.getX() * scaling,
- -std::round((height * scaling - height) + (absolutePos.getY() * scaling)),
- std::round(width * scaling),
- std::round(height * scaling));
+ subWidgets.clear();
+}
- // then cut the outer bounds
- glScissor(absolutePos.getX() * scaling,
- height - std::round((self->getHeight() + absolutePos.getY()) * scaling),
- std::round(self->getWidth() * scaling),
- std::round(self->getHeight() * scaling));
+void Widget::PrivateData::displaySubWidgets(const uint width, const uint height, const double scaling)
+{
+ for (std::list<Widget*>::iterator it = subWidgets.begin(); it != subWidgets.end(); ++it)
+ {
+ Widget* const widget(*it);
+ DISTRHO_SAFE_ASSERT_CONTINUE(widget->pData != this);
- glEnable(GL_SCISSOR_TEST);
- needsDisableScissor = true;
+ widget->pData->display(width, height, scaling, true);
}
-#endif
-
-#ifdef DGL_CAIRO
- cairo_t* cr = static_cast<const CairoGraphicsContext&>(parent.getGraphicsContext()).cairo;
- cairo_matrix_t matrix;
- cairo_get_matrix(cr, &matrix);
- cairo_translate(cr, absolutePos.getX(), absolutePos.getY());
- // TODO: scaling and cropping
-#endif
-
- // display widget
- self->onDisplay();
+}
-#ifdef DGL_CAIRO
- cairo_set_matrix(cr, &matrix);
-#endif
+void Widget::PrivateData::repaint()
+{
+ if (groupWidget != nullptr)
+ groupWidget->repaint();
+ else if (topLevelWidget != nullptr)
+ topLevelWidget->repaint();
+}
-#ifdef DGL_OPENGL
- if (needsDisableScissor)
- {
- glDisable(GL_SCISSOR_TEST);
- needsDisableScissor = false;
- }
-#endif
+// -----------------------------------------------------------------------
- displaySubWidgets(width, height, scaling);
+TopLevelWidget* Widget::PrivateData::findTopLevelWidget(Widget* const w)
+{
+ if (w->pData->topLevelWidget != nullptr)
+ return w->pData->topLevelWidget;
+ if (w->pData->groupWidget != nullptr)
+ return findTopLevelWidget(w->pData->groupWidget);
+ return nullptr;
}
// -----------------------------------------------------------------------
diff --git a/dgl/src/WidgetPrivateData.hpp b/dgl/src/WidgetPrivateData.hpp
@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
- * Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com>
+ * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
*
* 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
@@ -17,61 +17,41 @@
#ifndef DGL_WIDGET_PRIVATE_DATA_HPP_INCLUDED
#define DGL_WIDGET_PRIVATE_DATA_HPP_INCLUDED
-#include "../TopLevelWidget.hpp"
-#include "../Window.hpp"
+#include "../Widget.hpp"
-#include <vector>
+#include <list>
START_NAMESPACE_DGL
-// -----------------------------------------------------------------------
+// --------------------------------------------------------------------------------------------------------------------
struct Widget::PrivateData {
Widget* const self;
- Size<uint> size;
- std::vector<Widget*> subWidgets;
- TopLevelWidget& topLevelWidget;
-
+ TopLevelWidget* const topLevelWidget;
+ Widget* const groupWidget;
uint id;
bool needsScaling;
bool visible;
+ Size<uint> size;
+ std::list<Widget*> subWidgets;
- PrivateData(Widget* const s, TopLevelWidget& tlw)
- : self(s),
- size(0, 0),
- subWidgets(),
- topLevelWidget(tlw),
- id(0),
- needsScaling(false),
- visible(true)
- {
-// parent._addWidget(self);
- }
-
- ~PrivateData()
- {
-// parent._removeWidget(self);
- subWidgets.clear();
- }
+ PrivateData(Widget* const s, TopLevelWidget* const tlw);
+ PrivateData(Widget* const s, Widget* const g);
+ ~PrivateData();
- // display function is different depending on build type
+ // NOTE display function is different depending on build type
void display(const uint width, const uint height, const double scaling, const bool renderingSubWidget);
- void displaySubWidgets(const uint width, const uint height, const double scaling)
- {
- for (std::vector<Widget*>::iterator it = subWidgets.begin(); it != subWidgets.end(); ++it)
- {
- Widget* const widget(*it);
- DISTRHO_SAFE_ASSERT_CONTINUE(widget->pData != this);
+ void displaySubWidgets(const uint width, const uint height, const double scaling);
+
+ void repaint();
- widget->pData->display(width, height, scaling, true);
- }
- }
+ static TopLevelWidget* findTopLevelWidget(Widget* const w);
- DISTRHO_DECLARE_NON_COPY_STRUCT(PrivateData)
+ DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData)
};
-// -----------------------------------------------------------------------
+// --------------------------------------------------------------------------------------------------------------------
END_NAMESPACE_DGL
diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp
@@ -27,7 +27,7 @@ START_NAMESPACE_DGL
// : pData(new PrivateData(transientParentWindow.pData->fAppData, this, transientParentWindow)) {}
Window::Window(Application& app)
- : pData(new PrivateData(app.pData, this)) {}
+ : pData(new PrivateData(app, this)) {}
Window::Window(Application& app,
const uintptr_t parentWindowHandle,
@@ -35,7 +35,7 @@ Window::Window(Application& app,
const uint height,
const double scaling,
const bool resizable)
- : pData(new PrivateData(app.pData, this, parentWindowHandle, width, height, scaling, resizable)) {}
+ : pData(new PrivateData(app, this, parentWindowHandle, width, height, scaling, resizable)) {}
Window::~Window()
{
@@ -123,11 +123,21 @@ void Window::setTitle(const char* const title)
puglSetWindowTitle(pData->view, title);
}
+Application& Window::getApp() const noexcept
+{
+ return pData->app;
+}
+
uintptr_t Window::getNativeWindowHandle() const noexcept
{
return puglGetNativeWindow(pData->view);
}
+void Window::onReshape(const uint width, const uint height)
+{
+ puglFallbackOnResize(pData->view);
+}
+
#if 0
#if 0
void Window::exec(bool lockWait)
diff --git a/dgl/src/WindowPrivateData.cpp b/dgl/src/WindowPrivateData.cpp
@@ -40,8 +40,9 @@ START_NAMESPACE_DGL
// -----------------------------------------------------------------------
-Window::PrivateData::PrivateData(Application::PrivateData* const a, Window* const s)
- : appData(a),
+Window::PrivateData::PrivateData(Application& a, Window* const s)
+ : app(a),
+ appData(a.pData),
self(s),
view(puglNewView(appData->world)),
topLevelWidget(nullptr),
@@ -52,31 +53,37 @@ Window::PrivateData::PrivateData(Application::PrivateData* const a, Window* cons
init(DEFAULT_WIDTH, DEFAULT_HEIGHT, false);
}
-Window::PrivateData::PrivateData(Application::PrivateData* const a, Window* const s, Window& transientWindow)
- : appData(a),
+Window::PrivateData::PrivateData(Application& a, Window* const s, Window& transientWindow)
+ : app(a),
+ appData(a.pData),
self(s),
view(puglNewView(appData->world)),
topLevelWidget(nullptr),
isClosed(true),
isVisible(false),
- isEmbed(false)
+ isEmbed(false),
+ scaling(1.0),
+ autoScaling(1.0)
{
init(DEFAULT_WIDTH, DEFAULT_HEIGHT, false);
puglSetTransientFor(view, transientWindow.getNativeWindowHandle());
}
-Window::PrivateData::PrivateData(Application::PrivateData* const a, Window* const s,
+Window::PrivateData::PrivateData(Application& a, Window* const s,
const uintptr_t parentWindowHandle,
const uint width, const uint height,
- const double scaling, const bool resizable)
- : appData(a),
+ const double scale, const bool resizable)
+ : app(a),
+ appData(a.pData),
self(s),
view(puglNewView(appData->world)),
topLevelWidget(nullptr),
isClosed(parentWindowHandle == 0),
isVisible(parentWindowHandle != 0),
- isEmbed(parentWindowHandle != 0)
+ isEmbed(parentWindowHandle != 0),
+ scaling(scale),
+ autoScaling(1.0)
{
init(width, height, resizable);
@@ -257,9 +264,7 @@ void Window::PrivateData::onPuglDisplay()
#ifndef DPF_TEST_WINDOW_CPP
if (topLevelWidget != nullptr)
{
- topLevelWidget->onDisplayBefore();
topLevelWidget->onDisplay();
- topLevelWidget->onDisplayAfter();
}
else
#endif
@@ -274,12 +279,12 @@ void Window::PrivateData::onPuglReshape(const int width, const int height)
DGL_DBGp("PUGL: onReshape : %i %i\n", width, height);
+ self->onReshape(width, height);
+
#ifndef DPF_TEST_WINDOW_CPP
if (topLevelWidget != nullptr)
topLevelWidget->setSize(width, height);
- else
#endif
- puglFallbackOnResize(view);
}
static int printEvent(const PuglEvent* event, const char* prefix, const bool verbose);
diff --git a/dgl/src/WindowPrivateData.hpp b/dgl/src/WindowPrivateData.hpp
@@ -29,13 +29,13 @@ class TopLevelWidget;
// -----------------------------------------------------------------------
struct Window::PrivateData : IdleCallback {
- /** Handy typedef for ... */
- typedef Application::PrivateData AppData;
+ /* Reference to the DGL Application class this (private data) window associates with. */
+ Application& app;
- /** Direct access to DGL Application private data where we registers ourselves in. */
- AppData* const appData;
+ /** Direct access to the DGL Application private data where we registers ourselves in. */
+ Application::PrivateData* const appData;
- /** Pointer to the DGL Window class that this private data belongs to. */
+ /** Pointer to the the DGL Window class that this private data belongs to. */
Window* const self;
/** Pugl view instance. */
@@ -57,14 +57,20 @@ struct Window::PrivateData : IdleCallback {
/** Whether this Window is embed into another (usually not DGL-controlled) Window. */
const bool isEmbed;
+ /** Scaling to report to widgets on request, purely informational. */
+ double scaling;
+
+ /** Automatic scaling to apply on widgets, implemented internally. */
+ double autoScaling;
+
/** Constructor for a regular, standalone window. */
- PrivateData(AppData* appData, Window* self);
+ PrivateData(Application& app, Window* self);
/** Constructor for a regular, standalone window with a transient parent. */
- PrivateData(AppData* appData, Window* self, Window& transientWindow);
+ PrivateData(Application& app, Window* self, Window& transientWindow);
/** Constructor for an embed Window, with a few extra hints from the host side. */
- PrivateData(AppData* appData, Window* self, uintptr_t parentWindowHandle,
+ PrivateData(Application& app, Window* self, uintptr_t parentWindowHandle,
uint width, uint height, double scaling, bool resizable);
/** Destructor. */
diff --git a/tests/Demo.cpp b/tests/Demo.cpp
@@ -0,0 +1,198 @@
+/*
+ * DISTRHO Plugin Framework (DPF)
+ * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
+ *
+ * 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.
+ */
+
+#ifndef DGL_OPENGL
+#error OpenGL build required for Demo
+#endif
+
+#include "tests.hpp"
+
+// #define DPF_TEST_POINT_CPP
+#include "dgl/src/pugl.cpp"
+// #include "dgl/src/SubWidget.cpp"
+#include "dgl/src/Application.cpp"
+#include "dgl/src/ApplicationPrivateData.cpp"
+#include "dgl/src/Geometry.cpp"
+#include "dgl/src/OpenGL.cpp"
+#include "dgl/src/SubWidget.cpp"
+#include "dgl/src/TopLevelWidget.cpp"
+#include "dgl/src/TopLevelWidgetPrivateData.cpp"
+#include "dgl/src/Widget.cpp"
+#include "dgl/src/WidgetPrivateData.cpp"
+#include "dgl/src/Window.cpp"
+#include "dgl/src/WindowPrivateData.cpp"
+#include "dgl/StandaloneWindow.hpp"
+
+#include "widgets/ExampleColorWidget.hpp"
+
+START_NAMESPACE_DGL
+
+// --------------------------------------------------------------------------------------------------------------------
+
+// ------------------------------------------------------
+// Left side tab-like widget
+
+class LeftSideWidget : public SubWidget
+{
+public:
+ static const int kPageCount = 5;
+
+ class Callback
+ {
+ public:
+ virtual ~Callback() {}
+ virtual void curPageChanged(int curPage) = 0;
+ };
+
+ LeftSideWidget(Widget* parent, Callback* const cb)
+ : SubWidget(parent),
+ callback(cb),
+ curPage(0),
+ curHover(-1)
+ {
+ // for text
+// font = nvg.createFontFromFile("sans", "./nanovg_res/Roboto-Regular.ttf");
+
+// using namespace DemoArtwork;
+// img1.loadFromMemory(ico1Data, ico1Width, ico1Height, GL_BGR);
+// img2.loadFromMemory(ico2Data, ico2Width, ico2Height, GL_BGR);
+// img3.loadFromMemory(ico3Data, ico3Width, ico2Height, GL_BGR);
+// img4.loadFromMemory(ico4Data, ico4Width, ico4Height, GL_BGR);
+// img5.loadFromMemory(ico5Data, ico5Width, ico5Height, GL_BGR);
+ }
+
+private:
+ Callback* const callback;
+ int curPage, curHover;
+// Rectangle<int> bgIcon;
+// Line<int> lineSep;
+// Image img1, img2, img3, img4, img5;
+
+ // for text
+// NanoVG nvg;
+// NanoVG::FontId font;
+};
+
+// ------------------------------------------------------
+// Our Demo Window
+
+class DemoWindow : public StandaloneWindow,
+ public LeftSideWidget::Callback
+{
+ static const int kSidebarWidth = 81;
+
+ ExampleColorWidget wColor;
+ Widget* curWidget;
+
+public:
+ DemoWindow(Application& app)
+ : StandaloneWindow(app),
+ wColor(this),
+ curWidget(nullptr)
+ {
+ wColor.hide();
+// wImages.hide();
+// wRects.hide();
+// wShapes.hide();
+// wText.hide();
+// //wPerf.hide();
+
+ wColor.setAbsoluteX(kSidebarWidth);
+// wImages.setAbsoluteX(kSidebarWidth);
+// wRects.setAbsoluteX(kSidebarWidth);
+// wShapes.setAbsoluteX(kSidebarWidth);
+// wText.setAbsoluteX(kSidebarWidth);
+// wLeft.setAbsolutePos(2, 2);
+// wPerf.setAbsoluteY(5);
+
+ setSize(600, 500);
+ setTitle("DGL Demo");
+
+ curPageChanged(0);
+ }
+
+protected:
+ void curPageChanged(int curPage) override
+ {
+ if (curWidget != nullptr)
+ {
+ curWidget->hide();
+ curWidget = nullptr;
+ }
+
+ switch (curPage)
+ {
+ case 0:
+ curWidget = &wColor;
+ break;
+// case 1:
+// curWidget = &wImages;
+// break;
+// case 2:
+// curWidget = &wRects;
+// break;
+// case 3:
+// curWidget = &wShapes;
+// break;
+// case 4:
+// curWidget = &wText;
+// break;
+ }
+
+ if (curWidget != nullptr)
+ curWidget->show();
+ }
+
+ void onReshape(uint width, uint height) override
+ {
+ StandaloneWindow::onReshape(width, height);
+
+ if (width < kSidebarWidth)
+ return;
+
+ Size<uint> size(width-kSidebarWidth, height);
+ wColor.setSize(size);
+// wImages.setSize(size);
+// wRects.setSize(size);
+// wShapes.setSize(size);
+// wText.setSize(size);
+
+// wLeft.setSize(kSidebarWidth-4, height-4);
+// //wRezHandle.setAbsoluteX(width-wRezHandle.getWidth());
+// //wRezHandle.setAbsoluteY(height-wRezHandle.getHeight());
+//
+// wPerf.setAbsoluteX(width-wPerf.getWidth()-5);
+ }
+};
+
+// --------------------------------------------------------------------------------------------------------------------
+
+END_NAMESPACE_DGL
+
+int main()
+{
+ USE_NAMESPACE_DGL;
+
+ Application app;
+ DemoWindow win(app);
+
+ win.show();
+ app.exec();
+
+ return 0;
+}
+
+// --------------------------------------------------------------------------------------------------------------------
diff --git a/tests/Makefile b/tests/Makefile
@@ -25,6 +25,7 @@ ifeq ($(HAVE_CAIRO),true)
WTESTS = Window.cairo
endif
ifeq ($(HAVE_OPENGL),true)
+TESTS += Demo
WTESTS = Window.opengl
endif
ifeq ($(HAVE_VULKAN),true)
@@ -87,12 +88,17 @@ clean:
@echo "Compiling $< (Cairo)"
$(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(CAIRO_FLAGS) -DDGL_CAIRO -c -o $@
+../build/tests/Demo.cpp.o: Demo.cpp
+ -@mkdir -p ../build/tests
+ @echo "Compiling $< (OpenGL)"
+ $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(OPENGL_FLAGS) -DDGL_OPENGL -c -o $@
+
../build/tests/%.cpp.opengl.o: %.cpp
-@mkdir -p ../build/tests
@echo "Compiling $< (OpenGL)"
$(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(OPENGL_FLAGS) -DDGL_OPENGL -c -o $@
-../build/tests/%.cpp.vulkan.o: Window.cpp
+../build/tests/%.cpp.vulkan.o: %.cpp
-@mkdir -p ../build/tests
@echo "Compiling $< (Vulkan)"
$(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(OPENGL_FLAGS) -DDGL_VULKAN -c -o $@
@@ -108,6 +114,10 @@ clean:
@echo "Linking $*"
$(SILENT)$(CXX) $< $(LINK_FLAGS) $(DGL_SYSTEM_LIBS) $(CAIRO_LIBS) -o $@
+../build/tests/Demo: ../build/tests/Demo.cpp.o
+ @echo "Linking Demo"
+ $(SILENT)$(CXX) $< $(LINK_FLAGS) $(DGL_SYSTEM_LIBS) $(OPENGL_LIBS) -o $@
+
../build/tests/%.opengl: ../build/tests/%.cpp.opengl.o
@echo "Linking $*"
$(SILENT)$(CXX) $< $(LINK_FLAGS) $(DGL_SYSTEM_LIBS) $(OPENGL_LIBS) -o $@
diff --git a/tests/widgets/ExampleColorWidget.hpp b/tests/widgets/ExampleColorWidget.hpp
@@ -0,0 +1,134 @@
+/*
+ * DISTRHO Plugin Framework (DPF)
+ * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com>
+ *
+ * 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.
+ */
+
+#ifndef EXAMPLE_COLOR_WIDGET_HPP_INCLUDED
+#define EXAMPLE_COLOR_WIDGET_HPP_INCLUDED
+
+// ------------------------------------------------------
+// DGL Stuff
+
+#include "../../dgl/SubWidget.hpp"
+// #include "Window.hpp"
+
+START_NAMESPACE_DGL
+
+// ------------------------------------------------------
+// our widget
+
+class ExampleColorWidget : public SubWidget,
+ public IdleCallback
+{
+public:
+ ExampleColorWidget(TopLevelWidget* const topWidget)
+ : SubWidget(topWidget),
+ cur('r'),
+ reverse(false),
+ r(0), g(0), b(0)
+ {
+ setSize(300, 300);
+
+// groupWidget->getApp().addIdleCallback(this);
+ }
+
+protected:
+ void idleCallback() noexcept override
+ {
+ switch (cur)
+ {
+ case 'r':
+ if (reverse)
+ {
+ if (--r == 0)
+ cur = 'g';
+ }
+ else
+ {
+ if (++r == 100)
+ cur = 'g';
+ }
+ break;
+
+ case 'g':
+ if (reverse)
+ {
+ if (--g == 0)
+ cur = 'b';
+ }
+ else
+ {
+ if (++g == 100)
+ cur = 'b';
+ }
+ break;
+
+ case 'b':
+ if (reverse)
+ {
+ if (--b == 0)
+ {
+ cur = 'r';
+ reverse = false;
+ }
+ }
+ else
+ {
+ if (++b == 100)
+ {
+ cur = 'r';
+ reverse = true;
+ }
+ }
+ break;
+ }
+
+ repaint();
+ }
+
+ void onDisplay() override
+ {
+ // paint bg color (in full size)
+ glColor3b(r, g, b);
+ bgFull.draw();
+
+ // paint inverted color (in 2/3 size)
+ glColor3b(100-r, 100-g, 100-b);
+ bgSmall.draw();
+ }
+
+ void onResize(const ResizeEvent& ev) override
+ {
+ const uint width = ev.size.getWidth();
+ const uint height = ev.size.getHeight();
+
+ // full bg
+ bgFull = Rectangle<uint>(0, 0, width, height);
+
+ // small bg, centered 2/3 size
+ bgSmall = Rectangle<uint>(width/6, height/6, width*2/3, height*2/3);
+ }
+
+ char cur;
+ bool reverse;
+ int r, g, b;
+
+ Rectangle<uint> bgFull, bgSmall;
+};
+
+// ------------------------------------------------------
+
+END_NAMESPACE_DGL
+
+#endif // EXAMPLE_COLOR_WIDGET_HPP_INCLUDED