[fractal/fractal-next] Add base layout
- From: Julian Sparber <jsparber src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal/fractal-next] Add base layout
- Date: Tue, 16 Feb 2021 11:04:43 +0000 (UTC)
commit 9e8fa8aab548c69979237df3b698f6be6765920b
Author: Julian Sparber <julian sparber net>
Date: Sat Feb 13 00:16:16 2021 +0100
Add base layout
Cargo.toml | 2 +-
data/resources.gresource.xml | 14 +++
.../icons/scalable/actions/send-symbolic.svg | 52 ++++++++++
data/resources/style.css | 14 ++-
data/resources/ui/content.ui | 88 +++++++++++++++++
data/resources/ui/login.ui | 18 ++++
data/resources/ui/session.ui | 19 ++++
data/resources/ui/sidebar.ui | 56 +++++++++++
data/resources/ui/window.ui | 44 +++------
src/application.rs | 21 ++--
src/main.rs | 4 +-
src/meson.build | 7 +-
src/widgets/content.rs | 110 +++++++++++++++++++++
src/widgets/login.rs | 58 +++++++++++
src/widgets/mod.rs | 11 +++
src/widgets/session.rs | 63 ++++++++++++
src/widgets/sidebar.rs | 110 +++++++++++++++++++++
src/{ => widgets}/window.rs | 63 ++++++------
18 files changed, 679 insertions(+), 75 deletions(-)
---
diff --git a/Cargo.toml b/Cargo.toml
index 3e207658..f3fb9d4a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,6 +17,6 @@ git = "https://github.com/gtk-rs/gtk4-rs"
# We need to use the same version as libadwaita does
#rev = "abea0c9980bc083494eceb30dfab5eeb99a73118"
-[dependencies.libadwaita]
+[dependencies.adw]
package = "libadwaita"
git = "https://gitlab.gnome.org/bilelmoussaoui/libadwaita-rs.git"
diff --git a/data/resources.gresource.xml b/data/resources.gresource.xml
new file mode 100644
index 00000000..025bbe47
--- /dev/null
+++ b/data/resources.gresource.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/FractalNext/">
+ <file compressed="true" preprocess="xml-stripblanks"
alias="shortcuts.ui">resources/ui/shortcuts.ui</file>
+ <file compressed="true" preprocess="xml-stripblanks" alias="content.ui">resources/ui/content.ui</file>
+ <file compressed="true" preprocess="xml-stripblanks" alias="login.ui">resources/ui/login.ui</file>
+ <file compressed="true" preprocess="xml-stripblanks" alias="session.ui">resources/ui/session.ui</file>
+ <file compressed="true" preprocess="xml-stripblanks" alias="sidebar.ui">resources/ui/sidebar.ui</file>
+ <file compressed="true" preprocess="xml-stripblanks" alias="window.ui">resources/ui/window.ui</file>
+
+ <file compressed="true" alias="style.css">resources/style.css</file>
+ <file preprocess="xml-stripblanks"
alias="icons/scalable/actions/send-symbolic.svg">resources/icons/scalable/actions/send-symbolic.svg</file>
+ </gresource>
+</gresources>
diff --git a/data/resources/icons/scalable/actions/send-symbolic.svg
b/data/resources/icons/scalable/actions/send-symbolic.svg
new file mode 100644
index 00000000..01f60ca8
--- /dev/null
+++ b/data/resources/icons/scalable/actions/send-symbolic.svg
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ height="16"
+ id="svg7384"
+ version="1.1"
+ width="16">
+ <metadata
+ id="metadata90">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Gnome Symbolic Icon Theme</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <title
+ id="title9167">Gnome Symbolic Icon Theme</title>
+ <defs
+ id="defs7386">
+ <linearGradient
+ id="linearGradient7212"
+ osb:paint="solid">
+ <stop
+ id="stop7214"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ </linearGradient>
+ </defs>
+ <g
+ id="layer9"
+ style="display:inline"
+ transform="translate(-323.0002,125)">
+ <g
+ style="enable-background:new"
+ id="g876"
+ transform="translate(311.00017,-893)">
+ <path
+ id="path20012"
+ d="m 12.999904,769 14.000126,7.00002 -14.000126,6.99999 v -6 L 22.000471,776.00002 12.999904,775 Z"
+
style="fill:#241f31;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
/>
+ </g>
+ </g>
+</svg>
diff --git a/data/resources/style.css b/data/resources/style.css
index 3c4bd471..c3d88b6e 100644
--- a/data/resources/style.css
+++ b/data/resources/style.css
@@ -1,4 +1,16 @@
-.title-header{
+.title-header {
font-size: 36px;
font-weight: bold;
}
+
+.content {
+ background-color: @theme_base_color;
+}
+
+.content:backdrop {
+ background-color: @theme_unfocused_base_color;
+}
+
+.send-message-area {
+ margin: 6px;
+}
diff --git a/data/resources/ui/content.ui b/data/resources/ui/content.ui
new file mode 100644
index 00000000..411aa691
--- /dev/null
+++ b/data/resources/ui/content.ui
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="FrctlContent" parent="AdwBin">
+ <property name="vexpand">True</property>
+ <property name="hexpand">True</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="AdwHeaderBar" id="headerbar">
+ <property name="show-start-title-buttons" bind-source="FrctlContent" bind-property="compact"
bind-flags="sync-create" />
+ <child type="end">
+ <object class="GtkMenuButton" id="room_menu">
+ <property name="icon-name">view-more-symbolic</property>
+ </object>
+ </child>
+ <child type="end">
+ <object class="GtkToggleButton" id="search_content_button">
+ <property name="icon-name">system-search-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSearchBar" id="room_search">
+ <property name="search-mode-enabled" bind-source="search_content_button" bind-property="active"
/>
+ <property name="child">
+ <object class="AdwClamp">
+ <property name="hexpand">True</property>
+ <child>
+ <object class="GtkSearchEntry"/>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="AdwClamp">
+ <property name="vexpand">True</property>
+ <property name="hexpand">True</property>
+ <style>
+ <class name="content"/>
+ </style>
+ <child>
+ <object class="GtkListView" id="room_history">
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparator" />
+ </child>
+ <child>
+ <object class="AdwClamp">
+ <child>
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <style>
+ <class name="send-message-area"/>
+ </style>
+ <child>
+ <object class="GtkButton">
+ <property name="icon-name">mail-attachment-symbolic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="icon-name">format-justify-left-symbolic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="message_entry">
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="icon-name">send-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/data/resources/ui/login.ui b/data/resources/ui/login.ui
new file mode 100644
index 00000000..94347e78
--- /dev/null
+++ b/data/resources/ui/login.ui
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="FrctlLogin" parent="AdwBin">
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkHeaderBar" id="headerbar" />
+ </child>
+ <child>
+ <object class="AdwStatusPage">
+ <!-- TODO implement login -->
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/data/resources/ui/session.ui b/data/resources/ui/session.ui
new file mode 100644
index 00000000..0f0c5968
--- /dev/null
+++ b/data/resources/ui/session.ui
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="FrctlSession" parent="AdwBin">
+ <child>
+ <object class="AdwLeaflet" id="session">
+ <child>
+ <object class="FrctlSidebar" id="sidebar">
+ <property name="compact" bind-source="session" bind-property="folded" bind-flags="sync-create" />
+ </object>
+ </child>
+ <child>
+ <object class="FrctlContent" id="content">
+ <property name="compact" bind-source="session" bind-property="folded" bind-flags="sync-create" />
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/data/resources/ui/sidebar.ui b/data/resources/ui/sidebar.ui
new file mode 100644
index 00000000..4e315197
--- /dev/null
+++ b/data/resources/ui/sidebar.ui
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <menu id="primary_menu">
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Preferences</attribute>
+ <attribute name="action">app.preferences</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute>
+ <attribute name="action">win.show-help-overlay</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_About Fractal</attribute>
+ <attribute name="action">app.about</attribute>
+ </item>
+ </section>
+ </menu>
+ <template class="FrctlSidebar" parent="AdwBin">
+ <style>
+ <class name="sidebar"/>
+ </style>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="AdwHeaderBar" id="headerbar">
+ <property name="show-end-title-buttons" bind-source="FrctlSidebar" bind-property="compact"
bind-flags="sync-create" />
+ <child type="start">
+ <object class="GtkToggleButton" id="search_button">
+ <property name="icon-name">system-search-symbolic</property>
+ </object>
+ </child>
+ <child type="end">
+ <object class="GtkMenuButton" id="appmenu_button">
+ <property name="icon-name">open-menu-symbolic</property>
+ <property name="menu-model">primary_menu</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSearchBar" id="room_search">
+ <property name="search-mode-enabled" bind-source="search_button" bind-property="active" />
+ <property name="child">
+ <object class="GtkSearchEntry"/>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListView" id="listview" />
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/data/resources/ui/window.ui b/data/resources/ui/window.ui
index c89a8a35..95c2b884 100644
--- a/data/resources/ui/window.ui
+++ b/data/resources/ui/window.ui
@@ -1,39 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <menu id="primary_menu">
- <section>
- <item>
- <attribute name="label" translatable="yes">_Preferences</attribute>
- <attribute name="action">app.preferences</attribute>
- </item>
- <item>
- <attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute>
- <attribute name="action">win.show-help-overlay</attribute>
- </item>
- <item>
- <attribute name="label" translatable="yes">_About GTK Rust Template</attribute>
- <attribute name="action">app.about</attribute>
- </item>
- </section>
- </menu>
- <template class="ExampleApplicationWindow" parent="GtkApplicationWindow">
+ <template class="FrctlWindow" parent="AdwApplicationWindow">
<property name="default-width">600</property>
<property name="default-height">400</property>
- <child type="titlebar">
- <object class="GtkHeaderBar" id="headerbar">
- <child type="end">
- <object class="GtkMenuButton" id="appmenu_button">
- <property name="icon-name">open-menu-symbolic</property>
- <property name="menu-model">primary_menu</property>
- </object>
- </child>
- </object>
- </child>
<child>
- <object class="GtkLabel" id="label">
- <property name="label" translatable="yes">Hello world!</property>
- <style>
- <class name="title-header"/>
- </style>
+ <object class="GtkStack" id="main_stack">
+ <property name="visible-child">session</property>
+ <property name="transition-type">crossfade</property>
+ <child>
+ <object class="FrctlLogin" id="login" />
+ </child>
+ <!-- We currently only support one session, add other sessions to the main_Stack -->
+ <child>
+ <object class="FrctlSession" id="session" />
+ </child>
</object>
</child>
</template>
diff --git a/src/application.rs b/src/application.rs
index 7f8a50ed..996a14bb 100644
--- a/src/application.rs
+++ b/src/application.rs
@@ -1,5 +1,5 @@
use crate::config;
-use crate::window::ExampleApplicationWindow;
+use crate::widgets::FrctlWindow;
use gio::ApplicationFlags;
use glib::clone;
use glib::WeakRef;
@@ -17,7 +17,7 @@ mod imp {
#[derive(Debug)]
pub struct ExampleApplication {
- pub window: OnceCell<WeakRef<ExampleApplicationWindow>>,
+ pub window: OnceCell<WeakRef<FrctlWindow>>,
}
impl ObjectSubclass for ExampleApplication {
@@ -43,8 +43,7 @@ mod imp {
fn activate(&self, app: &Self::Type) {
debug!("GtkApplication<ExampleApplication>::activate");
- let priv_ = ExampleApplication::from_instance(app);
- if let Some(window) = priv_.window.get() {
+ if let Some(window) = self.window.get() {
let window = window.upgrade().unwrap();
window.show();
window.present();
@@ -54,7 +53,7 @@ mod imp {
app.set_resource_base_path(Some("/org/gnome/FractalNext/"));
app.setup_css();
- let window = ExampleApplicationWindow::new(app);
+ let window = FrctlWindow::new(app);
self.window
.set(window.downgrade())
.expect("Window already set.");
@@ -83,14 +82,18 @@ impl ExampleApplication {
pub fn new() -> Self {
glib::Object::new(&[
("application-id", &Some(config::APP_ID)),
- ("flags", &ApplicationFlags::empty()),
+ ("flags", &ApplicationFlags::default()),
])
.expect("Application initialization failed...")
}
- fn get_main_window(&self) -> ExampleApplicationWindow {
- let priv_ = imp::ExampleApplication::from_instance(self);
- priv_.window.get().unwrap().upgrade().unwrap()
+ fn get_main_window(&self) -> FrctlWindow {
+ imp::ExampleApplication::from_instance(self)
+ .window
+ .get()
+ .unwrap()
+ .upgrade()
+ .unwrap()
}
fn setup_gactions(&self) {
diff --git a/src/main.rs b/src/main.rs
index 4ab963e9..7a2ec43b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,8 +1,9 @@
mod application;
#[rustfmt::skip]
mod config;
-mod window;
+mod widgets;
+use adw;
use application::ExampleApplication;
use config::{GETTEXT_PACKAGE, LOCALEDIR, RESOURCES_FILE};
use gettextrs::*;
@@ -23,6 +24,7 @@ fn main() {
gtk::glib::set_prgname(Some("fractal"));
gtk::init().expect("Unable to start GTK4");
+ adw::init();
let res = gio::Resource::load(RESOURCES_FILE).expect("Could not load gresource file");
gio::resources_register(&res);
diff --git a/src/meson.build b/src/meson.build
index bc737b2c..27d59b67 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -22,7 +22,12 @@ sources = files(
'application.rs',
'config.rs',
'main.rs',
- 'window.rs',
+ 'widgets/window.rs',
+ 'widgets/content.rs',
+ 'widgets/sidebar.rs',
+ 'widgets/login.rs',
+ 'widgets/mod.rs',
+ 'widgets/session.rs',
)
custom_target(
diff --git a/src/widgets/content.rs b/src/widgets/content.rs
new file mode 100644
index 00000000..4554e3e3
--- /dev/null
+++ b/src/widgets/content.rs
@@ -0,0 +1,110 @@
+use adw;
+use adw::subclass::prelude::BinImpl;
+use gtk::subclass::prelude::*;
+use gtk::{self, prelude::*};
+use gtk::{glib, CompositeTemplate};
+
+mod imp {
+ use super::*;
+ use glib::subclass;
+ use std::cell::Cell;
+
+ #[derive(Debug, CompositeTemplate)]
+ #[template(resource = "/org/gnome/FractalNext/content.ui")]
+ pub struct FrctlContent {
+ pub compact: Cell<bool>,
+ #[template_child]
+ pub headerbar: TemplateChild<adw::HeaderBar>,
+ #[template_child]
+ pub room_history: TemplateChild<gtk::ListView>,
+ }
+
+ impl ObjectSubclass for FrctlContent {
+ const NAME: &'static str = "FrctlContent";
+ type Type = super::FrctlContent;
+ type ParentType = adw::Bin;
+ type Interfaces = ();
+ type Instance = subclass::simple::InstanceStruct<Self>;
+ type Class = subclass::simple::ClassStruct<Self>;
+
+ glib::object_subclass!();
+
+ fn new() -> Self {
+ Self {
+ compact: Cell::new(false),
+ headerbar: TemplateChild::default(),
+ room_history: TemplateChild::default(),
+ }
+ }
+
+ fn class_init(klass: &mut Self::Class) {
+ Self::bind_template(klass);
+ }
+
+ // You must call `Widget`'s `init_template()` within `instance_init()`.
+ fn instance_init(obj: &glib::subclass::InitializingObject<Self::Type>) {
+ obj.init_template();
+ }
+ }
+
+ impl ObjectImpl for FrctlContent {
+ fn properties() -> &'static [glib::ParamSpec] {
+ use once_cell::sync::Lazy;
+ static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
+ vec![glib::ParamSpec::boolean(
+ "compact",
+ "Compact",
+ "Wheter a compact view is used or not",
+ false,
+ glib::ParamFlags::READWRITE,
+ )]
+ });
+
+ PROPERTIES.as_ref()
+ }
+
+ fn set_property(
+ &self,
+ _obj: &Self::Type,
+ _id: usize,
+ value: &glib::Value,
+ pspec: &glib::ParamSpec,
+ ) {
+ match pspec.get_name() {
+ "compact" => {
+ let compact = value
+ .get()
+ .expect("type conformity checked by `Object::set_property`");
+ self.compact.set(compact.unwrap());
+ }
+ _ => unimplemented!(),
+ }
+ }
+
+ fn get_property(
+ &self,
+ _obj: &Self::Type,
+ _id: usize,
+ pspec: &glib::ParamSpec,
+ ) -> glib::Value {
+ match pspec.get_name() {
+ "compact" => self.compact.get().to_value(),
+ _ => unimplemented!(),
+ }
+ }
+ }
+
+ impl WidgetImpl for FrctlContent {}
+ impl BinImpl for FrctlContent {}
+}
+
+glib::wrapper! {
+ pub struct FrctlContent(ObjectSubclass<imp::FrctlContent>)
+ @extends gtk::Widget, adw::Bin, @implements gtk::Accessible;
+}
+
+impl FrctlContent {
+ pub fn new() -> Self {
+ glib::Object::new(&[]).expect("Failed to create FrctlContent")
+ }
+}
diff --git a/src/widgets/login.rs b/src/widgets/login.rs
new file mode 100644
index 00000000..06b607ea
--- /dev/null
+++ b/src/widgets/login.rs
@@ -0,0 +1,58 @@
+use adw;
+use adw::subclass::prelude::BinImpl;
+use gtk::subclass::prelude::*;
+use gtk::{self, prelude::*};
+use gtk::{glib, CompositeTemplate};
+
+mod imp {
+ use super::*;
+ use glib::subclass;
+
+ #[derive(Debug, CompositeTemplate)]
+ #[template(resource = "/org/gnome/FractalNext/login.ui")]
+ pub struct FrctlLogin {
+ #[template_child]
+ pub headerbar: TemplateChild<gtk::HeaderBar>,
+ }
+
+ impl ObjectSubclass for FrctlLogin {
+ const NAME: &'static str = "FrctlLogin";
+ type Type = super::FrctlLogin;
+ type ParentType = adw::Bin;
+ type Interfaces = ();
+ type Instance = subclass::simple::InstanceStruct<Self>;
+ type Class = subclass::simple::ClassStruct<Self>;
+
+ glib::object_subclass!();
+
+ fn new() -> Self {
+ Self {
+ headerbar: TemplateChild::default(),
+ }
+ }
+
+ fn class_init(klass: &mut Self::Class) {
+ Self::bind_template(klass);
+ }
+
+ // You must call `Widget`'s `init_template()` within `instance_init()`.
+ fn instance_init(obj: &glib::subclass::InitializingObject<Self::Type>) {
+ obj.init_template();
+ }
+ }
+
+ impl ObjectImpl for FrctlLogin {}
+ impl WidgetImpl for FrctlLogin {}
+ impl BinImpl for FrctlLogin {}
+}
+
+glib::wrapper! {
+ pub struct FrctlLogin(ObjectSubclass<imp::FrctlLogin>)
+ @extends gtk::Widget, adw::Bin, @implements gtk::Accessible;
+}
+
+impl FrctlLogin {
+ pub fn new() -> Self {
+ glib::Object::new(&[]).expect("Failed to create FrctlLogin")
+ }
+}
diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs
new file mode 100644
index 00000000..126ba693
--- /dev/null
+++ b/src/widgets/mod.rs
@@ -0,0 +1,11 @@
+mod content;
+mod login;
+mod session;
+mod sidebar;
+mod window;
+
+pub use crate::widgets::content::FrctlContent;
+pub use crate::widgets::login::FrctlLogin;
+pub use crate::widgets::session::FrctlSession;
+pub use crate::widgets::sidebar::FrctlSidebar;
+pub use crate::widgets::window::FrctlWindow;
diff --git a/src/widgets/session.rs b/src/widgets/session.rs
new file mode 100644
index 00000000..0f3b222b
--- /dev/null
+++ b/src/widgets/session.rs
@@ -0,0 +1,63 @@
+use crate::widgets::FrctlContent;
+use crate::widgets::FrctlSidebar;
+use adw;
+use adw::subclass::prelude::BinImpl;
+use gtk::subclass::prelude::*;
+use gtk::{self, prelude::*};
+use gtk::{glib, CompositeTemplate};
+
+mod imp {
+ use super::*;
+ use glib::subclass;
+
+ #[derive(Debug, CompositeTemplate)]
+ #[template(resource = "/org/gnome/FractalNext/session.ui")]
+ pub struct FrctlSession {
+ #[template_child]
+ pub sidebar: TemplateChild<FrctlSidebar>,
+ #[template_child]
+ pub content: TemplateChild<FrctlContent>,
+ }
+
+ impl ObjectSubclass for FrctlSession {
+ const NAME: &'static str = "FrctlSession";
+ type Type = super::FrctlSession;
+ type ParentType = adw::Bin;
+ type Interfaces = ();
+ type Instance = subclass::simple::InstanceStruct<Self>;
+ type Class = subclass::simple::ClassStruct<Self>;
+
+ glib::object_subclass!();
+
+ fn new() -> Self {
+ Self {
+ sidebar: TemplateChild::default(),
+ content: TemplateChild::default(),
+ }
+ }
+
+ fn class_init(klass: &mut Self::Class) {
+ Self::bind_template(klass);
+ }
+
+ // You must call `Widget`'s `init_template()` within `instance_init()`.
+ fn instance_init(obj: &glib::subclass::InitializingObject<Self::Type>) {
+ obj.init_template();
+ }
+ }
+
+ impl ObjectImpl for FrctlSession {}
+ impl WidgetImpl for FrctlSession {}
+ impl BinImpl for FrctlSession {}
+}
+
+glib::wrapper! {
+ pub struct FrctlSession(ObjectSubclass<imp::FrctlSession>)
+ @extends gtk::Widget, adw::Bin, @implements gtk::Accessible;
+}
+
+impl FrctlSession {
+ pub fn new() -> Self {
+ glib::Object::new(&[]).expect("Failed to create FrctlSession")
+ }
+}
diff --git a/src/widgets/sidebar.rs b/src/widgets/sidebar.rs
new file mode 100644
index 00000000..003fc346
--- /dev/null
+++ b/src/widgets/sidebar.rs
@@ -0,0 +1,110 @@
+use adw;
+use adw::subclass::prelude::BinImpl;
+use gtk::subclass::prelude::*;
+use gtk::{self, prelude::*};
+use gtk::{glib, CompositeTemplate};
+
+mod imp {
+ use super::*;
+ use glib::subclass;
+ use std::cell::Cell;
+
+ #[derive(Debug, CompositeTemplate)]
+ #[template(resource = "/org/gnome/FractalNext/sidebar.ui")]
+ pub struct FrctlSidebar {
+ pub compact: Cell<bool>,
+ #[template_child]
+ pub headerbar: TemplateChild<adw::HeaderBar>,
+ #[template_child]
+ pub listview: TemplateChild<gtk::ListView>,
+ }
+
+ impl ObjectSubclass for FrctlSidebar {
+ const NAME: &'static str = "FrctlSidebar";
+ type Type = super::FrctlSidebar;
+ type ParentType = adw::Bin;
+ type Interfaces = ();
+ type Instance = subclass::simple::InstanceStruct<Self>;
+ type Class = subclass::simple::ClassStruct<Self>;
+
+ glib::object_subclass!();
+
+ fn new() -> Self {
+ Self {
+ compact: Cell::new(false),
+ listview: TemplateChild::default(),
+ headerbar: TemplateChild::default(),
+ }
+ }
+
+ fn class_init(klass: &mut Self::Class) {
+ Self::bind_template(klass);
+ }
+
+ // You must call `Widget`'s `init_template()` within `instance_init()`.
+ fn instance_init(obj: &glib::subclass::InitializingObject<Self::Type>) {
+ obj.init_template();
+ }
+ }
+
+ impl ObjectImpl for FrctlSidebar {
+ fn properties() -> &'static [glib::ParamSpec] {
+ use once_cell::sync::Lazy;
+ static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
+ vec![glib::ParamSpec::boolean(
+ "compact",
+ "Compact",
+ "Wheter a compact view is used or not",
+ false,
+ glib::ParamFlags::READWRITE,
+ )]
+ });
+
+ PROPERTIES.as_ref()
+ }
+
+ fn set_property(
+ &self,
+ _obj: &Self::Type,
+ _id: usize,
+ value: &glib::Value,
+ pspec: &glib::ParamSpec,
+ ) {
+ match pspec.get_name() {
+ "compact" => {
+ let compact = value
+ .get()
+ .expect("type conformity checked by `Object::set_property`");
+ self.compact.set(compact.unwrap());
+ }
+ _ => unimplemented!(),
+ }
+ }
+
+ fn get_property(
+ &self,
+ _obj: &Self::Type,
+ _id: usize,
+ pspec: &glib::ParamSpec,
+ ) -> glib::Value {
+ match pspec.get_name() {
+ "compact" => self.compact.get().to_value(),
+ _ => unimplemented!(),
+ }
+ }
+ }
+
+ impl WidgetImpl for FrctlSidebar {}
+ impl BinImpl for FrctlSidebar {}
+}
+
+glib::wrapper! {
+ pub struct FrctlSidebar(ObjectSubclass<imp::FrctlSidebar>)
+ @extends gtk::Widget, adw::Bin, @implements gtk::Accessible;
+}
+
+impl FrctlSidebar {
+ pub fn new() -> Self {
+ glib::Object::new(&[]).expect("Failed to create FrctlSidebar")
+ }
+}
diff --git a/src/window.rs b/src/widgets/window.rs
similarity index 61%
rename from src/window.rs
rename to src/widgets/window.rs
index ed668918..379ed6af 100644
--- a/src/window.rs
+++ b/src/widgets/window.rs
@@ -1,5 +1,8 @@
use crate::application::ExampleApplication;
use crate::config::{APP_ID, PROFILE};
+use crate::widgets::FrctlLogin;
+use crate::widgets::FrctlSession;
+use adw::subclass::prelude::AdwApplicationWindowImpl;
use glib::signal::Inhibit;
use gtk::subclass::prelude::*;
use gtk::{self, prelude::*};
@@ -12,16 +15,22 @@ mod imp {
#[derive(Debug, CompositeTemplate)]
#[template(resource = "/org/gnome/FractalNext/window.ui")]
- pub struct ExampleApplicationWindow {
+ pub struct FrctlWindow {
#[template_child]
- pub headerbar: TemplateChild<gtk::HeaderBar>,
+ pub main_stack: TemplateChild<gtk::Stack>,
+ #[template_child]
+ pub login: TemplateChild<FrctlLogin>,
+ // Eventually we want to create the session dynamically, since we want multi account
+ // support
+ #[template_child]
+ pub session: TemplateChild<FrctlSession>,
pub settings: gio::Settings,
}
- impl ObjectSubclass for ExampleApplicationWindow {
- const NAME: &'static str = "ExampleApplicationWindow";
- type Type = super::ExampleApplicationWindow;
- type ParentType = gtk::ApplicationWindow;
+ impl ObjectSubclass for FrctlWindow {
+ const NAME: &'static str = "FrctlWindow";
+ type Type = super::FrctlWindow;
+ type ParentType = adw::ApplicationWindow;
type Interfaces = ();
type Instance = subclass::simple::InstanceStruct<Self>;
type Class = subclass::simple::ClassStruct<Self>;
@@ -30,7 +39,9 @@ mod imp {
fn new() -> Self {
Self {
- headerbar: TemplateChild::default(),
+ main_stack: TemplateChild::default(),
+ login: TemplateChild::default(),
+ session: TemplateChild::default(),
settings: gio::Settings::new(APP_ID),
}
}
@@ -45,7 +56,7 @@ mod imp {
}
}
- impl ObjectImpl for ExampleApplicationWindow {
+ impl ObjectImpl for FrctlWindow {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
@@ -55,7 +66,7 @@ mod imp {
// Devel Profile
if PROFILE == "Devel" {
- obj.get_style_context().add_class("devel");
+ obj.add_css_class("devel");
}
// load latest window state
@@ -63,7 +74,7 @@ mod imp {
}
}
- impl WindowImpl for ExampleApplicationWindow {
+ impl WindowImpl for FrctlWindow {
// save window state on delete event
fn close_request(&self, obj: &Self::Type) -> Inhibit {
if let Err(err) = obj.save_window_size() {
@@ -73,29 +84,24 @@ mod imp {
}
}
- impl WidgetImpl for ExampleApplicationWindow {}
- impl ApplicationWindowImpl for ExampleApplicationWindow {}
+ impl WidgetImpl for FrctlWindow {}
+ impl ApplicationWindowImpl for FrctlWindow {}
+ impl AdwApplicationWindowImpl for FrctlWindow {}
}
glib::wrapper! {
- pub struct ExampleApplicationWindow(ObjectSubclass<imp::ExampleApplicationWindow>)
- @extends gtk::Widget, gtk::Window, gtk::ApplicationWindow, @implements gio::ActionMap,
gio::ActionGroup;
+ pub struct FrctlWindow(ObjectSubclass<imp::FrctlWindow>)
+ @extends gtk::Widget, gtk::Window, gtk::ApplicationWindow, adw::ApplicationWindow, @implements
gio::ActionMap, gio::ActionGroup;
}
-impl ExampleApplicationWindow {
- pub fn new(app: &ExampleApplication) -> Self {
- let window: Self =
- glib::Object::new(&[]).expect("Failed to create ExampleApplicationWindow");
- window.set_application(Some(app));
-
- // Set icons for shell
- gtk::Window::set_default_icon_name(APP_ID);
-
- window
+impl FrctlWindow {
+ pub fn new(app: &FrctlApplication) -> Self {
+ glib::Object::new(&[("application", &Some(app)), ("icon-name", &Some(APP_ID))])
+ .expect("Failed to create FrctlWindow")
}
pub fn save_window_size(&self) -> Result<(), glib::BoolError> {
- let settings = &imp::ExampleApplicationWindow::from_instance(self).settings;
+ let settings = &imp::FrctlWindow::from_instance(self).settings;
let size = self.get_default_size();
@@ -108,16 +114,13 @@ impl ExampleApplicationWindow {
}
fn load_window_size(&self) {
- let settings = &imp::ExampleApplicationWindow::from_instance(self).settings;
+ let settings = &imp::FrctlWindow::from_instance(self).settings;
let width = settings.get_int("window-width");
let height = settings.get_int("window-height");
let is_maximized = settings.get_boolean("is-maximized");
self.set_default_size(width, height);
-
- if is_maximized {
- self.maximize();
- }
+ self.set_property_maximized(is_maximized);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]