diff --git a/src/components/sidebar/mod.rs b/src/components/sidebar/mod.rs
index 25b3ef2..7aa464a 100644
--- a/src/components/sidebar/mod.rs
+++ b/src/components/sidebar/mod.rs
@@ -1,3 +1,7 @@
+/* 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;
glib::wrapper! {
diff --git a/src/components/window/file.rs b/src/components/window/file.rs
index e5a0ada..3a51ce0 100644
--- a/src/components/window/file.rs
+++ b/src/components/window/file.rs
@@ -2,6 +2,8 @@
* 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 crate::lib::prelude::*;
+
use crate::components::editor::EchidnaCoreEditor;
use gio::Cancellable;
use glib::{clone, Priority};
@@ -64,7 +66,7 @@ impl FileImplementedEditor for super::EchidnaWindow {
fn open_file(notebook: >k::Notebook, file_location: gio::File) {
let file = File::builder().location(&file_location).build();
let editor_page = EchidnaCoreEditor::new(Some(file));
- notebook.prepend_page(
+ notebook.prepend_closable_page(
&editor_page,
Some(&Label::new(Some(
&file_location
diff --git a/src/components/window/window.ui b/src/components/window/window.ui
index 41b64b2..41f8876 100644
--- a/src/components/window/window.ui
+++ b/src/components/window/window.ui
@@ -27,16 +27,6 @@
-->
diff --git a/src/lib/closeable_tab.rs b/src/lib/closeable_tab.rs
new file mode 100644
index 0000000..85900df
--- /dev/null
+++ b/src/lib/closeable_tab.rs
@@ -0,0 +1,71 @@
+/* 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 glib::IsA;
+use gtk::{prelude::*, Box, Button, Widget};
+
+pub trait ClosableTabImplementedNotebook {
+ fn prepend_closable_page, U: IsA>(
+ &self,
+ child: &T,
+ tab_label: Option<&U>,
+ ) -> u32;
+ fn append_closable_page, U: IsA>(
+ &self,
+ child: &T,
+ tab_label: Option<&U>,
+ ) -> u32;
+
+ fn create_closable_tab>(tab_label: Option<&U>) -> (Box, Button);
+}
+
+impl ClosableTabImplementedNotebook for gtk::Notebook {
+ fn create_closable_tab>(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, U: IsA>(
+ &self,
+ child: &T,
+ tab_label: Option<&U>,
+ ) -> u32 {
+ let (tab, button) = &Self::create_closable_tab(tab_label);
+ let page = self.prepend_page(child, Some(tab));
+
+ button.connect_clicked(glib::clone!(@weak self as notebook =>
+ move |_| {
+ notebook.remove_page(Some(page));
+ }));
+
+ page
+ }
+
+ fn append_closable_page, U: IsA>(
+ &self,
+ child: &T,
+ tab_label: Option<&U>,
+ ) -> u32 {
+ let (tab, button) = &Self::create_closable_tab(tab_label);
+ let page = self.append_page(child, Some(tab));
+
+ button.connect_clicked(glib::clone!(@weak self as notebook =>
+ move |_| {
+ notebook.remove_page(Some(page));
+ }));
+
+ page
+ }
+}
diff --git a/src/lib/mod.rs b/src/lib/mod.rs
new file mode 100644
index 0000000..233c324
--- /dev/null
+++ b/src/lib/mod.rs
@@ -0,0 +1,9 @@
+/* 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 closeable_tab;
+
+pub mod prelude {
+ pub use super::closeable_tab::ClosableTabImplementedNotebook;
+}
diff --git a/src/main.rs b/src/main.rs
index 01d237c..7e257d6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,7 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
mod components;
-
+pub mod lib;
use app::EchidnaEditor;
use components::app;
use gtk::prelude::ApplicationExtManual;