Signed-off-by: falkTX <falktx@falktx.com>pull/272/head
@@ -6,8 +6,7 @@ | |||
include Makefile.base.mk | |||
all: dgl | |||
# examples gen | |||
all: dgl examples gen | |||
# -------------------------------------------------------------- | |||
@@ -19,6 +19,12 @@ | |||
#include "Widget.hpp" | |||
#ifdef DISTRHO_DEFINES_H_INCLUDED | |||
START_NAMESPACE_DISTRHO | |||
class UI; | |||
END_NAMESPACE_DISTRHO | |||
#endif | |||
START_NAMESPACE_DGL | |||
class Window; | |||
@@ -55,13 +61,25 @@ public: | |||
*/ | |||
Application& getApp() const noexcept; | |||
/** | |||
Get the window associated with this top-level widget. | |||
*/ | |||
Window& getWindow() const noexcept; | |||
void repaint() noexcept; | |||
void repaint(const Rectangle<uint>& rect) noexcept; | |||
// TODO deprecated | |||
Application& getParentApp() const noexcept { return getApp(); } | |||
Window& getParentWindow() const noexcept { return getWindow(); } | |||
private: | |||
struct PrivateData; | |||
PrivateData* const pData; | |||
friend class Window; | |||
#ifdef DISTRHO_DEFINES_H_INCLUDED | |||
friend class DISTRHO_NAMESPACE::UI; | |||
#endif | |||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(TopLevelWidget) | |||
}; | |||
@@ -32,7 +32,7 @@ START_NAMESPACE_DGL | |||
class Application; | |||
// class NanoWidget; | |||
// class Window; | |||
class Window; | |||
// class StandaloneWindow; | |||
class SubWidget; | |||
class TopLevelWidget; | |||
@@ -154,6 +154,12 @@ public: | |||
*/ | |||
Application& getApp() const noexcept; | |||
/** | |||
Get the window associated with this widget. | |||
This is the same as calling `getTopLevelWidget()->getWindow()`. | |||
*/ | |||
Window& getWindow() 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, | |||
@@ -174,6 +180,10 @@ public: | |||
*/ | |||
virtual void repaint() noexcept; | |||
// TODO deprecated | |||
Application& getParentApp() const noexcept { return getApp(); } | |||
Window& getParentWindow() const noexcept { return getWindow(); } | |||
protected: | |||
/** | |||
A function called to draw the widget contents. | |||
@@ -56,7 +56,17 @@ public: | |||
explicit Window(Application& app); | |||
/** | |||
Constructor for an embed Window, typically used in modules or plugins that run inside another host. | |||
Constructor for an embed Window without known size, | |||
typically used in modules or plugins that run inside another host. | |||
*/ | |||
explicit Window(Application& app, | |||
uintptr_t parentWindowHandle, | |||
double scaling, | |||
bool resizable); | |||
/** | |||
Constructor for an embed Window with known size, | |||
typically used in modules or plugins that run inside another host. | |||
*/ | |||
explicit Window(Application& app, | |||
uintptr_t parentWindowHandle, | |||
@@ -15,7 +15,7 @@ | |||
*/ | |||
#include "../NanoVG.hpp" | |||
#include "WidgetPrivateData.hpp" | |||
#include "SubWidgetPrivateData.hpp" | |||
#ifndef DGL_NO_SHARED_RESOURCES | |||
# include "Resources.hpp" | |||
@@ -956,68 +956,60 @@ struct NanoWidget<BaseWidget>::PrivateData { | |||
} | |||
}; | |||
// ----------------------------------------------------------------------- | |||
// SubWidget | |||
template <class BaseWidget> | |||
NanoWidget<BaseWidget>::NanoWidget(Widget* const parent, int flags) | |||
: BaseWidget(parent), | |||
NanoVG(flags), | |||
nData(new PrivateData(this)) | |||
{ | |||
BaseWidget::pData->needsViewportScaling = true; | |||
} | |||
// TopLevelWidget | |||
template <class BaseWidget> | |||
NanoWidget<BaseWidget>::NanoWidget(Window& windowToMapTo, int flags) | |||
: BaseWidget(windowToMapTo), | |||
template <> | |||
NanoWidget<SubWidget>::NanoWidget(Widget* const parent, int flags) | |||
: SubWidget(parent), | |||
NanoVG(flags), | |||
nData(new PrivateData(this)) | |||
{ | |||
pData->needsViewportScaling = true; | |||
} | |||
// StandaloneWindow | |||
template <class BaseWidget> | |||
NanoWidget<BaseWidget>::NanoWidget(Application& app, int flags) | |||
: BaseWidget(app), | |||
NanoVG(flags), | |||
nData(new PrivateData(this)) | |||
template <> | |||
NanoWidget<SubWidget>::~NanoWidget() | |||
{ | |||
delete nData; | |||
} | |||
/* | |||
NanoWidget::NanoWidget(Window& parent, int flags) | |||
: Widget(parent), | |||
// ----------------------------------------------------------------------- | |||
// TopLevelWidget | |||
template <> | |||
NanoWidget<TopLevelWidget>::NanoWidget(Window& windowToMapTo, int flags) | |||
: TopLevelWidget(windowToMapTo), | |||
NanoVG(flags), | |||
nData(new PrivateData(this)) | |||
{ | |||
pData->needsScaling = true; | |||
} | |||
NanoWidget::NanoWidget(Widget* groupWidget, int flags) | |||
: Widget(groupWidget, true), | |||
NanoVG(flags), | |||
nData(new PrivateData(this)) | |||
template <> | |||
NanoWidget<TopLevelWidget>::~NanoWidget() | |||
{ | |||
pData->needsScaling = true; | |||
delete nData; | |||
} | |||
NanoWidget::NanoWidget(NanoWidget* groupWidget) | |||
: Widget(groupWidget, false), | |||
NanoVG(groupWidget), | |||
// ----------------------------------------------------------------------- | |||
// StandaloneWindow | |||
template <> | |||
NanoWidget<StandaloneWindow>::NanoWidget(Application& app, int flags) | |||
: StandaloneWindow(app), | |||
NanoVG(flags), | |||
nData(new PrivateData(this)) | |||
{ | |||
pData->needsScaling = true; | |||
pData->skipDisplay = true; | |||
groupWidget->nData->subWidgets.push_back(this); | |||
} | |||
*/ | |||
template <class BaseWidget> | |||
NanoWidget<BaseWidget>::~NanoWidget() | |||
template <> | |||
NanoWidget<StandaloneWindow>::~NanoWidget() | |||
{ | |||
delete nData; | |||
} | |||
// ----------------------------------------------------------------------- | |||
template <class BaseWidget> | |||
void NanoWidget<BaseWidget>::onDisplay() | |||
{ | |||
@@ -110,6 +110,37 @@ void Rectangle<T>::_draw(const bool outline) | |||
glEnd(); | |||
} | |||
// ----------------------------------------------------------------------- | |||
// Possible template data types | |||
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>; | |||
// ----------------------------------------------------------------------- | |||
OpenGLImage::OpenGLImage() | |||
@@ -35,6 +35,11 @@ Application& TopLevelWidget::getApp() const noexcept | |||
return pData->window.getApp(); | |||
} | |||
Window& TopLevelWidget::getWindow() const noexcept | |||
{ | |||
return pData->window; | |||
} | |||
void TopLevelWidget::repaint() noexcept | |||
{ | |||
pData->window.repaint(); | |||
@@ -57,6 +57,11 @@ void TopLevelWidget::PrivateData::mouseEvent(const Events::MouseEvent& ev) | |||
selfw->pData->giveMouseEventForSubWidgets(rev); | |||
} | |||
void TopLevelWidget::PrivateData::fallbackOnResize() | |||
{ | |||
puglFallbackOnResize(window.pData->view); | |||
} | |||
// ----------------------------------------------------------------------- | |||
END_NAMESPACE_DGL |
@@ -34,6 +34,7 @@ struct TopLevelWidget::PrivateData { | |||
~PrivateData(); | |||
void display(); | |||
void mouseEvent(const Events::MouseEvent& ev); | |||
void fallbackOnResize(); | |||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData) | |||
}; | |||
@@ -127,6 +127,11 @@ Application& Widget::getApp() const noexcept | |||
return pData->topLevelWidget->getApp(); | |||
} | |||
Window& Widget::getWindow() const noexcept | |||
{ | |||
return pData->topLevelWidget->getWindow(); | |||
} | |||
TopLevelWidget* Widget::getTopLevelWidget() const noexcept | |||
{ | |||
return pData->topLevelWidget; | |||
@@ -29,6 +29,12 @@ START_NAMESPACE_DGL | |||
Window::Window(Application& app) | |||
: pData(new PrivateData(app, this)) {} | |||
Window::Window(Application& app, | |||
const uintptr_t parentWindowHandle, | |||
const double scaling, | |||
const bool resizable) | |||
: pData(new PrivateData(app, this, parentWindowHandle, scaling, resizable)) {} | |||
Window::Window(Application& app, | |||
const uintptr_t parentWindowHandle, | |||
const uint width, | |||
@@ -74,6 +74,36 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, Window& transi | |||
puglSetTransientFor(view, transientWindow.getNativeWindowHandle()); | |||
} | |||
Window::PrivateData::PrivateData(Application& a, Window* const s, | |||
const uintptr_t parentWindowHandle, | |||
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), | |||
scaling(scale), | |||
autoScaling(1.0), | |||
pendingVisibility(kPendingVisibilityNone) | |||
{ | |||
if (isEmbed) | |||
{ | |||
// puglSetDefaultSize(DEFAULT_WIDTH, DEFAULT_HEIGHT, height); | |||
puglSetParentWindow(view, parentWindowHandle); | |||
} | |||
init(DEFAULT_WIDTH, DEFAULT_HEIGHT, resizable); | |||
if (isEmbed) | |||
{ | |||
appData->oneWindowShown(); | |||
puglShow(view); | |||
} | |||
} | |||
Window::PrivateData::PrivateData(Application& a, Window* const s, | |||
const uintptr_t parentWindowHandle, | |||
const uint width, const uint height, | |||
@@ -77,6 +77,9 @@ struct Window::PrivateData : IdleCallback { | |||
/** Constructor for a regular, standalone window with a transient parent. */ | |||
explicit PrivateData(Application& app, Window* self, Window& transientWindow); | |||
/** Constructor for an embed Window, with a few extra hints from the host side. */ | |||
explicit PrivateData(Application& app, Window* self, uintptr_t parentWindowHandle, double scaling, bool resizable); | |||
/** Constructor for an embed Window, with a few extra hints from the host side. */ | |||
explicit PrivateData(Application& app, Window* self, uintptr_t parentWindowHandle, | |||
uint width, uint height, double scaling, bool resizable); | |||
@@ -26,10 +26,10 @@ | |||
typedef DISTRHO_NAMESPACE::ExternalWindow UIWidget; | |||
#elif DISTRHO_UI_USE_NANOVG | |||
# include "../dgl/NanoVG.hpp" | |||
typedef DGL_NAMESPACE::NanoWidget UIWidget; | |||
typedef DGL_NAMESPACE::NanoTopLevelWidget UIWidget; | |||
#else | |||
# include "../dgl/Widget.hpp" | |||
typedef DGL_NAMESPACE::Widget UIWidget; | |||
# include "../dgl/TopLevelWidget.hpp" | |||
typedef DGL_NAMESPACE::TopLevelWidget UIWidget; | |||
#endif | |||
#ifdef DGL_CAIRO | |||
@@ -259,7 +259,7 @@ protected: | |||
private: | |||
struct PrivateData; | |||
PrivateData* const pData; | |||
PrivateData* const uiData; | |||
friend class UIExporter; | |||
friend class UIExporterWindow; | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* DISTRHO Plugin Framework (DPF) | |||
* Copyright (C) 2012-2020 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,9 +17,11 @@ | |||
#include "DistrhoUIPrivateData.hpp" | |||
#include "src/WindowPrivateData.hpp" | |||
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
# include "src/WidgetPrivateData.hpp" | |||
# include "src/TopLevelWidgetPrivateData.hpp" | |||
#endif | |||
#include "NanoVG.hpp" | |||
START_NAMESPACE_DISTRHO | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
@@ -69,14 +71,12 @@ UI* createUiWrapper(void* const dspPtr, Window* const window) | |||
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
UI::UI(uint width, uint height) | |||
: UIWidget(width, height), | |||
pData(new PrivateData()) {} | |||
uiData(new PrivateData()) {} | |||
#else | |||
UI::UI(uint width, uint height) | |||
: UIWidget(*d_lastUiWindow), | |||
pData(new PrivateData()) | |||
uiData(new PrivateData()) | |||
{ | |||
((UIWidget*)this)->pData->needsFullViewport = false; | |||
if (width > 0 && height > 0) | |||
setSize(width, height); | |||
} | |||
@@ -84,7 +84,7 @@ UI::UI(uint width, uint height) | |||
UI::~UI() | |||
{ | |||
delete pData; | |||
delete uiData; | |||
} | |||
#if DISTRHO_UI_USER_RESIZABLE && !DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
@@ -93,10 +93,11 @@ void UI::setGeometryConstraints(uint minWidth, uint minHeight, bool keepAspectRa | |||
DISTRHO_SAFE_ASSERT_RETURN(minWidth > 0,); | |||
DISTRHO_SAFE_ASSERT_RETURN(minHeight > 0,); | |||
pData->automaticallyScale = automaticallyScale; | |||
pData->minWidth = minWidth; | |||
pData->minHeight = minHeight; | |||
uiData->automaticallyScale = automaticallyScale; | |||
uiData->minWidth = minWidth; | |||
uiData->minHeight = minHeight; | |||
#if 0 /* TODO */ | |||
Window& window(getParentWindow()); | |||
const double uiScaleFactor = window.getScaling(); | |||
@@ -104,6 +105,7 @@ void UI::setGeometryConstraints(uint minWidth, uint minHeight, bool keepAspectRa | |||
if (d_isNotZero(uiScaleFactor - 1.0)) | |||
setSize(getWidth() * uiScaleFactor, getHeight() * uiScaleFactor); | |||
#endif | |||
} | |||
#endif | |||
@@ -112,47 +114,47 @@ void UI::setGeometryConstraints(uint minWidth, uint minHeight, bool keepAspectRa | |||
uint UI::getBackgroundColor() const noexcept | |||
{ | |||
return pData->bgColor; | |||
return uiData->bgColor; | |||
} | |||
uint UI::getForegroundColor() const noexcept | |||
{ | |||
return pData->fgColor; | |||
return uiData->fgColor; | |||
} | |||
double UI::getSampleRate() const noexcept | |||
{ | |||
return pData->sampleRate; | |||
return uiData->sampleRate; | |||
} | |||
void UI::editParameter(uint32_t index, bool started) | |||
{ | |||
pData->editParamCallback(index + pData->parameterOffset, started); | |||
uiData->editParamCallback(index + uiData->parameterOffset, started); | |||
} | |||
void UI::setParameterValue(uint32_t index, float value) | |||
{ | |||
pData->setParamCallback(index + pData->parameterOffset, value); | |||
uiData->setParamCallback(index + uiData->parameterOffset, value); | |||
} | |||
#if DISTRHO_PLUGIN_WANT_STATE | |||
void UI::setState(const char* key, const char* value) | |||
{ | |||
pData->setStateCallback(key, value); | |||
uiData->setStateCallback(key, value); | |||
} | |||
#endif | |||
#if DISTRHO_PLUGIN_WANT_STATEFILES | |||
bool UI::requestStateFile(const char* key) | |||
{ | |||
return pData->fileRequestCallback(key); | |||
return uiData->fileRequestCallback(key); | |||
} | |||
#endif | |||
#if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
void UI::sendNote(uint8_t channel, uint8_t note, uint8_t velocity) | |||
{ | |||
pData->sendNoteCallback(channel, note, velocity); | |||
uiData->sendNoteCallback(channel, note, velocity); | |||
} | |||
#endif | |||
@@ -162,7 +164,7 @@ void UI::sendNote(uint8_t channel, uint8_t note, uint8_t velocity) | |||
void* UI::getPluginInstancePointer() const noexcept | |||
{ | |||
return pData->dspPtr; | |||
return uiData->dspPtr; | |||
} | |||
#endif | |||
@@ -203,9 +205,9 @@ void UI::uiFileBrowserSelected(const char*) | |||
} | |||
# endif | |||
void UI::uiReshape(uint width, uint height) | |||
void UI::uiReshape(uint, uint) | |||
{ | |||
Window::PrivateData::Fallback::onReshape(width, height); | |||
pData->fallbackOnResize(); | |||
} | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
@@ -213,13 +215,20 @@ void UI::uiReshape(uint width, uint height) | |||
void UI::onResize(const ResizeEvent& ev) | |||
{ | |||
if (pData->resizeInProgress) | |||
if (uiData->resizeInProgress) | |||
return; | |||
pData->setSizeCallback(ev.size.getWidth(), ev.size.getHeight()); | |||
uiData->setSizeCallback(ev.size.getWidth(), ev.size.getHeight()); | |||
} | |||
#endif // !DISTRHO_PLUGIN_HAS_EXTERNAL_UI | |||
// ----------------------------------------------------------------------------------------------------------- | |||
END_NAMESPACE_DISTRHO | |||
// ----------------------------------------------------------------------- | |||
// Possible template data types | |||
template class NanoWidget<SubWidget>; | |||
template class NanoWidget<TopLevelWidget>; | |||
template class NanoWidget<StandaloneWindow>; |
@@ -66,7 +66,7 @@ public: | |||
fIsReady(false) | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||
DISTRHO_SAFE_ASSERT_RETURN(fUI->pData != nullptr,); | |||
DISTRHO_SAFE_ASSERT_RETURN(fUI->uiData != nullptr,); | |||
setSize(fUI->getWidth(), fUI->getHeight()); | |||
} | |||
@@ -92,24 +92,27 @@ protected: | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||
UI::PrivateData* const pData = fUI->pData; | |||
DISTRHO_SAFE_ASSERT_RETURN(pData != nullptr,); | |||
UI::PrivateData* const uiData = fUI->uiData; | |||
DISTRHO_SAFE_ASSERT_RETURN(uiData != nullptr,); | |||
if (pData->automaticallyScale) | |||
#if 0 /* TODO */ | |||
if (uiData->automaticallyScale) | |||
{ | |||
const double scaleHorizontal = static_cast<double>(width) / static_cast<double>(pData->minWidth); | |||
const double scaleVertical = static_cast<double>(height) / static_cast<double>(pData->minHeight); | |||
const double scaleHorizontal = static_cast<double>(width) / static_cast<double>(uiData->minWidth); | |||
const double scaleVertical = static_cast<double>(height) / static_cast<double>(uiData->minHeight); | |||
_setAutoScaling(scaleHorizontal < scaleVertical ? scaleHorizontal : scaleVertical); | |||
} | |||
#endif | |||
pData->resizeInProgress = true; | |||
uiData->resizeInProgress = true; | |||
fUI->setSize(width, height); | |||
pData->resizeInProgress = false; | |||
uiData->resizeInProgress = false; | |||
fUI->uiReshape(width, height); | |||
fIsReady = true; | |||
} | |||
#if 0 /* TODO */ | |||
# ifndef DGL_FILE_BROWSER_DISABLED | |||
// custom file-browser selected | |||
void fileBrowserSelected(const char* filename) override | |||
@@ -119,6 +122,7 @@ protected: | |||
fUI->uiFileBrowserSelected(filename); | |||
} | |||
# endif | |||
#endif | |||
private: | |||
UI* const fUI; | |||
@@ -153,7 +157,7 @@ public: | |||
fChangingSize(false), | |||
fUI(glWindow.getUI()), | |||
#endif | |||
fData((fUI != nullptr) ? fUI->pData : nullptr) | |||
fData((fUI != nullptr) ? fUI->uiData : nullptr) | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,); | |||
@@ -325,8 +329,8 @@ public: | |||
DISTRHO_SAFE_ASSERT_RETURN(cb != nullptr,); | |||
DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,); | |||
glWindow.addIdleCallback(cb); | |||
glWindow.setVisible(true); | |||
glApp.addIdleCallback(cb); | |||
glApp.exec(); | |||
} | |||
@@ -338,7 +342,9 @@ public: | |||
void focus() | |||
{ | |||
#if 0 /* TODO */ | |||
glWindow.focus(); | |||
#endif | |||
} | |||
bool idle() | |||
@@ -415,7 +421,9 @@ public: | |||
void setWindowTransientWinId(const uintptr_t winId) | |||
{ | |||
#if 0 /* TODO */ | |||
glWindow.setTransientWinId(winId); | |||
#endif | |||
} | |||
bool setWindowVisible(const bool yesNo) | |||
@@ -427,12 +435,16 @@ public: | |||
bool handlePluginKeyboard(const bool press, const uint key) | |||
{ | |||
#if 0 /* TODO */ | |||
return glWindow.handlePluginKeyboard(press, key); | |||
#endif | |||
} | |||
bool handlePluginSpecial(const bool press, const DGL_NAMESPACE::Key key) | |||
{ | |||
#if 0 /* TODO */ | |||
return glWindow.handlePluginSpecial(press, key); | |||
#endif | |||
} | |||
#endif | |||