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
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
Initializes a text buffer from a pointer
§Safety
The pointer must be valid and this TextBuffer will take ownership of it
Sourcepub fn as_ptr(&self) -> *mut Fl_Text_Buffer
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
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?
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
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 }Sourcepub fn text(&self) -> String
pub fn text(&self) -> String
Returns the text of the buffer
Examples found in repository?
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
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 }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 append_bytes(&mut self, text: &[u8])
pub fn append_bytes(&mut self, text: &[u8])
Append bytes to the buffer
Sourcepub fn length(&self) -> i32
pub fn length(&self) -> i32
Get the length of the buffer
Examples found in repository?
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 }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
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
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?
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
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 }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?
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 }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?
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
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 }Sourcepub fn selection_position(&self) -> Option<(i32, i32)>
pub fn selection_position(&self) -> Option<(i32, i32)>
Returns the selection position
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
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.