Struct TextBuffer

Source
pub struct TextBuffer { /* private fields */ }
Expand description

Wraps a text buffer. The buffer is automatically cleaned up when the last reference is dropped.

Implementations§

Source§

impl TextBuffer

Source

pub unsafe fn delete(buf: Self)

Deletes the TextBuffer

§Safety

The buffer shouldn’t be deleted while the Display widget still needs it

Source

pub unsafe fn delete_buffer(buf: Self)

Deletes the TextBuffer

§Safety

The buffer shouldn’t be deleted while the Display widget still needs it

Source

pub unsafe fn from_ptr(ptr: *mut Fl_Text_Buffer) -> Self

Initializes a text buffer from a pointer

§Safety

The pointer must be valid and this TextBuffer will take ownership of it

Source

pub fn as_ptr(&self) -> *mut Fl_Text_Buffer

Returns the inner pointer from a text buffer

§Safety

The returned pointer is valid as long as this TextBuffer or any of its clones exist

Source

pub fn set_text(&mut self, txt: &str)

Sets the text of the buffer

Examples found in repository?
examples/editor.rs (line 203)
189fn menu_cb(m: &mut impl MenuExt) {
190    if let Ok(mpath) = m.item_pathname(None) {
191        let ed: text::TextEditor = app::widget_from_id("ed").unwrap();
192        match mpath.as_str() {
193            "&File/&New...\t" => {
194                STATE.with(|s| {
195                    if !s.buf.text().is_empty() {
196                        let c = dialog::choice(
197                            "Are you sure you want to clear the buffer?",
198                            "&Yes",
199                            "&No",
200                            "",
201                        );
202                        if c == Some(0) {
203                            s.buf.set_text("");
204                            s.saved = false;
205                        }
206                    }
207                });
208            }
209            "&File/&Open...\t" => {
210                if let Some(c) = nfc_get_file(dialog::NativeFileChooserType::BrowseFile) {
211                    if let Ok(text) = std::fs::read_to_string(&c) {
212                        STATE.with(move |s| {
213                            s.buf.set_text(&text);
214                            s.saved = false;
215                            s.current_file = c.clone();
216                        });
217                    }
218                }
219            }
220            "&File/&Save\t" => {
221                STATE.with(|s| {
222                    if !s.saved && s.current_file.exists() {
223                        std::fs::write(&s.current_file, s.buf.text()).ok();
224                    }
225                });
226            }
227            "&File/Save &as...\t" => {
228                if let Some(c) = nfc_get_file(dialog::NativeFileChooserType::BrowseSaveFile) {
229                    STATE.with(move |s| {
230                        std::fs::write(&c, s.buf.text()).ok();
231                        s.saved = true;
232                        s.current_file = c.clone();
233                    });
234                }
235            }
236            "&File/&Quit\t" => quit_cb(),
237            "&Edit/Cu&t\t" => ed.cut(),
238            "&Edit/&Copy\t" => ed.copy(),
239            "&Edit/&Paste\t" => ed.paste(),
240            "&Help/&About\t" => dialog::message("A minimal text editor written using fltk-rs!"),
241            _ => unreachable!(),
242        }
243    }
244}
More examples
Hide additional examples
examples/editor2.rs (line 400)
362    pub fn launch(&mut self) {
363        while self.app.wait() {
364            use Message::*;
365            if let Some(msg) = self.r.recv() {
366                match msg {
367                    Changed => {
368                        if !self.modified {
369                            self.modified = true;
370                            self.menu
371                                .menu
372                                .find_item("&File/&Save\t")
373                                .unwrap()
374                                .activate();
375                            self.menu
376                                .menu
377                                .find_item("&File/&Quit\t")
378                                .unwrap()
379                                .set_label_color(Color::Red);
380                            let name = match &self.filename {
381                                Some(f) => f.to_string_lossy().to_string(),
382                                None => "(Untitled)".to_string(),
383                            };
384                            self.main_win.set_label(&format!("* {name} - RustyEd"));
385                        }
386                    }
387                    New => {
388                        if self.buf.text() != "" {
389                            let clear = if let Some(x) = dialog::choice(
390                                "File unsaved, Do you wish to continue?",
391                                "&Yes",
392                                "&No!",
393                                "",
394                            ) {
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(&format!(
410                                        "An issue occured while loading the file: {e}"
411                                    )),
412                                }
413                            } else {
414                                dialog::alert("File does not exist!")
415                            }
416                        }
417                    }
418                    Save => {
419                        self.save_file().unwrap();
420                    }
421                    SaveAs => {
422                        self.save_file_as().unwrap();
423                    }
424                    Print => {
425                        let mut printer = printer::Printer::default();
426                        if printer.begin_job(0).is_ok() {
427                            let (w, h) = printer.printable_rect();
428                            self.printable.resize(
429                                self.printable.x(),
430                                self.printable.y(),
431                                w - 40,
432                                h - 40,
433                            );
434                            // Needs cleanup
435                            let line_count = self.printable.count_lines(
436                                0,
437                                self.printable.buffer().unwrap().length(),
438                                true,
439                            ) / 45;
440                            for i in 0..=line_count {
441                                self.printable.scroll(45 * i, 0);
442                                printer.begin_page().ok();
443                                printer.print_widget(&self.printable, 20, 20);
444                                printer.end_page().ok();
445                            }
446                            printer.end_job();
447                        }
448                    }
449                    Quit => {
450                        if self.modified {
451                            match dialog::choice(
452                                "Would you like to save your work?",
453                                "&Yes",
454                                "&No",
455                                "",
456                            ) {
457                                Some(0) => {
458                                    if self.save_file().unwrap() {
459                                        self.app.quit();
460                                    }
461                                }
462                                Some(1) => self.app.quit(),
463                                Some(_) | None => (),
464                            }
465                        } else {
466                            self.app.quit();
467                        }
468                    }
469                    Cut => self.editor.cut(),
470                    Copy => self.editor.copy(),
471                    Paste => self.editor.paste(),
472                    About => dialog::message(
473                        "This is an example application written in Rust and using the FLTK Gui library.",
474                    ),
475                }
476            }
477        }
478    }
Source

pub fn text(&self) -> String

Returns the text of the buffer

Examples found in repository?
examples/editor.rs (line 195)
189fn menu_cb(m: &mut impl MenuExt) {
190    if let Ok(mpath) = m.item_pathname(None) {
191        let ed: text::TextEditor = app::widget_from_id("ed").unwrap();
192        match mpath.as_str() {
193            "&File/&New...\t" => {
194                STATE.with(|s| {
195                    if !s.buf.text().is_empty() {
196                        let c = dialog::choice(
197                            "Are you sure you want to clear the buffer?",
198                            "&Yes",
199                            "&No",
200                            "",
201                        );
202                        if c == Some(0) {
203                            s.buf.set_text("");
204                            s.saved = false;
205                        }
206                    }
207                });
208            }
209            "&File/&Open...\t" => {
210                if let Some(c) = nfc_get_file(dialog::NativeFileChooserType::BrowseFile) {
211                    if let Ok(text) = std::fs::read_to_string(&c) {
212                        STATE.with(move |s| {
213                            s.buf.set_text(&text);
214                            s.saved = false;
215                            s.current_file = c.clone();
216                        });
217                    }
218                }
219            }
220            "&File/&Save\t" => {
221                STATE.with(|s| {
222                    if !s.saved && s.current_file.exists() {
223                        std::fs::write(&s.current_file, s.buf.text()).ok();
224                    }
225                });
226            }
227            "&File/Save &as...\t" => {
228                if let Some(c) = nfc_get_file(dialog::NativeFileChooserType::BrowseSaveFile) {
229                    STATE.with(move |s| {
230                        std::fs::write(&c, s.buf.text()).ok();
231                        s.saved = true;
232                        s.current_file = c.clone();
233                    });
234                }
235            }
236            "&File/&Quit\t" => quit_cb(),
237            "&Edit/Cu&t\t" => ed.cut(),
238            "&Edit/&Copy\t" => ed.copy(),
239            "&Edit/&Paste\t" => ed.paste(),
240            "&Help/&About\t" => dialog::message("A minimal text editor written using fltk-rs!"),
241            _ => unreachable!(),
242        }
243    }
244}
More examples
Hide additional examples
examples/editor2.rs (line 388)
362    pub fn launch(&mut self) {
363        while self.app.wait() {
364            use Message::*;
365            if let Some(msg) = self.r.recv() {
366                match msg {
367                    Changed => {
368                        if !self.modified {
369                            self.modified = true;
370                            self.menu
371                                .menu
372                                .find_item("&File/&Save\t")
373                                .unwrap()
374                                .activate();
375                            self.menu
376                                .menu
377                                .find_item("&File/&Quit\t")
378                                .unwrap()
379                                .set_label_color(Color::Red);
380                            let name = match &self.filename {
381                                Some(f) => f.to_string_lossy().to_string(),
382                                None => "(Untitled)".to_string(),
383                            };
384                            self.main_win.set_label(&format!("* {name} - RustyEd"));
385                        }
386                    }
387                    New => {
388                        if self.buf.text() != "" {
389                            let clear = if let Some(x) = dialog::choice(
390                                "File unsaved, Do you wish to continue?",
391                                "&Yes",
392                                "&No!",
393                                "",
394                            ) {
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(&format!(
410                                        "An issue occured while loading the file: {e}"
411                                    )),
412                                }
413                            } else {
414                                dialog::alert("File does not exist!")
415                            }
416                        }
417                    }
418                    Save => {
419                        self.save_file().unwrap();
420                    }
421                    SaveAs => {
422                        self.save_file_as().unwrap();
423                    }
424                    Print => {
425                        let mut printer = printer::Printer::default();
426                        if printer.begin_job(0).is_ok() {
427                            let (w, h) = printer.printable_rect();
428                            self.printable.resize(
429                                self.printable.x(),
430                                self.printable.y(),
431                                w - 40,
432                                h - 40,
433                            );
434                            // Needs cleanup
435                            let line_count = self.printable.count_lines(
436                                0,
437                                self.printable.buffer().unwrap().length(),
438                                true,
439                            ) / 45;
440                            for i in 0..=line_count {
441                                self.printable.scroll(45 * i, 0);
442                                printer.begin_page().ok();
443                                printer.print_widget(&self.printable, 20, 20);
444                                printer.end_page().ok();
445                            }
446                            printer.end_job();
447                        }
448                    }
449                    Quit => {
450                        if self.modified {
451                            match dialog::choice(
452                                "Would you like to save your work?",
453                                "&Yes",
454                                "&No",
455                                "",
456                            ) {
457                                Some(0) => {
458                                    if self.save_file().unwrap() {
459                                        self.app.quit();
460                                    }
461                                }
462                                Some(1) => self.app.quit(),
463                                Some(_) | None => (),
464                            }
465                        } else {
466                            self.app.quit();
467                        }
468                    }
469                    Cut => self.editor.cut(),
470                    Copy => self.editor.copy(),
471                    Paste => self.editor.paste(),
472                    About => dialog::message(
473                        "This is an example application written in Rust and using the FLTK Gui library.",
474                    ),
475                }
476            }
477        }
478    }
Source

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,
);
Source

pub fn append_bytes(&mut self, text: &[u8])

Append bytes to the buffer

Source

pub fn length(&self) -> i32

Get the length of the buffer

Examples found in repository?
examples/editor2.rs (line 437)
362    pub fn launch(&mut self) {
363        while self.app.wait() {
364            use Message::*;
365            if let Some(msg) = self.r.recv() {
366                match msg {
367                    Changed => {
368                        if !self.modified {
369                            self.modified = true;
370                            self.menu
371                                .menu
372                                .find_item("&File/&Save\t")
373                                .unwrap()
374                                .activate();
375                            self.menu
376                                .menu
377                                .find_item("&File/&Quit\t")
378                                .unwrap()
379                                .set_label_color(Color::Red);
380                            let name = match &self.filename {
381                                Some(f) => f.to_string_lossy().to_string(),
382                                None => "(Untitled)".to_string(),
383                            };
384                            self.main_win.set_label(&format!("* {name} - RustyEd"));
385                        }
386                    }
387                    New => {
388                        if self.buf.text() != "" {
389                            let clear = if let Some(x) = dialog::choice(
390                                "File unsaved, Do you wish to continue?",
391                                "&Yes",
392                                "&No!",
393                                "",
394                            ) {
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(&format!(
410                                        "An issue occured while loading the file: {e}"
411                                    )),
412                                }
413                            } else {
414                                dialog::alert("File does not exist!")
415                            }
416                        }
417                    }
418                    Save => {
419                        self.save_file().unwrap();
420                    }
421                    SaveAs => {
422                        self.save_file_as().unwrap();
423                    }
424                    Print => {
425                        let mut printer = printer::Printer::default();
426                        if printer.begin_job(0).is_ok() {
427                            let (w, h) = printer.printable_rect();
428                            self.printable.resize(
429                                self.printable.x(),
430                                self.printable.y(),
431                                w - 40,
432                                h - 40,
433                            );
434                            // Needs cleanup
435                            let line_count = self.printable.count_lines(
436                                0,
437                                self.printable.buffer().unwrap().length(),
438                                true,
439                            ) / 45;
440                            for i in 0..=line_count {
441                                self.printable.scroll(45 * i, 0);
442                                printer.begin_page().ok();
443                                printer.print_widget(&self.printable, 20, 20);
444                                printer.end_page().ok();
445                            }
446                            printer.end_job();
447                        }
448                    }
449                    Quit => {
450                        if self.modified {
451                            match dialog::choice(
452                                "Would you like to save your work?",
453                                "&Yes",
454                                "&No",
455                                "",
456                            ) {
457                                Some(0) => {
458                                    if self.save_file().unwrap() {
459                                        self.app.quit();
460                                    }
461                                }
462                                Some(1) => self.app.quit(),
463                                Some(_) | None => (),
464                            }
465                        } else {
466                            self.app.quit();
467                        }
468                    }
469                    Cut => self.editor.cut(),
470                    Copy => self.editor.copy(),
471                    Paste => self.editor.paste(),
472                    About => dialog::message(
473                        "This is an example application written in Rust and using the FLTK Gui library.",
474                    ),
475                }
476            }
477        }
478    }
Source

pub fn remove(&mut self, start: i32, end: i32)

Removes from the buffer

Source

pub fn text_range(&self, start: i32, end: i32) -> Option<String>

Returns the text within the range

Source

pub fn insert(&mut self, pos: i32, text: &str)

Inserts text into a position

Source

pub fn replace(&mut self, start: i32, end: i32, text: &str)

Replaces text from position start to end

Source

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

Source

pub fn copy(&self) -> TextBuffer

Copies whole text from a source buffer into a new buffer

Source

pub fn undo(&mut self) -> Result<(), FltkError>

Performs an undo operation on the buffer

§Errors

Errors on failure to undo

Source

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

Source

pub fn can_undo(&mut self, flag: bool)

Sets whether the buffer can undo

Source

pub fn get_can_undo(&mut self) -> bool

Gets whether the buffer can undo

Source

pub fn can_redo(&mut self) -> bool

Gets whether the buffer can redo

Source

pub fn load_file<P: AsRef<Path>>(&mut self, path: P) -> Result<(), FltkError>

Loads a file into the buffer

§Errors

Errors on failure to load file

Examples found in repository?
examples/editor.rs (line 164)
139fn handle_drag_drop(editor: &mut text::TextEditor) {
140    editor.handle({
141        let mut dnd = false;
142        let mut released = false;
143        let buf = editor.buffer().unwrap();
144        move |_, ev| match ev {
145            Event::DndEnter => {
146                dnd = true;
147                true
148            }
149            Event::DndDrag => true,
150            Event::DndRelease => {
151                released = true;
152                true
153            }
154            Event::Paste => {
155                if dnd && released {
156                    let path = app::event_text().unwrap();
157                    let path = path.trim();
158                    let path = path.replace("file://", "");
159                    let path = std::path::PathBuf::from(&path);
160                    if path.exists() {
161                        // we use a timeout to avoid pasting the path into the buffer
162                        app::add_timeout(0.0, {
163                            let mut buf = buf.clone();
164                            move |_| match buf.load_file(&path) {
165                                Ok(_) => (),
166                                Err(e) => dialog::alert(&format!(
167                                    "An issue occured while loading the file: {e}"
168                                )),
169                            }
170                        });
171                    }
172                    dnd = false;
173                    released = false;
174                    true
175                } else {
176                    false
177                }
178            }
179            Event::DndLeave => {
180                dnd = false;
181                released = false;
182                true
183            }
184            _ => false,
185        }
186    });
187}
More examples
Hide additional examples
examples/editor2.rs (line 230)
199    pub fn new(args: Vec<String>) -> Self {
200        let app = app::App::default().with_scheme(app::Scheme::Gtk);
201        app::background(211, 211, 211);
202        let (s, r) = app::channel::<Message>();
203        let mut buf = text::TextBuffer::default();
204        buf.set_tab_distance(4);
205        let mut main_win = window::Window::default()
206            .with_size(800, 600)
207            .with_label("RustyEd");
208        main_win.set_center_screen();
209        let menu = MyMenu::new(&s);
210        let modified = false;
211        menu.menu.find_item("&File/&Save\t").unwrap().deactivate();
212        let mut editor = MyEditor::new(buf.clone());
213        editor.emit(s, Message::Changed);
214        main_win.make_resizable(true);
215        // only resize editor, not the menu bar
216        main_win.resizable(&*editor);
217        main_win.end();
218        main_win.show();
219        main_win.set_callback(move |_| {
220            if app::event() == Event::Close {
221                s.send(Message::Quit);
222            }
223        });
224        let filename = if args.len() > 1 {
225            let file = path::Path::new(&args[1]);
226            assert!(
227                file.exists() && file.is_file(),
228                "An error occurred while opening the file!"
229            );
230            match buf.load_file(&args[1]) {
231                Ok(_) => Some(PathBuf::from(args[1].clone())),
232                Err(e) => {
233                    dialog::alert(&format!("An issue occured while loading the file: {e}"));
234                    None
235                }
236            }
237        } else {
238            None
239        };
240
241        // Handle drag and drop
242        editor.handle({
243            let mut dnd = false;
244            let mut released = false;
245            let buf = buf.clone();
246            move |_, ev| match ev {
247                Event::DndEnter => {
248                    dnd = true;
249                    true
250                }
251                Event::DndDrag => true,
252                Event::DndRelease => {
253                    released = true;
254                    true
255                }
256                Event::Paste => {
257                    if dnd && released {
258                        let path = app::event_text().unwrap();
259                        let path = path.trim();
260                        let path = path.replace("file://", "");
261                        let path = std::path::PathBuf::from(&path);
262                        if path.exists() {
263                            // we use a timeout to avoid pasting the path into the buffer
264                            app::add_timeout(0.0, {
265                                let mut buf = buf.clone();
266                                move |_| match buf.load_file(&path) {
267                                    Ok(_) => (),
268                                    Err(e) => dialog::alert(&format!(
269                                        "An issue occured while loading the file: {e}"
270                                    )),
271                                }
272                            });
273                        }
274                        dnd = false;
275                        released = false;
276                        true
277                    } else {
278                        false
279                    }
280                }
281                Event::DndLeave => {
282                    dnd = false;
283                    released = false;
284                    true
285                }
286                _ => false,
287            }
288        });
289
290        // What shows when we attempt to print
291        let mut printable = text::TextDisplay::default();
292        printable.set_frame(FrameType::NoBox);
293        printable.set_scrollbar_size(0);
294        printable.set_buffer(Some(buf.clone()));
295
296        Self {
297            app,
298            modified,
299            filename,
300            r,
301            main_win,
302            menu,
303            buf,
304            editor,
305            printable,
306        }
307    }
308
309    /** Called by "Save", test if file can be written, otherwise call save_file_as()
310     * afterwards. Will return true if the file is succesfully saved. */
311    pub fn save_file(&mut self) -> Result<bool, Box<dyn error::Error>> {
312        match &self.filename {
313            Some(f) => {
314                self.buf.save_file(f)?;
315                self.modified = false;
316                self.menu
317                    .menu
318                    .find_item("&File/&Save\t")
319                    .unwrap()
320                    .deactivate();
321                self.menu
322                    .menu
323                    .find_item("&File/&Quit\t")
324                    .unwrap()
325                    .set_label_color(Color::Black);
326                let name = match &self.filename {
327                    Some(f) => f.to_string_lossy().to_string(),
328                    None => "(Untitled)".to_string(),
329                };
330                self.main_win.set_label(&format!("{name} - RustyEd"));
331                Ok(true)
332            }
333            None => self.save_file_as(),
334        }
335    }
336
337    /** Called by "Save As..." or by "Save" in case no file was set yet.
338     * Returns true if the file was succesfully saved. */
339    pub fn save_file_as(&mut self) -> Result<bool, Box<dyn error::Error>> {
340        if let Some(c) = nfc_get_file(dialog::NativeFileChooserType::BrowseSaveFile) {
341            self.buf.save_file(&c)?;
342            self.modified = false;
343            self.menu
344                .menu
345                .find_item("&File/&Save\t")
346                .unwrap()
347                .deactivate();
348            self.menu
349                .menu
350                .find_item("&File/&Quit\t")
351                .unwrap()
352                .set_label_color(Color::Black);
353            self.filename = Some(c);
354            self.main_win
355                .set_label(&format!("{:?} - RustyEd", self.filename.as_ref().unwrap()));
356            Ok(true)
357        } else {
358            Ok(false)
359        }
360    }
361
362    pub fn launch(&mut self) {
363        while self.app.wait() {
364            use Message::*;
365            if let Some(msg) = self.r.recv() {
366                match msg {
367                    Changed => {
368                        if !self.modified {
369                            self.modified = true;
370                            self.menu
371                                .menu
372                                .find_item("&File/&Save\t")
373                                .unwrap()
374                                .activate();
375                            self.menu
376                                .menu
377                                .find_item("&File/&Quit\t")
378                                .unwrap()
379                                .set_label_color(Color::Red);
380                            let name = match &self.filename {
381                                Some(f) => f.to_string_lossy().to_string(),
382                                None => "(Untitled)".to_string(),
383                            };
384                            self.main_win.set_label(&format!("* {name} - RustyEd"));
385                        }
386                    }
387                    New => {
388                        if self.buf.text() != "" {
389                            let clear = if let Some(x) = dialog::choice(
390                                "File unsaved, Do you wish to continue?",
391                                "&Yes",
392                                "&No!",
393                                "",
394                            ) {
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(&format!(
410                                        "An issue occured while loading the file: {e}"
411                                    )),
412                                }
413                            } else {
414                                dialog::alert("File does not exist!")
415                            }
416                        }
417                    }
418                    Save => {
419                        self.save_file().unwrap();
420                    }
421                    SaveAs => {
422                        self.save_file_as().unwrap();
423                    }
424                    Print => {
425                        let mut printer = printer::Printer::default();
426                        if printer.begin_job(0).is_ok() {
427                            let (w, h) = printer.printable_rect();
428                            self.printable.resize(
429                                self.printable.x(),
430                                self.printable.y(),
431                                w - 40,
432                                h - 40,
433                            );
434                            // Needs cleanup
435                            let line_count = self.printable.count_lines(
436                                0,
437                                self.printable.buffer().unwrap().length(),
438                                true,
439                            ) / 45;
440                            for i in 0..=line_count {
441                                self.printable.scroll(45 * i, 0);
442                                printer.begin_page().ok();
443                                printer.print_widget(&self.printable, 20, 20);
444                                printer.end_page().ok();
445                            }
446                            printer.end_job();
447                        }
448                    }
449                    Quit => {
450                        if self.modified {
451                            match dialog::choice(
452                                "Would you like to save your work?",
453                                "&Yes",
454                                "&No",
455                                "",
456                            ) {
457                                Some(0) => {
458                                    if self.save_file().unwrap() {
459                                        self.app.quit();
460                                    }
461                                }
462                                Some(1) => self.app.quit(),
463                                Some(_) | None => (),
464                            }
465                        } else {
466                            self.app.quit();
467                        }
468                    }
469                    Cut => self.editor.cut(),
470                    Copy => self.editor.copy(),
471                    Paste => self.editor.paste(),
472                    About => dialog::message(
473                        "This is an example application written in Rust and using the FLTK Gui library.",
474                    ),
475                }
476            }
477        }
478    }
Source

pub fn save_file<P: AsRef<Path>>(&mut self, path: P) -> Result<(), FltkError>

Saves a buffer into a file

§Errors

Errors on failure to save file

Examples found in repository?
examples/editor2.rs (line 314)
311    pub fn save_file(&mut self) -> Result<bool, Box<dyn error::Error>> {
312        match &self.filename {
313            Some(f) => {
314                self.buf.save_file(f)?;
315                self.modified = false;
316                self.menu
317                    .menu
318                    .find_item("&File/&Save\t")
319                    .unwrap()
320                    .deactivate();
321                self.menu
322                    .menu
323                    .find_item("&File/&Quit\t")
324                    .unwrap()
325                    .set_label_color(Color::Black);
326                let name = match &self.filename {
327                    Some(f) => f.to_string_lossy().to_string(),
328                    None => "(Untitled)".to_string(),
329                };
330                self.main_win.set_label(&format!("{name} - RustyEd"));
331                Ok(true)
332            }
333            None => self.save_file_as(),
334        }
335    }
336
337    /** Called by "Save As..." or by "Save" in case no file was set yet.
338     * Returns true if the file was succesfully saved. */
339    pub fn save_file_as(&mut self) -> Result<bool, Box<dyn error::Error>> {
340        if let Some(c) = nfc_get_file(dialog::NativeFileChooserType::BrowseSaveFile) {
341            self.buf.save_file(&c)?;
342            self.modified = false;
343            self.menu
344                .menu
345                .find_item("&File/&Save\t")
346                .unwrap()
347                .deactivate();
348            self.menu
349                .menu
350                .find_item("&File/&Quit\t")
351                .unwrap()
352                .set_label_color(Color::Black);
353            self.filename = Some(c);
354            self.main_win
355                .set_label(&format!("{:?} - RustyEd", self.filename.as_ref().unwrap()));
356            Ok(true)
357        } else {
358            Ok(false)
359        }
360    }
Source

pub fn tab_distance(&self) -> i32

Returns the tab distance for the buffer

Source

pub fn set_tab_distance(&mut self, tab_dist: i32)

Sets the tab distance

Examples found in repository?
examples/editor.rs (line 251)
246fn main() {
247    let a = app::App::default().with_scheme(app::Scheme::Oxy);
248    app::get_system_colors();
249
250    let mut buf = text::TextBuffer::default();
251    buf.set_tab_distance(4);
252
253    let state = State::new(buf.clone());
254    app::GlobalState::new(state);
255
256    let mut w = window::Window::default()
257        .with_size(WIDTH, HEIGHT)
258        .with_label("Ted");
259    w.set_xclass("ted");
260    {
261        let mut col = group::Flex::default_fill().column();
262        col.set_pad(0);
263        let mut m = menu::SysMenuBar::default();
264        init_menu(&mut m);
265        let mut ed = text::TextEditor::default().with_id("ed");
266        ed.set_buffer(buf);
267        ed.set_linenumber_width(40);
268        ed.set_text_font(Font::Courier);
269        ed.set_when(When::Changed);
270        ed.set_callback(editor_cb);
271        handle_drag_drop(&mut ed);
272        w.resizable(&col);
273        col.fixed(&m, 30);
274        col.end();
275    }
276    w.end();
277    w.show();
278    w.set_callback(win_cb);
279    a.run().unwrap();
280}
More examples
Hide additional examples
examples/editor2.rs (line 204)
199    pub fn new(args: Vec<String>) -> Self {
200        let app = app::App::default().with_scheme(app::Scheme::Gtk);
201        app::background(211, 211, 211);
202        let (s, r) = app::channel::<Message>();
203        let mut buf = text::TextBuffer::default();
204        buf.set_tab_distance(4);
205        let mut main_win = window::Window::default()
206            .with_size(800, 600)
207            .with_label("RustyEd");
208        main_win.set_center_screen();
209        let menu = MyMenu::new(&s);
210        let modified = false;
211        menu.menu.find_item("&File/&Save\t").unwrap().deactivate();
212        let mut editor = MyEditor::new(buf.clone());
213        editor.emit(s, Message::Changed);
214        main_win.make_resizable(true);
215        // only resize editor, not the menu bar
216        main_win.resizable(&*editor);
217        main_win.end();
218        main_win.show();
219        main_win.set_callback(move |_| {
220            if app::event() == Event::Close {
221                s.send(Message::Quit);
222            }
223        });
224        let filename = if args.len() > 1 {
225            let file = path::Path::new(&args[1]);
226            assert!(
227                file.exists() && file.is_file(),
228                "An error occurred while opening the file!"
229            );
230            match buf.load_file(&args[1]) {
231                Ok(_) => Some(PathBuf::from(args[1].clone())),
232                Err(e) => {
233                    dialog::alert(&format!("An issue occured while loading the file: {e}"));
234                    None
235                }
236            }
237        } else {
238            None
239        };
240
241        // Handle drag and drop
242        editor.handle({
243            let mut dnd = false;
244            let mut released = false;
245            let buf = buf.clone();
246            move |_, ev| match ev {
247                Event::DndEnter => {
248                    dnd = true;
249                    true
250                }
251                Event::DndDrag => true,
252                Event::DndRelease => {
253                    released = true;
254                    true
255                }
256                Event::Paste => {
257                    if dnd && released {
258                        let path = app::event_text().unwrap();
259                        let path = path.trim();
260                        let path = path.replace("file://", "");
261                        let path = std::path::PathBuf::from(&path);
262                        if path.exists() {
263                            // we use a timeout to avoid pasting the path into the buffer
264                            app::add_timeout(0.0, {
265                                let mut buf = buf.clone();
266                                move |_| match buf.load_file(&path) {
267                                    Ok(_) => (),
268                                    Err(e) => dialog::alert(&format!(
269                                        "An issue occured while loading the file: {e}"
270                                    )),
271                                }
272                            });
273                        }
274                        dnd = false;
275                        released = false;
276                        true
277                    } else {
278                        false
279                    }
280                }
281                Event::DndLeave => {
282                    dnd = false;
283                    released = false;
284                    true
285                }
286                _ => false,
287            }
288        });
289
290        // What shows when we attempt to print
291        let mut printable = text::TextDisplay::default();
292        printable.set_frame(FrameType::NoBox);
293        printable.set_scrollbar_size(0);
294        printable.set_buffer(Some(buf.clone()));
295
296        Self {
297            app,
298            modified,
299            filename,
300            r,
301            main_win,
302            menu,
303            buf,
304            editor,
305            printable,
306        }
307    }
Source

pub fn select(&mut self, start: i32, end: i32)

Selects the text from start to end

Source

pub fn selected(&self) -> bool

Returns whether text is selected

Source

pub fn unselect(&mut self)

Unselects text

Source

pub fn selection_position(&self) -> Option<(i32, i32)>

Returns the selection position

Source

pub fn selection_text(&self) -> String

Returns the selection text

Source

pub fn remove_selection(&mut self)

Removes the selection

Source

pub fn replace_selection(&mut self, text: &str)

Replaces selection

Source

pub fn secondary_select(&mut self, start: i32, end: i32)

Secondary selects the text from start to end

Source

pub fn secondary_selected(&self) -> bool

Returns whether text is secondary selected

Source

pub fn secondary_unselect(&mut self)

Unselects text (secondary selection)

Source

pub fn secondary_selection_position(&self) -> Option<(i32, i32)>

Returns the secondary selection position

Source

pub fn secondary_selection_text(&self) -> String

Returns the secondary selection text

Source

pub fn remove_secondary_selection(&mut self)

Removes the secondary selection

Source

pub fn replace_secondary_selection(&mut self, text: &str)

Replaces the secondary selection

Source

pub fn highlight(&mut self, start: i32, end: i32)

Highlights selection

Source

pub fn is_highlighted(&self) -> bool

Returns whether text is highlighted

Source

pub fn unhighlight(&mut self)

Unhighlights text

Source

pub fn highlight_position(&self) -> Option<(i32, i32)>

Returns the highlight position

Source

pub fn highlight_text(&self) -> String

Returns the highlighted text

Source

pub fn line_text(&self, pos: i32) -> String

Returns the line at pos

Source

pub fn line_start(&self, pos: i32) -> i32

Returns the index of the line’s start position at pos

Source

pub fn word_start(&self, pos: i32) -> i32

Returns the index of the first character of a word at pos

Source

pub fn word_end(&self, pos: i32) -> i32

Returns the index of the last character of a word at pos

Source

pub fn count_lines(&self, start: i32, end: i32) -> i32

Counts the lines from start to end

Source

pub fn call_modify_callbacks(&mut self)

Calls the modify callbacks

Source

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

Source

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

Source

pub fn search_forward( &self, start_pos: i32, search_string: &str, match_case: bool, ) -> Option<i32>

Forward search for a string

Source

pub fn search_backward( &self, start_pos: i32, search_string: &str, match_case: bool, ) -> Option<i32>

Backward search for a string

Source

pub fn find_char_forward( &self, start_pos: i32, search_char: char, ) -> Option<i32>

Forward search for a char

Source

pub fn find_char_backward( &self, start_pos: i32, search_char: char, ) -> Option<i32>

Backward search for a char

Trait Implementations§

Source§

impl Clone for TextBuffer

Source§

fn clone(&self) -> TextBuffer

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for TextBuffer

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for TextBuffer

Source§

fn default() -> TextBuffer

Initialized a default text buffer

Source§

impl Drop for TextBuffer

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl PartialEq for TextBuffer

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Eq for TextBuffer

Source§

impl Send for TextBuffer

Available on non-crate feature single-threaded only.
Source§

impl Sync for TextBuffer

Available on non-crate feature single-threaded only.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.