Skip to content

Commit 889a273

Browse files
committed
Initial commit for "breeze" widgets
Signed-off-by: falkTX <[email protected]>
1 parent 22a91fb commit 889a273

File tree

5 files changed

+310
-1
lines changed

5 files changed

+310
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*.html
55
*.o
66
*.wasm
7+
/tests/breeze
78
/tests/imgui
89
/tests/opengl
910
/tests/textedit

opengl/DarkBreeze.cpp

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// DarkBreeze widgets for DPF
2+
// Copyright (C) 2025 Filipe Coelho <[email protected]>
3+
// SPDX-License-Identifier: ISC
4+
5+
// NOTE this file is WORK-IN-PROGRESS
6+
7+
#include "DarkBreeze.hpp"
8+
9+
START_NAMESPACE_DGL
10+
11+
static constexpr const char kColorBackgroundActive[] = "#292c30";
12+
static constexpr const char kColorBackgroundInactive[] = "#202326";
13+
static constexpr const char kColorSeparatorLine[] = "#535659";
14+
static constexpr const char kColorText[] = "#fcfcfc";
15+
16+
static constexpr const char kColorButtonFillActive[] = "#2d4655";
17+
static constexpr const char kColorButtonFillActiveHover[] = "#30576e";
18+
#define kColorButtonFillHover kColorBackgroundActive
19+
#define kColorButtonFillDefault kColorBackgroundActive
20+
static constexpr const char kColorButtonStrokeActive[] = "#3daee9";
21+
#define kColorButtonStrokeActiveHover kColorButtonStrokeActive
22+
#define kColorButtonStrokeHover kColorButtonStrokeActive
23+
#define kColorButtonStrokeDefault kColorSeparatorLine
24+
25+
static constexpr const uint kSizePadding = 1;
26+
static constexpr const uint kSizeButton = 32;
27+
static constexpr const uint kSizeRadius = 4;
28+
29+
// --------------------------------------------------------------------------------------------------------------------
30+
31+
DarkBreeze::DarkBreeze(Window& window)
32+
: NanoTopLevelWidget(window),
33+
colorActive(Color::fromHTML(kColorBackgroundActive)),
34+
colorInactive(Color::fromHTML(kColorBackgroundInactive)) {}
35+
36+
void DarkBreeze::setActive(const bool active2)
37+
{
38+
if (active == active2)
39+
return;
40+
41+
active = active2;
42+
repaint();
43+
}
44+
45+
void DarkBreeze::onNanoDisplay()
46+
{
47+
beginPath();
48+
rect(0, 0, getWidth(), getHeight());
49+
fillColor(active ? colorActive : colorInactive);
50+
fill();
51+
}
52+
53+
// --------------------------------------------------------------------------------------------------------------------
54+
55+
DarkBreezeButton::DarkBreezeButton(DarkBreeze* const parent)
56+
: NanoSubWidget(parent),
57+
ButtonEventHandler(this)
58+
{
59+
loadSharedResources();
60+
61+
constexpr uint size = kSizeButton + kSizePadding * 2;
62+
setSize(size, size);
63+
}
64+
65+
DarkBreezeButton::~DarkBreezeButton()
66+
{
67+
std::free(label);
68+
}
69+
70+
void DarkBreezeButton::setLabel(const char* const label2)
71+
{
72+
std::free(label);
73+
label = label2 != nullptr ? strdup(label2) : nullptr;
74+
75+
if (label != nullptr && label[0] != '\0')
76+
{
77+
Rectangle<float> bounds;
78+
// fontSize(theme.fontSize);
79+
textBounds(0, 0, label, nullptr, bounds);
80+
81+
const uint width = std::max(getWidth(), d_roundToUnsignedInt(bounds.getWidth()) + kSizePadding * 8);
82+
const uint height = std::max(getHeight(), d_roundToUnsignedInt(bounds.getHeight()) + kSizePadding * 2);
83+
setSize(width, height);
84+
}
85+
}
86+
87+
void DarkBreezeButton::onNanoDisplay()
88+
{
89+
beginPath();
90+
roundedRect(kSizePadding,
91+
kSizePadding,
92+
getWidth() - kSizePadding * 2,
93+
getHeight() - kSizePadding * 2,
94+
kSizeRadius);
95+
96+
d_stdout("state %d", getState());
97+
switch (getState())
98+
{
99+
case kButtonStateActive:
100+
fillColor(Color::fromHTML(kColorButtonFillActive));
101+
strokeColor(Color::fromHTML(kColorButtonStrokeActive));
102+
break;
103+
case kButtonStateActiveHover:
104+
fillColor(Color::fromHTML(kColorButtonFillActiveHover));
105+
strokeColor(Color::fromHTML(kColorButtonStrokeActiveHover));
106+
break;
107+
case kButtonStateHover:
108+
fillColor(Color::fromHTML(kColorButtonFillHover));
109+
strokeColor(Color::fromHTML(kColorButtonStrokeHover));
110+
break;
111+
case kButtonStateDefault:
112+
fillColor(Color::fromHTML(kColorButtonFillDefault));
113+
strokeColor(Color::fromHTML(kColorButtonStrokeDefault));
114+
break;
115+
}
116+
117+
fill();
118+
strokeWidth(1);
119+
stroke();
120+
121+
if (label != nullptr && label[0] != '\0')
122+
{
123+
fillColor(Color::fromHTML(kColorText));
124+
// fontSize(theme.fontSize);
125+
textAlign(ALIGN_CENTER|ALIGN_MIDDLE);
126+
text(getWidth() / 2, getHeight() / 2, label, nullptr);
127+
}
128+
}
129+
130+
bool DarkBreezeButton::onMouse(const MouseEvent& ev)
131+
{
132+
return mouseEvent(ev);
133+
}
134+
135+
bool DarkBreezeButton::onMotion(const MotionEvent& ev)
136+
{
137+
return motionEvent(ev);
138+
}
139+
140+
// --------------------------------------------------------------------------------------------------------------------
141+
142+
END_NAMESPACE_DGL

opengl/DarkBreeze.hpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// DarkBreeze widgets for DPF
2+
// Copyright (C) 2025 Filipe Coelho <[email protected]>
3+
// SPDX-License-Identifier: ISC
4+
5+
// NOTE this file is WORK-IN-PROGRESS
6+
7+
#pragma once
8+
9+
#include "EventHandlers.hpp"
10+
#include "NanoVG.hpp"
11+
12+
START_NAMESPACE_DGL
13+
14+
// --------------------------------------------------------------------------------------------------------------------
15+
16+
class DarkBreeze : public NanoTopLevelWidget
17+
{
18+
const Color colorActive, colorInactive;
19+
bool active = false;
20+
21+
public:
22+
explicit DarkBreeze(Window& window);
23+
24+
inline bool isActive() const noexcept
25+
{
26+
return active;
27+
}
28+
29+
void setActive(bool active);
30+
31+
protected:
32+
void onNanoDisplay() override;
33+
34+
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DarkBreeze)
35+
};
36+
37+
// --------------------------------------------------------------------------------------------------------------------
38+
39+
class DarkBreezeButton : public NanoSubWidget,
40+
public ButtonEventHandler
41+
{
42+
char* label = nullptr;
43+
44+
public:
45+
explicit DarkBreezeButton(DarkBreeze* parent);
46+
~DarkBreezeButton() override;
47+
48+
inline const char* getLabel() const noexcept
49+
{
50+
return label;
51+
}
52+
53+
void setLabel(const char* label);
54+
55+
protected:
56+
void onNanoDisplay() override;
57+
bool onMouse(const MouseEvent& ev) override;
58+
bool onMotion(const MotionEvent& ev) override;
59+
60+
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DarkBreezeButton)
61+
};
62+
63+
// --------------------------------------------------------------------------------------------------------------------
64+
65+
END_NAMESPACE_DGL

tests/Makefile

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@ endif
2626

2727
# ---------------------------------------------------------------------------------------------------------------------
2828

29-
all: imgui$(APP_EXT) opengl$(APP_EXT) textedit$(APP_EXT)
29+
all: breeze$(APP_EXT) imgui$(APP_EXT) opengl$(APP_EXT) textedit$(APP_EXT)
3030

3131
clean:
3232
rm -f *.d *.o *.js *.html *.wasm
33+
rm -f breeze$(APP_EXT)
3334
rm -f imgui$(APP_EXT)
3435
rm -f opengl$(APP_EXT)
3536
rm -f textedit$(APP_EXT)
@@ -55,6 +56,10 @@ $(DPF_DIR)/build/libdgl-vulkan.a:
5556

5657
# ---------------------------------------------------------------------------------------------------------------------
5758

59+
breeze$(APP_EXT): breeze.cpp.o $(DPF_DIR)/build/libdgl-opengl.a
60+
@echo "Linking $@"
61+
$(SILENT)$(CXX) $^ $(LINK_FLAGS) $(DGL_SYSTEM_LIBS) $(OPENGL_LIBS) -o $@
62+
5863
imgui$(APP_EXT): imgui.cpp.o imgui-src.cpp.o $(DPF_DIR)/build/libdgl-opengl.a
5964
@echo "Linking $@"
6065
$(SILENT)$(CXX) $^ $(LINK_FLAGS) $(DGL_SYSTEM_LIBS) $(OPENGL_LIBS) -o $@
@@ -69,6 +74,10 @@ textedit$(APP_EXT): textedit.cpp.o imgui-src.cpp.o $(DPF_DIR)/build/libdgl-openg
6974

7075
# ---------------------------------------------------------------------------------------------------------------------
7176

77+
breeze.cpp.o: breeze.cpp
78+
@echo "Compiling $<"
79+
$(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(OPENGL_FLAGS) -c -o $@
80+
7281
imgui.cpp.o: imgui.cpp
7382
@echo "Compiling $<"
7483
$(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(OPENGL_FLAGS) -c -o $@
@@ -87,6 +96,7 @@ textedit.cpp.o: textedit.cpp
8796

8897
# ---------------------------------------------------------------------------------------------------------------------
8998

99+
-include breeze.cpp.d
90100
-include cairo.cpp.d
91101
-include imgui.cpp.d
92102
-include imgui-src.cpp.d

tests/breeze.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* DISTRHO Plugin Framework (DPF)
3+
* Copyright (C) 2012-2025 Filipe Coelho <[email protected]>
4+
*
5+
* Permission to use, copy, modify, and/or distribute this software for any purpose with
6+
* or without fee is hereby granted, provided that the above copyright notice and this
7+
* permission notice appear in all copies.
8+
*
9+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
10+
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
11+
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12+
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
13+
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14+
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15+
*/
16+
17+
#include "Application.hpp"
18+
#include "Layout.hpp"
19+
#include "../opengl/DarkBreeze.cpp"
20+
21+
START_NAMESPACE_DGL
22+
23+
// --------------------------------------------------------------------------------------------------------------------
24+
25+
class BreezeStandaloneWindow : public StandaloneWindow
26+
{
27+
DarkBreeze breeze;
28+
ScopedPointer<DarkBreezeButton> button1;
29+
ScopedPointer<DarkBreezeButton> button2;
30+
ScopedPointer<DarkBreezeButton> button3;
31+
HorizontalLayout layout;
32+
33+
public:
34+
BreezeStandaloneWindow(Application& app)
35+
: StandaloneWindow(app),
36+
breeze(*this)
37+
{
38+
const double scaleFactor = getScaleFactor();
39+
setGeometryConstraints(500 * scaleFactor, 80 * scaleFactor, false);
40+
setSize(580 * scaleFactor, 80 * scaleFactor);
41+
setResizable(true);
42+
setTitle("Breeze");
43+
44+
button1 = new DarkBreezeButton(&breeze);
45+
button1->setLabel("fixed size button");
46+
47+
button2 = new DarkBreezeButton(&breeze);
48+
button2->setLabel("expanding button 1");
49+
50+
button3 = new DarkBreezeButton(&breeze);
51+
button3->setLabel("expanding button 2");
52+
53+
layout.widgets.push_back({button1, Fixed});
54+
layout.widgets.push_back({button2, Expanding});
55+
layout.widgets.push_back({button3, Expanding});
56+
layout.setAbsolutePos(0, 0, 6);
57+
layout.setSize(getWidth(), 6);
58+
59+
focus();
60+
}
61+
62+
protected:
63+
void onFocus(bool focus, CrossingMode mode) override
64+
{
65+
d_stdout("%d %d", focus, mode);
66+
breeze.setActive(focus);
67+
}
68+
69+
void onReshape(uint width, uint height) override
70+
{
71+
StandaloneWindow::onReshape(width, height);
72+
layout.setSize(width, 6);
73+
layout.setAbsolutePos(0, 0, 6);
74+
}
75+
};
76+
77+
// --------------------------------------------------------------------------------------------------------------------
78+
79+
END_NAMESPACE_DGL
80+
81+
int main(int, char**)
82+
{
83+
USE_NAMESPACE_DGL;
84+
85+
Application app;
86+
BreezeStandaloneWindow win(app);
87+
win.show();
88+
app.exec();
89+
90+
return 0;
91+
}

0 commit comments

Comments
 (0)