[fractal/wip/cdavis/next-style-cleanup: 1/2] components: Add RoomTitle component




commit 5d95eb56bbcf0c75ba727eaa41bbfeacdc9f00e4
Author: Christopher Davis <christopherdavis gnome org>
Date:   Fri Jun 25 13:49:18 2021 -0700

    components: Add RoomTitle component
    
    Adds a custom RoomTitle widget in place of AdwWindowTitle.
    This will allow us to have markup in titles and subtitles,
    and allow us to have tooltips set appropriately.

 data/resources/resources.gresource.xml    |   1 +
 data/resources/ui/content-room-history.ui |   2 +-
 data/resources/ui/room-title.ui           |  42 +++++++++
 src/components/mod.rs                     |   2 +
 src/components/room_title.rs              | 140 ++++++++++++++++++++++++++++++
 src/meson.build                           |   1 +
 src/session/content/room_history.rs       |   3 +
 7 files changed, 190 insertions(+), 1 deletion(-)
---
diff --git a/data/resources/resources.gresource.xml b/data/resources/resources.gresource.xml
index e3fa5bdb..2bde98bb 100644
--- a/data/resources/resources.gresource.xml
+++ b/data/resources/resources.gresource.xml
@@ -25,6 +25,7 @@
     <file compressed="true" preprocess="xml-stripblanks" alias="window.ui">ui/window.ui</file>
     <file compressed="true" preprocess="xml-stripblanks" 
alias="context-menu-bin.ui">ui/context-menu-bin.ui</file>
     <file compressed="true" preprocess="xml-stripblanks" alias="pill.ui">ui/pill.ui</file>
+    <file compressed="true" preprocess="xml-stripblanks" alias="room-title.ui">ui/room-title.ui</file>
     <file compressed="true" preprocess="xml-stripblanks" 
alias="spinner-button.ui">ui/spinner-button.ui</file>
     <file compressed="true" preprocess="xml-stripblanks" 
alias="in-app-notification.ui">ui/in-app-notification.ui</file>
     <file compressed="true" preprocess="xml-stripblanks" 
alias="components-avatar.ui">ui/components-avatar.ui</file>
diff --git a/data/resources/ui/content-room-history.ui b/data/resources/ui/content-room-history.ui
index 977d8238..cab3b0f0 100644
--- a/data/resources/ui/content-room-history.ui
+++ b/data/resources/ui/content-room-history.ui
@@ -31,7 +31,7 @@
               </object>
             </child>
             <child type="title">
-              <object class="AdwWindowTitle">
+              <object class="RoomTitle" id="room_title">
                 <binding name="title">
                   <lookup name="display-name">
                     <lookup name="room">ContentRoomHistory</lookup>
diff --git a/data/resources/ui/room-title.ui b/data/resources/ui/room-title.ui
new file mode 100644
index 00000000..26718b2f
--- /dev/null
+++ b/data/resources/ui/room-title.ui
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="RoomTitle" parent="AdwBin">
+    <child>
+      <object class="GtkBox" id="box">
+        <property name="orientation">vertical</property>
+        <property name="halign">center</property>
+        <property name="valign">center</property>
+        <child>
+          <object class="GtkLabel" id="title_label">
+            <property name="ellipsize">end</property>
+            <property name="halign">center</property>
+            <property name="wrap">False</property>
+            <property name="single-line-mode">True</property>
+            <property name="use-markup">True</property>
+            <property name="width-chars">5</property>
+            <property name="label" bind-source="RoomTitle" bind-property="title" bind-flags="sync-create"/>
+            <property name="tooltip-markup" bind-source="RoomTitle" bind-property="title" 
bind-flags="sync-create"/>
+            <style>
+              <class name="title"/>
+            </style>
+          </object>
+        </child>
+        <child>
+          <object class="GtkLabel" id="subtitle_label">
+            <property name="ellipsize">end</property>
+            <property name="halign">center</property>
+            <property name="wrap">False</property>
+            <property name="single-line-mode">True</property>
+            <property name="use-markup">True</property>
+            <property name="visible">False</property>
+            <property name="label" bind-source="RoomTitle" bind-property="subtitle" 
bind-flags="sync-create"/>
+            <property name="tooltip-markup" bind-source="RoomTitle" bind-property="subtitle" 
bind-flags="sync-create"/>
+            <style>
+              <class name="subtitle"/>
+            </style>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/components/mod.rs b/src/components/mod.rs
index 7296e89d..5d2e3e74 100644
--- a/src/components/mod.rs
+++ b/src/components/mod.rs
@@ -3,6 +3,7 @@ mod context_menu_bin;
 mod in_app_notification;
 mod label_with_widgets;
 mod pill;
+mod room_title;
 mod spinner_button;
 
 pub use self::avatar::Avatar;
@@ -10,4 +11,5 @@ pub use self::context_menu_bin::{ContextMenuBin, ContextMenuBinExt, ContextMenuB
 pub use self::in_app_notification::InAppNotification;
 pub use self::label_with_widgets::LabelWithWidgets;
 pub use self::pill::Pill;
+pub use self::room_title::RoomTitle;
 pub use self::spinner_button::SpinnerButton;
diff --git a/src/components/room_title.rs b/src/components/room_title.rs
new file mode 100644
index 00000000..26698a66
--- /dev/null
+++ b/src/components/room_title.rs
@@ -0,0 +1,140 @@
+use adw::subclass::prelude::*;
+use gtk::prelude::*;
+use gtk::subclass::prelude::*;
+use gtk::{glib, CompositeTemplate};
+
+mod imp {
+    use super::*;
+    use glib::subclass::InitializingObject;
+    use std::cell::RefCell;
+
+    #[derive(Debug, Default, CompositeTemplate)]
+    #[template(resource = "/org/gnome/FractalNext/room-title.ui")]
+    pub struct RoomTitle {
+        // The markup for the title
+        pub title: RefCell<Option<String>>,
+        // The markup for the subtitle
+        pub subtitle: RefCell<Option<String>>,
+        #[template_child]
+        pub title_label: TemplateChild<gtk::Label>,
+        #[template_child]
+        pub subtitle_label: TemplateChild<gtk::Label>,
+    }
+
+    #[glib::object_subclass]
+    impl ObjectSubclass for RoomTitle {
+        const NAME: &'static str = "RoomTitle";
+        type Type = super::RoomTitle;
+        type ParentType = adw::Bin;
+
+        fn class_init(klass: &mut Self::Class) {
+            Self::bind_template(klass);
+        }
+
+        fn instance_init(obj: &InitializingObject<Self>) {
+            obj.init_template();
+        }
+    }
+
+    impl ObjectImpl for RoomTitle {
+        fn properties() -> &'static [glib::ParamSpec] {
+            use once_cell::sync::Lazy;
+            static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
+                vec![
+                    glib::ParamSpec::new_string(
+                        "title",
+                        "Title",
+                        "The title of the room",
+                        None,
+                        glib::ParamFlags::READWRITE | glib::ParamFlags::EXPLICIT_NOTIFY,
+                    ),
+                    glib::ParamSpec::new_string(
+                        "subtitle",
+                        "Subtitle",
+                        "The subtitle of the room",
+                        None,
+                        glib::ParamFlags::READWRITE | glib::ParamFlags::EXPLICIT_NOTIFY,
+                    ),
+                ]
+            });
+
+            PROPERTIES.as_ref()
+        }
+
+        fn property(&self, obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
+            match pspec.name() {
+                "title" => obj.title().to_value(),
+                "subtitle" => obj.subtitle().to_value(),
+                _ => unimplemented!(),
+            }
+        }
+
+        fn set_property(
+            &self,
+            obj: &Self::Type,
+            _id: usize,
+            value: &glib::Value,
+            pspec: &glib::ParamSpec,
+        ) {
+            match pspec.name() {
+                "title" => obj.set_title(value.get().unwrap()),
+                "subtitle" => obj.set_subtitle(value.get().unwrap()),
+                _ => unimplemented!(),
+            }
+        }
+
+        fn constructed(&self, obj: &Self::Type) {
+            self.parent_constructed(obj);
+        }
+    }
+
+    impl WidgetImpl for RoomTitle {}
+    impl BinImpl for RoomTitle {}
+}
+
+glib::wrapper! {
+    pub struct RoomTitle(ObjectSubclass<imp::RoomTitle>)
+        @extends gtk::Widget, adw::Bin, @implements gtk::Accessible;
+}
+
+impl RoomTitle {
+    pub fn new() -> Self {
+        glib::Object::new(&[]).expect("Failed to create RoomTitle")
+    }
+
+    pub fn set_title(&self, title: Option<String>) {
+        let priv_ = imp::RoomTitle::from_instance(self);
+        // If there's an existing title, check that current title and new title aren't equal
+        if priv_.title.borrow().as_deref() != title.as_deref() {
+            priv_.title.replace(title);
+            priv_
+                .title_label
+                .set_visible(priv_.title.borrow().is_some());
+        }
+
+        self.notify("title");
+    }
+
+    pub fn title(&self) -> Option<String> {
+        let priv_ = imp::RoomTitle::from_instance(self);
+        priv_.title.borrow().clone()
+    }
+
+    pub fn set_subtitle(&self, subtitle: Option<String>) {
+        let priv_ = imp::RoomTitle::from_instance(self);
+        // If there's an existing subtitle, check that current subtitle and new subtitle aren't equal
+        if priv_.subtitle.borrow().as_deref() != subtitle.as_deref() {
+            priv_.subtitle.replace(subtitle);
+            priv_
+                .subtitle_label
+                .set_visible(priv_.subtitle.borrow().is_some());
+        }
+
+        self.notify("subtitle");
+    }
+
+    pub fn subtitle(&self) -> Option<String> {
+        let priv_ = imp::RoomTitle::from_instance(self);
+        priv_.subtitle.borrow().clone()
+    }
+}
diff --git a/src/meson.build b/src/meson.build
index db9f9599..b3e129b7 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -25,6 +25,7 @@ sources = files(
   'components/label_with_widgets.rs',
   'components/mod.rs',
   'components/pill.rs',
+  'components/room_title.rs',
   'components/in_app_notification.rs',
   'components/spinner_button.rs',
   'config.rs',
diff --git a/src/session/content/room_history.rs b/src/session/content/room_history.rs
index d6c902c3..cb06ea94 100644
--- a/src/session/content/room_history.rs
+++ b/src/session/content/room_history.rs
@@ -1,3 +1,4 @@
+use crate::components::RoomTitle;
 use crate::session::{content::ItemRow, content::MarkdownPopover, room::Room, room::RoomType};
 use adw::subclass::prelude::*;
 use gtk::{
@@ -22,6 +23,8 @@ mod imp {
         #[template_child]
         pub headerbar: TemplateChild<adw::HeaderBar>,
         #[template_child]
+        pub room_title: TemplateChild<RoomTitle>,
+        #[template_child]
         pub room_menu: TemplateChild<gtk::MenuButton>,
         #[template_child]
         pub listview: TemplateChild<gtk::ListView>,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]