Skip to content

Commit cd5d12f

Browse files
AKArientrigg
authored andcommitted
panel : menu : rewrite WfMenuItem to fix issues and add css sizing/styling
Labels were erroniously placed on the right of the icons, extra actions were not available in grid view. Fixes both issues. The size of icons were hard-coded. The icons now are now sized by the `widget-icon`/`app-button` style.
1 parent 403df37 commit cd5d12f

4 files changed

Lines changed: 177 additions & 115 deletions

File tree

metadata/panel.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,16 @@ If full_span is off, both sides of the panel will take the same amount of space,
254254
<default>42</default>
255255
<min>0</min>
256256
</option>
257+
<option name="menu_item_icon_size" type="int">
258+
<_short>Menu item icon size</_short>
259+
<default>48</default>
260+
<min>0</min>
261+
</option>
262+
<option name="menu_item_spacing" type="int">
263+
<_short>Space between menu items</_short>
264+
<default>8</default>
265+
<min>0</min>
266+
</option>
257267
<option name="menu_force_show_popup" type="bool">
258268
<_short>Force showing the menu popup</_short>
259269
<_long>Show the menu popup over other windows, even if it and the panel would be hidden otherwise.</_long>

src/panel/panel.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,7 @@ void WayfirePanelApp::on_activate()
591591
{
592592
{"panel/minimal_height", ""},
593593
{"panel/menu_icon_size", ".menu-icon"},
594+
{"panel/menu_item_icon_size", ".app-button"},
594595
{"panel/launchers_size", ".launcher"},
595596
{"panel/battery_icon_size", ".battery image"},
596597
{"panel/network_icon_size", ".network"},

src/panel/widgets/menu.cpp

Lines changed: 150 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -59,69 +59,130 @@ void WfMenuCategoryButton::on_click()
5959
menu->set_category(category);
6060
}
6161

62-
WfMenuMenuItem::WfMenuMenuItem(WayfireMenu *_menu, Glib::RefPtr<Gio::DesktopAppInfo> app) :
63-
Gtk::FlowBoxChild(), menu(_menu), m_app_info(app)
62+
WfMenuItem::WfMenuItem(WayfireMenu *_menu, Glib::RefPtr<Gio::DesktopAppInfo> app) :
63+
Gtk::FlowBoxChild(), menu(_menu), app_info(app)
6464
{
65-
m_image.set((const Glib::RefPtr<const Gio::Icon>&)app->get_icon());
66-
m_image.set_pixel_size(48);
67-
m_label.set_text(app->get_name());
68-
m_label.set_xalign(0.0);
69-
m_label.set_hexpand(true);
70-
m_has_actions = app->list_actions().size() > 0;
71-
m_button_box.append(m_image);
72-
m_button_box.append(m_label);
73-
74-
m_button.set_child(m_button_box);
75-
signals.push_back(m_button.signal_clicked().connect(
76-
[this] ()
65+
image.set((const Glib::RefPtr<const Gio::Icon>&)app->get_icon());
66+
67+
label.set_text(app->get_name());
68+
label.set_ellipsize(Pango::EllipsizeMode::END);
69+
70+
extra_actions_button.add_css_class("flat");
71+
extra_actions_button.add_css_class("app-button-extras");
72+
extra_actions_button.set_direction(Gtk::ArrowType::RIGHT);
73+
extra_actions_button.set_has_frame(false);
74+
75+
box.set_expand(false);
76+
box.add_css_class("flat");
77+
box.add_css_class("widget-icon");
78+
box.add_css_class("app-button");
79+
80+
auto left_click_g = Gtk::GestureClick::create();
81+
auto right_click_g = Gtk::GestureClick::create();
82+
auto long_press_g = Gtk::GestureLongPress::create();
83+
left_click_g->set_button(1);
84+
right_click_g->set_button(3);
85+
long_press_g->set_touch_only(true);
86+
87+
signals.push_back(left_click_g->signal_pressed().connect(
88+
[=] (int c, double x, double y)
7789
{
78-
this->on_click();
90+
on_click();
91+
left_click_g->set_state(Gtk::EventSequenceState::CLAIMED);
92+
}));
93+
signals.push_back(right_click_g->signal_pressed().connect(
94+
[=] (int c, double x, double y)
95+
{
96+
extra_actions_button.activate();
97+
right_click_g->set_state(Gtk::EventSequenceState::CLAIMED);
98+
}));
99+
signals.push_back(long_press_g->signal_pressed().connect(
100+
[=] (double x, double y)
101+
{
102+
extra_actions_button.activate();
103+
long_press_g->set_state(Gtk::EventSequenceState::CLAIMED);
104+
left_click_g->set_state(Gtk::EventSequenceState::DENIED);
79105
}));
80-
m_padding_box.append(m_button);
81-
m_label.set_ellipsize(Pango::EllipsizeMode::END);
82-
m_label.set_max_width_chars(5);
83-
m_button.add_css_class("flat");
84-
m_extra_actions_button.add_css_class("flat");
85-
m_extra_actions_button.add_css_class("app-button-extras");
86-
m_extra_actions_button.set_halign(Gtk::Align::END);
87-
m_extra_actions_button.set_direction(Gtk::ArrowType::RIGHT);
88-
m_extra_actions_button.set_has_frame(false);
89-
m_extra_actions_button.set_icon_name("arrow-right");
90-
m_menu = Gio::Menu::create();
91-
m_actions = Gio::SimpleActionGroup::create();
92-
m_extra_actions_button.hide();
93106

94107
if (menu->menu_list)
95108
{
96-
m_padding_box.append(m_extra_actions_button);
97-
this->set_size_request(menu->menu_min_content_width, 48);
98-
for (auto action : app->list_actions())
109+
label.set_hexpand(true);
110+
label.set_halign(Gtk::Align::FILL);
111+
label.set_halign(Gtk::Align::START);
112+
label.set_xalign(0.0);
113+
list_item.set_hexpand(true);
114+
box.set_hexpand(true);
115+
set_hexpand(true);
116+
box.set_orientation(Gtk::Orientation::HORIZONTAL);
117+
extra_actions_button.set_halign(Gtk::Align::END);
118+
extra_actions_button.set_icon_name("arrow-right");
119+
button.add_css_class("flat");
120+
121+
list_item.append(image);
122+
list_item.append(label);
123+
button.set_child(list_item);
124+
125+
list_item.add_controller(left_click_g);
126+
list_item.add_controller(right_click_g);
127+
list_item.add_controller(long_press_g);
128+
129+
box.append(button);
130+
box.append(extra_actions_button);
131+
132+
set_child(box);
133+
} else
134+
{
135+
label.set_max_width_chars(0);
136+
box.set_orientation(Gtk::Orientation::VERTICAL);
137+
box.append(image);
138+
if (app->list_actions().size() == 0)
99139
{
100-
std::stringstream ss;
101-
ss << "app." << action;
102-
std::string full_action = ss.str();
140+
button.set_child(box);
141+
button.add_css_class("flat");
142+
set_child(button);
143+
} else
144+
{
145+
extra_actions_button.set_child(box);
146+
extra_actions_button.add_css_class("flat");
147+
set_child(extra_actions_button);
148+
}
103149

104-
auto menu_item = Gio::MenuItem::create(m_app_info->get_action_name(action), full_action);
150+
box.add_controller(left_click_g);
151+
box.add_controller(right_click_g);
152+
box.add_controller(long_press_g);
105153

106-
auto action_obj = Gio::SimpleAction::create(action);
107-
signals.push_back(action_obj->signal_activate().connect(
108-
[this, action] (Glib::VariantBase vb)
109-
{
110-
auto ctx = Gdk::Display::get_default()->get_app_launch_context();
111-
m_app_info->launch_action(action, ctx);
112-
menu->hide_menu();
113-
}));
114-
m_menu->append_item(menu_item);
115-
m_actions->add_action(action_obj);
116-
117-
m_extra_actions_button.show();
118-
}
154+
box.append(label);
155+
}
119156

120-
m_extra_actions_button.set_menu_model(m_menu);
157+
m_menu = Gio::Menu::create();
158+
actions = Gio::SimpleActionGroup::create();
159+
extra_actions_button.hide();
160+
161+
for (auto action : app->list_actions())
162+
{
163+
std::stringstream ss;
164+
ss << "app." << action;
165+
std::string full_action = ss.str();
166+
167+
auto menu_item = Gio::MenuItem::create(app_info->get_action_name(action), full_action);
168+
169+
auto action_obj = Gio::SimpleAction::create(action);
170+
signals.push_back(action_obj->signal_activate().connect(
171+
[this, action] (Glib::VariantBase vb)
172+
{
173+
auto ctx = Gdk::Display::get_default()->get_app_launch_context();
174+
app_info->launch_action(action, ctx);
175+
menu->hide_menu();
176+
}));
177+
m_menu->append_item(menu_item);
178+
actions->add_action(action_obj);
179+
180+
extra_actions_button.show();
121181
}
122182

123-
set_child(m_padding_box);
124-
add_css_class("app-button");
183+
extra_actions_button.set_menu_model(m_menu);
184+
extra_actions_button.insert_action_group("app", actions);
185+
125186
set_has_tooltip();
126187
signals.push_back(signal_query_tooltip().connect([=] (int x, int y, bool key_mode,
127188
const std::shared_ptr<Gtk::Tooltip>& tooltip) ->
@@ -130,54 +191,31 @@ WfMenuMenuItem::WfMenuMenuItem(WayfireMenu *_menu, Glib::RefPtr<Gio::DesktopAppI
130191
tooltip->set_text(app->get_name());
131192
return true;
132193
}, false));
133-
m_extra_actions_button.insert_action_group("app", m_actions);
134-
135-
auto click_gesture = Gtk::GestureClick::create();
136-
auto long_press = Gtk::GestureLongPress::create();
137-
long_press->set_touch_only(true);
138-
long_press->signal_pressed().connect(
139-
[=] (double x, double y)
140-
{
141-
m_extra_actions_button.activate();
142-
long_press->set_state(Gtk::EventSequenceState::CLAIMED);
143-
click_gesture->set_state(Gtk::EventSequenceState::DENIED);
144-
});
145-
click_gesture->set_button(3);
146-
signals.push_back(click_gesture->signal_pressed().connect([=] (int count, double x, double y)
147-
{
148-
click_gesture->set_state(Gtk::EventSequenceState::CLAIMED);
149-
}));
150-
signals.push_back(click_gesture->signal_released().connect([=] (int count, double x, double y)
151-
{
152-
m_extra_actions_button.activate();
153-
}));
154-
m_button.add_controller(long_press);
155-
m_button.add_controller(click_gesture);
156194
}
157195

158-
WfMenuMenuItem::~WfMenuMenuItem()
196+
WfMenuItem::~WfMenuItem()
159197
{
160198
for (auto signal : signals)
161199
{
162200
signal.disconnect();
163201
}
164202
}
165203

166-
void WfMenuMenuItem::on_click()
204+
void WfMenuItem::on_click()
167205
{
168206
auto ctx = Gdk::Display::get_default()->get_app_launch_context();
169-
m_app_info->launch(std::vector<Glib::RefPtr<Gio::File>>(), ctx);
207+
app_info->launch(std::vector<Glib::RefPtr<Gio::File>>(), ctx);
170208
menu->hide_menu();
171209
}
172210

173-
void WfMenuMenuItem::set_search_value(uint32_t value)
211+
void WfMenuItem::set_search_value(uint32_t value)
174212
{
175-
m_search_value = value;
213+
search_value = value;
176214
}
177215

178-
uint32_t WfMenuMenuItem::get_search_value()
216+
uint32_t WfMenuItem::get_search_value()
179217
{
180-
return m_search_value;
218+
return search_value;
181219
}
182220

183221
/* Fuzzy search for pattern in text. We use a greedy algorithm as follows:
@@ -209,12 +247,12 @@ static bool fuzzy_match(Glib::ustring text, Glib::ustring pattern)
209247
return i == pattern.length();
210248
}
211249

212-
uint32_t WfMenuMenuItem::fuzzy_match(Glib::ustring pattern)
250+
uint32_t WfMenuItem::fuzzy_match(Glib::ustring pattern)
213251
{
214252
uint32_t match_score = 0;
215-
Glib::ustring name = m_app_info->get_name();
216-
Glib::ustring long_name = m_app_info->get_display_name();
217-
Glib::ustring progr = m_app_info->get_executable();
253+
Glib::ustring name = app_info->get_name();
254+
Glib::ustring long_name = app_info->get_display_name();
255+
Glib::ustring progr = app_info->get_executable();
218256

219257
auto name_lower = name.lowercase();
220258
auto long_name_lower = long_name.lowercase();
@@ -239,13 +277,13 @@ uint32_t WfMenuMenuItem::fuzzy_match(Glib::ustring pattern)
239277
return match_score;
240278
}
241279

242-
uint32_t WfMenuMenuItem::matches(Glib::ustring pattern)
280+
uint32_t WfMenuItem::matches(Glib::ustring pattern)
243281
{
244282
uint32_t match_score = 0;
245-
Glib::ustring long_name = m_app_info->get_display_name();
246-
Glib::ustring name = m_app_info->get_name();
247-
Glib::ustring progr = m_app_info->get_executable();
248-
Glib::ustring descr = m_app_info->get_description();
283+
Glib::ustring long_name = app_info->get_display_name();
284+
Glib::ustring name = app_info->get_name();
285+
Glib::ustring progr = app_info->get_executable();
286+
Glib::ustring descr = app_info->get_description();
249287

250288
auto name_lower = name.lowercase();
251289
auto long_name_lower = long_name.lowercase();
@@ -280,10 +318,10 @@ uint32_t WfMenuMenuItem::matches(Glib::ustring pattern)
280318
return match_score;
281319
}
282320

283-
bool WfMenuMenuItem::operator <(const WfMenuMenuItem& other)
321+
bool WfMenuItem::operator <(const WfMenuItem& other)
284322
{
285-
return Glib::ustring(m_app_info->get_name()).lowercase() <
286-
Glib::ustring(other.m_app_info->get_name()).lowercase();
323+
return Glib::ustring(app_info->get_name()).lowercase() <
324+
Glib::ustring(other.app_info->get_name()).lowercase();
287325
}
288326

289327
void WayfireMenu::load_menu_item(AppInfo app_info)
@@ -384,7 +422,7 @@ void WayfireMenu::populate_menu_items(std::string category)
384422

385423
for (auto app_info : category_list[category]->items)
386424
{
387-
auto app = new WfMenuMenuItem(this, app_info);
425+
auto app = new WfMenuItem(this, app_info);
388426
flowbox.append(*app);
389427
}
390428
}
@@ -478,7 +516,7 @@ void WayfireMenu::on_search_changed()
478516

479517
bool WayfireMenu::on_filter(Gtk::FlowBoxChild *child)
480518
{
481-
auto button = dynamic_cast<WfMenuMenuItem*>(child);
519+
auto button = dynamic_cast<WfMenuItem*>(child);
482520
assert(button);
483521

484522
auto text = search_entry.get_text();
@@ -497,8 +535,8 @@ bool WayfireMenu::on_filter(Gtk::FlowBoxChild *child)
497535

498536
bool WayfireMenu::on_sort(Gtk::FlowBoxChild *a, Gtk::FlowBoxChild *b)
499537
{
500-
auto b1 = dynamic_cast<WfMenuMenuItem*>(a);
501-
auto b2 = dynamic_cast<WfMenuMenuItem*>(b);
538+
auto b1 = dynamic_cast<WfMenuItem*>(a);
539+
auto b2 = dynamic_cast<WfMenuItem*>(b);
502540
assert(b1 && b2);
503541

504542
if (m_sort_names)
@@ -606,7 +644,7 @@ void WayfireMenu::setup_popover_layout()
606644
auto children = flowbox.get_selected_children();
607645
if (children.size() == 1)
608646
{
609-
auto child = dynamic_cast<WfMenuMenuItem*>(children[0]);
647+
auto child = dynamic_cast<WfMenuItem*>(children[0]);
610648
child->on_click();
611649
}
612650

@@ -706,6 +744,14 @@ void WayfireMenu::update_popover_layout()
706744
popover_layout_box.remove(box_bottom);
707745
}
708746

747+
if (menu_list)
748+
{
749+
flowbox.set_max_children_per_line(1);
750+
} else
751+
{
752+
flowbox.set_max_children_per_line(-1);
753+
}
754+
709755
if ((std::string)panel_position == WF_WINDOW_POSITION_TOP)
710756
{
711757
popover_layout_box.append(search_entry);
@@ -933,6 +979,11 @@ void WayfireMenu::init(Gtk::Box *container)
933979

934980
// configuration reloading callbacks
935981
menu_icon.set_callback([=] () { update_icon(); });
982+
flowbox_spacing.set_callback([=] ()
983+
{
984+
flowbox.set_column_spacing(flowbox_spacing.value());
985+
flowbox.set_column_spacing(flowbox_spacing.value());
986+
});
936987
menu_min_category_width.set_callback([=] () { update_category_width(); });
937988
menu_min_content_height.set_callback([=] () { update_content_height(); });
938989
menu_min_content_width.set_callback([=] () { update_content_width(); });
@@ -1080,7 +1131,7 @@ void WayfireMenu::select_first_flowbox_item()
10801131
auto child = flowbox.get_child_at_index(0);
10811132
if (child)
10821133
{
1083-
auto cast_child = dynamic_cast<WfMenuMenuItem*>(child);
1134+
auto cast_child = dynamic_cast<WfMenuItem*>(child);
10841135
if (cast_child)
10851136
{
10861137
flowbox.select_child(*cast_child);

0 commit comments

Comments
 (0)