Alright here’s my code:
/*
* This file is part of budgie-desktop
*
* Copyright © 2015-2019 Budgie Desktop Developers
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
public class BudgieMenu : Budgie.Plugin, Peas.ExtensionBase
{
public Budgie.Applet get_panel_widget(string uuid)
{
return new BudgieMenuApplet(uuid);
}
}
[GtkTemplate (ui = "/com/solus-project/budgie-menu/settings.ui")]
public class BudgieMenuSettings : Gtk.Grid
{
[GtkChild]
private Gtk.Switch? switch_menu_label;
[GtkChild]
private Gtk.Switch? switch_menu_compact;
[GtkChild]
private Gtk.Switch? switch_menu_headers;
[GtkChild]
private Gtk.Switch? switch_menu_categories_hover;
[GtkChild]
private Gtk.Entry? entry_label;
[GtkChild]
private Gtk.Entry? entry_icon_pick;
[GtkChild]
private Gtk.Button? button_icon_pick;
private Settings? settings;
public BudgieMenuSettings(Settings? settings)
{
this.settings = settings;
settings.bind("enable-menu-label", switch_menu_label, "active", SettingsBindFlags.DEFAULT);
settings.bind("menu-compact", switch_menu_compact, "active", SettingsBindFlags.DEFAULT);
settings.bind("menu-headers", switch_menu_headers, "active", SettingsBindFlags.DEFAULT);
settings.bind("menu-categories-hover", switch_menu_categories_hover, "active", SettingsBindFlags.DEFAULT);
settings.bind("menu-label", entry_label, "text", SettingsBindFlags.DEFAULT);
settings.bind("menu-icon", entry_icon_pick, "text", SettingsBindFlags.DEFAULT);
this.button_icon_pick.clicked.connect(on_pick_click);
}
/**
* Handle the icon picker
*/
void on_pick_click()
{
IconChooser chooser = new IconChooser(this.get_toplevel() as Gtk.Window);
string? response = chooser.run();
chooser.destroy();
if (response != null) {
this.entry_icon_pick.set_text(response);
}
}
}
public class BudgieMenuApplet : Budgie.Applet
{
protected Gtk.ToggleButton widget;
protected BudgieMenuWindow? popover;
protected Settings settings;
Gtk.Image img;
Gtk.Label label;
Budgie.PanelPosition panel_position = Budgie.PanelPosition.BOTTOM;
int pixel_size = 32;
private unowned Budgie.PopoverManager? manager = null;
public string uuid { public set ; public get; }
public override Gtk.Widget? get_settings_ui()
{
return new BudgieMenuSettings(this.get_applet_settings(uuid));
}
public override bool supports_settings()
{
return true;
}
public BudgieMenuApplet(string uuid)
{
Object(uuid: uuid);
settings_schema = "com.solus-project.budgie-menu";
settings_prefix = "/com/solus-project/budgie-panel/instance/budgie-menu";
settings = this.get_applet_settings(uuid);
settings.changed.connect(on_settings_changed);
widget = new Gtk.ToggleButton();
widget.relief = Gtk.ReliefStyle.NONE;
img = new Gtk.Image.from_icon_name("view-grid-symbolic", Gtk.IconSize.INVALID);
img.pixel_size = pixel_size;
img.no_show_all = true;
var layout = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0);
layout.pack_start(img, true, true, 0);
label = new Gtk.Label("");
label.halign = Gtk.Align.START;
layout.pack_start(label, true, true, 3);
widget.add(layout);
// Better styling to fit in with the budgie-panel
var st = widget.get_style_context();
st.add_class("budgie-menu-launcher");
st.add_class("panel-button");
popover = new BudgieMenuWindow(settings, widget);
popover.bind_property("visible", widget, "active");
widget.button_press_event.connect((e)=> {
if (e.button != 1) {
return Gdk.EVENT_PROPAGATE;
}
if (popover.get_visible()) {
popover.hide();
} else {
popover.get_child().show_all();
this.manager.show_popover(widget);
}
return Gdk.EVENT_STOP;
});
popover.get_child().show_all();
supported_actions = Budgie.PanelAction.MENU;
add(widget);
show_all();
layout.valign = Gtk.Align.CENTER;
valign = Gtk.Align.FILL;
halign = Gtk.Align.FILL;
on_settings_changed("enable-menu-label");
on_settings_changed("menu-icon");
on_settings_changed("menu-label");
/* Potentially reload icon on pixel size jumps */
panel_size_changed.connect((p,i,s)=> {
if (this.pixel_size != i) {
this.pixel_size = (int)i;
this.on_settings_changed("menu-icon");
}
});
popover.key_release_event.connect((e)=> {
if (e.keyval == Gdk.Key.Escape) {
popover.hide();
}
return Gdk.EVENT_PROPAGATE;
});
}
public override void panel_position_changed(Budgie.PanelPosition position)
{
this.panel_position = position;
bool vertical = (position == Budgie.PanelPosition.LEFT || position == Budgie.PanelPosition.RIGHT);
int margin = vertical ? 0 : 3;
img.set_margin_end(margin);
on_settings_changed("enable-menu-label");
}
public override void invoke_action(Budgie.PanelAction action)
{
if ((action & Budgie.PanelAction.MENU) != 0) {
if (popover.get_visible()) {
popover.hide();
} else {
popover.get_child().show_all();
this.manager.show_popover(widget);
}
}
}
protected void on_settings_changed(string key)
{
bool should_show = true;
switch (key)
{
case "menu-icon":
string? icon = settings.get_string(key);
if ("/" in icon) {
try {
Gdk.Pixbuf pixbuf = new Gdk.Pixbuf.from_file(icon);
img.set_from_pixbuf(pixbuf.scale_simple(this.pixel_size, this.pixel_size, Gdk.InterpType.BILINEAR));
} catch (Error e) {
warning("Failed to update Budgie Menu applet icon: %s", e.message);
img.set_from_icon_name("view-grid-symbolic", Gtk.IconSize.INVALID); // Revert to view-grid-symbolic
}
} else if (icon == "") {
should_show = false;
} else {
img.set_from_icon_name(icon, Gtk.IconSize.INVALID);
}
img.set_pixel_size(this.pixel_size);
img.set_visible(should_show);
break;
case "menu-label":
label.set_label(settings.get_string(key));
break;
case "enable-menu-label":
bool visible = (panel_position == Budgie.PanelPosition.TOP ||
panel_position == Budgie.PanelPosition.BOTTOM) &&
settings.get_boolean(key);
label.set_visible(visible);
break;
default:
break;
}
}
public override void update_popovers(Budgie.PopoverManager? manager)
{
this.manager = manager;
manager.register_popover(widget, popover);
}
} // End class
[ModuleInit]
public void peas_register_types(TypeModule module)
{
// boilerplate - all modules need this
var objmodule = module as Peas.ObjectModule;
objmodule.register_extension_type(typeof(Budgie.Plugin), typeof(BudgieMenu));
}
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=4 expandtab:
* :indentSize=4:tabSize=4:noTabs=true:
*/
/*
* This file is part of budgie-desktop
*
* Copyright © 2015-2019 Budgie Desktop Developers
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
public class PlacesIndicator : Budgie.Plugin, Peas.ExtensionBase
{
public Budgie.Applet get_panel_widget(string uuid) {
return new PlacesIndicatorApplet(uuid);
}
}
[GtkTemplate (ui = "/com/solus-project/places-indicator/settings.ui")]
public class PlacesIndicatorSettings : Gtk.Grid
{
[GtkChild]
private Gtk.Switch? switch_label;
[GtkChild]
private Gtk.Switch? switch_places;
[GtkChild]
private Gtk.Switch? switch_expand_places;
[GtkChild]
private Gtk.Switch? switch_drives;
[GtkChild]
private Gtk.Switch? switch_networks;
private GLib.Settings? settings;
public PlacesIndicatorSettings(GLib.Settings? settings)
{
this.settings = settings;
settings.bind("show-label", switch_label, "active", GLib.SettingsBindFlags.DEFAULT);
settings.bind("expand-places", switch_expand_places, "active", GLib.SettingsBindFlags.DEFAULT);
settings.bind("show-places", switch_places, "active", GLib.SettingsBindFlags.DEFAULT);
settings.bind("show-drives", switch_drives, "active", GLib.SettingsBindFlags.DEFAULT);
settings.bind("show-networks", switch_networks, "active", GLib.SettingsBindFlags.DEFAULT);
}
}
public class PlacesIndicatorApplet : Budgie.Applet
{
private Gtk.EventBox? ebox;
private PlacesIndicatorWindow? popover;
private Gtk.Label label;
private Gtk.Image image;
private Budgie.PanelPosition panel_position = Budgie.PanelPosition.BOTTOM;
private unowned Budgie.PopoverManager? manager = null;
private GLib.Settings settings;
public string uuid { public set ; public get; }
public override Gtk.Widget? get_settings_ui() {
return new PlacesIndicatorSettings(get_applet_settings(uuid));
}
public override bool supports_settings() {
return true;
}
public PlacesIndicatorApplet(string uuid)
{
Object(uuid: uuid);
settings_schema = "com.solus-project.places-indicator";
settings_prefix = "/com/solus-project/budgie-panel/instance/places-indicator";
settings = get_applet_settings(uuid);
settings.changed.connect(on_settings_changed);
ebox = new Gtk.EventBox();
Gtk.Box layout = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0);
ebox.add(layout);
image = new Gtk.Image.from_icon_name("folder-symbolic", Gtk.IconSize.MENU);
layout.pack_start(image, true, true, 3);
label = new Gtk.Label(_("Places"));
label.halign = Gtk.Align.START;
layout.pack_start(label, true, true, 3);
popover = new PlacesIndicatorWindow(image);
ebox.button_press_event.connect((e)=> {
if (e.button != 1) {
return Gdk.EVENT_PROPAGATE;
}
toggle_popover();
return Gdk.EVENT_STOP;
});
popover.get_child().show_all();
add(ebox);
show_all();
on_settings_changed("show-label");
on_settings_changed("expand-places");
on_settings_changed("show-places");
on_settings_changed("show-drives");
on_settings_changed("show-networks");
}
public override void panel_position_changed(Budgie.PanelPosition position)
{
this.panel_position = position;
on_settings_changed("show-label");
}
public void toggle_popover()
{
if (popover.get_visible()) {
popover.hide();
} else {
popover.get_child().show_all();
this.manager.show_popover(ebox);
}
}
public override void invoke_action(Budgie.PanelAction action) {
toggle_popover();
}
public override void update_popovers(Budgie.PopoverManager? manager)
{
this.manager = manager;
manager.register_popover(ebox, popover);
}
protected void on_settings_changed(string key)
{
switch (key)
{
case "show-label":
bool visible = (panel_position == Budgie.PanelPosition.TOP ||
panel_position == Budgie.PanelPosition.BOTTOM) &&
settings.get_boolean(key);
label.set_visible(visible);
break;
case "expand-places":
popover.expand_places = settings.get_boolean(key);
break;
case "show-places":
popover.show_places = settings.get_boolean(key);
break;
case "show-drives":
popover.show_drives = settings.get_boolean(key);
break;
case "show-networks":
popover.show_networks = settings.get_boolean(key);
break;
default:
break;
}
}
}
[ModuleInit]
public void peas_register_types(TypeModule module)
{
// boilerplate - all modules need this
var objmodule = module as Peas.ObjectModule;
objmodule.register_extension_type(typeof(Budgie.Plugin), typeof(PlacesIndicator));
}
Doesn’t show up in Budgie Desktop Settings. budgie-panel --replace
throws:
** (budgie-panel:3392): WARNING **: 13:31:15.501: BudgieMenuWindow.vala:190: Software has no parent directory, not adding to menu
I have it in the /usr/lib… dir (along with all other necessary files, ofc). What’s wrong with this @fossfreedom ?
Line 190: }
(with a ton of leading spaces that markdown doesn’t wanna show)