pub struct TextBuffer { /* private fields */ }Expand description
Wraps a text buffer, Cloning a text buffer invalidates the underlying pointer, thus the no derive(Clone)
Implementations§
Source§impl TextBuffer
impl TextBuffer
Sourcepub unsafe fn delete(buf: Self)
pub unsafe fn delete(buf: Self)
Deletes the TextBuffer
§Safety
The buffer shouldn’t be deleted while the Display widget still needs it
Sourcepub unsafe fn delete_buffer(buf: Self)
pub unsafe fn delete_buffer(buf: Self)
Deletes the TextBuffer
§Safety
The buffer shouldn’t be deleted while the Display widget still needs it
Sourcepub unsafe fn from_ptr(ptr: *mut Fl_Text_Buffer) -> Self
pub unsafe fn from_ptr(ptr: *mut Fl_Text_Buffer) -> Self
Sourcepub unsafe fn as_ptr(&self) -> *mut Fl_Text_Buffer
pub unsafe fn as_ptr(&self) -> *mut Fl_Text_Buffer
Returns the inner pointer from a text buffer
§Safety
Can return multiple mutable pointers to the same buffer
Sourcepub fn set_text(&mut self, txt: &str)
pub fn set_text(&mut self, txt: &str)
Sets the text of the buffer
Examples found in repository?
195fn menu_cb(m: &mut impl MenuExt) {
196 if let Ok(mpath) = m.item_pathname(None) {
197 let ed: text::TextEditor = app::widget_from_id("ed").unwrap();
198 match mpath.as_str() {
199 "&File/&New...\t" => {
200 STATE.with(|s| {
201 if !s.buf.text().is_empty() {
202 let c = dialog::choice2_default(
203 "Are you sure you want to clear the buffer?",
204 "&Yes",
205 "&No",
206 "",
207 );
208 if c == Some(0) {
209 s.buf.set_text("");
210 s.saved = false;
211 }
212 }
213 });
214 }
215 "&File/&Open...\t" => {
216 if let Some(c) = nfc_get_file(dialog::NativeFileChooserType::BrowseFile) {
217 if let Ok(text) = std::fs::read_to_string(&c) {
218 STATE.with(move |s| {
219 s.buf.set_text(&text);
220 s.saved = false;
221 s.current_file = c.clone();
222 });
223 }
224 }
225 }
226 "&File/&Save\t" => {
227 STATE.with(|s| {
228 if !s.saved && s.current_file.exists() {
229 std::fs::write(&s.current_file, s.buf.text()).ok();
230 }
231 });
232 }
233 "&File/Save &as...\t" => {
234 if let Some(c) = nfc_get_file(dialog::NativeFileChooserType::BrowseSaveFile) {
235 STATE.with(move |s| {
236 std::fs::write(&c, s.buf.text()).ok();
237 s.saved = true;
238 s.current_file = c.clone();
239 });
240 }
241 }
242 "&File/&Quit\t" => quit_cb(),
243 "&Edit/Cu&t\t" => ed.cut(),
244 "&Edit/&Copy\t" => ed.copy(),
245 "&Edit/&Paste\t" => ed.paste(),
246 "&Help/&About\t" => {
247 dialog::message_default("A minimal text editor written using fltk-rs!")
248 }
249 _ => unreachable!(),
250 }
251 }
252}More examples
31 fn apply_style(
32 &mut self,
33 pos: Option<i32>,
34 ins_items: Option<i32>,
35 del_items: Option<i32>,
36 repl_start: Option<i32>,
37 repl_end: Option<i32>,
38 font: Font,
39 size: i32,
40 color: Color,
41 attr: TextAttr,
42 text_editor: &mut TextEditor,
43 ) {
44 let mut style_buffer = text_editor.style_buffer().unwrap_or_default();
45
46 // get existent style or create new one
47 let style_char =
48 match self.style_table.iter().position(|s| {
49 s.font == font && s.size == size && s.color == color && s.attr == attr
50 }) {
51 Some(i) => ((i + 65) as u8 as char).to_string(),
52 None => {
53 self.style_table.push(StyleTableEntryExt {
54 color,
55 font,
56 size,
57 attr,
58 bgcolor: Color::Black,
59 });
60 ((self.style_table.len() + 64) as u8 as char).to_string()
61 }
62 };
63
64 // insert, delete or replace char index style to the style_buffer
65 match ins_items {
66 Some(n) if n > 0 => {
67 // insert items with style
68 style_buffer.insert(pos.unwrap(), style_char.repeat(n as usize).as_str());
69 }
70 _ => match del_items {
71 Some(n) if n > 0 => {
72 // delete items with style
73 style_buffer.remove(pos.unwrap(), pos.unwrap() + n);
74 }
75 _ => match repl_end {
76 Some(n) if n > 0 => {
77 // replace items style
78 style_buffer.replace(
79 repl_start.unwrap(),
80 repl_end.unwrap(),
81 style_char
82 .repeat((repl_end.unwrap() - repl_start.unwrap()) as usize)
83 .as_str(),
84 );
85 }
86 _ => {}
87 },
88 },
89 }
90
91 // compact styles on the buffer and reorganize the char index on the style_buffer
92 let mut style_index = style_buffer
93 .text()
94 .chars()
95 .map(|c| (c as usize) - 65)
96 .collect::<Vec<usize>>();
97 style_index.sort_unstable();
98 style_index.dedup();
99 for (i, &v) in style_index.iter().enumerate() {
100 self.style_table.swap(i, v);
101 style_buffer.set_text(
102 style_buffer
103 .text()
104 .replace(
105 (v + 65) as u8 as char,
106 ((i + 65) as u8 as char).to_string().as_str(),
107 )
108 .as_str(),
109 );
110 }
111
112 // remove unused indexes
113 //self.style_table = self.style_table.drain(in_buff.len()..).collect();
114 self.style_table.truncate(style_index.len());
115 text_editor.set_highlight_data_ext(style_buffer, self.style_table.to_owned());
116
117 // uncomment this line to see that the style_table is compact
118 // println!("total styles: {}", self.style_table.len());
119 }375 pub fn launch(&mut self) {
376 while self.app.wait() {
377 use Message::*;
378 if let Some(msg) = self.r.recv() {
379 match msg {
380 Changed => {
381 if !self.modified {
382 self.modified = true;
383 self.menu.menu.find_item("&File/&Save\t").unwrap().activate();
384 self.menu.menu.find_item("&File/&Quit\t").unwrap().set_label_color(Color::Red);
385 let name = match &self.filename {
386 Some(f) => f.to_string_lossy().to_string(),
387 None => "(Untitled)".to_string(),
388 };
389 self.main_win.set_label(&format!("* {name} - RustyEd"));
390 }
391 }
392 New => {
393 if self.buf.text() != "" {
394 let clear = if let Some(x) = dialog::choice2(center().0 - 200, center().1 - 100, "File unsaved, Do you wish to continue?", "&Yes", "&No!", "") {
395 x == 0
396 } else {
397 false
398 };
399 if clear {
400 self.buf.set_text("");
401 }
402 }
403 },
404 Open => {
405 if let Some(c) = nfc_get_file(dialog::NativeFileChooserType::BrowseFile) {
406 if c.exists() {
407 match self.buf.load_file(&c) {
408 Ok(_) => self.filename = Some(c),
409 Err(e) => dialog::alert(center().0 - 200, center().1 - 100, &format!("An issue occured while loading the file: {e}")),
410 }
411 } else {
412 dialog::alert(center().0 - 200, center().1 - 100, "File does not exist!")
413 }
414 }
415 },
416 Save => { self.save_file().unwrap(); },
417 SaveAs => { self.save_file_as().unwrap(); },
418 Print => {
419 let mut printer = printer::Printer::default();
420 if printer.begin_job(0).is_ok() {
421 let (w, h) = printer.printable_rect();
422 self.printable.set_size(w - 40, h - 40);
423 // Needs cleanup
424 let line_count = self.printable.count_lines(0, self.printable.buffer().unwrap().length(), true) / 45;
425 for i in 0..=line_count {
426 self.printable.scroll(45 * i, 0);
427 printer.begin_page().ok();
428 printer.print_widget(&self.printable, 20, 20);
429 printer.end_page().ok();
430 }
431 printer.end_job();
432 }
433 },
434 Quit => {
435 if self.modified {
436 match dialog::choice2(center().0 - 200, center().1 - 100,
437 "Would you like to save your work?", "&Yes", "&No", "") {
438 Some(0) => {
439 if self.save_file().unwrap() {
440 self.app.quit();
441 }
442 },
443 Some(1) => { self.app.quit() },
444 Some(_) | None => (),
445 }
446 } else {
447 self.app.quit();
448 }
449 },
450 Cut => self.editor.cut(),
451 Copy => self.editor.copy(),
452 Paste => self.editor.paste(),
453 About => dialog::message(center().0 - 300, center().1 - 100, "This is an example application written in Rust and using the FLTK Gui library."),
454 }
455 }
456 }
457 }Sourcepub fn text(&self) -> String
pub fn text(&self) -> String
Returns the text of the buffer
Examples found in repository?
195fn menu_cb(m: &mut impl MenuExt) {
196 if let Ok(mpath) = m.item_pathname(None) {
197 let ed: text::TextEditor = app::widget_from_id("ed").unwrap();
198 match mpath.as_str() {
199 "&File/&New...\t" => {
200 STATE.with(|s| {
201 if !s.buf.text().is_empty() {
202 let c = dialog::choice2_default(
203 "Are you sure you want to clear the buffer?",
204 "&Yes",
205 "&No",
206 "",
207 );
208 if c == Some(0) {
209 s.buf.set_text("");
210 s.saved = false;
211 }
212 }
213 });
214 }
215 "&File/&Open...\t" => {
216 if let Some(c) = nfc_get_file(dialog::NativeFileChooserType::BrowseFile) {
217 if let Ok(text) = std::fs::read_to_string(&c) {
218 STATE.with(move |s| {
219 s.buf.set_text(&text);
220 s.saved = false;
221 s.current_file = c.clone();
222 });
223 }
224 }
225 }
226 "&File/&Save\t" => {
227 STATE.with(|s| {
228 if !s.saved && s.current_file.exists() {
229 std::fs::write(&s.current_file, s.buf.text()).ok();
230 }
231 });
232 }
233 "&File/Save &as...\t" => {
234 if let Some(c) = nfc_get_file(dialog::NativeFileChooserType::BrowseSaveFile) {
235 STATE.with(move |s| {
236 std::fs::write(&c, s.buf.text()).ok();
237 s.saved = true;
238 s.current_file = c.clone();
239 });
240 }
241 }
242 "&File/&Quit\t" => quit_cb(),
243 "&Edit/Cu&t\t" => ed.cut(),
244 "&Edit/&Copy\t" => ed.copy(),
245 "&Edit/&Paste\t" => ed.paste(),
246 "&Help/&About\t" => {
247 dialog::message_default("A minimal text editor written using fltk-rs!")
248 }
249 _ => unreachable!(),
250 }
251 }
252}More examples
31 fn apply_style(
32 &mut self,
33 pos: Option<i32>,
34 ins_items: Option<i32>,
35 del_items: Option<i32>,
36 repl_start: Option<i32>,
37 repl_end: Option<i32>,
38 font: Font,
39 size: i32,
40 color: Color,
41 attr: TextAttr,
42 text_editor: &mut TextEditor,
43 ) {
44 let mut style_buffer = text_editor.style_buffer().unwrap_or_default();
45
46 // get existent style or create new one
47 let style_char =
48 match self.style_table.iter().position(|s| {
49 s.font == font && s.size == size && s.color == color && s.attr == attr
50 }) {
51 Some(i) => ((i + 65) as u8 as char).to_string(),
52 None => {
53 self.style_table.push(StyleTableEntryExt {
54 color,
55 font,
56 size,
57 attr,
58 bgcolor: Color::Black,
59 });
60 ((self.style_table.len() + 64) as u8 as char).to_string()
61 }
62 };
63
64 // insert, delete or replace char index style to the style_buffer
65 match ins_items {
66 Some(n) if n > 0 => {
67 // insert items with style
68 style_buffer.insert(pos.unwrap(), style_char.repeat(n as usize).as_str());
69 }
70 _ => match del_items {
71 Some(n) if n > 0 => {
72 // delete items with style
73 style_buffer.remove(pos.unwrap(), pos.unwrap() + n);
74 }
75 _ => match repl_end {
76 Some(n) if n > 0 => {
77 // replace items style
78 style_buffer.replace(
79 repl_start.unwrap(),
80 repl_end.unwrap(),
81 style_char
82 .repeat((repl_end.unwrap() - repl_start.unwrap()) as usize)
83 .as_str(),
84 );
85 }
86 _ => {}
87 },
88 },
89 }
90
91 // compact styles on the buffer and reorganize the char index on the style_buffer
92 let mut style_index = style_buffer
93 .text()
94 .chars()
95 .map(|c| (c as usize) - 65)
96 .collect::<Vec<usize>>();
97 style_index.sort_unstable();
98 style_index.dedup();
99 for (i, &v) in style_index.iter().enumerate() {
100 self.style_table.swap(i, v);
101 style_buffer.set_text(
102 style_buffer
103 .text()
104 .replace(
105 (v + 65) as u8 as char,
106 ((i + 65) as u8 as char).to_string().as_str(),
107 )
108 .as_str(),
109 );
110 }
111
112 // remove unused indexes
113 //self.style_table = self.style_table.drain(in_buff.len()..).collect();
114 self.style_table.truncate(style_index.len());
115 text_editor.set_highlight_data_ext(style_buffer, self.style_table.to_owned());
116
117 // uncomment this line to see that the style_table is compact
118 // println!("total styles: {}", self.style_table.len());
119 }375 pub fn launch(&mut self) {
376 while self.app.wait() {
377 use Message::*;
378 if let Some(msg) = self.r.recv() {
379 match msg {
380 Changed => {
381 if !self.modified {
382 self.modified = true;
383 self.menu.menu.find_item("&File/&Save\t").unwrap().activate();
384 self.menu.menu.find_item("&File/&Quit\t").unwrap().set_label_color(Color::Red);
385 let name = match &self.filename {
386 Some(f) => f.to_string_lossy().to_string(),
387 None => "(Untitled)".to_string(),
388 };
389 self.main_win.set_label(&format!("* {name} - RustyEd"));
390 }
391 }
392 New => {
393 if self.buf.text() != "" {
394 let clear = if let Some(x) = dialog::choice2(center().0 - 200, center().1 - 100, "File unsaved, Do you wish to continue?", "&Yes", "&No!", "") {
395 x == 0
396 } else {
397 false
398 };
399 if clear {
400 self.buf.set_text("");
401 }
402 }
403 },
404 Open => {
405 if let Some(c) = nfc_get_file(dialog::NativeFileChooserType::BrowseFile) {
406 if c.exists() {
407 match self.buf.load_file(&c) {
408 Ok(_) => self.filename = Some(c),
409 Err(e) => dialog::alert(center().0 - 200, center().1 - 100, &format!("An issue occured while loading the file: {e}")),
410 }
411 } else {
412 dialog::alert(center().0 - 200, center().1 - 100, "File does not exist!")
413 }
414 }
415 },
416 Save => { self.save_file().unwrap(); },
417 SaveAs => { self.save_file_as().unwrap(); },
418 Print => {
419 let mut printer = printer::Printer::default();
420 if printer.begin_job(0).is_ok() {
421 let (w, h) = printer.printable_rect();
422 self.printable.set_size(w - 40, h - 40);
423 // Needs cleanup
424 let line_count = self.printable.count_lines(0, self.printable.buffer().unwrap().length(), true) / 45;
425 for i in 0..=line_count {
426 self.printable.scroll(45 * i, 0);
427 printer.begin_page().ok();
428 printer.print_widget(&self.printable, 20, 20);
429 printer.end_page().ok();
430 }
431 printer.end_job();
432 }
433 },
434 Quit => {
435 if self.modified {
436 match dialog::choice2(center().0 - 200, center().1 - 100,
437 "Would you like to save your work?", "&Yes", "&No", "") {
438 Some(0) => {
439 if self.save_file().unwrap() {
440 self.app.quit();
441 }
442 },
443 Some(1) => { self.app.quit() },
444 Some(_) | None => (),
445 }
446 } else {
447 self.app.quit();
448 }
449 },
450 Cut => self.editor.cut(),
451 Copy => self.editor.copy(),
452 Paste => self.editor.paste(),
453 About => dialog::message(center().0 - 300, center().1 - 100, "This is an example application written in Rust and using the FLTK Gui library."),
454 }
455 }
456 }
457 }Sourcepub fn append(&mut self, text: &str)
pub fn append(&mut self, text: &str)
Appends to the buffer. To append and scroll to the end of the buffer:
use fltk::{prelude::*, *};
let txt = "Some long text!";
let buf = text::TextBuffer::default();
let mut disp = text::TextDisplay::default();
disp.set_buffer(Some(buf));
disp.buffer().unwrap().append(txt);
disp.set_insert_position(disp.buffer().unwrap().length());
disp.scroll(
disp.count_lines(0, disp.buffer().unwrap().length(), true),
0,
);Sourcepub fn length(&self) -> i32
pub fn length(&self) -> i32
Get the length of the buffer
Examples found in repository?
375 pub fn launch(&mut self) {
376 while self.app.wait() {
377 use Message::*;
378 if let Some(msg) = self.r.recv() {
379 match msg {
380 Changed => {
381 if !self.modified {
382 self.modified = true;
383 self.menu.menu.find_item("&File/&Save\t").unwrap().activate();
384 self.menu.menu.find_item("&File/&Quit\t").unwrap().set_label_color(Color::Red);
385 let name = match &self.filename {
386 Some(f) => f.to_string_lossy().to_string(),
387 None => "(Untitled)".to_string(),
388 };
389 self.main_win.set_label(&format!("* {name} - RustyEd"));
390 }
391 }
392 New => {
393 if self.buf.text() != "" {
394 let clear = if let Some(x) = dialog::choice2(center().0 - 200, center().1 - 100, "File unsaved, Do you wish to continue?", "&Yes", "&No!", "") {
395 x == 0
396 } else {
397 false
398 };
399 if clear {
400 self.buf.set_text("");
401 }
402 }
403 },
404 Open => {
405 if let Some(c) = nfc_get_file(dialog::NativeFileChooserType::BrowseFile) {
406 if c.exists() {
407 match self.buf.load_file(&c) {
408 Ok(_) => self.filename = Some(c),
409 Err(e) => dialog::alert(center().0 - 200, center().1 - 100, &format!("An issue occured while loading the file: {e}")),
410 }
411 } else {
412 dialog::alert(center().0 - 200, center().1 - 100, "File does not exist!")
413 }
414 }
415 },
416 Save => { self.save_file().unwrap(); },
417 SaveAs => { self.save_file_as().unwrap(); },
418 Print => {
419 let mut printer = printer::Printer::default();
420 if printer.begin_job(0).is_ok() {
421 let (w, h) = printer.printable_rect();
422 self.printable.set_size(w - 40, h - 40);
423 // Needs cleanup
424 let line_count = self.printable.count_lines(0, self.printable.buffer().unwrap().length(), true) / 45;
425 for i in 0..=line_count {
426 self.printable.scroll(45 * i, 0);
427 printer.begin_page().ok();
428 printer.print_widget(&self.printable, 20, 20);
429 printer.end_page().ok();
430 }
431 printer.end_job();
432 }
433 },
434 Quit => {
435 if self.modified {
436 match dialog::choice2(center().0 - 200, center().1 - 100,
437 "Would you like to save your work?", "&Yes", "&No", "") {
438 Some(0) => {
439 if self.save_file().unwrap() {
440 self.app.quit();
441 }
442 },
443 Some(1) => { self.app.quit() },
444 Some(_) | None => (),
445 }
446 } else {
447 self.app.quit();
448 }
449 },
450 Cut => self.editor.cut(),
451 Copy => self.editor.copy(),
452 Paste => self.editor.paste(),
453 About => dialog::message(center().0 - 300, center().1 - 100, "This is an example application written in Rust and using the FLTK Gui library."),
454 }
455 }
456 }
457 }More examples
122fn main() {
123 let style = Rc::from(RefCell::from(Style::new()));
124
125 let app = App::default().with_scheme(Scheme::Gleam);
126 let mut wind = Window::default()
127 .with_size(500, 200)
128 .with_label("Highlight");
129 let mut vpack = Pack::new(4, 4, 492, 192, "");
130 vpack.set_spacing(4);
131 let mut text_editor = TextEditor::default().with_size(492, 163);
132
133 let mut hpack = Pack::new(4, 4, 492, 25, "").with_type(PackType::Horizontal);
134 hpack.set_spacing(8);
135 let mut font = Choice::default().with_size(130, 25);
136 let mut choice = Choice::default().with_size(130, 25);
137 let mut size = Spinner::default().with_size(60, 25);
138
139 let mut color = Choice::default().with_size(100, 25);
140 let mut btn_clear = Button::default().with_size(40, 25).with_label("X");
141 hpack.end();
142
143 vpack.end();
144 wind.end();
145 wind.show();
146
147 text_editor.wrap_mode(fltk::text::WrapMode::AtBounds, 0);
148 text_editor.set_buffer(TextBuffer::default());
149
150 font.add_choice("Courier|Helvetica|Times");
151 font.set_value(0);
152 font.set_tooltip("Font");
153
154 choice.add_choice("Normal|Underline|Strike");
155 choice.set_value(0);
156
157 size.set_value(18.0);
158 size.set_step(1.0);
159 size.set_range(12.0, 28.0);
160 size.set_tooltip("Size");
161
162 color.set_tooltip("Color");
163 color.add_choice("#000000|#ff0000|#00ff00|#0000ff|#ffff00|#00ffff");
164 color.set_value(0);
165
166 btn_clear.set_label_color(Color::Red);
167 btn_clear.set_tooltip("Clear style");
168
169 // set colors
170 for mut item in color.clone() {
171 if let Some(lbl) = item.label() {
172 item.set_label_color(Color::from_u32(
173 u32::from_str_radix(lbl.trim().strip_prefix('#').unwrap(), 16)
174 .ok()
175 .unwrap(),
176 ));
177 }
178 }
179
180 let style_rc1 = Rc::clone(&style);
181
182 text_editor.buffer().unwrap().add_modify_callback({
183 let mut text_editor1 = text_editor.clone();
184 let font1 = font.clone();
185 let size1 = size.clone();
186 let color1 = color.clone();
187 let choice1 = choice.clone();
188 move |pos: i32, ins_items: i32, del_items: i32, _: i32, _: &str| {
189 let attr = if choice1.value() == 1 {
190 TextAttr::Underline
191 } else if choice1.value() == 2 {
192 TextAttr::StrikeThrough
193 } else {
194 TextAttr::None
195 };
196 if ins_items > 0 || del_items > 0 {
197 let mut style = style_rc1.borrow_mut();
198 let color = Color::from_u32(
199 u32::from_str_radix(
200 color1
201 .text(color1.value())
202 .unwrap()
203 .trim()
204 .strip_prefix('#')
205 .unwrap(),
206 16,
207 )
208 .ok()
209 .unwrap(),
210 );
211 style.apply_style(
212 Some(pos),
213 Some(ins_items),
214 Some(del_items),
215 None,
216 None,
217 Font::by_name(font1.text(font1.value()).unwrap().trim()),
218 size1.value() as i32,
219 color,
220 attr,
221 &mut text_editor1,
222 );
223 }
224 }
225 });
226
227 color.set_callback({
228 let size = size.clone();
229 let font = font.clone();
230 let choice = choice.clone();
231 let mut text_editor = text_editor.clone();
232 let style_rc1 = Rc::clone(&style);
233 move |color| {
234 let attr = match choice.value() {
235 0 => TextAttr::None,
236 1 => TextAttr::Underline,
237 2 => TextAttr::StrikeThrough,
238 _ => unreachable!(),
239 };
240 if let Some(buf) = text_editor.buffer() {
241 if let Some((s, e)) = buf.selection_position() {
242 let mut style = style_rc1.borrow_mut();
243 let color = Color::from_u32(
244 u32::from_str_radix(
245 color
246 .text(color.value())
247 .unwrap()
248 .trim()
249 .strip_prefix('#')
250 .unwrap(),
251 16,
252 )
253 .ok()
254 .unwrap(),
255 );
256 style.apply_style(
257 None,
258 None,
259 None,
260 Some(s),
261 Some(e),
262 Font::by_name(font.text(font.value()).unwrap().trim()),
263 size.value() as i32,
264 color,
265 attr,
266 &mut text_editor,
267 );
268 }
269 }
270 }
271 });
272
273 // get the style from the current cursor position
274 text_editor.handle({
275 let style_rc1 = Rc::clone(&style);
276 let mut font1 = font.clone();
277 let mut size1 = size.clone();
278 let mut color1 = color.clone();
279 move |te, e| match e {
280 Event::KeyUp | Event::Released => {
281 if let Some(buff) = te.style_buffer() {
282 let i = te.insert_position();
283 if let Some(t) = buff.text_range(i, i + 1) {
284 if !t.is_empty() {
285 let style = style_rc1.borrow_mut();
286 if let Some(i) = t.chars().next().map(|c| (c as usize - 65)) {
287 if let Some(style) = style.style_table.get(i) {
288 if let Some(mn) = font1.find_item(&format!("{:?}", style.font))
289 {
290 font1.set_item(&mn);
291 }
292 size1.set_value(style.size as f64);
293 let (r, g, b) = style.color.to_rgb();
294 if let Some(mn) =
295 color1.find_item(format!("{r:02x}{g:02x}{b:02x}").as_str())
296 {
297 color1.set_item(&mn);
298 }
299 }
300 }
301 }
302 }
303 }
304 true
305 }
306 _ => false,
307 }
308 });
309
310 choice.set_callback({
311 let mut color1 = color.clone();
312 move |_| color1.do_callback()
313 });
314
315 font.set_callback({
316 let mut color1 = color.clone();
317 move |_| color1.do_callback()
318 });
319
320 size.set_callback({
321 let mut color1 = color.clone();
322 move |_| color1.do_callback()
323 });
324
325 // clear style of the current selection or, if no text is selected, clear all text style
326 btn_clear.set_callback({
327 let style_rc1 = Rc::clone(&style);
328 let text_editor1 = text_editor.clone();
329 move |_| {
330 match text_editor1.buffer().unwrap().selection_position() {
331 Some((_, _)) => {
332 font.set_value(0);
333 size.set_value(18.0);
334 color.set_value(0);
335 choice.set_value(0);
336 color.do_callback();
337 }
338 None => {
339 font.set_value(0);
340 size.set_value(18.0);
341 color.set_value(0);
342 style_rc1.borrow_mut().apply_style(
343 None,
344 None,
345 None,
346 Some(0),
347 Some(text_editor1.buffer().unwrap().length()),
348 Font::Courier,
349 16,
350 Color::Black,
351 TextAttr::None,
352 &mut text_editor,
353 );
354 }
355 };
356 }
357 });
358
359 app.run().unwrap();
360}Sourcepub fn remove(&mut self, start: i32, end: i32)
pub fn remove(&mut self, start: i32, end: i32)
Removes from the buffer
Examples found in repository?
31 fn apply_style(
32 &mut self,
33 pos: Option<i32>,
34 ins_items: Option<i32>,
35 del_items: Option<i32>,
36 repl_start: Option<i32>,
37 repl_end: Option<i32>,
38 font: Font,
39 size: i32,
40 color: Color,
41 attr: TextAttr,
42 text_editor: &mut TextEditor,
43 ) {
44 let mut style_buffer = text_editor.style_buffer().unwrap_or_default();
45
46 // get existent style or create new one
47 let style_char =
48 match self.style_table.iter().position(|s| {
49 s.font == font && s.size == size && s.color == color && s.attr == attr
50 }) {
51 Some(i) => ((i + 65) as u8 as char).to_string(),
52 None => {
53 self.style_table.push(StyleTableEntryExt {
54 color,
55 font,
56 size,
57 attr,
58 bgcolor: Color::Black,
59 });
60 ((self.style_table.len() + 64) as u8 as char).to_string()
61 }
62 };
63
64 // insert, delete or replace char index style to the style_buffer
65 match ins_items {
66 Some(n) if n > 0 => {
67 // insert items with style
68 style_buffer.insert(pos.unwrap(), style_char.repeat(n as usize).as_str());
69 }
70 _ => match del_items {
71 Some(n) if n > 0 => {
72 // delete items with style
73 style_buffer.remove(pos.unwrap(), pos.unwrap() + n);
74 }
75 _ => match repl_end {
76 Some(n) if n > 0 => {
77 // replace items style
78 style_buffer.replace(
79 repl_start.unwrap(),
80 repl_end.unwrap(),
81 style_char
82 .repeat((repl_end.unwrap() - repl_start.unwrap()) as usize)
83 .as_str(),
84 );
85 }
86 _ => {}
87 },
88 },
89 }
90
91 // compact styles on the buffer and reorganize the char index on the style_buffer
92 let mut style_index = style_buffer
93 .text()
94 .chars()
95 .map(|c| (c as usize) - 65)
96 .collect::<Vec<usize>>();
97 style_index.sort_unstable();
98 style_index.dedup();
99 for (i, &v) in style_index.iter().enumerate() {
100 self.style_table.swap(i, v);
101 style_buffer.set_text(
102 style_buffer
103 .text()
104 .replace(
105 (v + 65) as u8 as char,
106 ((i + 65) as u8 as char).to_string().as_str(),
107 )
108 .as_str(),
109 );
110 }
111
112 // remove unused indexes
113 //self.style_table = self.style_table.drain(in_buff.len()..).collect();
114 self.style_table.truncate(style_index.len());
115 text_editor.set_highlight_data_ext(style_buffer, self.style_table.to_owned());
116
117 // uncomment this line to see that the style_table is compact
118 // println!("total styles: {}", self.style_table.len());
119 }Sourcepub fn text_range(&self, start: i32, end: i32) -> Option<String>
pub fn text_range(&self, start: i32, end: i32) -> Option<String>
Returns the text within the range
Examples found in repository?
122fn main() {
123 let style = Rc::from(RefCell::from(Style::new()));
124
125 let app = App::default().with_scheme(Scheme::Gleam);
126 let mut wind = Window::default()
127 .with_size(500, 200)
128 .with_label("Highlight");
129 let mut vpack = Pack::new(4, 4, 492, 192, "");
130 vpack.set_spacing(4);
131 let mut text_editor = TextEditor::default().with_size(492, 163);
132
133 let mut hpack = Pack::new(4, 4, 492, 25, "").with_type(PackType::Horizontal);
134 hpack.set_spacing(8);
135 let mut font = Choice::default().with_size(130, 25);
136 let mut choice = Choice::default().with_size(130, 25);
137 let mut size = Spinner::default().with_size(60, 25);
138
139 let mut color = Choice::default().with_size(100, 25);
140 let mut btn_clear = Button::default().with_size(40, 25).with_label("X");
141 hpack.end();
142
143 vpack.end();
144 wind.end();
145 wind.show();
146
147 text_editor.wrap_mode(fltk::text::WrapMode::AtBounds, 0);
148 text_editor.set_buffer(TextBuffer::default());
149
150 font.add_choice("Courier|Helvetica|Times");
151 font.set_value(0);
152 font.set_tooltip("Font");
153
154 choice.add_choice("Normal|Underline|Strike");
155 choice.set_value(0);
156
157 size.set_value(18.0);
158 size.set_step(1.0);
159 size.set_range(12.0, 28.0);
160 size.set_tooltip("Size");
161
162 color.set_tooltip("Color");
163 color.add_choice("#000000|#ff0000|#00ff00|#0000ff|#ffff00|#00ffff");
164 color.set_value(0);
165
166 btn_clear.set_label_color(Color::Red);
167 btn_clear.set_tooltip("Clear style");
168
169 // set colors
170 for mut item in color.clone() {
171 if let Some(lbl) = item.label() {
172 item.set_label_color(Color::from_u32(
173 u32::from_str_radix(lbl.trim().strip_prefix('#').unwrap(), 16)
174 .ok()
175 .unwrap(),
176 ));
177 }
178 }
179
180 let style_rc1 = Rc::clone(&style);
181
182 text_editor.buffer().unwrap().add_modify_callback({
183 let mut text_editor1 = text_editor.clone();
184 let font1 = font.clone();
185 let size1 = size.clone();
186 let color1 = color.clone();
187 let choice1 = choice.clone();
188 move |pos: i32, ins_items: i32, del_items: i32, _: i32, _: &str| {
189 let attr = if choice1.value() == 1 {
190 TextAttr::Underline
191 } else if choice1.value() == 2 {
192 TextAttr::StrikeThrough
193 } else {
194 TextAttr::None
195 };
196 if ins_items > 0 || del_items > 0 {
197 let mut style = style_rc1.borrow_mut();
198 let color = Color::from_u32(
199 u32::from_str_radix(
200 color1
201 .text(color1.value())
202 .unwrap()
203 .trim()
204 .strip_prefix('#')
205 .unwrap(),
206 16,
207 )
208 .ok()
209 .unwrap(),
210 );
211 style.apply_style(
212 Some(pos),
213 Some(ins_items),
214 Some(del_items),
215 None,
216 None,
217 Font::by_name(font1.text(font1.value()).unwrap().trim()),
218 size1.value() as i32,
219 color,
220 attr,
221 &mut text_editor1,
222 );
223 }
224 }
225 });
226
227 color.set_callback({
228 let size = size.clone();
229 let font = font.clone();
230 let choice = choice.clone();
231 let mut text_editor = text_editor.clone();
232 let style_rc1 = Rc::clone(&style);
233 move |color| {
234 let attr = match choice.value() {
235 0 => TextAttr::None,
236 1 => TextAttr::Underline,
237 2 => TextAttr::StrikeThrough,
238 _ => unreachable!(),
239 };
240 if let Some(buf) = text_editor.buffer() {
241 if let Some((s, e)) = buf.selection_position() {
242 let mut style = style_rc1.borrow_mut();
243 let color = Color::from_u32(
244 u32::from_str_radix(
245 color
246 .text(color.value())
247 .unwrap()
248 .trim()
249 .strip_prefix('#')
250 .unwrap(),
251 16,
252 )
253 .ok()
254 .unwrap(),
255 );
256 style.apply_style(
257 None,
258 None,
259 None,
260 Some(s),
261 Some(e),
262 Font::by_name(font.text(font.value()).unwrap().trim()),
263 size.value() as i32,
264 color,
265 attr,
266 &mut text_editor,
267 );
268 }
269 }
270 }
271 });
272
273 // get the style from the current cursor position
274 text_editor.handle({
275 let style_rc1 = Rc::clone(&style);
276 let mut font1 = font.clone();
277 let mut size1 = size.clone();
278 let mut color1 = color.clone();
279 move |te, e| match e {
280 Event::KeyUp | Event::Released => {
281 if let Some(buff) = te.style_buffer() {
282 let i = te.insert_position();
283 if let Some(t) = buff.text_range(i, i + 1) {
284 if !t.is_empty() {
285 let style = style_rc1.borrow_mut();
286 if let Some(i) = t.chars().next().map(|c| (c as usize - 65)) {
287 if let Some(style) = style.style_table.get(i) {
288 if let Some(mn) = font1.find_item(&format!("{:?}", style.font))
289 {
290 font1.set_item(&mn);
291 }
292 size1.set_value(style.size as f64);
293 let (r, g, b) = style.color.to_rgb();
294 if let Some(mn) =
295 color1.find_item(format!("{r:02x}{g:02x}{b:02x}").as_str())
296 {
297 color1.set_item(&mn);
298 }
299 }
300 }
301 }
302 }
303 }
304 true
305 }
306 _ => false,
307 }
308 });
309
310 choice.set_callback({
311 let mut color1 = color.clone();
312 move |_| color1.do_callback()
313 });
314
315 font.set_callback({
316 let mut color1 = color.clone();
317 move |_| color1.do_callback()
318 });
319
320 size.set_callback({
321 let mut color1 = color.clone();
322 move |_| color1.do_callback()
323 });
324
325 // clear style of the current selection or, if no text is selected, clear all text style
326 btn_clear.set_callback({
327 let style_rc1 = Rc::clone(&style);
328 let text_editor1 = text_editor.clone();
329 move |_| {
330 match text_editor1.buffer().unwrap().selection_position() {
331 Some((_, _)) => {
332 font.set_value(0);
333 size.set_value(18.0);
334 color.set_value(0);
335 choice.set_value(0);
336 color.do_callback();
337 }
338 None => {
339 font.set_value(0);
340 size.set_value(18.0);
341 color.set_value(0);
342 style_rc1.borrow_mut().apply_style(
343 None,
344 None,
345 None,
346 Some(0),
347 Some(text_editor1.buffer().unwrap().length()),
348 Font::Courier,
349 16,
350 Color::Black,
351 TextAttr::None,
352 &mut text_editor,
353 );
354 }
355 };
356 }
357 });
358
359 app.run().unwrap();
360}Sourcepub fn insert(&mut self, pos: i32, text: &str)
pub fn insert(&mut self, pos: i32, text: &str)
Inserts text into a position
Examples found in repository?
31 fn apply_style(
32 &mut self,
33 pos: Option<i32>,
34 ins_items: Option<i32>,
35 del_items: Option<i32>,
36 repl_start: Option<i32>,
37 repl_end: Option<i32>,
38 font: Font,
39 size: i32,
40 color: Color,
41 attr: TextAttr,
42 text_editor: &mut TextEditor,
43 ) {
44 let mut style_buffer = text_editor.style_buffer().unwrap_or_default();
45
46 // get existent style or create new one
47 let style_char =
48 match self.style_table.iter().position(|s| {
49 s.font == font && s.size == size && s.color == color && s.attr == attr
50 }) {
51 Some(i) => ((i + 65) as u8 as char).to_string(),
52 None => {
53 self.style_table.push(StyleTableEntryExt {
54 color,
55 font,
56 size,
57 attr,
58 bgcolor: Color::Black,
59 });
60 ((self.style_table.len() + 64) as u8 as char).to_string()
61 }
62 };
63
64 // insert, delete or replace char index style to the style_buffer
65 match ins_items {
66 Some(n) if n > 0 => {
67 // insert items with style
68 style_buffer.insert(pos.unwrap(), style_char.repeat(n as usize).as_str());
69 }
70 _ => match del_items {
71 Some(n) if n > 0 => {
72 // delete items with style
73 style_buffer.remove(pos.unwrap(), pos.unwrap() + n);
74 }
75 _ => match repl_end {
76 Some(n) if n > 0 => {
77 // replace items style
78 style_buffer.replace(
79 repl_start.unwrap(),
80 repl_end.unwrap(),
81 style_char
82 .repeat((repl_end.unwrap() - repl_start.unwrap()) as usize)
83 .as_str(),
84 );
85 }
86 _ => {}
87 },
88 },
89 }
90
91 // compact styles on the buffer and reorganize the char index on the style_buffer
92 let mut style_index = style_buffer
93 .text()
94 .chars()
95 .map(|c| (c as usize) - 65)
96 .collect::<Vec<usize>>();
97 style_index.sort_unstable();
98 style_index.dedup();
99 for (i, &v) in style_index.iter().enumerate() {
100 self.style_table.swap(i, v);
101 style_buffer.set_text(
102 style_buffer
103 .text()
104 .replace(
105 (v + 65) as u8 as char,
106 ((i + 65) as u8 as char).to_string().as_str(),
107 )
108 .as_str(),
109 );
110 }
111
112 // remove unused indexes
113 //self.style_table = self.style_table.drain(in_buff.len()..).collect();
114 self.style_table.truncate(style_index.len());
115 text_editor.set_highlight_data_ext(style_buffer, self.style_table.to_owned());
116
117 // uncomment this line to see that the style_table is compact
118 // println!("total styles: {}", self.style_table.len());
119 }Sourcepub fn replace(&mut self, start: i32, end: i32, text: &str)
pub fn replace(&mut self, start: i32, end: i32, text: &str)
Replaces text from position start to end
Examples found in repository?
31 fn apply_style(
32 &mut self,
33 pos: Option<i32>,
34 ins_items: Option<i32>,
35 del_items: Option<i32>,
36 repl_start: Option<i32>,
37 repl_end: Option<i32>,
38 font: Font,
39 size: i32,
40 color: Color,
41 attr: TextAttr,
42 text_editor: &mut TextEditor,
43 ) {
44 let mut style_buffer = text_editor.style_buffer().unwrap_or_default();
45
46 // get existent style or create new one
47 let style_char =
48 match self.style_table.iter().position(|s| {
49 s.font == font && s.size == size && s.color == color && s.attr == attr
50 }) {
51 Some(i) => ((i + 65) as u8 as char).to_string(),
52 None => {
53 self.style_table.push(StyleTableEntryExt {
54 color,
55 font,
56 size,
57 attr,
58 bgcolor: Color::Black,
59 });
60 ((self.style_table.len() + 64) as u8 as char).to_string()
61 }
62 };
63
64 // insert, delete or replace char index style to the style_buffer
65 match ins_items {
66 Some(n) if n > 0 => {
67 // insert items with style
68 style_buffer.insert(pos.unwrap(), style_char.repeat(n as usize).as_str());
69 }
70 _ => match del_items {
71 Some(n) if n > 0 => {
72 // delete items with style
73 style_buffer.remove(pos.unwrap(), pos.unwrap() + n);
74 }
75 _ => match repl_end {
76 Some(n) if n > 0 => {
77 // replace items style
78 style_buffer.replace(
79 repl_start.unwrap(),
80 repl_end.unwrap(),
81 style_char
82 .repeat((repl_end.unwrap() - repl_start.unwrap()) as usize)
83 .as_str(),
84 );
85 }
86 _ => {}
87 },
88 },
89 }
90
91 // compact styles on the buffer and reorganize the char index on the style_buffer
92 let mut style_index = style_buffer
93 .text()
94 .chars()
95 .map(|c| (c as usize) - 65)
96 .collect::<Vec<usize>>();
97 style_index.sort_unstable();
98 style_index.dedup();
99 for (i, &v) in style_index.iter().enumerate() {
100 self.style_table.swap(i, v);
101 style_buffer.set_text(
102 style_buffer
103 .text()
104 .replace(
105 (v + 65) as u8 as char,
106 ((i + 65) as u8 as char).to_string().as_str(),
107 )
108 .as_str(),
109 );
110 }
111
112 // remove unused indexes
113 //self.style_table = self.style_table.drain(in_buff.len()..).collect();
114 self.style_table.truncate(style_index.len());
115 text_editor.set_highlight_data_ext(style_buffer, self.style_table.to_owned());
116
117 // uncomment this line to see that the style_table is compact
118 // println!("total styles: {}", self.style_table.len());
119 }Sourcepub fn copy_from(
&mut self,
source_buf: &TextBuffer,
start: i32,
end: i32,
to: i32,
)
pub fn copy_from( &mut self, source_buf: &TextBuffer, start: i32, end: i32, to: i32, )
Copies text from a source buffer into the current buffer
Sourcepub fn copy(&self) -> TextBuffer
pub fn copy(&self) -> TextBuffer
Copies whole text from a source buffer into a new buffer
Sourcepub fn redo(&mut self) -> Result<i32, FltkError>
pub fn redo(&mut self) -> Result<i32, FltkError>
Performs a redo operation on the buffer. Returns the cursor position.
§Errors
Errors on failure to undo
Sourcepub fn get_can_undo(&mut self) -> bool
pub fn get_can_undo(&mut self) -> bool
Gets whether the buffer can undo
Sourcepub fn load_file<P: AsRef<Path>>(&mut self, path: P) -> Result<(), FltkError>
pub fn load_file<P: AsRef<Path>>(&mut self, path: P) -> Result<(), FltkError>
Examples found in repository?
145fn handle_drag_drop(editor: &mut text::TextEditor) {
146 editor.handle({
147 let mut dnd = false;
148 let mut released = false;
149 let buf = editor.buffer().unwrap();
150 move |_, ev| match ev {
151 Event::DndEnter => {
152 dnd = true;
153 true
154 }
155 Event::DndDrag => true,
156 Event::DndRelease => {
157 released = true;
158 true
159 }
160 Event::Paste => {
161 if dnd && released {
162 let path = app::event_text();
163 let path = path.trim();
164 let path = path.replace("file://", "");
165 let path = std::path::PathBuf::from(&path);
166 if path.exists() {
167 // we use a timeout to avoid pasting the path into the buffer
168 app::add_timeout3(0.0, {
169 let mut buf = buf.clone();
170 move |_| match buf.load_file(&path) {
171 Ok(_) => (),
172 Err(e) => dialog::alert_default(&format!(
173 "An issue occured while loading the file: {e}"
174 )),
175 }
176 });
177 }
178 dnd = false;
179 released = false;
180 true
181 } else {
182 false
183 }
184 }
185 Event::DndLeave => {
186 dnd = false;
187 released = false;
188 true
189 }
190 _ => false,
191 }
192 });
193}More examples
206 pub fn new(args: Vec<String>) -> Self {
207 let app = app::App::default().with_scheme(app::Scheme::Gtk);
208 app::background(211, 211, 211);
209 let (s, r) = app::channel::<Message>();
210 let mut buf = text::TextBuffer::default();
211 buf.set_tab_distance(4);
212 let mut main_win = window::Window::default()
213 .with_size(800, 600)
214 .center_screen()
215 .with_label("RustyEd");
216 let menu = MyMenu::new(&s);
217 let modified = false;
218 menu.menu.find_item("&File/&Save\t").unwrap().deactivate();
219 let mut editor = MyEditor::new(buf.clone());
220 editor.emit(s, Message::Changed);
221 main_win.make_resizable(true);
222 // only resize editor, not the menu bar
223 main_win.resizable(&*editor);
224 main_win.end();
225 main_win.show();
226 main_win.set_callback(move |_| {
227 if app::event() == Event::Close {
228 s.send(Message::Quit);
229 }
230 });
231 let filename = if args.len() > 1 {
232 let file = path::Path::new(&args[1]);
233 assert!(
234 file.exists() && file.is_file(),
235 "An error occurred while opening the file!"
236 );
237 match buf.load_file(&args[1]) {
238 Ok(_) => Some(PathBuf::from(args[1].clone())),
239 Err(e) => {
240 dialog::alert(
241 center().0 - 200,
242 center().1 - 100,
243 &format!("An issue occured while loading the file: {e}"),
244 );
245 None
246 }
247 }
248 } else {
249 None
250 };
251
252 // Handle drag and drop
253 editor.handle({
254 let mut dnd = false;
255 let mut released = false;
256 let buf = buf.clone();
257 move |_, ev| match ev {
258 Event::DndEnter => {
259 dnd = true;
260 true
261 }
262 Event::DndDrag => true,
263 Event::DndRelease => {
264 released = true;
265 true
266 }
267 Event::Paste => {
268 if dnd && released {
269 let path = app::event_text();
270 let path = path.trim();
271 let path = path.replace("file://", "");
272 let path = std::path::PathBuf::from(&path);
273 if path.exists() {
274 // we use a timeout to avoid pasting the path into the buffer
275 app::add_timeout3(0.0, {
276 let mut buf = buf.clone();
277 move |_| match buf.load_file(&path) {
278 Ok(_) => (),
279 Err(e) => dialog::alert(
280 center().0 - 200,
281 center().1 - 100,
282 &format!("An issue occured while loading the file: {e}"),
283 ),
284 }
285 });
286 }
287 dnd = false;
288 released = false;
289 true
290 } else {
291 false
292 }
293 }
294 Event::DndLeave => {
295 dnd = false;
296 released = false;
297 true
298 }
299 _ => false,
300 }
301 });
302
303 // What shows when we attempt to print
304 let mut printable = text::TextDisplay::default();
305 printable.set_frame(FrameType::NoBox);
306 printable.set_scrollbar_size(0);
307 printable.set_buffer(Some(buf.clone()));
308
309 Self {
310 app,
311 modified,
312 filename,
313 r,
314 main_win,
315 menu,
316 buf,
317 editor,
318 printable,
319 }
320 }
321
322 /** Called by "Save", test if file can be written, otherwise call save_file_as()
323 * afterwards. Will return true if the file is succesfully saved. */
324 pub fn save_file(&mut self) -> Result<bool, Box<dyn error::Error>> {
325 match &self.filename {
326 Some(f) => {
327 self.buf.save_file(f)?;
328 self.modified = false;
329 self.menu
330 .menu
331 .find_item("&File/&Save\t")
332 .unwrap()
333 .deactivate();
334 self.menu
335 .menu
336 .find_item("&File/&Quit\t")
337 .unwrap()
338 .set_label_color(Color::Black);
339 let name = match &self.filename {
340 Some(f) => f.to_string_lossy().to_string(),
341 None => "(Untitled)".to_string(),
342 };
343 self.main_win.set_label(&format!("{name} - RustyEd"));
344 Ok(true)
345 }
346 None => self.save_file_as(),
347 }
348 }
349
350 /** Called by "Save As..." or by "Save" in case no file was set yet.
351 * Returns true if the file was succesfully saved. */
352 pub fn save_file_as(&mut self) -> Result<bool, Box<dyn error::Error>> {
353 if let Some(c) = nfc_get_file(dialog::NativeFileChooserType::BrowseSaveFile) {
354 self.buf.save_file(&c)?;
355 self.modified = false;
356 self.menu
357 .menu
358 .find_item("&File/&Save\t")
359 .unwrap()
360 .deactivate();
361 self.menu
362 .menu
363 .find_item("&File/&Quit\t")
364 .unwrap()
365 .set_label_color(Color::Black);
366 self.filename = Some(c);
367 self.main_win
368 .set_label(&format!("{:?} - RustyEd", self.filename.as_ref().unwrap()));
369 Ok(true)
370 } else {
371 Ok(false)
372 }
373 }
374
375 pub fn launch(&mut self) {
376 while self.app.wait() {
377 use Message::*;
378 if let Some(msg) = self.r.recv() {
379 match msg {
380 Changed => {
381 if !self.modified {
382 self.modified = true;
383 self.menu.menu.find_item("&File/&Save\t").unwrap().activate();
384 self.menu.menu.find_item("&File/&Quit\t").unwrap().set_label_color(Color::Red);
385 let name = match &self.filename {
386 Some(f) => f.to_string_lossy().to_string(),
387 None => "(Untitled)".to_string(),
388 };
389 self.main_win.set_label(&format!("* {name} - RustyEd"));
390 }
391 }
392 New => {
393 if self.buf.text() != "" {
394 let clear = if let Some(x) = dialog::choice2(center().0 - 200, center().1 - 100, "File unsaved, Do you wish to continue?", "&Yes", "&No!", "") {
395 x == 0
396 } else {
397 false
398 };
399 if clear {
400 self.buf.set_text("");
401 }
402 }
403 },
404 Open => {
405 if let Some(c) = nfc_get_file(dialog::NativeFileChooserType::BrowseFile) {
406 if c.exists() {
407 match self.buf.load_file(&c) {
408 Ok(_) => self.filename = Some(c),
409 Err(e) => dialog::alert(center().0 - 200, center().1 - 100, &format!("An issue occured while loading the file: {e}")),
410 }
411 } else {
412 dialog::alert(center().0 - 200, center().1 - 100, "File does not exist!")
413 }
414 }
415 },
416 Save => { self.save_file().unwrap(); },
417 SaveAs => { self.save_file_as().unwrap(); },
418 Print => {
419 let mut printer = printer::Printer::default();
420 if printer.begin_job(0).is_ok() {
421 let (w, h) = printer.printable_rect();
422 self.printable.set_size(w - 40, h - 40);
423 // Needs cleanup
424 let line_count = self.printable.count_lines(0, self.printable.buffer().unwrap().length(), true) / 45;
425 for i in 0..=line_count {
426 self.printable.scroll(45 * i, 0);
427 printer.begin_page().ok();
428 printer.print_widget(&self.printable, 20, 20);
429 printer.end_page().ok();
430 }
431 printer.end_job();
432 }
433 },
434 Quit => {
435 if self.modified {
436 match dialog::choice2(center().0 - 200, center().1 - 100,
437 "Would you like to save your work?", "&Yes", "&No", "") {
438 Some(0) => {
439 if self.save_file().unwrap() {
440 self.app.quit();
441 }
442 },
443 Some(1) => { self.app.quit() },
444 Some(_) | None => (),
445 }
446 } else {
447 self.app.quit();
448 }
449 },
450 Cut => self.editor.cut(),
451 Copy => self.editor.copy(),
452 Paste => self.editor.paste(),
453 About => dialog::message(center().0 - 300, center().1 - 100, "This is an example application written in Rust and using the FLTK Gui library."),
454 }
455 }
456 }
457 }Sourcepub fn save_file<P: AsRef<Path>>(&mut self, path: P) -> Result<(), FltkError>
pub fn save_file<P: AsRef<Path>>(&mut self, path: P) -> Result<(), FltkError>
Examples found in repository?
324 pub fn save_file(&mut self) -> Result<bool, Box<dyn error::Error>> {
325 match &self.filename {
326 Some(f) => {
327 self.buf.save_file(f)?;
328 self.modified = false;
329 self.menu
330 .menu
331 .find_item("&File/&Save\t")
332 .unwrap()
333 .deactivate();
334 self.menu
335 .menu
336 .find_item("&File/&Quit\t")
337 .unwrap()
338 .set_label_color(Color::Black);
339 let name = match &self.filename {
340 Some(f) => f.to_string_lossy().to_string(),
341 None => "(Untitled)".to_string(),
342 };
343 self.main_win.set_label(&format!("{name} - RustyEd"));
344 Ok(true)
345 }
346 None => self.save_file_as(),
347 }
348 }
349
350 /** Called by "Save As..." or by "Save" in case no file was set yet.
351 * Returns true if the file was succesfully saved. */
352 pub fn save_file_as(&mut self) -> Result<bool, Box<dyn error::Error>> {
353 if let Some(c) = nfc_get_file(dialog::NativeFileChooserType::BrowseSaveFile) {
354 self.buf.save_file(&c)?;
355 self.modified = false;
356 self.menu
357 .menu
358 .find_item("&File/&Save\t")
359 .unwrap()
360 .deactivate();
361 self.menu
362 .menu
363 .find_item("&File/&Quit\t")
364 .unwrap()
365 .set_label_color(Color::Black);
366 self.filename = Some(c);
367 self.main_win
368 .set_label(&format!("{:?} - RustyEd", self.filename.as_ref().unwrap()));
369 Ok(true)
370 } else {
371 Ok(false)
372 }
373 }Sourcepub fn tab_distance(&self) -> i32
pub fn tab_distance(&self) -> i32
Returns the tab distance for the buffer
Sourcepub fn set_tab_distance(&mut self, tab_dist: i32)
pub fn set_tab_distance(&mut self, tab_dist: i32)
Sets the tab distance
Examples found in repository?
254fn main() {
255 let a = app::App::default().with_scheme(app::Scheme::Oxy);
256 app::get_system_colors();
257
258 let mut buf = text::TextBuffer::default();
259 buf.set_tab_distance(4);
260
261 let state = State::new(buf.clone());
262 app::GlobalState::new(state);
263
264 let mut w = window::Window::default()
265 .with_size(WIDTH, HEIGHT)
266 .with_label("Ted");
267 w.set_xclass("ted");
268 {
269 let mut col = group::Flex::default_fill().column();
270 col.set_pad(0);
271 let mut m = menu::SysMenuBar::default();
272 init_menu(&mut m);
273 let mut ed = text::TextEditor::default().with_id("ed");
274 ed.set_buffer(buf);
275 ed.set_linenumber_width(40);
276 ed.set_text_font(Font::Courier);
277 ed.set_trigger(CallbackTrigger::Changed);
278 ed.set_callback(editor_cb);
279 handle_drag_drop(&mut ed);
280 w.resizable(&col);
281 col.fixed(&m, 30);
282 col.end();
283 }
284 w.end();
285 w.show();
286 w.set_callback(win_cb);
287 a.run().unwrap();
288}More examples
206 pub fn new(args: Vec<String>) -> Self {
207 let app = app::App::default().with_scheme(app::Scheme::Gtk);
208 app::background(211, 211, 211);
209 let (s, r) = app::channel::<Message>();
210 let mut buf = text::TextBuffer::default();
211 buf.set_tab_distance(4);
212 let mut main_win = window::Window::default()
213 .with_size(800, 600)
214 .center_screen()
215 .with_label("RustyEd");
216 let menu = MyMenu::new(&s);
217 let modified = false;
218 menu.menu.find_item("&File/&Save\t").unwrap().deactivate();
219 let mut editor = MyEditor::new(buf.clone());
220 editor.emit(s, Message::Changed);
221 main_win.make_resizable(true);
222 // only resize editor, not the menu bar
223 main_win.resizable(&*editor);
224 main_win.end();
225 main_win.show();
226 main_win.set_callback(move |_| {
227 if app::event() == Event::Close {
228 s.send(Message::Quit);
229 }
230 });
231 let filename = if args.len() > 1 {
232 let file = path::Path::new(&args[1]);
233 assert!(
234 file.exists() && file.is_file(),
235 "An error occurred while opening the file!"
236 );
237 match buf.load_file(&args[1]) {
238 Ok(_) => Some(PathBuf::from(args[1].clone())),
239 Err(e) => {
240 dialog::alert(
241 center().0 - 200,
242 center().1 - 100,
243 &format!("An issue occured while loading the file: {e}"),
244 );
245 None
246 }
247 }
248 } else {
249 None
250 };
251
252 // Handle drag and drop
253 editor.handle({
254 let mut dnd = false;
255 let mut released = false;
256 let buf = buf.clone();
257 move |_, ev| match ev {
258 Event::DndEnter => {
259 dnd = true;
260 true
261 }
262 Event::DndDrag => true,
263 Event::DndRelease => {
264 released = true;
265 true
266 }
267 Event::Paste => {
268 if dnd && released {
269 let path = app::event_text();
270 let path = path.trim();
271 let path = path.replace("file://", "");
272 let path = std::path::PathBuf::from(&path);
273 if path.exists() {
274 // we use a timeout to avoid pasting the path into the buffer
275 app::add_timeout3(0.0, {
276 let mut buf = buf.clone();
277 move |_| match buf.load_file(&path) {
278 Ok(_) => (),
279 Err(e) => dialog::alert(
280 center().0 - 200,
281 center().1 - 100,
282 &format!("An issue occured while loading the file: {e}"),
283 ),
284 }
285 });
286 }
287 dnd = false;
288 released = false;
289 true
290 } else {
291 false
292 }
293 }
294 Event::DndLeave => {
295 dnd = false;
296 released = false;
297 true
298 }
299 _ => false,
300 }
301 });
302
303 // What shows when we attempt to print
304 let mut printable = text::TextDisplay::default();
305 printable.set_frame(FrameType::NoBox);
306 printable.set_scrollbar_size(0);
307 printable.set_buffer(Some(buf.clone()));
308
309 Self {
310 app,
311 modified,
312 filename,
313 r,
314 main_win,
315 menu,
316 buf,
317 editor,
318 printable,
319 }
320 }Sourcepub fn selection_position(&self) -> Option<(i32, i32)>
pub fn selection_position(&self) -> Option<(i32, i32)>
Returns the selection position
Examples found in repository?
122fn main() {
123 let style = Rc::from(RefCell::from(Style::new()));
124
125 let app = App::default().with_scheme(Scheme::Gleam);
126 let mut wind = Window::default()
127 .with_size(500, 200)
128 .with_label("Highlight");
129 let mut vpack = Pack::new(4, 4, 492, 192, "");
130 vpack.set_spacing(4);
131 let mut text_editor = TextEditor::default().with_size(492, 163);
132
133 let mut hpack = Pack::new(4, 4, 492, 25, "").with_type(PackType::Horizontal);
134 hpack.set_spacing(8);
135 let mut font = Choice::default().with_size(130, 25);
136 let mut choice = Choice::default().with_size(130, 25);
137 let mut size = Spinner::default().with_size(60, 25);
138
139 let mut color = Choice::default().with_size(100, 25);
140 let mut btn_clear = Button::default().with_size(40, 25).with_label("X");
141 hpack.end();
142
143 vpack.end();
144 wind.end();
145 wind.show();
146
147 text_editor.wrap_mode(fltk::text::WrapMode::AtBounds, 0);
148 text_editor.set_buffer(TextBuffer::default());
149
150 font.add_choice("Courier|Helvetica|Times");
151 font.set_value(0);
152 font.set_tooltip("Font");
153
154 choice.add_choice("Normal|Underline|Strike");
155 choice.set_value(0);
156
157 size.set_value(18.0);
158 size.set_step(1.0);
159 size.set_range(12.0, 28.0);
160 size.set_tooltip("Size");
161
162 color.set_tooltip("Color");
163 color.add_choice("#000000|#ff0000|#00ff00|#0000ff|#ffff00|#00ffff");
164 color.set_value(0);
165
166 btn_clear.set_label_color(Color::Red);
167 btn_clear.set_tooltip("Clear style");
168
169 // set colors
170 for mut item in color.clone() {
171 if let Some(lbl) = item.label() {
172 item.set_label_color(Color::from_u32(
173 u32::from_str_radix(lbl.trim().strip_prefix('#').unwrap(), 16)
174 .ok()
175 .unwrap(),
176 ));
177 }
178 }
179
180 let style_rc1 = Rc::clone(&style);
181
182 text_editor.buffer().unwrap().add_modify_callback({
183 let mut text_editor1 = text_editor.clone();
184 let font1 = font.clone();
185 let size1 = size.clone();
186 let color1 = color.clone();
187 let choice1 = choice.clone();
188 move |pos: i32, ins_items: i32, del_items: i32, _: i32, _: &str| {
189 let attr = if choice1.value() == 1 {
190 TextAttr::Underline
191 } else if choice1.value() == 2 {
192 TextAttr::StrikeThrough
193 } else {
194 TextAttr::None
195 };
196 if ins_items > 0 || del_items > 0 {
197 let mut style = style_rc1.borrow_mut();
198 let color = Color::from_u32(
199 u32::from_str_radix(
200 color1
201 .text(color1.value())
202 .unwrap()
203 .trim()
204 .strip_prefix('#')
205 .unwrap(),
206 16,
207 )
208 .ok()
209 .unwrap(),
210 );
211 style.apply_style(
212 Some(pos),
213 Some(ins_items),
214 Some(del_items),
215 None,
216 None,
217 Font::by_name(font1.text(font1.value()).unwrap().trim()),
218 size1.value() as i32,
219 color,
220 attr,
221 &mut text_editor1,
222 );
223 }
224 }
225 });
226
227 color.set_callback({
228 let size = size.clone();
229 let font = font.clone();
230 let choice = choice.clone();
231 let mut text_editor = text_editor.clone();
232 let style_rc1 = Rc::clone(&style);
233 move |color| {
234 let attr = match choice.value() {
235 0 => TextAttr::None,
236 1 => TextAttr::Underline,
237 2 => TextAttr::StrikeThrough,
238 _ => unreachable!(),
239 };
240 if let Some(buf) = text_editor.buffer() {
241 if let Some((s, e)) = buf.selection_position() {
242 let mut style = style_rc1.borrow_mut();
243 let color = Color::from_u32(
244 u32::from_str_radix(
245 color
246 .text(color.value())
247 .unwrap()
248 .trim()
249 .strip_prefix('#')
250 .unwrap(),
251 16,
252 )
253 .ok()
254 .unwrap(),
255 );
256 style.apply_style(
257 None,
258 None,
259 None,
260 Some(s),
261 Some(e),
262 Font::by_name(font.text(font.value()).unwrap().trim()),
263 size.value() as i32,
264 color,
265 attr,
266 &mut text_editor,
267 );
268 }
269 }
270 }
271 });
272
273 // get the style from the current cursor position
274 text_editor.handle({
275 let style_rc1 = Rc::clone(&style);
276 let mut font1 = font.clone();
277 let mut size1 = size.clone();
278 let mut color1 = color.clone();
279 move |te, e| match e {
280 Event::KeyUp | Event::Released => {
281 if let Some(buff) = te.style_buffer() {
282 let i = te.insert_position();
283 if let Some(t) = buff.text_range(i, i + 1) {
284 if !t.is_empty() {
285 let style = style_rc1.borrow_mut();
286 if let Some(i) = t.chars().next().map(|c| (c as usize - 65)) {
287 if let Some(style) = style.style_table.get(i) {
288 if let Some(mn) = font1.find_item(&format!("{:?}", style.font))
289 {
290 font1.set_item(&mn);
291 }
292 size1.set_value(style.size as f64);
293 let (r, g, b) = style.color.to_rgb();
294 if let Some(mn) =
295 color1.find_item(format!("{r:02x}{g:02x}{b:02x}").as_str())
296 {
297 color1.set_item(&mn);
298 }
299 }
300 }
301 }
302 }
303 }
304 true
305 }
306 _ => false,
307 }
308 });
309
310 choice.set_callback({
311 let mut color1 = color.clone();
312 move |_| color1.do_callback()
313 });
314
315 font.set_callback({
316 let mut color1 = color.clone();
317 move |_| color1.do_callback()
318 });
319
320 size.set_callback({
321 let mut color1 = color.clone();
322 move |_| color1.do_callback()
323 });
324
325 // clear style of the current selection or, if no text is selected, clear all text style
326 btn_clear.set_callback({
327 let style_rc1 = Rc::clone(&style);
328 let text_editor1 = text_editor.clone();
329 move |_| {
330 match text_editor1.buffer().unwrap().selection_position() {
331 Some((_, _)) => {
332 font.set_value(0);
333 size.set_value(18.0);
334 color.set_value(0);
335 choice.set_value(0);
336 color.do_callback();
337 }
338 None => {
339 font.set_value(0);
340 size.set_value(18.0);
341 color.set_value(0);
342 style_rc1.borrow_mut().apply_style(
343 None,
344 None,
345 None,
346 Some(0),
347 Some(text_editor1.buffer().unwrap().length()),
348 Font::Courier,
349 16,
350 Color::Black,
351 TextAttr::None,
352 &mut text_editor,
353 );
354 }
355 };
356 }
357 });
358
359 app.run().unwrap();
360}Sourcepub fn selection_text(&self) -> String
pub fn selection_text(&self) -> String
Returns the selection text
Sourcepub fn remove_selection(&mut self)
pub fn remove_selection(&mut self)
Removes the selection
Sourcepub fn replace_selection(&mut self, text: &str)
pub fn replace_selection(&mut self, text: &str)
Replaces selection
Sourcepub fn secondary_select(&mut self, start: i32, end: i32)
pub fn secondary_select(&mut self, start: i32, end: i32)
Secondary selects the text from start to end
Sourcepub fn secondary_selected(&self) -> bool
pub fn secondary_selected(&self) -> bool
Returns whether text is secondary selected
Sourcepub fn secondary_unselect(&mut self)
pub fn secondary_unselect(&mut self)
Unselects text (secondary selection)
Sourcepub fn secondary_selection_position(&self) -> Option<(i32, i32)>
pub fn secondary_selection_position(&self) -> Option<(i32, i32)>
Returns the secondary selection position
Sourcepub fn secondary_selection_text(&self) -> String
pub fn secondary_selection_text(&self) -> String
Returns the secondary selection text
Sourcepub fn remove_secondary_selection(&mut self)
pub fn remove_secondary_selection(&mut self)
Removes the secondary selection
Sourcepub fn replace_secondary_selection(&mut self, text: &str)
pub fn replace_secondary_selection(&mut self, text: &str)
Replaces the secondary selection
Sourcepub fn is_highlighted(&self) -> bool
pub fn is_highlighted(&self) -> bool
Returns whether text is highlighted
Sourcepub fn unhighlight(&mut self)
pub fn unhighlight(&mut self)
Unhighlights text
Sourcepub fn highlight_position(&self) -> Option<(i32, i32)>
pub fn highlight_position(&self) -> Option<(i32, i32)>
Returns the highlight position
Sourcepub fn highlight_text(&self) -> String
pub fn highlight_text(&self) -> String
Returns the highlighted text
Sourcepub fn line_start(&self, pos: i32) -> i32
pub fn line_start(&self, pos: i32) -> i32
Returns the index of the line’s start position at pos
Sourcepub fn word_start(&self, pos: i32) -> i32
pub fn word_start(&self, pos: i32) -> i32
Returns the index of the first character of a word at pos
Sourcepub fn word_end(&self, pos: i32) -> i32
pub fn word_end(&self, pos: i32) -> i32
Returns the index of the last character of a word at pos
Sourcepub fn count_lines(&self, start: i32, end: i32) -> i32
pub fn count_lines(&self, start: i32, end: i32) -> i32
Counts the lines from start to end
Sourcepub fn call_modify_callbacks(&mut self)
pub fn call_modify_callbacks(&mut self)
Calls the modify callbacks
Sourcepub fn add_modify_callback<F: FnMut(i32, i32, i32, i32, &str) + 'static>(
&mut self,
cb: F,
)
pub fn add_modify_callback<F: FnMut(i32, i32, i32, i32, &str) + 'static>( &mut self, cb: F, )
Adds a modify callback.
callback args:
pos: i32, inserted items: i32, deleted items: i32, restyled items: i32, deleted_text
Examples found in repository?
122fn main() {
123 let style = Rc::from(RefCell::from(Style::new()));
124
125 let app = App::default().with_scheme(Scheme::Gleam);
126 let mut wind = Window::default()
127 .with_size(500, 200)
128 .with_label("Highlight");
129 let mut vpack = Pack::new(4, 4, 492, 192, "");
130 vpack.set_spacing(4);
131 let mut text_editor = TextEditor::default().with_size(492, 163);
132
133 let mut hpack = Pack::new(4, 4, 492, 25, "").with_type(PackType::Horizontal);
134 hpack.set_spacing(8);
135 let mut font = Choice::default().with_size(130, 25);
136 let mut choice = Choice::default().with_size(130, 25);
137 let mut size = Spinner::default().with_size(60, 25);
138
139 let mut color = Choice::default().with_size(100, 25);
140 let mut btn_clear = Button::default().with_size(40, 25).with_label("X");
141 hpack.end();
142
143 vpack.end();
144 wind.end();
145 wind.show();
146
147 text_editor.wrap_mode(fltk::text::WrapMode::AtBounds, 0);
148 text_editor.set_buffer(TextBuffer::default());
149
150 font.add_choice("Courier|Helvetica|Times");
151 font.set_value(0);
152 font.set_tooltip("Font");
153
154 choice.add_choice("Normal|Underline|Strike");
155 choice.set_value(0);
156
157 size.set_value(18.0);
158 size.set_step(1.0);
159 size.set_range(12.0, 28.0);
160 size.set_tooltip("Size");
161
162 color.set_tooltip("Color");
163 color.add_choice("#000000|#ff0000|#00ff00|#0000ff|#ffff00|#00ffff");
164 color.set_value(0);
165
166 btn_clear.set_label_color(Color::Red);
167 btn_clear.set_tooltip("Clear style");
168
169 // set colors
170 for mut item in color.clone() {
171 if let Some(lbl) = item.label() {
172 item.set_label_color(Color::from_u32(
173 u32::from_str_radix(lbl.trim().strip_prefix('#').unwrap(), 16)
174 .ok()
175 .unwrap(),
176 ));
177 }
178 }
179
180 let style_rc1 = Rc::clone(&style);
181
182 text_editor.buffer().unwrap().add_modify_callback({
183 let mut text_editor1 = text_editor.clone();
184 let font1 = font.clone();
185 let size1 = size.clone();
186 let color1 = color.clone();
187 let choice1 = choice.clone();
188 move |pos: i32, ins_items: i32, del_items: i32, _: i32, _: &str| {
189 let attr = if choice1.value() == 1 {
190 TextAttr::Underline
191 } else if choice1.value() == 2 {
192 TextAttr::StrikeThrough
193 } else {
194 TextAttr::None
195 };
196 if ins_items > 0 || del_items > 0 {
197 let mut style = style_rc1.borrow_mut();
198 let color = Color::from_u32(
199 u32::from_str_radix(
200 color1
201 .text(color1.value())
202 .unwrap()
203 .trim()
204 .strip_prefix('#')
205 .unwrap(),
206 16,
207 )
208 .ok()
209 .unwrap(),
210 );
211 style.apply_style(
212 Some(pos),
213 Some(ins_items),
214 Some(del_items),
215 None,
216 None,
217 Font::by_name(font1.text(font1.value()).unwrap().trim()),
218 size1.value() as i32,
219 color,
220 attr,
221 &mut text_editor1,
222 );
223 }
224 }
225 });
226
227 color.set_callback({
228 let size = size.clone();
229 let font = font.clone();
230 let choice = choice.clone();
231 let mut text_editor = text_editor.clone();
232 let style_rc1 = Rc::clone(&style);
233 move |color| {
234 let attr = match choice.value() {
235 0 => TextAttr::None,
236 1 => TextAttr::Underline,
237 2 => TextAttr::StrikeThrough,
238 _ => unreachable!(),
239 };
240 if let Some(buf) = text_editor.buffer() {
241 if let Some((s, e)) = buf.selection_position() {
242 let mut style = style_rc1.borrow_mut();
243 let color = Color::from_u32(
244 u32::from_str_radix(
245 color
246 .text(color.value())
247 .unwrap()
248 .trim()
249 .strip_prefix('#')
250 .unwrap(),
251 16,
252 )
253 .ok()
254 .unwrap(),
255 );
256 style.apply_style(
257 None,
258 None,
259 None,
260 Some(s),
261 Some(e),
262 Font::by_name(font.text(font.value()).unwrap().trim()),
263 size.value() as i32,
264 color,
265 attr,
266 &mut text_editor,
267 );
268 }
269 }
270 }
271 });
272
273 // get the style from the current cursor position
274 text_editor.handle({
275 let style_rc1 = Rc::clone(&style);
276 let mut font1 = font.clone();
277 let mut size1 = size.clone();
278 let mut color1 = color.clone();
279 move |te, e| match e {
280 Event::KeyUp | Event::Released => {
281 if let Some(buff) = te.style_buffer() {
282 let i = te.insert_position();
283 if let Some(t) = buff.text_range(i, i + 1) {
284 if !t.is_empty() {
285 let style = style_rc1.borrow_mut();
286 if let Some(i) = t.chars().next().map(|c| (c as usize - 65)) {
287 if let Some(style) = style.style_table.get(i) {
288 if let Some(mn) = font1.find_item(&format!("{:?}", style.font))
289 {
290 font1.set_item(&mn);
291 }
292 size1.set_value(style.size as f64);
293 let (r, g, b) = style.color.to_rgb();
294 if let Some(mn) =
295 color1.find_item(format!("{r:02x}{g:02x}{b:02x}").as_str())
296 {
297 color1.set_item(&mn);
298 }
299 }
300 }
301 }
302 }
303 }
304 true
305 }
306 _ => false,
307 }
308 });
309
310 choice.set_callback({
311 let mut color1 = color.clone();
312 move |_| color1.do_callback()
313 });
314
315 font.set_callback({
316 let mut color1 = color.clone();
317 move |_| color1.do_callback()
318 });
319
320 size.set_callback({
321 let mut color1 = color.clone();
322 move |_| color1.do_callback()
323 });
324
325 // clear style of the current selection or, if no text is selected, clear all text style
326 btn_clear.set_callback({
327 let style_rc1 = Rc::clone(&style);
328 let text_editor1 = text_editor.clone();
329 move |_| {
330 match text_editor1.buffer().unwrap().selection_position() {
331 Some((_, _)) => {
332 font.set_value(0);
333 size.set_value(18.0);
334 color.set_value(0);
335 choice.set_value(0);
336 color.do_callback();
337 }
338 None => {
339 font.set_value(0);
340 size.set_value(18.0);
341 color.set_value(0);
342 style_rc1.borrow_mut().apply_style(
343 None,
344 None,
345 None,
346 Some(0),
347 Some(text_editor1.buffer().unwrap().length()),
348 Font::Courier,
349 16,
350 Color::Black,
351 TextAttr::None,
352 &mut text_editor,
353 );
354 }
355 };
356 }
357 });
358
359 app.run().unwrap();
360}Sourcepub fn remove_modify_callback<F: FnMut(i32, i32, i32, i32, &str) + 'static>(
&mut self,
cb: F,
)
pub fn remove_modify_callback<F: FnMut(i32, i32, i32, i32, &str) + 'static>( &mut self, cb: F, )
Removes a modify callback.
callback args:
pos: i32, inserted items: i32, deleted items: i32, restyled items: i32, deleted_text
Sourcepub fn search_forward(
&self,
start_pos: i32,
search_string: &str,
match_case: bool,
) -> Option<i32>
pub fn search_forward( &self, start_pos: i32, search_string: &str, match_case: bool, ) -> Option<i32>
Forward search for a string
Sourcepub fn search_backward(
&self,
start_pos: i32,
search_string: &str,
match_case: bool,
) -> Option<i32>
pub fn search_backward( &self, start_pos: i32, search_string: &str, match_case: bool, ) -> Option<i32>
Backward search for a string
Trait Implementations§
Source§impl Clone for TextBuffer
impl Clone for TextBuffer
Source§fn clone(&self) -> TextBuffer
fn clone(&self) -> TextBuffer
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for TextBuffer
impl Debug for TextBuffer
Source§impl Default for TextBuffer
impl Default for TextBuffer
Source§fn default() -> TextBuffer
fn default() -> TextBuffer
Initialized a default text buffer
Source§impl Drop for TextBuffer
impl Drop for TextBuffer
Source§impl PartialEq for TextBuffer
impl PartialEq for TextBuffer
impl Eq for TextBuffer
impl Send for TextBuffer
single-threaded only.impl Sync for TextBuffer
single-threaded only.