summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorAylur <[email protected]>2024-09-22 00:16:56 +0000
committerAylur <[email protected]>2024-09-22 00:16:56 +0000
commitbcd912764fb6a709284aaa07399403d045a50ef2 (patch)
tree0a313dc788e3f390aab1d810f5f59911623431ea /examples
parent5ae0a9ed1cba13242d12ffe2ad4848eac7dd8915 (diff)
examples: add vala bar
Diffstat (limited to 'examples')
-rw-r--r--examples/vala/simple-bar/README.md13
-rw-r--r--examples/vala/simple-bar/app.in.vala15
-rw-r--r--examples/vala/simple-bar/app.vala14
-rw-r--r--examples/vala/simple-bar/flake.lock62
-rw-r--r--examples/vala/simple-bar/flake.nix23
-rw-r--r--examples/vala/simple-bar/meson.build38
-rw-r--r--examples/vala/simple-bar/style.scss88
-rw-r--r--examples/vala/simple-bar/widget/Bar.vala215
8 files changed, 373 insertions, 95 deletions
diff --git a/examples/vala/simple-bar/README.md b/examples/vala/simple-bar/README.md
new file mode 100644
index 0000000..997e4bf
--- /dev/null
+++ b/examples/vala/simple-bar/README.md
@@ -0,0 +1,13 @@
+# Simple Bar Example
+
+![simple-bar](https://github.com/user-attachments/assets/a306c864-56b7-44c4-8820-81f424f32b9b)
+
+A simple bar for Hyprland using
+
+- [Audio library](https://aylur.github.io/astal/libraries/audio).
+- [Battery library](https://aylur.github.io/astal/libraries/battery).
+- [Hyprland library](https://aylur.github.io/astal/libraries/hyprland).
+- [Mpris library](https://aylur.github.io/astal/libraries/mpris).
+- [Network library](https://aylur.github.io/astal/libraries/network).
+- [Tray library](https://aylur.github.io/astal/libraries/tray).
+- [WirePlumber library](https://aylur.github.io/astal/libraries/wireplumber).
diff --git a/examples/vala/simple-bar/app.in.vala b/examples/vala/simple-bar/app.in.vala
new file mode 100644
index 0000000..1d61b3a
--- /dev/null
+++ b/examples/vala/simple-bar/app.in.vala
@@ -0,0 +1,15 @@
+class App : Astal.Application {
+ public static App instance;
+
+ public override void activate () {
+ foreach (var mon in this.monitors)
+ add_window(new Bar(mon));
+
+ apply_css("@STYLE@");
+ }
+
+ public static int main() {
+ App.instance = new App();
+ return App.instance.run(null);
+ }
+}
diff --git a/examples/vala/simple-bar/app.vala b/examples/vala/simple-bar/app.vala
deleted file mode 100644
index ccd3957..0000000
--- a/examples/vala/simple-bar/app.vala
+++ /dev/null
@@ -1,14 +0,0 @@
-class Application : Astal.Application {
- Application() {
-
- }
-
- public override void activate () {
- this.add_window(new Bar());
- }
-
- public static int main() {
- var app = new Application();
- return app.run(null);
- }
-}
diff --git a/examples/vala/simple-bar/flake.lock b/examples/vala/simple-bar/flake.lock
deleted file mode 100644
index 34fb84f..0000000
--- a/examples/vala/simple-bar/flake.lock
+++ /dev/null
@@ -1,62 +0,0 @@
-{
- "nodes": {
- "astal": {
- "inputs": {
- "nixpkgs": "nixpkgs"
- },
- "locked": {
- "lastModified": 1726702968,
- "narHash": "sha256-kRS/WZzwBiVgfBVz0HTRl4FnmUEHDIRp0962rrFtvk8=",
- "owner": "aylur",
- "repo": "astal",
- "rev": "a819c41afcdde7b4bbe0ecf04dc8a84c87cc3c75",
- "type": "github"
- },
- "original": {
- "owner": "aylur",
- "repo": "astal",
- "type": "github"
- }
- },
- "nixpkgs": {
- "locked": {
- "lastModified": 1716293225,
- "narHash": "sha256-pU9ViBVE3XYb70xZx+jK6SEVphvt7xMTbm6yDIF4xPs=",
- "owner": "nixos",
- "repo": "nixpkgs",
- "rev": "3eaeaeb6b1e08a016380c279f8846e0bd8808916",
- "type": "github"
- },
- "original": {
- "owner": "nixos",
- "ref": "nixos-unstable",
- "repo": "nixpkgs",
- "type": "github"
- }
- },
- "nixpkgs_2": {
- "locked": {
- "lastModified": 1726463316,
- "narHash": "sha256-gI9kkaH0ZjakJOKrdjaI/VbaMEo9qBbSUl93DnU7f4c=",
- "owner": "nixos",
- "repo": "nixpkgs",
- "rev": "99dc8785f6a0adac95f5e2ab05cc2e1bf666d172",
- "type": "github"
- },
- "original": {
- "owner": "nixos",
- "ref": "nixos-unstable",
- "repo": "nixpkgs",
- "type": "github"
- }
- },
- "root": {
- "inputs": {
- "astal": "astal",
- "nixpkgs": "nixpkgs_2"
- }
- }
- },
- "root": "root",
- "version": 7
-}
diff --git a/examples/vala/simple-bar/flake.nix b/examples/vala/simple-bar/flake.nix
index 9b977a2..78bfb62 100644
--- a/examples/vala/simple-bar/flake.nix
+++ b/examples/vala/simple-bar/flake.nix
@@ -14,21 +14,26 @@
in {
packages.${system} = {
default = pkgs.stdenv.mkDerivation {
- pname = "simple-bar";
- version = "git";
+ name = "simple-bar";
src = ./.;
- nativeBuildInputs = [
- pkgs.meson
- pkgs.ninja
- pkgs.pkg-config
- pkgs.vala
- pkgs.gobject-introspection
+ nativeBuildInputs = with pkgs; [
+ meson
+ ninja
+ pkg-config
+ vala
+ gobject-introspection
+ dart-sass
];
buildInputs = [
- astal.packages.${system}.default
+ astal.packages.${system}.astal
astal.packages.${system}.battery
+ astal.packages.${system}.wireplumber
+ astal.packages.${system}.network
+ astal.packages.${system}.tray
+ astal.packages.${system}.mpris
+ astal.packages.${system}.hyprland
];
};
};
diff --git a/examples/vala/simple-bar/meson.build b/examples/vala/simple-bar/meson.build
index 960ce0d..d0ef209 100644
--- a/examples/vala/simple-bar/meson.build
+++ b/examples/vala/simple-bar/meson.build
@@ -1,23 +1,51 @@
project('simple-bar', 'vala', 'c')
-sources = files(
- 'widget/Bar.vala',
- 'app.vala',
-)
+bindir = get_option('prefix') / get_option('bindir')
+libdir = get_option('prefix') / get_option('libdir')
pkgconfig_deps = [
dependency('glib-2.0'),
dependency('gobject-2.0'),
dependency('gtk+-3.0'),
+ dependency('libnm'),
dependency('astal-0.1'),
dependency('astal-battery-0.1'),
+ dependency('astal-wireplumber-0.1'),
+ dependency('astal-network-0.1'),
+ dependency('astal-tray-0.1'),
+ dependency('astal-mpris-0.1'),
+ dependency('astal-hyprland-0.1'),
]
# needed for GLib.Math
deps = pkgconfig_deps + meson.get_compiler('c').find_library('m')
+custom_target(
+ 'style.css',
+ command: [
+ find_program('sass'),
+ meson.project_source_root() / 'style.scss',
+ '@OUTPUT@',
+ ],
+ output: 'style.css',
+ install: true,
+ install_dir: libdir,
+)
+
+main = configure_file(
+ input: 'app.in.vala',
+ output: 'app.vala',
+ configuration: {'STYLE': libdir / 'style.css'},
+)
+
+sources = files(
+ 'widget/Bar.vala',
+)
+
executable(
'simple-bar',
- sources,
+ [sources, main],
dependencies: deps,
+ install: true,
+ install_dir: bindir,
)
diff --git a/examples/vala/simple-bar/style.scss b/examples/vala/simple-bar/style.scss
new file mode 100644
index 0000000..f98286e
--- /dev/null
+++ b/examples/vala/simple-bar/style.scss
@@ -0,0 +1,88 @@
+$bg: #212223;
+$fg: #f1f1f1;
+$accent: #378DF7;
+$radius: 7px;
+
+window.Bar {
+ border: none;
+ box-shadow: none;
+ background-color: $bg;
+ color: $fg;
+ font-size: 1.1em;
+ font-weight: bold;
+
+ button {
+ all: unset;
+ background-color: transparent;
+
+ &:hover label {
+ background-color: transparentize($fg, 0.84);
+ border-color: transparentize($accent, 0.8);
+ }
+
+ &:active label {
+ background-color: transparentize($fg, 0.8)
+ }
+ }
+
+ label {
+ transition: 200ms;
+ padding: 0 8px;
+ margin: 2px;
+ border-radius: $radius;
+ border: 1pt solid transparent;
+ }
+
+ .Workspaces .focused label {
+ color: $accent;
+ border-color: $accent;
+ }
+
+ .FocusedClient {
+ color: $accent;
+ }
+
+ .Media .Cover {
+ min-height: 1.2em;
+ min-width: 1.2em;
+ border-radius: $radius;
+ background-position: center;
+ background-size: contain;
+ }
+
+ .Battery label {
+ padding-left: 0;
+ margin-left: 0;
+ }
+
+ .AudioSlider {
+ * {
+ all: unset;
+ }
+
+ icon {
+ margin-right: .6em;
+ }
+
+ margin: 0 1em;
+
+ trough {
+ background-color: transparentize($fg, 0.8);
+ border-radius: $radius;
+ }
+
+ highlight {
+ background-color: $accent;
+ min-height: .8em;
+ border-radius: $radius;
+ }
+
+ slider {
+ background-color: $fg;
+ border-radius: $radius;
+ min-height: 1em;
+ min-width: 1em;
+ margin: -.2em;
+ }
+ }
+}
diff --git a/examples/vala/simple-bar/widget/Bar.vala b/examples/vala/simple-bar/widget/Bar.vala
index 4d42f9c..438e8b7 100644
--- a/examples/vala/simple-bar/widget/Bar.vala
+++ b/examples/vala/simple-bar/widget/Bar.vala
@@ -1,3 +1,175 @@
+class Workspaces : Gtk.Box {
+ AstalHyprland.Hyprland hypr = AstalHyprland.get_default();
+ public Workspaces() {
+ Astal.widget_set_class_names(this, {"Workspaces"});
+ hypr.notify["workspaces"].connect(sync);
+ sync();
+ }
+
+ void sync() {
+ foreach (var child in get_children())
+ child.destroy();
+
+ foreach (var ws in hypr.workspaces)
+ add(button(ws));
+ }
+
+ Gtk.Button button(AstalHyprland.Workspace ws) {
+ var btn = new Gtk.Button() {
+ visible = true,
+ label = ws.id.to_string()
+ };
+
+ hypr.notify["focused-workspace"].connect(() => {
+ var focused = hypr.focused_workspace == ws;
+ if (focused) {
+ Astal.widget_set_class_names(btn, {"focused"});
+ } else {
+ Astal.widget_set_class_names(btn, {});
+ }
+ });
+
+ btn.clicked.connect(ws.focus);
+ return btn;
+ }
+}
+
+class FocusedClient : Gtk.Box {
+ public FocusedClient() {
+ Astal.widget_set_class_names(this, {"Focused"});
+ AstalHyprland.get_default().notify["focused-client"].connect(sync);
+ sync();
+ }
+
+ void sync() {
+ foreach (var child in get_children())
+ child.destroy();
+
+ var client = AstalHyprland.get_default().focused_client;
+ if (client == null)
+ return;
+
+ var label = new Gtk.Label(client.title) { visible = true };
+ client.bind_property("title", label, "label", BindingFlags.SYNC_CREATE);
+ add(label);
+ }
+}
+
+class Media : Gtk.Box {
+ AstalMpris.Mpris mpris = AstalMpris.get_default();
+
+ public Media() {
+ Astal.widget_set_class_names(this, {"Media"});
+ mpris.notify["players"].connect(sync);
+ sync();
+ }
+
+ void sync() {
+ foreach (var child in get_children())
+ child.destroy();
+
+ if (mpris.players.length() == 0) {
+ add(new Gtk.Label("Nothing Playing"));
+ return;
+ }
+
+ var player = mpris.players.nth_data(0);
+ var label = new Gtk.Label(null);
+ var cover = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0) {
+ valign = Gtk.Align.CENTER
+ };
+
+ Astal.widget_set_class_names(cover, {"Cover"});
+ player.bind_property("title", label, "label", BindingFlags.SYNC_CREATE, (_, src, ref trgt) => {
+ var title = player.title;
+ var artist = player.artist;
+ trgt.set_string(@"$artist - $title");
+ return true;
+ });
+
+ var id = player.notify["cover-art"].connect(() => {
+ var art = player.cover_art;
+ Astal.widget_set_css(cover, @"background-image: url('$art')");
+ });
+
+ cover.destroy.connect(() => player.disconnect(id));
+ add(cover);
+ add(label);
+ }
+}
+
+class SysTray : Gtk.Box {
+ HashTable<string, Gtk.Widget> items = new HashTable<string, Gtk.Widget>(str_hash, str_equal);
+ AstalTray.Tray tray = AstalTray.get_default();
+
+ public SysTray() {
+ tray.item_added.connect(add_item);
+ tray.item_removed.connect(remove_item);
+ }
+
+ void add_item(string id) {
+ if (items.contains(id))
+ return;
+
+ var item = tray.get_item(id);
+
+ if (item.icon_theme_path != null)
+ App.instance.add_icons(item.icon_theme_path);
+
+ var menu = item.create_menu();
+ var btn = new Astal.Button();
+ var icon = new Astal.Icon();
+
+ btn.clicked.connect(() => {
+ if (menu != null)
+ menu.popup_at_widget(this, Gdk.Gravity.SOUTH, Gdk.Gravity.NORTH, null);
+ });
+
+ btn.destroy.connect(() => {
+ if (menu != null)
+ menu.destroy();
+ });
+
+ item.bind_property("tooltip-markup", btn, "tooltip-markup", BindingFlags.SYNC_CREATE);
+ item.bind_property("gicon", icon, "gicon", BindingFlags.SYNC_CREATE);
+ add(btn);
+ items.set(id, btn);
+ }
+
+ void remove_item(string id) {
+ if (!items.contains(id))
+ return;
+
+ items.remove(id);
+ }
+}
+
+class Wifi : Astal.Icon {
+ public Wifi() {
+ Astal.widget_set_class_names(this, {"Wifi"});
+ var wifi = AstalNetwork.get_default().wifi;
+ wifi.bind_property("ssid", this, "tooltip-text", BindingFlags.SYNC_CREATE);
+ wifi.bind_property("icon-name", this, "icon", BindingFlags.SYNC_CREATE);
+ }
+}
+
+class AudioSlider : Gtk.Box {
+ Astal.Icon icon = new Astal.Icon();
+ Astal.Slider slider = new Astal.Slider() { hexpand = true };
+
+ public AudioSlider() {
+ add(icon);
+ add(slider);
+ Astal.widget_set_class_names(this, {"AudioSlider"});
+ Astal.widget_set_css(this, "min-width: 140px");
+
+ var speaker = AstalWp.get_default().audio.default_speaker;
+ speaker.bind_property("volume-icon", icon, "icon", BindingFlags.SYNC_CREATE);
+ speaker.bind_property("volume", slider, "value", BindingFlags.SYNC_CREATE);
+ slider.dragged.connect(() => speaker.volume = slider.value);
+ }
+}
+
class Battery : Gtk.Box {
Astal.Icon icon = new Astal.Icon();
Astal.Label label = new Astal.Label();
@@ -5,8 +177,10 @@ class Battery : Gtk.Box {
public Battery() {
add(icon);
add(label);
+ Astal.widget_set_class_names(this, {"Battery"});
var bat = AstalBattery.get_default();
+ bat.bind_property("is-present", this, "visible", BindingFlags.SYNC_CREATE);
bat.bind_property("battery-icon-name", icon, "icon", BindingFlags.SYNC_CREATE);
bat.bind_property("percentage", label, "label", BindingFlags.SYNC_CREATE, (_, src, ref trgt) => {
var p = Math.floor(src.get_double() * 100);
@@ -16,7 +190,7 @@ class Battery : Gtk.Box {
}
}
-class Clock : Astal.Label {
+class Time : Astal.Label {
string format;
Astal.Time interval;
@@ -24,25 +198,56 @@ class Clock : Astal.Label {
label = new DateTime.now_local().format(format);
}
- public Clock(string format = "%H:%M - %A %e.") {
+ public Time(string format = "%H:%M - %A %e.") {
this.format = format;
interval = Astal.Time.interval(1000, null);
interval.now.connect(sync);
destroy.connect(interval.cancel);
+ Astal.widget_set_class_names(this, {"Time"});
}
}
class Left : Gtk.Box {
public Left() {
- add(new Clock());
+ Object(hexpand: true, halign: Gtk.Align.START);
+ add(new Workspaces());
+ add(new FocusedClient());
+ }
+}
+
+class Center : Gtk.Box {
+ public Center() {
+ add(new Media());
+ }
+}
+
+class Right : Gtk.Box {
+ public Right() {
+ Object(hexpand: true, halign: Gtk.Align.END);
+ add(new SysTray());
+ add(new Wifi());
+ add(new AudioSlider());
add(new Battery());
+ add(new Time());
}
}
class Bar : Astal.Window {
- public Bar() {
+ public Bar(Gdk.Monitor monitor) {
+ Object(
+ anchor: Astal.WindowAnchor.TOP
+ | Astal.WindowAnchor.LEFT
+ | Astal.WindowAnchor.RIGHT,
+ exclusivity: Astal.Exclusivity.EXCLUSIVE,
+ gdkmonitor: monitor
+ );
+
+ Astal.widget_set_class_names(this, {"Bar"});
+
add(new Astal.CenterBox() {
- start_widget = new Left()
+ start_widget = new Left(),
+ center_widget = new Center(),
+ end_widget = new Right(),
});
show_all();