Browse Source

Start adding back widget stuff, almost at drawing step

Signed-off-by: falkTX <falktx@falktx.com>
pull/272/head
falkTX 4 years ago
parent
commit
c6e9bec693
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
22 changed files with 747 additions and 328 deletions
  1. +1
    -1
      dgl/Application.hpp
  2. +46
    -3
      dgl/Cairo.hpp
  3. +37
    -17
      dgl/StandaloneWindow.hpp
  4. +3
    -11
      dgl/TopLevelWidget.hpp
  5. +47
    -26
      dgl/Widget.hpp
  6. +14
    -5
      dgl/Window.hpp
  7. +24
    -45
      dgl/src/Cairo.cpp
  8. +61
    -45
      dgl/src/OpenGL.cpp
  9. +4
    -5
      dgl/src/StandaloneWindow.cpp
  10. +13
    -2
      dgl/src/SubWidget.cpp
  11. +7
    -13
      dgl/src/SubWidgetPrivateData.hpp
  12. +5
    -7
      dgl/src/TopLevelWidget.cpp
  13. +13
    -9
      dgl/src/TopLevelWidgetPrivateData.cpp
  14. +14
    -13
      dgl/src/Widget.cpp
  15. +53
    -64
      dgl/src/WidgetPrivateData.cpp
  16. +18
    -38
      dgl/src/WidgetPrivateData.hpp
  17. +12
    -2
      dgl/src/Window.cpp
  18. +18
    -13
      dgl/src/WindowPrivateData.cpp
  19. +14
    -8
      dgl/src/WindowPrivateData.hpp
  20. +198
    -0
      tests/Demo.cpp
  21. +11
    -1
      tests/Makefile
  22. +134
    -0
      tests/widgets/ExampleColorWidget.hpp

+ 1
- 1
dgl/Application.hpp View File

@@ -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.


+ 46
- 3
dgl/Cairo.hpp View File

@@ -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



+ 37
- 17
dgl/StandaloneWindow.hpp View File

@@ -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)
};


+ 3
- 11
dgl/TopLevelWidget.hpp View File

@@ -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.


+ 47
- 26
dgl/Widget.hpp View File

@@ -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.
@@ -131,17 +136,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;


+ 14
- 5
dgl/Window.hpp View File

@@ -22,6 +22,7 @@
START_NAMESPACE_DGL

class Application;
class TopLevelWidget;

// -----------------------------------------------------------------------

@@ -151,6 +152,11 @@ public:
const char* getTitle() const noexcept;
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:
@@ -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);


+ 24
- 45
dgl/src/Cairo.cpp View File

@@ -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);
}

// -----------------------------------------------------------------------



+ 61
- 45
dgl/src/OpenGL.cpp View File

@@ -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);
}

// -----------------------------------------------------------------------



+ 4
- 5
dgl/src/StandaloneWindow.cpp View File

@@ -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()
{


+ 13
- 2
dgl/src/SubWidget.cpp View File

@@ -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

+ 7
- 13
dgl/src/SubWidgetPrivateData.hpp View File

@@ -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



+ 5
- 7
dgl/src/TopLevelWidget.cpp View File

@@ -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);
}



+ 13
- 9
dgl/src/TopLevelWidgetPrivateData.cpp View File

@@ -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);
}
}*/
}

// -----------------------------------------------------------------------


+ 14
- 13
dgl/src/Widget.cpp View File

@@ -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;
}


+ 53
- 64
dgl/src/WidgetPrivateData.cpp View File

@@ -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;
}

// -----------------------------------------------------------------------


+ 18
- 38
dgl/src/WidgetPrivateData.hpp View File

@@ -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



+ 12
- 2
dgl/src/Window.cpp View File

@@ -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)


+ 18
- 13
dgl/src/WindowPrivateData.cpp View File

@@ -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);


+ 14
- 8
dgl/src/WindowPrivateData.hpp View File

@@ -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. */


+ 198
- 0
tests/Demo.cpp View File

@@ -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;
}

// --------------------------------------------------------------------------------------------------------------------

+ 11
- 1
tests/Makefile View File

@@ -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 $@


+ 134
- 0
tests/widgets/ExampleColorWidget.hpp View File

@@ -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

Loading…
Cancel
Save