Merge branch 'main' into feat/workspaces

merge-requests/12/head
Nefo Fortressia 2021-12-18 11:01:11 +07:00
commit 40dad9e212
Signed by: fortressia
GPG Key ID: 6D7972CC76174995
11 changed files with 137 additions and 182 deletions

118
Cargo.lock generated
View File

@ -20,12 +20,6 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bumpalo"
version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
[[package]] [[package]]
name = "cairo-rs" name = "cairo-rs"
version = "0.14.7" version = "0.14.7"
@ -68,12 +62,6 @@ dependencies = [
"smallvec", "smallvec",
] ]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "echidna" name = "echidna"
version = "0.1.0" version = "0.1.0"
@ -87,7 +75,6 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"sourceview5", "sourceview5",
"webbrowser",
] ]
[[package]] [[package]]
@ -438,36 +425,12 @@ version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "js-sys"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.102" version = "0.2.102"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103" checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103"
[[package]]
name = "log"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "memoffset" name = "memoffset"
version = "0.6.4" version = "0.6.4"
@ -843,87 +806,6 @@ version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
name = "wasm-bindgen"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
[[package]]
name = "web-sys"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "webbrowser"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecad156490d6b620308ed411cfee90d280b3cbd13e189ea0d3fada8acc89158a"
dependencies = [
"web-sys",
"widestring",
"winapi",
]
[[package]]
name = "widestring"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c"
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"

View File

@ -1,7 +1,7 @@
[package] [package]
name = "echidna" name = "echidna"
version = "0.1.0" version = "0.1.0"
edition = "2018" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -14,5 +14,4 @@ serde = { version = "^1.0.130", features = ["derive"] }
relative-path = "^1.5.0" relative-path = "^1.5.0"
gdk = { version = "^0.3.0", package = "gdk4"} gdk = { version = "^0.3.0", package = "gdk4"}
sourceview = { package = "sourceview5", version = "^0.1.0", git = "https://github.com/EchidnaHQ/sourceview" } sourceview = { package = "sourceview5", version = "^0.1.0", git = "https://github.com/EchidnaHQ/sourceview" }
webbrowser = { version = "^0.5.5" }
once_cell = "1" once_cell = "1"

View File

@ -67,7 +67,7 @@ impl EchidnaCoreEditor {
|_, _| {}, |_, _| {},
|result| { |result| {
if result.is_err() { if result.is_err() {
panic!(result.err()); panic!("Found an error when loading the file into the text editor's buffer. {:#?}", result.err());
} }
}, },
); );

View File

@ -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 {

View File

@ -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: &gtk::Builder,
child: &glib::Object,
type_: Option<&str>,
) {
buildable.prepend(child.downcast_ref::<gtk::Widget>().unwrap());
}
}

View File

@ -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)
}
}

View File

@ -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>

View File

@ -8,7 +8,7 @@ use crate::components::editor::EchidnaCoreEditor;
use gio::Cancellable; use gio::Cancellable;
use glib::{clone, Priority}; use glib::{clone, Priority};
use gtk::{ use gtk::{
prelude::*, subclass::prelude::*, FileChooserAction, FileChooserDialog, Label, ResponseType, prelude::*, subclass::prelude::*, FileChooserAction, FileChooserNative, Label, ResponseType,
}; };
use sourceview::{prelude::*, Buffer, File, FileSaver}; use sourceview::{prelude::*, Buffer, File, FileSaver};
@ -36,14 +36,12 @@ impl FileImplementedEditor for super::EchidnaWindow {
Perhaps some of the last points should not be implemented in this function but rather in another function that keeps track of every files. Perhaps some of the last points should not be implemented in this function but rather in another function that keeps track of every files.
*/ */
fn action_open_file(&self) { fn action_open_file(&self) {
let dialog: FileChooserDialog = FileChooserDialog::new( let dialog = FileChooserNative::new(
Some("Open a file"), Some("Open a file"),
Some(self), Some(self),
FileChooserAction::Open, FileChooserAction::Open,
&[ Some("Open"),
("Cancel", ResponseType::Cancel), Some("Cancel"),
("Open", ResponseType::Accept),
],
); );
dialog.set_visible(true); dialog.set_visible(true);
@ -81,14 +79,12 @@ impl FileImplementedEditor for super::EchidnaWindow {
} }
fn action_save_file_as(&self) { fn action_save_file_as(&self) {
let dialog = FileChooserDialog::new( let dialog = FileChooserNative::new(
Some("Save File As"), Some("Save File As"),
Some(self), Some(self),
FileChooserAction::Save, FileChooserAction::Save,
&[ Some("Open"),
("Cancel", ResponseType::Cancel), Some("Cancel"),
("Save", ResponseType::Accept),
],
); );
dialog.set_current_name("untitled"); dialog.set_current_name("untitled");
@ -114,7 +110,7 @@ impl FileImplementedEditor for super::EchidnaWindow {
"Couldn't get the page of the current index. Try again." "Couldn't get the page of the current index. Try again."
).downcast::<EchidnaCoreEditor>() { ).downcast::<EchidnaCoreEditor>() {
Ok(res) => page = res, Ok(res) => page = res,
Err(e) => panic!(format!("We got an error when trying to downcast the current tab page into EchidnaCoreEditor:\n{}", e)) Err(e) => panic!("We got an error when trying to downcast the current tab page into EchidnaCoreEditor:\n{}", e)
} }
let buffer: Buffer = page.to_imp().sourceview.buffer().downcast().expect("Could not downcast the editor's buffer to GtkSourceBuffer."); let buffer: Buffer = page.to_imp().sourceview.buffer().downcast().expect("Could not downcast the editor's buffer to GtkSourceBuffer.");
@ -129,7 +125,7 @@ impl FileImplementedEditor for super::EchidnaWindow {
|_, _| {}, |_, _| {},
|result| { |result| {
if result.is_err() { if result.is_err() {
panic!(format!("Found an error while saving the file:\n{}", result.err().expect("No error"))) panic!("Found an error while saving the file:\n{}", result.err().expect("No error"))
} }
}); });

View File

@ -67,7 +67,7 @@ impl MenubarImplementedEditor for EchidnaWindow {
about_dialog.set_license_type(gtk::License::Mpl20); about_dialog.set_license_type(gtk::License::Mpl20);
about_dialog.set_program_name(Some("Echidna Code Editor")); about_dialog.set_program_name(Some("Echidna Code Editor"));
about_dialog.set_website(Some("https://github.com/EchidnaHQ/Echidna")); about_dialog.set_website(Some("https://gitlab.com/EchidnaHQ/Echidna"));
about_dialog.set_authors(&["FortressValkriye"]); about_dialog.set_authors(&["FortressValkriye"]);
about_dialog.set_copyright(Some("Made with by ❤️ Echidna contributors")); about_dialog.set_copyright(Some("Made with by ❤️ Echidna contributors"));
about_dialog.set_visible(true); about_dialog.set_visible(true);
@ -78,18 +78,20 @@ impl MenubarImplementedEditor for EchidnaWindow {
app.add_action(&act_report_issue); app.add_action(&act_report_issue);
act_report_issue.connect_activate(|_action, _variant| { act_report_issue.connect_activate(clone!(@weak self as win =>
webbrowser::open("https://github.com/EchidnaHQ/Echidna/issues/new"); move |_action, _variant| {
}); gtk::show_uri(Some(&win), "https://github.com/EchidnaHQ/Echidna/issues/new", gdk::CURRENT_TIME);
}));
} }
{ {
let act_search_feature_requests = SimpleAction::new("search-feature-requests", None); let act_search_feature_requests = SimpleAction::new("search-feature-requests", None);
app.add_action(&act_search_feature_requests); app.add_action(&act_search_feature_requests);
act_search_feature_requests.connect_activate(|_action, _variant| { act_search_feature_requests.connect_activate(clone!(@weak self as win =>
webbrowser::open("https://github.com/EchidnaHQ/Echidna/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement"); move |_action, _variant| {
}); gtk::show_uri(Some(&win), "https://github.com/EchidnaHQ/Echidna/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement", gdk::CURRENT_TIME);
}));
} }
{ {
let act_window_close = SimpleAction::new("close", None); let act_window_close = SimpleAction::new("close", None);

View File

@ -7,10 +7,7 @@ use gio::{File, FileQueryInfoFlags, FileType, SimpleAction};
use glib::clone; use glib::clone;
use glib::types::Type; use glib::types::Type;
use gtk::prelude::*; use gtk::prelude::*;
use gtk::{ use gtk::{ApplicationWindow, FileChooserAction, FileChooserNative, ResponseType, TreeStore};
Application, ApplicationWindow, FileChooserAction, FileChooserDialog, ResponseType, TreeStore,
TreeView,
};
use relative_path::RelativePath; use relative_path::RelativePath;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::path::Path; use std::path::Path;
@ -47,14 +44,12 @@ impl WorkspaceImplementedEditor for EchidnaWindow {
_action: &SimpleAction, _action: &SimpleAction,
_variant: Option<&glib::Variant>, _variant: Option<&glib::Variant>,
) { ) {
let dialog: FileChooserDialog = FileChooserDialog::new( let dialog = FileChooserNative::new(
Some("Open a file"), Some("Open a file"),
Some(&window), Some(&window),
FileChooserAction::Open, FileChooserAction::Open,
&[ Some("Open"),
("Cancel", ResponseType::Cancel), Some("Cancel"),
("Open", ResponseType::Accept),
],
); );
dialog.set_visible(true); dialog.set_visible(true);
dialog.connect_response(clone!(@weak self as win => dialog.connect_response(clone!(@weak self as win =>
@ -79,7 +74,7 @@ impl WorkspaceImplementedEditor for EchidnaWindow {
* *
* Basically, this is just the same as Open Folder, but it's many folders. * Basically, this is just the same as Open Folder, but it's many folders.
* *
* - Open a FileChooserDialog, set to only view .code-workspace files. * - Open a FileChooserNative, set to only view .code-workspace files.
* - If the user pressed cancel, destroy the dialog. If the user opened a .code-workspace file: * - If the user pressed cancel, destroy the dialog. If the user opened a .code-workspace file:
* - Get the workspace file, load and parse its content, .code-workspace files are in JSON with comments. But JSON only should be fine, for now. * - Get the workspace file, load and parse its content, .code-workspace files are in JSON with comments. But JSON only should be fine, for now.
* - Iterate over folders listed in the workspace file. * - Iterate over folders listed in the workspace file.
@ -127,7 +122,6 @@ impl WorkspaceImplementedEditor for EchidnaWindow {
*/ */
fn recursive_add_files_into_tree_store(&self, parent_file: File, tree: &TreeStore) { fn recursive_add_files_into_tree_store(&self, parent_file: File, tree: &TreeStore) {
let child_enumerate_cancellable = Cancellable::new(); let child_enumerate_cancellable = Cancellable::new();
let child_files = parent_file let child_files = parent_file
.enumerate_children( .enumerate_children(
"*", "*",

View File

@ -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
} }