Merge branch 'main' of github.com:noctalia-dev/nextalia

This commit is contained in:
Lemmy
2026-04-03 20:01:06 -04:00
16 changed files with 231 additions and 61 deletions
+2
View File
@@ -208,6 +208,8 @@ add_executable(noctalia
src/ui/Widget.cpp
src/ui/WidgetFactory.cpp
src/ui/controls/Box.cpp
src/ui/controls/Button.cpp
src/ui/controls/Chip.cpp
src/ui/controls/Label.cpp
src/ui/widgets/ClockWidget.cpp
src/ui/widgets/SpacerWidget.cpp
-1
View File
@@ -1,5 +1,4 @@
#include "render/GlRenderer.hpp"
#include "render/core/Palette.hpp"
#include "render/scene/Node.hpp"
#include "render/scene/RectNode.hpp"
#include "render/scene/TextNode.hpp"
+4 -3
View File
@@ -2,7 +2,8 @@
#include "config/ConfigService.hpp"
#include "core/Log.hpp"
#include "render/core/Palette.hpp"
#include "ui/style/Palette.hpp"
#include "ui/style/Style.hpp"
#include "render/scene/RectNode.hpp"
#include "time/TimeService.hpp"
#include "ui/Widget.hpp"
@@ -230,9 +231,9 @@ void Bar::buildScene(BarInstance& instance, std::uint32_t width, std::uint32_t h
0.85f),
.fillMode = FillMode::LinearGradient,
.gradientDirection = GradientDirection::Vertical,
.radius = 10.0f,
.radius = Style::radiusMd,
.softness = 1.2f,
.borderWidth = 1.0f,
.borderWidth = Style::borderWidth,
});
instance.sceneRoot->addChild(std::move(bg));
+15
View File
@@ -3,6 +3,8 @@
#include "render/core/Renderer.hpp"
#include "render/scene/RectNode.hpp"
#include "ui/controls/Label.hpp"
#include "ui/style/Palette.hpp"
#include "ui/style/Style.hpp"
#include <algorithm>
#include <memory>
@@ -73,6 +75,19 @@ void Box::setBorderWidth(float bw) {
m_background->setStyle(style);
}
void Box::applyCardChrome() {
setRadius(Style::radiusMd);
setBorderColor(kRosePinePalette.overlay);
setBorderWidth(Style::borderWidth);
setBackground(kRosePinePalette.surface);
}
void Box::applyBarRowLayout() {
setDirection(BoxDirection::Horizontal);
setGap(Style::spaceXs);
setAlign(BoxAlign::Center);
}
void Box::ensureBackground() {
if (m_background != nullptr) {
return;
+4
View File
@@ -32,6 +32,10 @@ public:
void setBorderColor(const Color& color);
void setBorderWidth(float width);
void applyCardChrome();
void applyBarRowLayout();
[[nodiscard]] BoxDirection direction() const noexcept { return m_direction; }
[[nodiscard]] float gap() const noexcept { return m_gap; }
[[nodiscard]] BoxAlign align() const noexcept { return m_align; }
+71
View File
@@ -0,0 +1,71 @@
#include "ui/controls/Button.hpp"
#include "render/core/Color.hpp"
#include "ui/controls/Label.hpp"
#include "ui/style/Palette.hpp"
#include "ui/style/Style.hpp"
#include <memory>
Button::Button() {
setAlign(BoxAlign::Center);
setPadding(Style::paddingV, Style::paddingH, Style::paddingV, Style::paddingH);
setRadius(Style::radiusMd);
auto label = std::make_unique<Label>();
m_label = static_cast<Label*>(addChild(std::move(label)));
applyVariant();
}
void Button::setText(std::string_view text) {
m_label->setText(text);
}
void Button::setFontSize(float size) {
m_label->setFontSize(size);
}
void Button::setVariant(ButtonVariant variant) {
if (m_variant == variant) {
return;
}
m_variant = variant;
applyVariant();
}
void Button::applyVariant() {
setPadding(Style::paddingV, Style::paddingH, Style::paddingV, Style::paddingH);
setRadius(Style::radiusMd);
switch (m_variant) {
case ButtonVariant::Default:
setBackground(kRosePinePalette.iris);
m_label->setColor(kRosePinePalette.base);
setBorderColor(kRosePinePalette.overlay);
setBorderWidth(0.0f);
break;
case ButtonVariant::Secondary:
setBackground(kRosePinePalette.overlay);
m_label->setColor(kRosePinePalette.text);
setBorderColor(kRosePinePalette.overlay);
setBorderWidth(0.0f);
break;
case ButtonVariant::Destructive:
setBackground(kRosePinePalette.love);
m_label->setColor(kRosePinePalette.base);
setBorderColor(kRosePinePalette.overlay);
setBorderWidth(0.0f);
break;
case ButtonVariant::Outline:
setBackground(rgba(0.0f, 0.0f, 0.0f, 0.0f));
m_label->setColor(kRosePinePalette.text);
setBorderColor(kRosePinePalette.overlay);
setBorderWidth(Style::borderWidth);
break;
case ButtonVariant::Ghost:
setBackground(rgba(0.0f, 0.0f, 0.0f, 0.0f));
m_label->setColor(kRosePinePalette.text);
setBorderWidth(0.0f);
break;
}
}
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#include "ui/controls/Box.hpp"
#include <string_view>
class Label;
enum class ButtonVariant : std::uint8_t {
Default,
Secondary,
Destructive,
Outline,
Ghost,
};
class Button : public Box {
public:
Button();
void setText(std::string_view text);
void setFontSize(float size);
void setVariant(ButtonVariant variant);
[[nodiscard]] Label* label() const noexcept { return m_label; }
private:
void applyVariant();
Label* m_label = nullptr;
ButtonVariant m_variant = ButtonVariant::Default;
};
+33
View File
@@ -0,0 +1,33 @@
#include "ui/controls/Chip.hpp"
#include "ui/controls/Label.hpp"
#include "ui/style/Palette.hpp"
#include "ui/style/Style.hpp"
#include <memory>
Chip::Chip() {
setAlign(BoxAlign::Center);
setPadding(Style::paddingV, Style::paddingH, Style::paddingV, Style::paddingH);
setRadius(Style::radiusMd);
auto label = std::make_unique<Label>();
m_label = static_cast<Label*>(addChild(std::move(label)));
m_label->setFontSize(Style::fontSizeXs);
setWorkspaceActive(false);
}
void Chip::setText(std::string_view text) {
m_label->setText(text);
}
void Chip::setWorkspaceActive(bool active) {
if (active) {
setBackground(kRosePinePalette.love);
m_label->setColor(kRosePinePalette.base);
} else {
setBackground(kRosePinePalette.overlay);
m_label->setColor(kRosePinePalette.subtle);
}
setBorderWidth(0.0f);
}
+22
View File
@@ -0,0 +1,22 @@
#pragma once
#include "ui/controls/Box.hpp"
#include <string_view>
class Label;
// Compact label + rounded fill for bar items (e.g. workspace). Not a Button — no
// pointer/press semantics; chrome matches borderless shadcn-style chips.
class Chip : public Box {
public:
Chip();
void setText(std::string_view text);
void setWorkspaceActive(bool active);
[[nodiscard]] Label* label() const noexcept { return m_label; }
private:
Label* m_label = nullptr;
};
+9
View File
@@ -2,12 +2,16 @@
#include "render/core/Renderer.hpp"
#include "render/scene/TextNode.hpp"
#include "ui/style/Palette.hpp"
#include "ui/style/Style.hpp"
#include <memory>
Label::Label() {
auto textNode = std::make_unique<TextNode>();
m_textNode = static_cast<TextNode*>(addChild(std::move(textNode)));
m_textNode->setFontSize(Style::fontSizeSm);
m_textNode->setColor(kRosePinePalette.text);
}
void Label::setText(std::string_view text) {
@@ -42,6 +46,11 @@ float Label::maxWidth() const noexcept {
return m_textNode->maxWidth();
}
void Label::applyBarTextStyle() {
m_textNode->setFontSize(Style::fontSizeBar);
m_textNode->setColor(kRosePinePalette.text);
}
void Label::measure(Renderer& renderer) {
auto metrics = renderer.measureText(m_textNode->text(), m_textNode->fontSize());
setSize(metrics.width, metrics.bottom - metrics.top);
+2
View File
@@ -25,6 +25,8 @@ public:
void measure(Renderer& renderer);
void applyBarTextStyle();
private:
TextNode* m_textNode = nullptr;
};
+24
View File
@@ -0,0 +1,24 @@
#pragma once
namespace Style {
inline constexpr float radiusSm = 2.0f;
inline constexpr float radiusMd = 5.0f;
inline constexpr float radiusLg = 8.0f;
inline constexpr float radiusFull = 9999.0f;
inline constexpr float borderWidth = 1.0f;
inline constexpr float spaceXs = 4.0f;
inline constexpr float spaceSm = 8.0f;
inline constexpr float spaceMd = 12.0f;
inline constexpr float spaceLg = 16.0f;
inline constexpr float paddingV = spaceXs;
inline constexpr float paddingH = spaceSm;
inline constexpr float fontSizeXs = 12.0f;
inline constexpr float fontSizeSm = 14.0f;
inline constexpr float fontSizeBar = 13.0f;
}
+1 -3
View File
@@ -1,6 +1,5 @@
#include "ui/widgets/ClockWidget.hpp"
#include "render/core/Palette.hpp"
#include "render/core/Renderer.hpp"
#include "time/TimeService.hpp"
#include "ui/controls/Label.hpp"
@@ -11,8 +10,7 @@ ClockWidget::ClockWidget(const TimeService& timeService, std::string format)
void ClockWidget::create(Renderer& renderer) {
auto label = std::make_unique<Label>();
label->setFontSize(13.0f);
label->setColor(kRosePinePalette.text);
label->applyBarTextStyle();
m_label = label.get();
m_root = std::move(label);
update(renderer);
+5 -2
View File
@@ -1,11 +1,14 @@
#include "ui/widgets/SpacerWidget.hpp"
#include "ui/controls/Box.hpp"
SpacerWidget::SpacerWidget(float width)
: m_fixedWidth(width) {}
void SpacerWidget::create(Renderer& /*renderer*/) {
m_root = std::make_unique<Node>();
m_root->setSize(m_fixedWidth, 0.0f);
auto box = std::make_unique<Box>();
box->setSize(m_fixedWidth, 0.0f);
m_root = std::unique_ptr<Node>(box.release());
}
void SpacerWidget::layout(Renderer& /*renderer*/, float /*barWidth*/, float barHeight) {
+7 -52
View File
@@ -1,36 +1,22 @@
#include "ui/widgets/WorkspacesWidget.hpp"
#include "core/Log.hpp"
#include "render/core/Color.hpp"
#include "render/core/Palette.hpp"
#include "render/core/Renderer.hpp"
#include "render/scene/Node.hpp"
#include "ui/controls/Box.hpp"
#include "ui/controls/Label.hpp"
#include "ui/controls/Chip.hpp"
#include "cursor-shape-v1-client-protocol.h"
#include <linux/input-event-codes.h>
namespace {
constexpr float kPillFontSize = 12.0f;
constexpr float kPillPaddingV = 3.0f;
constexpr float kPillPaddingH = 6.0f;
constexpr float kPillRadius = 10.0f;
constexpr float kGap = 4.0f;
} // namespace
WorkspacesWidget::WorkspacesWidget(WaylandConnection& connection, wl_output* output)
: m_connection(connection)
, m_output(output) {}
void WorkspacesWidget::create(Renderer& renderer) {
auto container = std::make_unique<Box>();
container->setDirection(BoxDirection::Horizontal);
container->setGap(kGap);
container->setAlign(BoxAlign::Center);
container->applyBarRowLayout();
m_container = container.get();
m_root = std::move(container);
@@ -47,7 +33,6 @@ void WorkspacesWidget::update(Renderer& renderer) {
return;
}
// Check if state changed
bool changed = current.size() != m_cachedState.size();
if (!changed) {
for (std::size_t i = 0; i < current.size(); ++i) {
@@ -99,8 +84,6 @@ std::uint32_t WorkspacesWidget::cursorShape() const {
int WorkspacesWidget::pillIndexAt(float localX, float localY) const {
const auto& kids = m_container->children();
// Skip background rect (child 0 if Box has one)
// Box children: [bg_rect, pill0, pill1, ...]
// The first child is the background rect added by Box::setBackground
std::size_t start = 0;
if (!kids.empty() && kids[0]->type() == NodeType::Rect) {
start = 1;
@@ -111,7 +94,6 @@ int WorkspacesWidget::pillIndexAt(float localX, float localY) const {
float absX = 0.0f, absY = 0.0f;
Node::absolutePosition(child, absX, absY);
// Convert to widget-local: our localX/localY is relative to widget root (m_container)
float containerAbsX = 0.0f, containerAbsY = 0.0f;
Node::absolutePosition(m_container, containerAbsX, containerAbsY);
float childLocalX = absX - containerAbsX;
@@ -127,7 +109,6 @@ int WorkspacesWidget::pillIndexAt(float localX, float localY) const {
}
void WorkspacesWidget::rebuild(Renderer& renderer) {
// Remove all children
while (!m_container->children().empty()) {
m_container->removeChild(m_container->children().back().get());
}
@@ -140,36 +121,10 @@ void WorkspacesWidget::rebuild(Renderer& renderer) {
for (const auto& ws : workspaces) {
m_workspaceIds.push_back(ws.id);
if (ws.active) {
auto pill = std::make_unique<Box>();
pill->setPadding(kPillPaddingV, kPillPaddingH, kPillPaddingV, kPillPaddingH);
pill->setBackground(kRosePinePalette.love);
pill->setRadius(kPillRadius);
pill->setAlign(BoxAlign::Center);
auto label = std::make_unique<Label>();
label->setText(ws.name);
label->setFontSize(kPillFontSize);
label->setColor(kRosePinePalette.base);
pill->addChild(std::move(label));
pill->layout(renderer);
m_container->addChild(std::move(pill));
} else {
auto pill = std::make_unique<Box>();
pill->setPadding(kPillPaddingV, kPillPaddingH, kPillPaddingV, kPillPaddingH);
pill->setBackground(rgba(1.0f, 1.0f, 1.0f, 0.08f));
pill->setRadius(kPillRadius);
pill->setAlign(BoxAlign::Center);
auto label = std::make_unique<Label>();
label->setText(ws.name);
label->setFontSize(kPillFontSize);
label->setColor(kRosePinePalette.subtle);
pill->addChild(std::move(label));
pill->layout(renderer);
m_container->addChild(std::move(pill));
}
auto pill = std::make_unique<Chip>();
pill->setText(ws.name);
pill->setWorkspaceActive(ws.active);
pill->layout(renderer);
m_container->addChild(std::move(pill));
}
}