refactor: make tab label their own widget
Merge branch 'refactor/closable-tabs' into 'main' See merge request EchidnaHQ/Echidna!15merge-requests/17/merge
commit
c1193df8a2
|
@ -5,11 +5,13 @@
|
||||||
pub mod app;
|
pub mod app;
|
||||||
pub mod editor;
|
pub mod editor;
|
||||||
pub mod sidebar;
|
pub mod sidebar;
|
||||||
|
pub mod tab_label;
|
||||||
pub mod window;
|
pub mod window;
|
||||||
|
|
||||||
pub use app::EchidnaEditor;
|
pub use app::EchidnaEditor;
|
||||||
pub use editor::EchidnaCoreEditor;
|
pub use editor::EchidnaCoreEditor;
|
||||||
pub use sidebar::EchidnaSidebar;
|
pub use sidebar::EchidnaSidebar;
|
||||||
|
pub use tab_label::TabLabel;
|
||||||
pub use window::EchidnaWindow;
|
pub use window::EchidnaWindow;
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use gtk::prelude::*;
|
||||||
|
use gtk::subclass::prelude::*;
|
||||||
|
use gtk::CompositeTemplate;
|
||||||
|
|
||||||
|
#[derive(Default, CompositeTemplate)]
|
||||||
|
#[template(file = "./tab-label.ui")]
|
||||||
|
pub struct TabLabel {
|
||||||
|
#[template_child]
|
||||||
|
pub button: TemplateChild<gtk::Button>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[glib::object_subclass]
|
||||||
|
impl ObjectSubclass for TabLabel {
|
||||||
|
const NAME: &'static str = "TabLabel";
|
||||||
|
type Type = super::TabLabel;
|
||||||
|
type ParentType = gtk::Box;
|
||||||
|
|
||||||
|
fn class_init(klass: &mut Self::Class) {
|
||||||
|
Self::bind_template(klass);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
|
||||||
|
obj.init_template();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ObjectImpl for TabLabel {}
|
||||||
|
impl WidgetImpl for TabLabel {}
|
||||||
|
impl BoxImpl for TabLabel {}
|
||||||
|
|
||||||
|
impl BuildableImpl for TabLabel {
|
||||||
|
fn add_child(
|
||||||
|
&self,
|
||||||
|
buildable: &Self::Type,
|
||||||
|
builder: >k::Builder,
|
||||||
|
child: &glib::Object,
|
||||||
|
type_: Option<&str>,
|
||||||
|
) {
|
||||||
|
buildable.prepend(child.downcast_ref::<gtk::Widget>().unwrap());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
pub mod imp;
|
||||||
|
use glib::IsA;
|
||||||
|
use gtk::prelude::*;
|
||||||
|
use gtk::subclass::prelude::*;
|
||||||
|
|
||||||
|
glib::wrapper! {
|
||||||
|
pub struct TabLabel(ObjectSubclass<imp::TabLabel>)
|
||||||
|
@extends gtk::Box, gtk::Widget,
|
||||||
|
@implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget, gtk::Orientable;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TabLabel {
|
||||||
|
pub fn new<U: IsA<gtk::Widget>>(tab_label: Option<&U>) -> Self {
|
||||||
|
let this: Self = glib::Object::new(&[]).expect("Failed to create 'TabLabel' component.");
|
||||||
|
|
||||||
|
if tab_label.is_some() {
|
||||||
|
this.prepend(tab_label.unwrap());
|
||||||
|
}
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_imp(&self) -> &imp::TabLabel {
|
||||||
|
imp::TabLabel::from_instance(self)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk+" version="4.5.0" />
|
||||||
|
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
- file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
-->
|
||||||
|
<template class="TabLabel">
|
||||||
|
<property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="button">
|
||||||
|
<property name="has-frame">0</property>
|
||||||
|
<property name="icon-name">window-close-symbolic</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</template>
|
||||||
|
</interface>
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use crate::components::tab_label::TabLabel;
|
||||||
use glib::IsA;
|
use glib::IsA;
|
||||||
use gtk::{prelude::*, Box, Button, Widget};
|
use gtk::{prelude::*, Box, Button, Widget};
|
||||||
|
|
||||||
|
@ -16,39 +17,24 @@ pub trait ClosableTabImplementedNotebook {
|
||||||
child: &T,
|
child: &T,
|
||||||
tab_label: Option<&U>,
|
tab_label: Option<&U>,
|
||||||
) -> u32;
|
) -> u32;
|
||||||
|
|
||||||
fn create_closable_tab<U: IsA<Widget>>(tab_label: Option<&U>) -> (Box, Button);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClosableTabImplementedNotebook for gtk::Notebook {
|
impl ClosableTabImplementedNotebook for gtk::Notebook {
|
||||||
fn create_closable_tab<U: IsA<Widget>>(tab_label: Option<&U>) -> (Box, Button) {
|
|
||||||
let tab = Box::new(gtk::Orientation::Horizontal, 5);
|
|
||||||
if tab_label.is_some() {
|
|
||||||
tab.append(tab_label.unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
let button = gtk::Button::new();
|
|
||||||
|
|
||||||
button.set_icon_name("window-close-symbolic");
|
|
||||||
button.set_has_frame(false);
|
|
||||||
|
|
||||||
tab.append(&button);
|
|
||||||
|
|
||||||
(tab, button)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prepend_closable_page<T: IsA<Widget>, U: IsA<Widget>>(
|
fn prepend_closable_page<T: IsA<Widget>, U: IsA<Widget>>(
|
||||||
&self,
|
&self,
|
||||||
child: &T,
|
child: &T,
|
||||||
tab_label: Option<&U>,
|
tab_label: Option<&U>,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
let (tab, button) = &Self::create_closable_tab(tab_label);
|
let tab_label_widget = TabLabel::new(tab_label);
|
||||||
let page = self.prepend_page(child, Some(tab));
|
let page = self.prepend_page(child, Some(&tab_label_widget));
|
||||||
|
|
||||||
button.connect_clicked(glib::clone!(@weak self as notebook =>
|
tab_label_widget
|
||||||
move |_| {
|
.to_imp()
|
||||||
notebook.remove_page(Some(page));
|
.button
|
||||||
}));
|
.connect_clicked(glib::clone!(@weak self as notebook =>
|
||||||
|
move |_| {
|
||||||
|
notebook.remove_page(Some(page));
|
||||||
|
}));
|
||||||
|
|
||||||
page
|
page
|
||||||
}
|
}
|
||||||
|
@ -58,13 +44,16 @@ impl ClosableTabImplementedNotebook for gtk::Notebook {
|
||||||
child: &T,
|
child: &T,
|
||||||
tab_label: Option<&U>,
|
tab_label: Option<&U>,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
let (tab, button) = &Self::create_closable_tab(tab_label);
|
let tab_label_widget = TabLabel::new(tab_label);
|
||||||
let page = self.append_page(child, Some(tab));
|
let page = self.append_page(child, Some(&tab_label_widget));
|
||||||
|
|
||||||
button.connect_clicked(glib::clone!(@weak self as notebook =>
|
tab_label_widget
|
||||||
move |_| {
|
.to_imp()
|
||||||
notebook.remove_page(Some(page));
|
.button
|
||||||
}));
|
.connect_clicked(glib::clone!(@weak self as notebook =>
|
||||||
|
move |_| {
|
||||||
|
notebook.remove_page(Some(page));
|
||||||
|
}));
|
||||||
|
|
||||||
page
|
page
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue