mirror of
https://github.com/YGGverse/Yoda.git
synced 2025-09-14 16:02:05 +00:00
reorganize shared input components
This commit is contained in:
parent
266d29b336
commit
41d30f82fd
@ -75,6 +75,6 @@ impl Input {
|
||||
}
|
||||
|
||||
pub fn set_new_titan(&self, on_send: impl Fn(titan::Header, Bytes, Box<dyn Fn()>) + 'static) {
|
||||
self.update(Some(>k::Notebook::titan(on_send)));
|
||||
self.update(Some(>k::Box::titan(on_send)));
|
||||
}
|
||||
}
|
||||
|
@ -1,35 +1,93 @@
|
||||
mod control;
|
||||
mod file;
|
||||
mod header;
|
||||
mod tab;
|
||||
mod text;
|
||||
mod title;
|
||||
|
||||
use control::Control;
|
||||
use file::File;
|
||||
use gtk::{
|
||||
glib::{uuid_string_random, Bytes},
|
||||
Notebook,
|
||||
};
|
||||
use gtk::{glib::Bytes, Notebook};
|
||||
pub use header::Header;
|
||||
use tab::Tab;
|
||||
use text::Text;
|
||||
use title::Title;
|
||||
|
||||
pub trait Titan {
|
||||
fn titan(callback: impl Fn(Header, Bytes, Box<dyn Fn()>) + 'static) -> Self;
|
||||
}
|
||||
|
||||
impl Titan for Notebook {
|
||||
impl Titan for gtk::Box {
|
||||
fn titan(callback: impl Fn(Header, Bytes, Box<dyn Fn()>) + 'static) -> Self {
|
||||
use gtk::{Box, Label};
|
||||
use gtk::{glib::uuid_string_random, Box, Label, TextView};
|
||||
use std::{cell::Cell, rc::Rc};
|
||||
|
||||
let notebook = Notebook::builder()
|
||||
.name(format!("s{}", uuid_string_random()))
|
||||
.show_border(false)
|
||||
.build();
|
||||
// Init components
|
||||
let header = Rc::new(Cell::new(Header {
|
||||
mime: None,
|
||||
token: None,
|
||||
}));
|
||||
let control = Rc::new(Control::build(&header));
|
||||
|
||||
notebook.append_page(&Box::text(callback), Some(&Label::title("Text")));
|
||||
notebook.append_page(&Box::file(), Some(&Label::title("File")));
|
||||
let text = TextView::text(&control);
|
||||
let file = File::build(&control);
|
||||
|
||||
notebook_css_patch(¬ebook);
|
||||
notebook
|
||||
let notebook = {
|
||||
let notebook = Notebook::builder()
|
||||
.name(format!("s{}", uuid_string_random()))
|
||||
.show_border(false)
|
||||
.build();
|
||||
|
||||
notebook.append_page(&text, Some(&Label::tab("Text")));
|
||||
notebook.append_page(&file.button, Some(&Label::tab("File")));
|
||||
|
||||
notebook.connect_switch_page({
|
||||
let control = control.clone();
|
||||
let text = text.clone();
|
||||
move |_, _, i| {
|
||||
if i == 0 {
|
||||
control.update(Some(text.len()), Some(text.count()))
|
||||
} else {
|
||||
control.update(file.size(), None)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
notebook_css_patch(¬ebook);
|
||||
notebook
|
||||
};
|
||||
|
||||
// Init main widget
|
||||
let g_box = {
|
||||
use gtk::{prelude::BoxExt, Orientation};
|
||||
|
||||
let g_box = {
|
||||
const MARGIN: i32 = 8;
|
||||
Box::builder()
|
||||
.margin_end(MARGIN)
|
||||
.margin_start(MARGIN)
|
||||
.orientation(Orientation::Vertical)
|
||||
.spacing(MARGIN)
|
||||
.build()
|
||||
};
|
||||
|
||||
g_box.append(¬ebook);
|
||||
g_box.append(&control.g_box);
|
||||
g_box
|
||||
};
|
||||
|
||||
// Init events
|
||||
/*control.upload.connect_clicked(move |this| {
|
||||
this.set_uploading();
|
||||
callback(
|
||||
header.take(),
|
||||
Bytes::from(form.text().as_bytes()),
|
||||
Box::new({
|
||||
let this = this.clone();
|
||||
move || this.set_resend() // on failure
|
||||
}),
|
||||
)
|
||||
});*/
|
||||
|
||||
g_box
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,6 @@ use options::Options;
|
||||
use std::{cell::Cell, rc::Rc};
|
||||
pub use upload::Upload;
|
||||
|
||||
const SPACING: i32 = 8;
|
||||
|
||||
pub struct Control {
|
||||
pub counter: Label,
|
||||
pub upload: Button,
|
||||
@ -31,11 +29,15 @@ impl Control {
|
||||
let upload = Button::upload();
|
||||
|
||||
// Init main widget
|
||||
let g_box = Box::builder()
|
||||
.halign(Align::End)
|
||||
.orientation(Orientation::Horizontal)
|
||||
.spacing(SPACING)
|
||||
.build();
|
||||
let g_box = {
|
||||
const MARGIN: i32 = 8;
|
||||
Box::builder()
|
||||
.halign(Align::End)
|
||||
.margin_bottom(MARGIN)
|
||||
.orientation(Orientation::Horizontal)
|
||||
.spacing(MARGIN)
|
||||
.build()
|
||||
};
|
||||
|
||||
g_box.append(&counter);
|
||||
g_box.append(&options);
|
||||
@ -50,9 +52,10 @@ impl Control {
|
||||
}
|
||||
|
||||
// Actions
|
||||
pub fn update(&self, chars_count: i32, bytes_total: usize) {
|
||||
pub fn update(&self, bytes_total: Option<usize>, chars_count: Option<i32>) {
|
||||
// Update children components
|
||||
self.counter.update(chars_count, bytes_total);
|
||||
self.upload.set_sensitive(bytes_total > 0);
|
||||
self.counter.update(bytes_total, chars_count);
|
||||
self.upload
|
||||
.set_sensitive(bytes_total.is_some_and(|this| this > 0));
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
use gtk::Label;
|
||||
|
||||
pub trait Counter {
|
||||
fn counter() -> Self;
|
||||
fn update(&self, bytes_total: Option<usize>, chars_count: Option<i32>);
|
||||
}
|
||||
|
||||
impl Counter for Label {
|
||||
// Constructors
|
||||
|
||||
fn counter() -> Self {
|
||||
Label::builder().css_classes(["dim-label"]).build() // @TODO use `dimmed` in Adw 1.6,
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
||||
fn update(&self, bytes_total: Option<usize>, chars_count: Option<i32>) {
|
||||
use gtk::prelude::WidgetExt;
|
||||
|
||||
self.set_visible(if let Some(bytes_total) = bytes_total {
|
||||
if let Some(chars_count) = chars_count {
|
||||
if chars_count > 0 {
|
||||
self.set_label(&bytes_total.to_string());
|
||||
self.set_tooltip_markup(Some(&format_text_tooltip(bytes_total, chars_count)));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
self.set_label(&format_file_tooltip(bytes_total));
|
||||
self.set_tooltip_markup(None);
|
||||
true
|
||||
}
|
||||
} else {
|
||||
false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Tools
|
||||
|
||||
fn format_file_tooltip(bytes_total: usize) -> String {
|
||||
use crate::tool::Format;
|
||||
bytes_total.bytes()
|
||||
}
|
||||
|
||||
fn format_text_tooltip(bytes_total: usize, chars_count: i32) -> String {
|
||||
use plurify::Plurify;
|
||||
format!(
|
||||
"{bytes_total} {} <sup>/ {chars_count} {}</sup>",
|
||||
(bytes_total).plurify(&["byte", "bytes", "bytes"]),
|
||||
(chars_count as usize).plurify(&["char", "chars", "chars"]),
|
||||
)
|
||||
}
|
@ -1,97 +1,86 @@
|
||||
mod control;
|
||||
mod form;
|
||||
use super::Control;
|
||||
use gtk::{glib::Bytes, Button};
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use super::Header;
|
||||
use control::Control;
|
||||
use gtk::Box;
|
||||
|
||||
pub trait File {
|
||||
fn file() -> Self;
|
||||
pub struct File {
|
||||
buffer: Rc<RefCell<Option<Bytes>>>,
|
||||
pub button: Button,
|
||||
}
|
||||
|
||||
impl File for Box {
|
||||
fn file() -> Self {
|
||||
use form::Form;
|
||||
impl File {
|
||||
pub fn build(control: &Rc<Control>) -> Self {
|
||||
use gtk::{
|
||||
gio::Cancellable,
|
||||
prelude::{ButtonExt, FileExt, WidgetExt},
|
||||
Button, FileDialog, Window,
|
||||
};
|
||||
use std::{cell::Cell, rc::Rc};
|
||||
|
||||
// Init components
|
||||
let header = Rc::new(Cell::new(Header {
|
||||
mime: None,
|
||||
token: None,
|
||||
}));
|
||||
let control = Rc::new(Control::build(&header));
|
||||
let form = Button::form();
|
||||
let buffer = Rc::new(RefCell::new(None));
|
||||
|
||||
// Init main widget
|
||||
let g_box = {
|
||||
use gtk::{prelude::BoxExt, Orientation};
|
||||
|
||||
const MARGIN: i32 = 8;
|
||||
|
||||
let g_box = Box::builder()
|
||||
.margin_end(MARGIN)
|
||||
.margin_start(MARGIN)
|
||||
.orientation(Orientation::Vertical)
|
||||
.spacing(MARGIN)
|
||||
.build();
|
||||
|
||||
g_box.append(&form);
|
||||
g_box.append(&control.g_box);
|
||||
g_box
|
||||
};
|
||||
let button = Button::builder()
|
||||
.label("Choose a file..")
|
||||
.margin_top(4)
|
||||
.build();
|
||||
|
||||
// Init events
|
||||
form.connect_clicked(move |form| {
|
||||
const CLASS: (&str, &str, &str) = ("error", "warning", "success");
|
||||
button.connect_clicked({
|
||||
let control = control.clone();
|
||||
let buffer = buffer.clone();
|
||||
move |this| {
|
||||
const CLASS: (&str, &str, &str) = ("error", "warning", "success");
|
||||
|
||||
// reset
|
||||
control.update(None);
|
||||
form.set_sensitive(false);
|
||||
form.remove_css_class(CLASS.0);
|
||||
form.remove_css_class(CLASS.1);
|
||||
form.remove_css_class(CLASS.2);
|
||||
// reset
|
||||
control.update(None, None);
|
||||
this.set_sensitive(false);
|
||||
this.remove_css_class(CLASS.0);
|
||||
this.remove_css_class(CLASS.1);
|
||||
this.remove_css_class(CLASS.2);
|
||||
|
||||
FileDialog::builder()
|
||||
.build()
|
||||
.open(Window::NONE, Cancellable::NONE, {
|
||||
let control = control.clone();
|
||||
let form = form.clone();
|
||||
move |result| match result {
|
||||
Ok(file) => match file.path() {
|
||||
Some(path) => {
|
||||
form.set_label("Buffering, please wait..");
|
||||
file.load_bytes_async(Cancellable::NONE, move |result| match result
|
||||
{
|
||||
Ok((bytes, _)) => {
|
||||
control.update(Some(bytes.len()));
|
||||
FileDialog::builder()
|
||||
.build()
|
||||
.open(Window::NONE, Cancellable::NONE, {
|
||||
let control = control.clone();
|
||||
let buffer = buffer.clone();
|
||||
let this = this.clone();
|
||||
move |result| match result {
|
||||
Ok(file) => match file.path() {
|
||||
Some(path) => {
|
||||
this.set_label("Buffering, please wait.."); // @TODO progress
|
||||
file.load_bytes_async(Cancellable::NONE, move |result| {
|
||||
match result {
|
||||
Ok((bytes, _)) => {
|
||||
control.update(Some(bytes.len()), None);
|
||||
buffer.replace(Some(bytes));
|
||||
|
||||
form.set_label(path.to_str().unwrap());
|
||||
form.set_css_classes(&[CLASS.2]);
|
||||
form.set_sensitive(true);
|
||||
}
|
||||
Err(e) => {
|
||||
form.set_css_classes(&[CLASS.0]);
|
||||
form.set_label(e.message());
|
||||
form.set_sensitive(true);
|
||||
}
|
||||
})
|
||||
this.set_css_classes(&[CLASS.2]);
|
||||
this.set_label(path.to_str().unwrap());
|
||||
this.set_sensitive(true);
|
||||
}
|
||||
Err(e) => {
|
||||
this.set_css_classes(&[CLASS.0]);
|
||||
this.set_label(e.message());
|
||||
this.set_sensitive(true);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
None => todo!(),
|
||||
},
|
||||
Err(e) => {
|
||||
this.set_css_classes(&[CLASS.1]);
|
||||
this.set_label(e.message());
|
||||
this.set_sensitive(true);
|
||||
}
|
||||
None => todo!(),
|
||||
},
|
||||
Err(e) => {
|
||||
form.set_css_classes(&[CLASS.1]);
|
||||
form.set_label(e.message());
|
||||
form.set_sensitive(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
g_box
|
||||
Self { buffer, button }
|
||||
}
|
||||
|
||||
pub fn size(&self) -> Option<usize> {
|
||||
self.buffer.borrow().as_ref().map(|bytes| bytes.len())
|
||||
}
|
||||
}
|
||||
|
@ -1,58 +0,0 @@
|
||||
mod counter;
|
||||
mod options;
|
||||
mod upload;
|
||||
|
||||
use super::Header;
|
||||
use counter::Counter;
|
||||
use gtk::{Box, Button, Label};
|
||||
use options::Options;
|
||||
use std::{cell::Cell, rc::Rc};
|
||||
use upload::Upload;
|
||||
|
||||
pub struct Control {
|
||||
counter: Label,
|
||||
options: Button,
|
||||
upload: Button,
|
||||
pub g_box: Box,
|
||||
}
|
||||
|
||||
impl Control {
|
||||
pub fn build(header: &Rc<Cell<Header>>) -> Self {
|
||||
// Init components
|
||||
let counter = Label::counter();
|
||||
let options = Button::options(header);
|
||||
let upload = Button::upload();
|
||||
|
||||
// Init main widget
|
||||
let g_box = {
|
||||
use gtk::{prelude::BoxExt, Align, Orientation};
|
||||
let g_box = Box::builder()
|
||||
.halign(Align::End)
|
||||
.orientation(Orientation::Horizontal)
|
||||
.spacing(8)
|
||||
.build();
|
||||
|
||||
g_box.append(&counter);
|
||||
g_box.append(&options);
|
||||
g_box.append(&upload);
|
||||
g_box
|
||||
};
|
||||
|
||||
Self {
|
||||
counter,
|
||||
options,
|
||||
upload,
|
||||
g_box,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&self, bytes_total: Option<usize>) {
|
||||
use gtk::prelude::WidgetExt;
|
||||
|
||||
self.counter.update(bytes_total);
|
||||
|
||||
let is_some = bytes_total.is_some();
|
||||
self.options.set_sensitive(is_some);
|
||||
self.upload.set_sensitive(is_some);
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
use gtk::{prelude::WidgetExt, Label};
|
||||
|
||||
pub trait Counter {
|
||||
fn counter() -> Self;
|
||||
fn update(&self, bytes_total: Option<usize>);
|
||||
}
|
||||
|
||||
impl Counter for Label {
|
||||
// Constructors
|
||||
|
||||
fn counter() -> Self {
|
||||
Label::builder().css_classes(["dim-label"]).build() // @TODO use `dimmed` in Adw 1.6,
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
||||
fn update(&self, bytes_total: Option<usize>) {
|
||||
self.set_visible(if let Some(bytes_total) = bytes_total {
|
||||
use crate::tool::Format;
|
||||
self.set_text(&bytes_total.bytes());
|
||||
true
|
||||
} else {
|
||||
false
|
||||
})
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
use super::Header;
|
||||
use gtk::{
|
||||
prelude::{ButtonExt, WidgetExt},
|
||||
Button,
|
||||
};
|
||||
use std::{cell::Cell, rc::Rc};
|
||||
|
||||
pub trait Options {
|
||||
fn options(header: &Rc<Cell<Header>>) -> Self;
|
||||
}
|
||||
|
||||
impl Options for Button {
|
||||
fn options(header: &Rc<Cell<Header>>) -> Self {
|
||||
let button = Button::builder()
|
||||
.icon_name("emblem-system-symbolic")
|
||||
// @TODO deactivate by default on dyn MIME type detection only
|
||||
// .sensitive(false)
|
||||
.tooltip_text("Options")
|
||||
.build();
|
||||
|
||||
button.connect_clicked({
|
||||
let header = header.clone();
|
||||
move |this| {
|
||||
this.set_sensitive(false); // lock
|
||||
header.take().dialog(Some(this), {
|
||||
let this = this.clone();
|
||||
let header = header.clone();
|
||||
move |options| {
|
||||
header.replace(options);
|
||||
this.set_sensitive(true); // unlock
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
button
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
use gtk::Button;
|
||||
|
||||
pub trait Form {
|
||||
fn form() -> Self;
|
||||
}
|
||||
|
||||
impl Form for Button {
|
||||
fn form() -> Self {
|
||||
use gtk::prelude::{ButtonExt, WidgetExt};
|
||||
|
||||
let button = Button::builder()
|
||||
.label("Choose a file..")
|
||||
.margin_top(4)
|
||||
.build();
|
||||
|
||||
button.connect_clicked(|this| {
|
||||
this.set_sensitive(false); // lock
|
||||
});
|
||||
|
||||
button
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
use gtk::Label;
|
||||
|
||||
pub trait Title {
|
||||
fn title(label: &str) -> Self;
|
||||
pub trait Tab {
|
||||
fn tab(label: &str) -> Self;
|
||||
}
|
||||
|
||||
impl Title for Label {
|
||||
fn title(label: &str) -> Self {
|
||||
impl Tab for Label {
|
||||
fn tab(label: &str) -> Self {
|
||||
Label::builder()
|
||||
.css_classes(["heading"])
|
||||
.label(label)
|
@ -1,71 +1,42 @@
|
||||
mod control;
|
||||
mod form;
|
||||
|
||||
use super::Header;
|
||||
use gtk::glib::Bytes;
|
||||
use super::Control;
|
||||
use gtk::{
|
||||
prelude::{TextBufferExt, TextViewExt},
|
||||
TextView,
|
||||
};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub trait Text {
|
||||
fn text(callback: impl Fn(Header, Bytes, Box<dyn Fn()>) + 'static) -> Self;
|
||||
fn text(control: &Rc<Control>) -> Self;
|
||||
fn len(&self) -> usize;
|
||||
fn count(&self) -> i32;
|
||||
}
|
||||
|
||||
impl Text for gtk::Box {
|
||||
fn text(callback: impl Fn(Header, Bytes, Box<dyn Fn()>) + 'static) -> Self {
|
||||
use control::{Control, Upload};
|
||||
impl Text for TextView {
|
||||
fn text(control: &Rc<Control>) -> Self {
|
||||
use form::Form;
|
||||
use gtk::{
|
||||
prelude::{BoxExt, ButtonExt, TextBufferExt, TextViewExt},
|
||||
Orientation, TextView,
|
||||
};
|
||||
use std::{cell::Cell, rc::Rc};
|
||||
|
||||
// Init components
|
||||
let header = Rc::new(Cell::new(Header {
|
||||
mime: Some("text/plain".into()), // some servers require not empty content type
|
||||
token: None,
|
||||
}));
|
||||
let control = Rc::new(Control::build(&header));
|
||||
let form = TextView::form();
|
||||
let text_view = TextView::form();
|
||||
|
||||
// Init widget
|
||||
let g_box = {
|
||||
const MARGIN: i32 = 8;
|
||||
let g_box = gtk::Box::builder()
|
||||
.margin_bottom(MARGIN / 2)
|
||||
.margin_end(MARGIN)
|
||||
.margin_start(MARGIN)
|
||||
.orientation(Orientation::Vertical)
|
||||
.spacing(MARGIN)
|
||||
.build();
|
||||
|
||||
g_box.append(&form);
|
||||
g_box.append(&control.g_box);
|
||||
g_box
|
||||
};
|
||||
|
||||
// Connect events
|
||||
|
||||
form.buffer().connect_changed({
|
||||
text_view.buffer().connect_changed({
|
||||
let control = control.clone();
|
||||
move |this| {
|
||||
control.update(
|
||||
this.char_count(),
|
||||
this.text(&this.start_iter(), &this.end_iter(), true).len(),
|
||||
)
|
||||
}
|
||||
let text_view = text_view.clone();
|
||||
move |text_buffer| control.update(Some(text_view.len()), Some(text_buffer.char_count()))
|
||||
});
|
||||
|
||||
control.upload.connect_clicked(move |this| {
|
||||
this.set_uploading();
|
||||
callback(
|
||||
header.take(),
|
||||
Bytes::from(form.text().as_bytes()),
|
||||
Box::new({
|
||||
let this = this.clone();
|
||||
move || this.set_resend() // on failure
|
||||
}),
|
||||
)
|
||||
});
|
||||
text_view
|
||||
}
|
||||
|
||||
g_box
|
||||
fn count(&self) -> i32 {
|
||||
self.buffer().char_count()
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
let buffer = self.buffer();
|
||||
|
||||
buffer
|
||||
.text(&buffer.start_iter(), &buffer.end_iter(), true)
|
||||
.len()
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +0,0 @@
|
||||
use gtk::{prelude::WidgetExt, Label};
|
||||
use plurify::Plurify;
|
||||
|
||||
pub trait Counter {
|
||||
fn counter() -> Self;
|
||||
fn update(&self, char_count: i32, bytes_total: usize);
|
||||
}
|
||||
|
||||
impl Counter for Label {
|
||||
// Constructors
|
||||
|
||||
fn counter() -> Self {
|
||||
Label::builder().css_classes(["dim-label"]).build() // @TODO use `dimmed` in Adw 1.6,
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
||||
fn update(&self, chars_count: i32, bytes_total: usize) {
|
||||
self.set_visible(if bytes_total > 0 {
|
||||
self.set_label(&bytes_total.to_string());
|
||||
self.set_tooltip_markup(Some(&format!(
|
||||
"{bytes_total} {} <sup>/ {chars_count} {}</sup>",
|
||||
(bytes_total).plurify(&["byte", "bytes", "bytes"]),
|
||||
(chars_count as usize).plurify(&["char", "chars", "chars"]),
|
||||
)));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
})
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
use gtk::{
|
||||
prelude::{ButtonExt, WidgetExt},
|
||||
Button,
|
||||
};
|
||||
|
||||
pub trait Upload {
|
||||
fn upload() -> Self;
|
||||
fn set_uploading(&self);
|
||||
fn set_resend(&self);
|
||||
}
|
||||
|
||||
impl Upload for Button {
|
||||
fn upload() -> Self {
|
||||
Button::builder()
|
||||
// @TODO this class not looks well with default GTK Notebook widget
|
||||
// activate it after upgrade to `ToggleGroup` in Adw v1.7 / Ubuntu 26.04
|
||||
// .css_classes(["accent"]) // | `suggested-action`
|
||||
.label("Upload")
|
||||
.sensitive(false)
|
||||
.build()
|
||||
}
|
||||
fn set_uploading(&self) {
|
||||
self.set_sensitive(false);
|
||||
self.set_label("uploading..");
|
||||
}
|
||||
fn set_resend(&self) {
|
||||
self.set_sensitive(true);
|
||||
self.set_label("Resend");
|
||||
}
|
||||
}
|
@ -1,14 +1,9 @@
|
||||
use gtk::{
|
||||
glib::GString,
|
||||
prelude::{TextBufferExt, TextViewExt, WidgetExt},
|
||||
TextView, WrapMode,
|
||||
};
|
||||
use gtk::{prelude::WidgetExt, TextView, WrapMode};
|
||||
use libspelling::{Checker, TextBufferAdapter};
|
||||
use sourceview::Buffer;
|
||||
|
||||
pub trait Form {
|
||||
fn form() -> Self;
|
||||
fn text(&self) -> GString;
|
||||
}
|
||||
|
||||
impl Form for TextView {
|
||||
@ -51,11 +46,4 @@ impl Form for TextView {
|
||||
// Return activated `Self`
|
||||
text_view
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
||||
fn text(&self) -> GString {
|
||||
let buffer = self.buffer();
|
||||
buffer.text(&buffer.start_iter(), &buffer.end_iter(), true)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user