diff --git a/demo/data/ui/window.blp b/demo/data/ui/window.blp index 46ba0fa0..bb81cf02 100644 --- a/demo/data/ui/window.blp +++ b/demo/data/ui/window.blp @@ -69,6 +69,15 @@ template $DemoMainWindow : He.ApplicationWindow { margin-end: 18; margin-bottom: 18; + He.TipView { + tip: He.Tip { + image: "view-list-symbolic"; + title: "Lists"; + message: "This is a list. It may contain actionable blocks."; + }; + tip-style: view; + } + He.MiniContentBlock { title: "Mini Content Block"; subtitle: "Subtitle"; diff --git a/lib/Main.vala b/lib/Main.vala index c70195a3..341b5f74 100644 --- a/lib/Main.vala +++ b/lib/Main.vala @@ -83,6 +83,9 @@ namespace He { typeof (He.TextField).ensure (); typeof (He.TimePicker).ensure (); typeof (He.TintButton).ensure (); + typeof (He.Tip).ensure (); + typeof (He.TipView).ensure (); + typeof (He.TipViewStyle).ensure (); typeof (He.Toast).ensure (); typeof (He.View).ensure (); typeof (He.ViewAux).ensure (); diff --git a/lib/Models/Tip.vala b/lib/Models/Tip.vala new file mode 100644 index 00000000..f961574a --- /dev/null +++ b/lib/Models/Tip.vala @@ -0,0 +1,110 @@ +/* +* Copyright (c) 2024 Fyra Labs +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser 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 Lesser General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301 USA +*/ + +/** +* A TipViewStyle changes the visual look of a tip. +*/ +public enum He.TipViewStyle { + NONE = 0, + POPUP = 1, + VIEW = 2; + + public string to_css_class () { + switch (this) { + case POPUP: + return "tip-popup"; + + case VIEW: + return "tip-view"; + + case NONE: + default: + return "tip-view"; + } + } + + public string to_string () { + return this.to_css_class (); + } +} + +/** +* A Tip is a helper object for onboarding flow tips in an app's first launch. +*/ +public class He.Tip : Object { + /** + * The Tip's title. + */ + private string _title; + public string title { + get { + return _title; + } + set { + if (value != null) + _title = value; + } + } + /** + * The Tip's image. May be an icon, or a small image. + */ + private string _image; + public string image { + get { + return _image; + } + set { + if (value != null) + _image = value; + } + } + /** + * The Tip's message. Maximum of two lines. + */ + private string _message; + public string message { + get { + return _message; + } + set { + if (value != null) + _message = value; + } + } + /** + * The Tip's action button label. Must be an actionable word like "Learn More…". + */ + private string _action_label; + public string action_label { + get { + return _action_label; + } + set { + if (value != null) + _action_label = value; + } + } + + public Tip (string title, string? image, string? message, string? action_label) { + this.title = title; + this.image = image; + this.message = message; + this.action_label = action_label; + } +} \ No newline at end of file diff --git a/lib/Widgets/TipView.vala b/lib/Widgets/TipView.vala new file mode 100644 index 00000000..4a8cbeab --- /dev/null +++ b/lib/Widgets/TipView.vala @@ -0,0 +1,137 @@ +/* +* Copyright (c) 2024 Fyra Labs +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser 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 Lesser General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301 USA +*/ + +/** +* A TipView is a helper widget for onboarding flow tips in an app's first launch. +*/ +public class He.TipView : He.Bin { + private Gtk.Image image = new Gtk.Image (); + private Gtk.Label title = new Gtk.Label (""); + private Gtk.Label message = new Gtk.Label (""); + + /** + * Emitted when the Tip is closed by activating the close button. + */ + public signal void closed (); + + /** + * The action button of the Tip. + */ + public He.TextButton button = new He.TextButton (""); + + /** + * The style of the Tip. + */ + private He.TipViewStyle _tip_style; + public He.TipViewStyle tip_style { + get { + return _tip_style; + } + set { + if (_tip_style != He.TipViewStyle.NONE) this.remove_css_class (_tip_style.to_css_class ()); + if (value != He.TipViewStyle.NONE) this.add_css_class (value.to_css_class ()); + + _tip_style = value; + } + } + + /** + * The Tip itself. Contains image, title, message. + */ + private He.Tip _tip; + public He.Tip tip { + get { + return _tip; + } + set { + title.set_label (value.title != null ? value.title : "Title"); + image.set_from_icon_name (value.image != null ? value.image : "info-symbolic"); + message.set_label (value.message != null ? value.message : "Message here."); + button.set_label (value.action_label != null ? value.action_label : "Learn More…"); + + if (value.action_label == null) { + button.visible = false; + } else { + button.visible = true; + } + + _tip = value; + } + } + + /** + * Creates a TipView. + * @param tip The Tip to use. + * @param tip_style The TipViewStyle to use. + */ + public TipView (He.Tip tip, He.TipViewStyle? tip_style) { + this.tip_style = tip_style; + this.tip = tip; + } + + ~TipView () { + this.dispose (); + } + + static construct { + set_layout_manager_type (typeof (Gtk.BoxLayout)); + } + + construct { + var main_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12) { + hexpand = true + }; + var body_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 12); + var label_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 6) { + hexpand = true + }; + + var close_button = new He.DisclosureButton ("window-close-symbolic"); + close_button.set_valign (Gtk.Align.START); + close_button.clicked.connect (() => { + this.visible = false; + closed (); + }); + + image.set_valign (Gtk.Align.START); + image.set_pixel_size (24); + + title.add_css_class ("caption"); + title.set_halign (Gtk.Align.START); + + message.set_halign (Gtk.Align.START); + message.set_width_chars (20); + message.set_ellipsize (Pango.EllipsizeMode.END); + message.set_lines (2); + + label_box.append (title); + label_box.append (message); + body_box.append (label_box); + + button.visible = false; + + body_box.append (button); + + main_box.append (image); + main_box.append (body_box); + main_box.append (close_button); + + this.child = main_box; + } +} \ No newline at end of file diff --git a/lib/meson.build b/lib/meson.build index cdd22020..68d61a06 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -17,6 +17,7 @@ libhelium_sources += files( 'Models/Schemes/SchemeFactory.vala', 'Models/Schemes/Vibrant.vala', 'Models/StyleManager.vala', + 'Models/Tip.vala', 'Models/View.vala', 'Models/Window.vala', 'Utils/Color.vala', @@ -90,6 +91,7 @@ libhelium_sources += files( 'Widgets/TextField.vala', 'Widgets/TimePicker.vala', 'Widgets/TintButton.vala', + 'Widgets/TipView.vala', 'Widgets/Toast.vala', 'Widgets/ViewAux.vala', 'Widgets/ViewChooser.vala',