From 887c44bf68fa7baab99b7f6960dc771fc3e261a5 Mon Sep 17 00:00:00 2001 From: dmitry Date: Sat, 1 Jul 2023 00:18:57 +0300 Subject: [PATCH] finish MVP --- include/modules/hyprland/workspaces.hpp | 24 ++++- src/modules/hyprland/workspaces.cpp | 119 +++++++++++++++++++++--- 2 files changed, 126 insertions(+), 17 deletions(-) diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp index 7903fef..0b8a452 100644 --- a/include/modules/hyprland/workspaces.hpp +++ b/include/modules/hyprland/workspaces.hpp @@ -7,17 +7,27 @@ namespace waybar::modules::hyprland { +struct WorkspaceDto { + int id; + + static WorkspaceDto parse(const Json::Value& value); +}; + class Workspace { public: Workspace(int id); - int id() { return id_; }; + Workspace(WorkspaceDto dto); + int id() const { return id_; }; + int active() const { return active_; }; + std::string& select_icon(std::map& icons_map); + void set_active(bool value = true) { active_ = value; }; Gtk::Button& button() { return button_; }; - static Workspace parse(const Json::Value&); - void update(); + void update(const std::string& format, const std::string& icon); private: int id_; + bool active_; Gtk::Button button_; Gtk::Box content_; @@ -33,9 +43,13 @@ class Workspaces : public AModule, public EventHandler { private: void onEvent(const std::string&) override; + void sort_workspaces(); - std::vector workspaces; - + std::string format_; + std::map icons_map_; + bool with_icon_; + int active_workspace_id; + std::vector workspaces_; std::mutex mutex_; const Bar& bar_; Gtk::Box box_; diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index 4a19a59..54a425d 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -1,15 +1,32 @@ #include "modules/hyprland/workspaces.hpp" +#include #include #include +#include #include namespace waybar::modules::hyprland { + Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value &config) : AModule(config, "workspaces", id, false, false), bar_(bar), box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0) { + Json::Value config_format = config["format"]; + + format_ = config_format.isString() ? config_format.asString() : "{id}"; + with_icon_ = format_.find("{icon}") != std::string::npos; + + if (with_icon_ && icons_map_.empty()) { + Json::Value format_icons = config["format-icons"]; + for (std::string &name : format_icons.getMemberNames()) { + icons_map_.emplace(name, format_icons[name].asString()); + } + + icons_map_.emplace("", ""); + } + box_.set_name("workspaces"); if (!id.empty()) { box_.get_style_context()->add_class(id); @@ -22,33 +39,64 @@ Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value init(); + gIPC->registerForIPC("workspace", this); gIPC->registerForIPC("createworkspace", this); gIPC->registerForIPC("destroyworkspace", this); - gIPC->registerForIPC("urgent", this); } auto Workspaces::update() -> void { std::lock_guard lock(mutex_); - for (Workspace &workspace : workspaces) { - workspace.update(); + for (Workspace &workspace : workspaces_) { + workspace.set_active(workspace.id() == active_workspace_id); + + std::string &workspace_icon = icons_map_[""]; + if (with_icon_) { + workspace_icon = workspace.select_icon(icons_map_); + } + + workspace.update(format_, workspace_icon); } + AModule::update(); } -void Workspaces::onEvent(const std::string &ev) { dp.emit(); } +void Workspaces::onEvent(const std::string &ev) { + std::string eventName(begin(ev), begin(ev) + ev.find_first_of('>')); + std::string payload = ev.substr(eventName.size() + 2); + if (eventName == "workspace") { + std::from_chars(payload.data(), payload.data() + payload.size(), active_workspace_id); + } else if (eventName == "destroyworkspace") { + int deleted_workspace_id; + std::from_chars(payload.data(), payload.data() + payload.size(), deleted_workspace_id); + workspaces_.erase(std::remove_if(workspaces_.begin(), workspaces_.end(), + [&](Workspace &x) { return x.id() == deleted_workspace_id; })); + } else if (eventName == "createworkspace") { + int new_workspace_id; + std::from_chars(payload.data(), payload.data() + payload.size(), new_workspace_id); + workspaces_.push_back(new_workspace_id); + Gtk::Button& new_workspace_button = workspaces_.back().button(); + box_.pack_end(new_workspace_button, false, false); + sort_workspaces(); + new_workspace_button.show_all(); + } + + dp.emit(); +} void Workspaces::init() { - const auto activeWorkspace = Workspace::parse(gIPC->getSocket1JsonReply("activeworkspace")); + const auto activeWorkspace = WorkspaceDto::parse(gIPC->getSocket1JsonReply("activeworkspace")); + active_workspace_id = activeWorkspace.id; const Json::Value workspaces_json = gIPC->getSocket1JsonReply("workspaces"); for (const Json::Value &workspace_json : workspaces_json) { - workspaces.push_back(Workspace::parse(workspace_json)); + workspaces_.push_back(Workspace(WorkspaceDto::parse(workspace_json))); } - std::sort(workspaces.begin(), workspaces.end(), - [](Workspace &lhs, Workspace &rhs) { return lhs.id() < rhs.id(); }); - for (auto &workspace : workspaces) { + + for (auto &workspace : workspaces_) { box_.pack_start(workspace.button(), false, false); } + sort_workspaces(); + dp.emit(); } @@ -58,15 +106,62 @@ Workspaces::~Workspaces() { std::lock_guard lg(mutex_); } -Workspace Workspace::Workspace::parse(const Json::Value &value) { - return Workspace{value["id"].asInt()}; +WorkspaceDto WorkspaceDto::parse(const Json::Value &value) { + return WorkspaceDto{value["id"].asInt()}; } +Workspace::Workspace(WorkspaceDto dto) : Workspace(dto.id){}; + Workspace::Workspace(int id) : id_(id) { button_.set_relief(Gtk::RELIEF_NONE); content_.set_center_widget(label_); button_.add(content_); }; -void Workspace::update() { label_.set_text(std::to_string(id_)); } +void add_or_remove_class(Glib::RefPtr context, bool condition, + const std::string &class_name) { + if (condition) { + context->add_class(class_name); + } else { + context->remove_class(class_name); + } +} + +void Workspace::update(const std::string &format, const std::string &icon) { + Glib::RefPtr style_context = button_.get_style_context(); + add_or_remove_class(style_context, active(), "active"); + + label_.set_markup( + fmt::format(fmt::runtime(format), fmt::arg("id", id()), fmt::arg("icon", icon))); +} + +void Workspaces::sort_workspaces() { + std::sort(workspaces_.begin(), workspaces_.end(), + [](Workspace &lhs, Workspace &rhs) { return lhs.id() < rhs.id(); }); + + for (size_t i = 0; i < workspaces_.size(); ++i) { + box_.reorder_child(workspaces_[i].button(), i); + } +} + +std::string &Workspace::select_icon(std::map &icons_map) { + if (active()) { + auto active_icon_it = icons_map.find("active"); + if (active_icon_it != icons_map.end()) { + return active_icon_it->second; + } + } + + auto named_icon_it = icons_map.find(std::to_string(id())); + if (named_icon_it != icons_map.end()) { + return named_icon_it->second; + } + + auto default_icon_it = icons_map.find("default"); + if (default_icon_it != icons_map.end()) { + return default_icon_it->second; + } + + return icons_map[""]; +} } // namespace waybar::modules::hyprland