Merge pull request #2574 from Syndelis/feat/group-drawers
This commit is contained in:
		
						commit
						93daf089b5
					
				|  | @ -12,6 +12,7 @@ | |||
| #include <vector> | ||||
| 
 | ||||
| #include "AModule.hpp" | ||||
| #include "group.hpp" | ||||
| #include "xdg-output-unstable-v1-client-protocol.h" | ||||
| 
 | ||||
| namespace waybar { | ||||
|  | @ -101,7 +102,7 @@ class Bar { | |||
|  private: | ||||
|   void onMap(GdkEventAny *); | ||||
|   auto setupWidgets() -> void; | ||||
|   void getModules(const Factory &, const std::string &, Gtk::Box *); | ||||
|   void getModules(const Factory &, const std::string &, waybar::Group *); | ||||
|   void setupAltFormatKeyForModule(const std::string &module_name); | ||||
|   void setupAltFormatKeyForModuleList(const char *module_list_name); | ||||
|   void setMode(const bar_mode &); | ||||
|  |  | |||
|  | @ -5,18 +5,31 @@ | |||
| #include <json/json.h> | ||||
| 
 | ||||
| #include "AModule.hpp" | ||||
| #include "bar.hpp" | ||||
| #include "factory.hpp" | ||||
| #include "gtkmm/revealer.h" | ||||
| 
 | ||||
| namespace waybar { | ||||
| 
 | ||||
| class Group : public AModule { | ||||
|  public: | ||||
|   Group(const std::string&, const std::string&, const Json::Value&, bool); | ||||
|   ~Group() = default; | ||||
|   virtual ~Group() = default; | ||||
|   auto update() -> void override; | ||||
|   operator Gtk::Widget&() override; | ||||
| 
 | ||||
|   virtual Gtk::Box& getBox(); | ||||
|   void addWidget(Gtk::Widget& widget); | ||||
| 
 | ||||
|   bool handleMouseHover(GdkEventCrossing* const& e); | ||||
| 
 | ||||
|  protected: | ||||
|   Gtk::Box box; | ||||
|   Gtk::Box revealer_box; | ||||
|   Gtk::Revealer revealer; | ||||
|   bool is_first_widget = true; | ||||
|   bool is_drawer = false; | ||||
|   std::string add_class_to_drawer_children; | ||||
| 
 | ||||
|   void addHoverHandlerTo(Gtk::Widget& widget); | ||||
| }; | ||||
| 
 | ||||
| }  // namespace waybar
 | ||||
|  |  | |||
|  | @ -240,7 +240,7 @@ Valid options for the "rotate" property are: 0, 90, 180 and 270. | |||
| 
 | ||||
| ## Grouping modules | ||||
| 
 | ||||
| Module groups allow stacking modules in the direction orthogonal to the bar direction. When the bar is positioned on the top or bottom of the screen, modules in a group are stacked vertically. Likewise, when positioned on the left or right, modules in a group are stacked horizontally. | ||||
| Module groups allow stacking modules in any direction. By default, when the bar is positioned on the top or bottom of the screen, modules in a group are stacked vertically. Likewise, when positioned on the left or right, modules in a group are stacked horizontally. This can be changed with the "orientation" property. | ||||
| 
 | ||||
| A module group is defined by specifying a module named "group/some-group-name". The group must also be configured with a list of contained modules. Example: | ||||
| 
 | ||||
|  | @ -263,6 +263,43 @@ A module group is defined by specifying a module named "group/some-group-name". | |||
| 
 | ||||
| Valid options for the (optional) "orientation" property are: "horizontal", "vertical", "inherit", and "orthogonal" (default). | ||||
| 
 | ||||
| ## Group Drawers | ||||
| 
 | ||||
| A group may hide all but one element, showing them only on mouse hover. In order to configure this, you can use the `drawer` property, whose value is an object with the following properties: | ||||
| 
 | ||||
| *transition-duration*: ++ | ||||
| 	typeof: integer ++ | ||||
| 	default: 500 ++ | ||||
| 	Defines the duration of the transition animation in milliseconds. | ||||
| 
 | ||||
| *children-class*: ++ | ||||
| 	typeof: string ++ | ||||
| 	default: "hidden" ++ | ||||
| 	Defines the CSS class to be applied to the hidden elements. | ||||
| 
 | ||||
| *transition-left-to-right*: ++ | ||||
| 	typeof: bool ++ | ||||
| 	default: true ++ | ||||
| 	Defines the direction of the transition animation. If true, the hidden elements will slide from left to right. If false, they will slide from right to left. | ||||
| 	When the bar is vertical, it reads as top-to-bottom. | ||||
| 
 | ||||
| ``` | ||||
| "group/power": { | ||||
|     "orientation": "inherit", | ||||
|     "drawer": { | ||||
|         "transition-duration": 500, | ||||
|         "children-class": "not-power", | ||||
|         "transition-left-to-right": false, | ||||
|     }, | ||||
|     "modules": [ | ||||
|         "custom/power", // First element is the "group leader" and won't ever be hidden | ||||
|         "custom/quit", | ||||
|         "custom/lock", | ||||
|         "custom/reboot", | ||||
|     ] | ||||
| }, | ||||
| ``` | ||||
| 
 | ||||
| # SUPPORTED MODULES | ||||
| 
 | ||||
| - *waybar-backlight(5)* | ||||
|  |  | |||
							
								
								
									
										11
									
								
								src/bar.cpp
								
								
								
								
							
							
						
						
									
										11
									
								
								src/bar.cpp
								
								
								
								
							|  | @ -740,7 +740,7 @@ void waybar::Bar::handleSignal(int signal) { | |||
| } | ||||
| 
 | ||||
| void waybar::Bar::getModules(const Factory& factory, const std::string& pos, | ||||
|                              Gtk::Box* group = nullptr) { | ||||
|                              waybar::Group* group = nullptr) { | ||||
|   auto module_list = group ? config[pos]["modules"] : config[pos]; | ||||
|   if (module_list.isArray()) { | ||||
|     for (const auto& name : module_list) { | ||||
|  | @ -753,10 +753,11 @@ void waybar::Bar::getModules(const Factory& factory, const std::string& pos, | |||
|           auto id_name = ref.substr(6, hash_pos - 6); | ||||
|           auto class_name = hash_pos != std::string::npos ? ref.substr(hash_pos + 1) : ""; | ||||
| 
 | ||||
|           auto parent = group ? group : &this->box_; | ||||
|           auto vertical = parent->get_orientation() == Gtk::ORIENTATION_VERTICAL; | ||||
|           auto vertical = (group ? group->getBox().get_orientation() : box_.get_orientation()) == | ||||
|                           Gtk::ORIENTATION_VERTICAL; | ||||
| 
 | ||||
|           auto group_module = new waybar::Group(id_name, class_name, config[ref], vertical); | ||||
|           getModules(factory, ref, &group_module->box); | ||||
|           getModules(factory, ref, group_module); | ||||
|           module = group_module; | ||||
|         } else { | ||||
|           module = factory.makeModule(ref); | ||||
|  | @ -765,7 +766,7 @@ void waybar::Bar::getModules(const Factory& factory, const std::string& pos, | |||
|         std::shared_ptr<AModule> module_sp(module); | ||||
|         modules_all_.emplace_back(module_sp); | ||||
|         if (group) { | ||||
|           group->pack_start(*module, false, false); | ||||
|           group->addWidget(*module); | ||||
|         } else { | ||||
|           if (pos == "modules-left") { | ||||
|             modules_left_.emplace_back(module_sp); | ||||
|  |  | |||
|  | @ -4,12 +4,32 @@ | |||
| 
 | ||||
| #include <util/command.hpp> | ||||
| 
 | ||||
| #include "gdkmm/device.h" | ||||
| #include "gtkmm/widget.h" | ||||
| 
 | ||||
| namespace waybar { | ||||
| 
 | ||||
| const Gtk::RevealerTransitionType getPreferredTransitionType(bool is_vertical, bool left_to_right) { | ||||
|   if (is_vertical) { | ||||
|     if (left_to_right) { | ||||
|       return Gtk::RevealerTransitionType::REVEALER_TRANSITION_TYPE_SLIDE_DOWN; | ||||
|     } else { | ||||
|       return Gtk::RevealerTransitionType::REVEALER_TRANSITION_TYPE_SLIDE_UP; | ||||
|     } | ||||
|   } else { | ||||
|     if (left_to_right) { | ||||
|       return Gtk::RevealerTransitionType::REVEALER_TRANSITION_TYPE_SLIDE_RIGHT; | ||||
|     } else { | ||||
|       return Gtk::RevealerTransitionType::REVEALER_TRANSITION_TYPE_SLIDE_LEFT; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| Group::Group(const std::string& name, const std::string& id, const Json::Value& config, | ||||
|              bool vertical) | ||||
|     : AModule(config, name, id, false, false), | ||||
|       box{vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0} { | ||||
|     : AModule(config, name, id, true, true), | ||||
|       box{vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0}, | ||||
|       revealer_box{vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0} { | ||||
|   box.set_name(name_); | ||||
|   if (!id.empty()) { | ||||
|     box.get_style_context()->add_class(id); | ||||
|  | @ -29,12 +49,77 @@ Group::Group(const std::string& name, const std::string& id, const Json::Value& | |||
|   } else { | ||||
|     throw std::runtime_error("Invalid orientation value: " + orientation); | ||||
|   } | ||||
| 
 | ||||
|   if (config_["drawer"].isObject()) { | ||||
|     is_drawer = true; | ||||
| 
 | ||||
|     const auto& drawer_config = config_["drawer"]; | ||||
|     const int transition_duration = | ||||
|         (drawer_config["transition-duration"].isInt() ? drawer_config["transition-duration"].asInt() | ||||
|                                                       : 500); | ||||
|     add_class_to_drawer_children = | ||||
|         (drawer_config["children-class"].isString() ? drawer_config["children-class"].asString() | ||||
|                                                     : "drawer-child"); | ||||
|     const bool left_to_right = (drawer_config["transition-left-to-right"].isBool() | ||||
|                                     ? drawer_config["transition-left-to-right"].asBool() | ||||
|                                     : true); | ||||
| 
 | ||||
|     auto transition_type = getPreferredTransitionType(vertical, left_to_right); | ||||
| 
 | ||||
|     revealer.set_transition_type(transition_type); | ||||
|     revealer.set_transition_duration(transition_duration); | ||||
|     revealer.set_reveal_child(false); | ||||
| 
 | ||||
|     revealer.get_style_context()->add_class("drawer"); | ||||
| 
 | ||||
|     revealer.add(revealer_box); | ||||
|     box.pack_start(revealer); | ||||
| 
 | ||||
|     addHoverHandlerTo(revealer); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| bool Group::handleMouseHover(GdkEventCrossing* const& e) { | ||||
|   switch (e->type) { | ||||
|     case GDK_ENTER_NOTIFY: | ||||
|       revealer.set_reveal_child(true); | ||||
|       break; | ||||
|     case GDK_LEAVE_NOTIFY: | ||||
|       revealer.set_reveal_child(false); | ||||
|       break; | ||||
|     default: | ||||
|       break; | ||||
|   } | ||||
| 
 | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| void Group::addHoverHandlerTo(Gtk::Widget& widget) { | ||||
|   widget.add_events(Gdk::EventMask::ENTER_NOTIFY_MASK | Gdk::EventMask::LEAVE_NOTIFY_MASK); | ||||
|   widget.signal_enter_notify_event().connect(sigc::mem_fun(*this, &Group::handleMouseHover)); | ||||
|   widget.signal_leave_notify_event().connect(sigc::mem_fun(*this, &Group::handleMouseHover)); | ||||
| } | ||||
| 
 | ||||
| auto Group::update() -> void { | ||||
|   // noop
 | ||||
| } | ||||
| 
 | ||||
| Gtk::Box& Group::getBox() { return is_drawer ? (is_first_widget ? box : revealer_box) : box; } | ||||
| 
 | ||||
| void Group::addWidget(Gtk::Widget& widget) { | ||||
|   getBox().pack_start(widget, false, false); | ||||
| 
 | ||||
|   if (is_drawer) { | ||||
|     // Necessary because of GTK's hitbox detection
 | ||||
|     addHoverHandlerTo(widget); | ||||
|     if (!is_first_widget) { | ||||
|       widget.get_style_context()->add_class(add_class_to_drawer_children); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   is_first_widget = false; | ||||
| } | ||||
| 
 | ||||
| Group::operator Gtk::Widget&() { return box; } | ||||
| 
 | ||||
| }  // namespace waybar
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue