From 2e12fa26c45e0efda298e2a702ab5916527603d6 Mon Sep 17 00:00:00 2001 From: Vasiliy Doylov Date: Sat, 15 Mar 2025 17:37:54 +0300 Subject: [PATCH] Add floating window logic Signed-off-by: Vasiliy Doylov --- data/io.gitlab.nekocwd.pipetap.gschema.xml | 22 +++- data/meson.build | 4 +- src/application.vala | 17 ++- src/gui/main_bar.blp | 75 +++++++++++ src/gui/main_bar.vala | 6 + src/gui/window.blp | 50 ++++++++ src/gui/window.vala | 121 ++++++++++++++++++ src/icons/angled-arrows-symbolic.svg | 2 + src/icons/camera-focus-symbolic.svg | 2 + src/icons/camera-iso-symbolic.svg | 2 + src/icons/camera-photo-symbolic.svg | 7 + ...ouble-ended-arrows-horizontal-symbolic.svg | 2 + .../double-ended-arrows-vertical-symbolic.svg | 2 + src/icons/left-large-symbolic.svg | 2 + src/icons/move-tool-symbolic.svg | 2 + src/icons/right-large-symbolic.svg | 2 + src/meson.build | 6 +- src/pipetap.gresource.xml | 17 ++- src/style.css | 3 + src/window.blp | 48 ------- src/window.vala | 41 ------ 21 files changed, 335 insertions(+), 98 deletions(-) create mode 100644 src/gui/main_bar.blp create mode 100644 src/gui/main_bar.vala create mode 100644 src/gui/window.blp create mode 100644 src/gui/window.vala create mode 100644 src/icons/angled-arrows-symbolic.svg create mode 100644 src/icons/camera-focus-symbolic.svg create mode 100644 src/icons/camera-iso-symbolic.svg create mode 100644 src/icons/camera-photo-symbolic.svg create mode 100644 src/icons/double-ended-arrows-horizontal-symbolic.svg create mode 100644 src/icons/double-ended-arrows-vertical-symbolic.svg create mode 100644 src/icons/left-large-symbolic.svg create mode 100644 src/icons/move-tool-symbolic.svg create mode 100644 src/icons/right-large-symbolic.svg create mode 100644 src/style.css delete mode 100644 src/window.blp delete mode 100644 src/window.vala diff --git a/data/io.gitlab.nekocwd.pipetap.gschema.xml b/data/io.gitlab.nekocwd.pipetap.gschema.xml index 6d62d31..9876709 100644 --- a/data/io.gitlab.nekocwd.pipetap.gschema.xml +++ b/data/io.gitlab.nekocwd.pipetap.gschema.xml @@ -1,5 +1,23 @@ - + + + 0 + + + 0 + + + 0 + + + 0 + + + false + - + + + + \ No newline at end of file diff --git a/data/meson.build b/data/meson.build index ce4c2d0..1df2113 100644 --- a/data/meson.build +++ b/data/meson.build @@ -28,7 +28,9 @@ test( ) install_data( - 'io.gitlab.nekocwd.pipetap.gschema.xml', + [ + 'io.gitlab.nekocwd.pipetap.gschema.xml', + ], install_dir: get_option('datadir') / 'glib-2.0' / 'schemas', ) diff --git a/src/application.vala b/src/application.vala index e355519..e7f6784 100644 --- a/src/application.vala +++ b/src/application.vala @@ -19,6 +19,9 @@ */ public class PipeTap.Application : Adw.Application { + public Settings settings; + public bool adjust_overlay_visible { get; set; } + public Application () { Object ( application_id: "io.gitlab.nekocwd.pipetap", @@ -30,15 +33,25 @@ public class PipeTap.Application : Adw.Application { ActionEntry[] action_entries = { { "about", this.on_about_action }, { "preferences", this.on_preferences_action }, - { "quit", this.quit } + { "quit", this.quit }, + { "adjust-overlays", () => { adjust_overlay_visible = !adjust_overlay_visible; } } }; this.add_action_entries (action_entries, this); this.set_accels_for_action ("app.quit", { "q" }); + settings = new Settings ("io.gitlab.nekocwd.pipetap"); } public override void activate () { base.activate (); - var win = this.active_window ?? new PipeTap.Window (this); + + var styling = new Gtk.CssProvider (); + styling.load_from_resource ("/io/gitlab/nekocwd/pipetap/style.css"); + Gtk.StyleContext.add_provider_for_display (Gdk.Display.get_default (), + styling, + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + + var win = this.active_window ?? new PipeTap.Ui.MainBar (this); + var win2 = new PipeTap.Ui.MainBar (this); win.present (); } diff --git a/src/gui/main_bar.blp b/src/gui/main_bar.blp new file mode 100644 index 0000000..e9fb49c --- /dev/null +++ b/src/gui/main_bar.blp @@ -0,0 +1,75 @@ +using Gtk 4.0; +using Adw 1; + +template $PipeTapUiMainBar: $PipeTapUiFloatingWindow { + title: _("PipeTap"); + window-name: "main-controls"; + default-width: 60; + default-height: 60; + + content: Gtk.Box { + orientation: bind template.orientation; + halign: fill; + homogeneous: true; + spacing: 10; + + Gtk.Button { + icon-name: "camera-iso-symbolic"; + tooltip-text: _("Exposure"); + + styles [ + "flat", + ] + } + + Gtk.Button { + icon-name: "camera-focus-symbolic"; + tooltip-text: _("Focus"); + + styles [ + "flat", + ] + } + + Gtk.MenuButton { + primary: true; + icon-name: "open-menu-symbolic"; + tooltip-text: _("Main Menu"); + menu-model: primary_menu; + + styles [ + "flat", + ] + } + }; +} + +menu primary_menu { + section { + item { + label: _("_Adjust overlays"); + action: "app.adjust-overlays"; + } + + item { + label: _("_Preferences"); + action: "app.preferences"; + } + + /* + item { + label: _("_Keyboard Shortcuts"); + action: "win.show-help-overlay"; + } + */ + item { + label: _("_About PipeTap"); + action: "app.about"; + } + + item { + label: _("Quit"); + action: "app.quit"; + } + } +} diff --git a/src/gui/main_bar.vala b/src/gui/main_bar.vala new file mode 100644 index 0000000..f9709a7 --- /dev/null +++ b/src/gui/main_bar.vala @@ -0,0 +1,6 @@ +[GtkTemplate (ui = "/io/gitlab/nekocwd/pipetap/gui/main_bar.ui")] +public class PipeTap.Ui.MainBar : PipeTap.Ui.FloatingWindow { + public MainBar (Gtk.Application app) { + base (app); + } +} \ No newline at end of file diff --git a/src/gui/window.blp b/src/gui/window.blp new file mode 100644 index 0000000..dfd6b96 --- /dev/null +++ b/src/gui/window.blp @@ -0,0 +1,50 @@ +using Gtk 4.0; +using Adw 1; + +template $PipeTapUiFloatingWindow: Gtk.Window { + title: _("PipeTap"); + default-width: 800; + default-height: 100; + + styles [ + "pt-transparent", + "osd", + ] + + Box { + orientation: bind template.orientation; + + Button resize { + visible: bind template.resize-visible; + + styles [ + "flat", + ] + } + + Adw.Bin content_bin { + valign: fill; + halign: fill; + hexpand: true; + vexpand: true; + } + + Button rotate { + visible: bind template.rotate-visible; + icon-name: "angled-arrows-symbolic"; + + styles [ + "flat", + ] + } + + Button move { + visible: bind template.move-visible; + icon-name: "move-tool-symbolic"; + + styles [ + "flat", + ] + } + } +} diff --git a/src/gui/window.vala b/src/gui/window.vala new file mode 100644 index 0000000..aa851b9 --- /dev/null +++ b/src/gui/window.vala @@ -0,0 +1,121 @@ +/* window.vala + * + * Copyright 2025 Vasiliy Doylov + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +/* + * That's shitcode!!!! + * TODO: Refactor it before first release (or at least somewhen) + */ + +[GtkTemplate (ui = "/io/gitlab/nekocwd/pipetap/gui/window.ui")] +public class PipeTap.Ui.FloatingWindow : Gtk.Window, Gtk.Orientable { + [GtkChild] + private unowned Gtk.Button move; + [GtkChild] + private unowned Gtk.Button resize; + [GtkChild] + private unowned Gtk.Button rotate; + [GtkChild] + private unowned Adw.Bin content_bin; + + public Gtk.Orientation orientation { get; set; default = Gtk.Orientation.HORIZONTAL; } + + public bool resize_visible { get; set; } + public bool rotate_visible { get; set; } + public bool move_visible { get; set; } + + public string window_name { get; set; default = ""; } + + protected double pos_sy { get; set; } + protected double pos_sx { get; set; } + protected double pos_ex { get; set; } + protected double pos_ey { get; set; } + + public Gtk.Widget content { get { return content_bin.get_child (); } set { content_bin.set_child (value); } } + + public FloatingWindow (Gtk.Application app) { + Object (application: app); + GtkLayerShell.init_for_window (this); + + var move_controller = new Gtk.GestureDrag (); + move_controller.drag_update.connect ((ox, oy) => { + pos_sy += (int) oy; + pos_sx -= (int) ox; + }); + move_controller.end.connect (move_controller.reset); + move.add_controller (move_controller); + + var resize_controller = new Gtk.GestureDrag (); + resize_controller.drag_update.connect ((ox, oy) => { + pos_ex += (int) ox; + pos_ey += (int) oy; + }); + resize_controller.end.connect (resize_controller.reset); + resize.add_controller (resize_controller); + + bind_property ("orientation", resize, "icon_name", GLib.BindingFlags.SYNC_CREATE, (binding, src, ref dst) => { + dst.set_string (orientation == Gtk.Orientation.VERTICAL ? "double-ended-arrows-vertical-symbolic" : "double-ended-arrows-horizontal-symbolic"); + return true; + }); + + rotate.clicked.connect (() => { + orientation = orientation == Gtk.Orientation.HORIZONTAL ? Gtk.Orientation.VERTICAL : Gtk.Orientation.HORIZONTAL; + }); + + var positions = ((PipeTap.Application) app).settings.get_child (window_name + "-pos"); + positions.bind_with_mapping ("orientation", this, "orientation", GLib.SettingsBindFlags.DEFAULT, + (value, variant) => + { value = variant.get_boolean () ? Gtk.Orientation.VERTICAL : Gtk.Orientation.HORIZONTAL; return true; }, + (value) => + { return ((Gtk.Orientation) value) == Gtk.Orientation.VERTICAL; }, + null, null + ); + positions.bind ("start-x", this, "pos-sx", GLib.SettingsBindFlags.DEFAULT); + positions.bind ("start-y", this, "pos-sy", GLib.SettingsBindFlags.DEFAULT); + positions.bind ("end-x", this, "pos-ex", GLib.SettingsBindFlags.DEFAULT); + positions.bind ("end-y", this, "pos-ey", GLib.SettingsBindFlags.DEFAULT); + + notify["pos-sx"].connect (set_position); + notify["pos-sy"].connect (set_position); + notify["pos-ex"].connect (set_position); + notify["pos-ey"].connect (set_position); + notify["orientation"].connect (set_position); + set_position (); + + app.bind_property ("adjust-overlay-visible", this, "move-visible", GLib.BindingFlags.SYNC_CREATE); + app.bind_property ("adjust-overlay-visible", this, "resize-visible", GLib.BindingFlags.SYNC_CREATE); + app.bind_property ("adjust-overlay-visible", this, "rotate-visible", GLib.BindingFlags.SYNC_CREATE); + } + + void set_position () { + var vertical = orientation == Gtk.Orientation.VERTICAL; + GtkLayerShell.set_anchor (this, GtkLayerShell.Edge.TOP, true); + GtkLayerShell.set_anchor (this, GtkLayerShell.Edge.BOTTOM, vertical); + GtkLayerShell.set_anchor (this, GtkLayerShell.Edge.RIGHT, true); + GtkLayerShell.set_anchor (this, GtkLayerShell.Edge.LEFT, !vertical); + var y = pos_sy; + if (vertical) + y = pos_ey + pos_sy; + + GtkLayerShell.set_margin (this, GtkLayerShell.Edge.TOP, int.max ((int) y, 0)); + GtkLayerShell.set_margin (this, GtkLayerShell.Edge.RIGHT, int.max ((int) pos_sx, 0)); + GtkLayerShell.set_margin (this, GtkLayerShell.Edge.LEFT, int.max ((int) (pos_ex - pos_sx), 0)); + GtkLayerShell.set_margin (this, GtkLayerShell.Edge.BOTTOM, int.max ((int) (-pos_sy), 0)); + } +} \ No newline at end of file diff --git a/src/icons/angled-arrows-symbolic.svg b/src/icons/angled-arrows-symbolic.svg new file mode 100644 index 0000000..674097c --- /dev/null +++ b/src/icons/angled-arrows-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/src/icons/camera-focus-symbolic.svg b/src/icons/camera-focus-symbolic.svg new file mode 100644 index 0000000..157e180 --- /dev/null +++ b/src/icons/camera-focus-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/src/icons/camera-iso-symbolic.svg b/src/icons/camera-iso-symbolic.svg new file mode 100644 index 0000000..480c255 --- /dev/null +++ b/src/icons/camera-iso-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/src/icons/camera-photo-symbolic.svg b/src/icons/camera-photo-symbolic.svg new file mode 100644 index 0000000..ad32b0d --- /dev/null +++ b/src/icons/camera-photo-symbolic.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/icons/double-ended-arrows-horizontal-symbolic.svg b/src/icons/double-ended-arrows-horizontal-symbolic.svg new file mode 100644 index 0000000..d2e77f2 --- /dev/null +++ b/src/icons/double-ended-arrows-horizontal-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/src/icons/double-ended-arrows-vertical-symbolic.svg b/src/icons/double-ended-arrows-vertical-symbolic.svg new file mode 100644 index 0000000..c6a52a5 --- /dev/null +++ b/src/icons/double-ended-arrows-vertical-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/src/icons/left-large-symbolic.svg b/src/icons/left-large-symbolic.svg new file mode 100644 index 0000000..35ec1fe --- /dev/null +++ b/src/icons/left-large-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/src/icons/move-tool-symbolic.svg b/src/icons/move-tool-symbolic.svg new file mode 100644 index 0000000..51a32ba --- /dev/null +++ b/src/icons/move-tool-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/src/icons/right-large-symbolic.svg b/src/icons/right-large-symbolic.svg new file mode 100644 index 0000000..3d76598 --- /dev/null +++ b/src/icons/right-large-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/src/meson.build b/src/meson.build index 2f5619c..266a3e1 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,7 +1,8 @@ pipetap_sources = [ 'main.vala', 'application.vala', - 'window.vala', + 'gui/window.vala', + 'gui/main_bar.vala', ] pipetap_deps = [ @@ -15,7 +16,8 @@ blueprints = custom_target( 'blueprints', input: files( 'gtk/help-overlay.blp', - 'window.blp', + 'gui/main_bar.blp', + 'gui/window.blp', ), output: '.', command: [ diff --git a/src/pipetap.gresource.xml b/src/pipetap.gresource.xml index 96f2d97..3d04e2e 100644 --- a/src/pipetap.gresource.xml +++ b/src/pipetap.gresource.xml @@ -1,7 +1,20 @@ - window.ui + gui/window.ui + gui/main_bar.ui gtk/help-overlay.ui + style.css - + + icons/right-large-symbolic.svg + icons/left-large-symbolic.svg + icons/camera-photo-symbolic.svg + icons/move-tool-symbolic.svg + icons/double-ended-arrows-horizontal-symbolic.svg + icons/double-ended-arrows-vertical-symbolic.svg + icons/camera-iso-symbolic.svg + icons/camera-focus-symbolic.svg + icons/angled-arrows-symbolic.svg + + \ No newline at end of file diff --git a/src/style.css b/src/style.css new file mode 100644 index 0000000..27a928f --- /dev/null +++ b/src/style.css @@ -0,0 +1,3 @@ +.pt-transparent { + border-radius: 10px; +} \ No newline at end of file diff --git a/src/window.blp b/src/window.blp deleted file mode 100644 index ea5dedc..0000000 --- a/src/window.blp +++ /dev/null @@ -1,48 +0,0 @@ -using Gtk 4.0; -using Adw 1; - -template $PipeTapWindow: Adw.ApplicationWindow { - title: _("PipeTap"); - default-width: 800; - default-height: 600; - - content: Adw.ToolbarView { - [top] - Adw.HeaderBar { - [end] - MenuButton { - primary: true; - icon-name: "open-menu-symbolic"; - tooltip-text: _("Main Menu"); - menu-model: primary_menu; - } - } - - content: Label label { - label: _("Hello, World!"); - - styles [ - "title-1", - ] - }; - }; -} - -menu primary_menu { - section { - item { - label: _("_Preferences"); - action: "app.preferences"; - } - - item { - label: _("_Keyboard Shortcuts"); - action: "win.show-help-overlay"; - } - - item { - label: _("_About PipeTap"); - action: "app.about"; - } - } -} diff --git a/src/window.vala b/src/window.vala deleted file mode 100644 index ff3a7b7..0000000 --- a/src/window.vala +++ /dev/null @@ -1,41 +0,0 @@ -/* window.vala - * - * Copyright 2025 Vasiliy Doylov - * - * 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -[GtkTemplate(ui = "/io/gitlab/nekocwd/pipetap/window.ui")] -public class PipeTap.Window : Adw.ApplicationWindow { - [GtkChild] - private unowned Gtk.Label label; - - public Window(Gtk.Application app) { - Object(application: app); - GtkLayerShell.init_for_window(this); - set_position(); - } - - void set_position() { - GtkLayerShell.set_anchor(this, GtkLayerShell.Edge.BOTTOM, true); - GtkLayerShell.set_anchor(this, GtkLayerShell.Edge.BOTTOM, true); - GtkLayerShell.set_anchor(this, GtkLayerShell.Edge.LEFT, true); - - GtkLayerShell.set_margin(this, GtkLayerShell.Edge.TOP, 100); - GtkLayerShell.set_margin(this, GtkLayerShell.Edge.BOTTOM, 100); - GtkLayerShell.set_margin(this, GtkLayerShell.Edge.LEFT, 100); - } -} \ No newline at end of file