mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
Merge branch 'main' of github.com:noctalia-dev/nextalia
This commit is contained in:
@@ -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,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
@@ -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));
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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);
|
||||
|
||||
@@ -25,6 +25,8 @@ public:
|
||||
|
||||
void measure(Renderer& renderer);
|
||||
|
||||
void applyBarTextStyle();
|
||||
|
||||
private:
|
||||
TextNode* m_textNode = nullptr;
|
||||
};
|
||||
|
||||
@@ -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,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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user