diff options
author | Aylur <[email protected]> | 2024-09-22 00:16:56 +0000 |
---|---|---|
committer | Aylur <[email protected]> | 2024-09-22 00:16:56 +0000 |
commit | bcd912764fb6a709284aaa07399403d045a50ef2 (patch) | |
tree | 0a313dc788e3f390aab1d810f5f59911623431ea /examples | |
parent | 5ae0a9ed1cba13242d12ffe2ad4848eac7dd8915 (diff) |
examples: add vala bar
Diffstat (limited to 'examples')
-rw-r--r-- | examples/vala/simple-bar/README.md | 13 | ||||
-rw-r--r-- | examples/vala/simple-bar/app.in.vala | 15 | ||||
-rw-r--r-- | examples/vala/simple-bar/app.vala | 14 | ||||
-rw-r--r-- | examples/vala/simple-bar/flake.lock | 62 | ||||
-rw-r--r-- | examples/vala/simple-bar/flake.nix | 23 | ||||
-rw-r--r-- | examples/vala/simple-bar/meson.build | 38 | ||||
-rw-r--r-- | examples/vala/simple-bar/style.scss | 88 | ||||
-rw-r--r-- | examples/vala/simple-bar/widget/Bar.vala | 215 |
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 + + + +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(); |