URI: 
       mod.rs - icy_draw - icy_draw is the successor to mystic draw. fork / mirror
  HTML git clone https://git.drkhsh.at/icy_draw.git
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       mod.rs (25439B)
       ---
            1 mod undo;
            2 
            3 use std::{path::Path, sync::Arc};
            4 
            5 use eframe::{
            6     egui::{self, Id, Layout, RichText, Sense},
            7     emath::Align2,
            8     epaint::{mutex::Mutex, Color32, FontFamily, FontId, Pos2, Rect, Rounding, Vec2},
            9 };
           10 use i18n_embed_fl::fl;
           11 use icy_engine::{
           12     util::{pop_data, push_data, BITFONT_GLYPH},
           13     BitFont, Buffer, EngineResult, Glyph, Size, TextAttribute, TextPane,
           14 };
           15 use icy_engine_egui::{show_terminal_area, BufferView};
           16 
           17 use crate::{model::Tool, to_message, AnsiEditor, ClipboardHandler, Document, DocumentOptions, Message, TerminalResult, UndoHandler, SETTINGS};
           18 
           19 use self::undo::UndoOperation;
           20 
           21 pub struct BitFontEditor {
           22     id: usize,
           23     original_font: BitFont,
           24     last_updated_font: BitFont,
           25     font: BitFont,
           26 
           27     width: i32,
           28     height: i32,
           29 
           30     buffer_view: Arc<Mutex<BufferView>>,
           31 
           32     selected_char_opt: Option<char>,
           33     undo_stack: Arc<Mutex<Vec<Box<dyn UndoOperation>>>>,
           34     redo_stack: Vec<Box<dyn UndoOperation>>,
           35     old_data: Option<Vec<u8>>,
           36 
           37     send_update_message: bool,
           38 }
           39 
           40 pub enum DrawGlyphStyle {
           41     Normal,
           42     Selected,
           43     GrayOut,
           44 }
           45 
           46 impl BitFontEditor {
           47     pub fn new(gl: &Arc<glow::Context>, id: usize, font: BitFont) -> Self {
           48         let mut buffer = Buffer::new(Size::new(10, 10));
           49         buffer.is_terminal_buffer = false;
           50         let mut buffer_view = BufferView::from_buffer(gl, buffer);
           51         buffer_view.interactive = false;
           52         let buffer_view = Arc::new(Mutex::new(buffer_view));
           53         let size = font.size;
           54         let last_updated_font = font.clone();
           55         Self {
           56             id,
           57             buffer_view,
           58             original_font: font.clone(),
           59             last_updated_font,
           60             font,
           61             width: size.width,
           62             height: size.height,
           63             selected_char_opt: Some('A'),
           64             undo_stack: Arc::new(Mutex::new(Vec::new())),
           65             redo_stack: Vec::new(),
           66             old_data: None,
           67             send_update_message: false,
           68         }
           69     }
           70 
           71     pub fn draw_glyph(ui: &mut egui::Ui, font: &BitFont, style: DrawGlyphStyle, ch: char) -> egui::Response {
           72         let scale = 3.;
           73         let (id, stroke_rect) = ui.allocate_space(Vec2::new(scale * font.size.width as f32, scale * font.size.height as f32));
           74         let response = ui.interact(stroke_rect, id, Sense::click());
           75         let col = if response.hovered() {
           76             match style {
           77                 DrawGlyphStyle::Normal => Color32::LIGHT_GRAY,
           78                 DrawGlyphStyle::Selected => Color32::WHITE,
           79                 DrawGlyphStyle::GrayOut => Color32::GRAY,
           80             }
           81         } else {
           82             match style {
           83                 DrawGlyphStyle::Normal => Color32::GRAY,
           84                 DrawGlyphStyle::Selected => Color32::YELLOW,
           85                 DrawGlyphStyle::GrayOut => Color32::DARK_GRAY,
           86             }
           87         };
           88 
           89         let painter = ui.painter_at(stroke_rect);
           90         painter.rect_filled(stroke_rect, Rounding::ZERO, Color32::BLACK);
           91         let s = font.size;
           92         if let Some(glyph) = font.get_glyph(ch) {
           93             for y in 0..s.height {
           94                 for x in 0..s.width {
           95                     if glyph.data[y as usize] & (128 >> x) != 0 {
           96                         painter.rect_filled(
           97                             Rect::from_min_size(
           98                                 Pos2::new(stroke_rect.left() + x as f32 * scale, stroke_rect.top() + y as f32 * scale),
           99                                 Vec2::new(scale, scale),
          100                             ),
          101                             Rounding::ZERO,
          102                             col,
          103                         );
          104                     }
          105                 }
          106             }
          107         }
          108         response
          109     }
          110 
          111     pub fn update_tile_area(&mut self) {
          112         let lock = &mut self.buffer_view.lock();
          113         let buf = lock.get_buffer_mut();
          114         buf.set_font(0, self.font.clone());
          115 
          116         let ch = self.selected_char_opt.unwrap_or(' ');
          117         for y in 0..buf.get_width() {
          118             for x in 0..buf.get_height() {
          119                 buf.layers[0].set_char(
          120                     (x, y),
          121                     icy_engine::AttributedChar {
          122                         ch,
          123                         attribute: TextAttribute::default(),
          124                     },
          125                 );
          126             }
          127         }
          128         self.send_update_message = true;
          129         lock.redraw_view();
          130     }
          131 
          132     pub fn edit_glyph(&mut self) -> impl egui::Widget + '_ {
          133         move |ui: &mut egui::Ui| {
          134             let scale = 20.;
          135             let border = 2.;
          136 
          137             let left_ruler = 20.0;
          138             let top_ruler = 20.0;
          139 
          140             let (id, stroke_rect) = ui.allocate_space(Vec2::new(
          141                 1. + (border + scale) * self.font.size.width as f32 + left_ruler,
          142                 1. + (border + scale) * self.font.size.height as f32 + top_ruler,
          143             ));
          144             let mut response = ui.interact(stroke_rect, id, Sense::click_and_drag());
          145 
          146             let painter = ui.painter_at(stroke_rect);
          147             painter.rect_filled(stroke_rect, Rounding::ZERO, Color32::DARK_GRAY);
          148 
          149             let s = self.font.size;
          150 
          151             /*   if response.clicked() {
          152                 if let Some(pos) = response.hover_pos() {
          153                     if let Some(number) = self.selected_char_opt {
          154                         if let Some(glyph) = self.font.get_glyph_mut(number) {
          155                             println!("click!");
          156                             let y = ((pos.y - stroke_rect.top()) / (scale + border)) as usize;
          157                             let x = ((pos.x - stroke_rect.left()) / (scale + border)) as usize;
          158                             if glyph.data[y] & (128 >> x) != 0 {
          159                                 println!("unset!");
          160                                 glyph.data[y] &= !(128 >> x);
          161                             } else {
          162                                 println!("set!");
          163                                 glyph.data[y] |= 128 >> x;
          164                             }
          165                             self.is_dirty = true;
          166                             response.mark_changed();
          167                         }
          168                     }
          169                 }
          170             } else { */
          171             if response.drag_started_by(egui::PointerButton::Primary) || response.drag_started_by(egui::PointerButton::Secondary) {
          172                 self.start_edit();
          173             }
          174 
          175             if response.drag_released_by(egui::PointerButton::Primary) || response.drag_released_by(egui::PointerButton::Secondary) {
          176                 self.end_edit();
          177             }
          178 
          179             if response.dragged_by(egui::PointerButton::Primary) {
          180                 if let Some(pos) = response.hover_pos() {
          181                     if let Some(number) = self.selected_char_opt {
          182                         if let Some(glyph) = self.font.get_glyph_mut(number) {
          183                             let y = ((pos.y - left_ruler - stroke_rect.top()) / (scale + border)) as usize;
          184                             let x = ((pos.x - top_ruler - stroke_rect.left()) / (scale + border)) as usize;
          185                             if y < glyph.data.len() && x < 8 {
          186                                 glyph.data[y] |= 128 >> x;
          187                                 self.update_tile_area();
          188                                 response.mark_changed();
          189                             }
          190                         }
          191                     }
          192                 }
          193             }
          194 
          195             if response.dragged_by(egui::PointerButton::Secondary) {
          196                 if let Some(pos) = response.hover_pos() {
          197                     if let Some(number) = self.selected_char_opt {
          198                         if let Some(glyph) = self.font.get_glyph_mut(number) {
          199                             let y = ((pos.y - left_ruler - stroke_rect.top()) / (scale + border)) as usize;
          200                             let x = ((pos.x - top_ruler - stroke_rect.left()) / (scale + border)) as usize;
          201                             if y < glyph.data.len() && x < 8 {
          202                                 glyph.data[y] &= !(128 >> x);
          203                                 self.update_tile_area();
          204                                 response.mark_changed();
          205                             }
          206                         }
          207                     }
          208                 }
          209             }
          210             if let Some(number) = self.selected_char_opt {
          211                 if let Some(glyph) = self.font.get_glyph_mut(number) {
          212                     painter.rect_filled(
          213                         Rect::from_min_size(
          214                             Pos2::new(stroke_rect.left(), stroke_rect.top()),
          215                             Vec2::new(
          216                                 2. + left_ruler + s.width as f32 * (border + scale),
          217                                 2. + top_ruler + s.height as f32 * (border + scale),
          218                             ),
          219                         ),
          220                         Rounding::ZERO,
          221                         ui.style().visuals.extreme_bg_color,
          222                     );
          223 
          224                     for x in 0..s.width {
          225                         let pos = Pos2::new(
          226                             2. + left_ruler + stroke_rect.left() + (x as f32 + 0.5) * (border + scale),
          227                             2. + top_ruler / 2. + stroke_rect.top(),
          228                         );
          229                         let col = if let Some(pos) = response.hover_pos() {
          230                             if x == ((pos.x - (2. + left_ruler + stroke_rect.left())) / (border + scale)) as i32 {
          231                                 ui.style().visuals.strong_text_color()
          232                             } else {
          233                                 ui.style().visuals.text_color()
          234                             }
          235                         } else {
          236                             ui.style().visuals.text_color()
          237                         };
          238 
          239                         painter.text(
          240                             pos,
          241                             Align2::CENTER_CENTER,
          242                             (x + 1).to_string(),
          243                             FontId::new(12.0, FontFamily::Proportional),
          244                             col,
          245                         );
          246                     }
          247                     for y in 0..s.height {
          248                         let pos = Pos2::new(
          249                             2. + left_ruler / 2. + stroke_rect.left(),
          250                             2. + top_ruler + stroke_rect.top() + (y as f32 + 0.5) * (border + scale),
          251                         );
          252                         let col = if let Some(pos) = response.hover_pos() {
          253                             if y == ((pos.y - (2. + top_ruler + stroke_rect.top())) / (border + scale)) as i32 {
          254                                 ui.style().visuals.strong_text_color()
          255                             } else {
          256                                 ui.style().visuals.text_color()
          257                             }
          258                         } else {
          259                             ui.style().visuals.text_color()
          260                         };
          261 
          262                         painter.text(
          263                             pos,
          264                             Align2::CENTER_CENTER,
          265                             (y + 1).to_string(),
          266                             FontId::new(12.0, FontFamily::Proportional),
          267                             col,
          268                         );
          269                     }
          270 
          271                     for y in 0..s.height {
          272                         for x in 0..s.width {
          273                             let rect = Rect::from_min_size(
          274                                 Pos2::new(
          275                                     2. + left_ruler + stroke_rect.left() + x as f32 * (border + scale),
          276                                     2. + top_ruler + stroke_rect.top() + y as f32 * (border + scale),
          277                                 ),
          278                                 Vec2::new(scale, scale),
          279                             );
          280                             let col = if glyph.data[y as usize] & (128 >> x) != 0 {
          281                                 if let Some(pos) = response.hover_pos() {
          282                                     if rect.contains(pos) {
          283                                         Color32::WHITE
          284                                     } else {
          285                                         Color32::GRAY
          286                                     }
          287                                 } else {
          288                                     Color32::GRAY
          289                                 }
          290                             } else if let Some(pos) = response.hover_pos() {
          291                                 if rect.contains(pos) {
          292                                     Color32::DARK_GRAY
          293                                 } else {
          294                                     Color32::BLACK
          295                                 }
          296                             } else {
          297                                 Color32::BLACK
          298                             };
          299                             painter.rect_filled(rect, Rounding::ZERO, col);
          300                         }
          301                     }
          302                 }
          303             }
          304             response
          305         }
          306     }
          307 
          308     fn push_undo(&mut self, mut op: Box<dyn UndoOperation>) -> EngineResult<()> {
          309         op.redo(self)?;
          310         self.undo_stack.lock().push(op);
          311         self.redo_stack.clear();
          312         self.update_tile_area();
          313         Ok(())
          314     }
          315 
          316     fn clear_selected_glyph(&mut self) -> EngineResult<()> {
          317         if let Some(number) = self.selected_char_opt {
          318             let op = undo::ClearGlyph::new(number);
          319             self.push_undo(Box::new(op))?;
          320         }
          321         Ok(())
          322     }
          323 
          324     fn inverse_selected_glyph(&mut self) -> EngineResult<()> {
          325         if let Some(number) = self.selected_char_opt {
          326             let op = undo::InverseGlyph::new(number);
          327             self.push_undo(Box::new(op))?;
          328         }
          329         Ok(())
          330     }
          331 
          332     fn left_selected_glyph(&mut self) -> EngineResult<()> {
          333         if let Some(number) = self.selected_char_opt {
          334             let op = undo::LeftGlyph::new(number);
          335             self.push_undo(Box::new(op))?;
          336         }
          337         Ok(())
          338     }
          339 
          340     fn right_selected_glyph(&mut self) -> EngineResult<()> {
          341         if let Some(number) = self.selected_char_opt {
          342             let op = undo::RightGlyph::new(number);
          343             self.push_undo(Box::new(op))?;
          344         }
          345         Ok(())
          346     }
          347 
          348     fn up_selected_glyph(&mut self) -> EngineResult<()> {
          349         if let Some(number) = self.selected_char_opt {
          350             let op = undo::UpGlyph::new(number);
          351             self.push_undo(Box::new(op))?;
          352         }
          353         Ok(())
          354     }
          355 
          356     fn down_selected_glyph(&mut self) -> EngineResult<()> {
          357         if let Some(number) = self.selected_char_opt {
          358             let op = undo::DownGlyph::new(number);
          359             self.push_undo(Box::new(op))?;
          360         }
          361         Ok(())
          362     }
          363 
          364     fn flip_x_selected_glyph(&mut self) -> EngineResult<()> {
          365         if let Some(number) = self.selected_char_opt {
          366             let op = undo::FlipX::new(number);
          367             self.push_undo(Box::new(op))?;
          368         }
          369         Ok(())
          370     }
          371 
          372     fn flip_y_selected_glyph(&mut self) -> EngineResult<()> {
          373         if let Some(number) = self.selected_char_opt {
          374             let op = undo::FlipY::new(number);
          375             self.push_undo(Box::new(op))?;
          376         }
          377         Ok(())
          378     }
          379 
          380     fn resize_font(&mut self) -> EngineResult<()> {
          381         let old_font = self.font.clone();
          382         let mut new_font = self.font.clone();
          383 
          384         for glyph in new_font.glyphs.values_mut() {
          385             glyph.data.resize(self.height as usize, 0);
          386         }
          387         new_font.size = Size::new(self.width, self.height);
          388 
          389         let op = undo::ResizeFont::new(old_font, new_font);
          390         self.push_undo(Box::new(op))?;
          391         Ok(())
          392     }
          393 
          394     fn start_edit(&mut self) {
          395         if let Some(number) = self.selected_char_opt {
          396             if let Some(glyph) = self.font.get_glyph_mut(number) {
          397                 self.old_data = Some(glyph.data.clone());
          398             }
          399         }
          400     }
          401 
          402     fn end_edit(&mut self) {
          403         if self.old_data.is_none() {
          404             return;
          405         }
          406         if let Some(number) = self.selected_char_opt {
          407             if let Some(glyph) = self.font.get_glyph(number) {
          408                 if let Some(old_data) = self.old_data.take() {
          409                     let op = undo::Edit::new(number, glyph.data.clone(), old_data);
          410                     self.undo_stack.lock().push(Box::new(op));
          411                     self.redo_stack.clear();
          412                 } else {
          413                     log::error!("no old_data for BitFontEditor:end_edit");
          414                 }
          415             }
          416         }
          417     }
          418 }
          419 
          420 impl ClipboardHandler for BitFontEditor {
          421     fn can_copy(&self) -> bool {
          422         self.selected_char_opt.is_some()
          423     }
          424 
          425     fn copy(&mut self) -> EngineResult<()> {
          426         if let Some(ch) = self.selected_char_opt {
          427             if let Some(data) = self.font.get_clipboard_data(ch) {
          428                 push_data(BITFONT_GLYPH, &data)?;
          429             }
          430         }
          431         Ok(())
          432     }
          433 
          434     fn can_paste(&self) -> bool {
          435         if self.selected_char_opt.is_none() {
          436             return false;
          437         }
          438 
          439         pop_data(BITFONT_GLYPH).is_some()
          440     }
          441 
          442     fn paste(&mut self) -> EngineResult<()> {
          443         if let Some(data) = pop_data(BITFONT_GLYPH) {
          444             let (_, g) = Glyph::from_clipbard_data(&data);
          445             if let Some(ch) = self.selected_char_opt {
          446                 let op = undo::Paste::new(ch, g);
          447                 self.push_undo(Box::new(op))?;
          448             }
          449         }
          450         Ok(())
          451     }
          452 }
          453 
          454 impl UndoHandler for BitFontEditor {
          455     fn undo_description(&self) -> Option<String> {
          456         self.undo_stack.lock().last().map(|op| op.get_description())
          457     }
          458 
          459     fn can_undo(&self) -> bool {
          460         !self.undo_stack.lock().is_empty()
          461     }
          462 
          463     fn undo(&mut self) -> EngineResult<Option<Message>> {
          464         let Some(mut op) = self.undo_stack.lock().pop() else {
          465             return Ok(None);
          466         };
          467 
          468         op.undo(self)?;
          469         self.redo_stack.push(op);
          470         self.update_tile_area();
          471         self.send_update_message = true;
          472         Ok(None)
          473     }
          474 
          475     fn redo_description(&self) -> Option<String> {
          476         self.redo_stack.last().map(|op| op.get_description())
          477     }
          478 
          479     fn can_redo(&self) -> bool {
          480         !self.redo_stack.is_empty()
          481     }
          482 
          483     fn redo(&mut self) -> EngineResult<Option<Message>> {
          484         if let Some(mut op) = self.redo_stack.pop() {
          485             op.redo(self)?;
          486             self.undo_stack.lock().push(op);
          487             return Ok(None);
          488         }
          489         self.update_tile_area();
          490         self.send_update_message = true;
          491         Ok(None)
          492     }
          493 }
          494 
          495 impl Document for BitFontEditor {
          496     fn default_extension(&self) -> &'static str {
          497         "psf"
          498     }
          499 
          500     fn undo_stack_len(&self) -> usize {
          501         self.undo_stack.lock().len()
          502     }
          503 
          504     fn show_ui(&mut self, ui: &mut eframe::egui::Ui, _cur_tool: &mut Box<dyn Tool>, _selected_tool: usize, _options: &DocumentOptions) -> Option<Message> {
          505         let mut message = None;
          506         ui.add_space(16.);
          507         ui.vertical_centered(|ui| {
          508             ui.horizontal(|ui| {
          509                 ui.add_space(120.);
          510                 ui.add(self.edit_glyph());
          511 
          512                 ui.vertical(|ui| {
          513                     ui.add_space(20.);
          514                     ui.horizontal(|ui| {
          515                         if ui.button(fl!(crate::LANGUAGE_LOADER, "font-editor-clear")).clicked() {
          516                             message = to_message(self.clear_selected_glyph());
          517                         }
          518                         if ui.button(fl!(crate::LANGUAGE_LOADER, "font-editor-inverse")).clicked() {
          519                             message = to_message(self.inverse_selected_glyph());
          520                         }
          521                     });
          522                     ui.add_space(8.);
          523                     ui.horizontal(|ui| {
          524                         ui.add_space(14.);
          525 
          526                         if ui.button("⬆").clicked() {
          527                             message = to_message(self.up_selected_glyph());
          528                         }
          529                     });
          530 
          531                     ui.horizontal(|ui| {
          532                         if ui.button("⬅").clicked() {
          533                             message = to_message(self.left_selected_glyph());
          534                         }
          535 
          536                         if ui.button("➡").clicked() {
          537                             message = to_message(self.right_selected_glyph());
          538                         }
          539                     });
          540 
          541                     ui.horizontal(|ui| {
          542                         ui.add_space(14.);
          543 
          544                         if ui.button("⬇").clicked() {
          545                             message = to_message(self.down_selected_glyph());
          546                         }
          547                     });
          548                     ui.add_space(8.);
          549 
          550                     ui.horizontal(|ui| {
          551                         if ui.button(fl!(crate::LANGUAGE_LOADER, "font-editor-flip_x")).clicked() {
          552                             message = to_message(self.flip_x_selected_glyph());
          553                         }
          554 
          555                         if ui.button(fl!(crate::LANGUAGE_LOADER, "font-editor-flip_y")).clicked() {
          556                             message = to_message(self.flip_y_selected_glyph());
          557                         }
          558                     });
          559 
          560                     egui::Grid::new("some_unique_id").num_columns(2).spacing([4.0, 8.0]).show(ui, |ui| {
          561                         ui.with_layout(Layout::right_to_left(egui::Align::Center), |ui| {
          562                             ui.label(fl!(crate::LANGUAGE_LOADER, "new-file-width"));
          563                         });
          564                         ui.add(egui::Slider::new(&mut self.width, 2..=8));
          565                         ui.end_row();
          566 
          567                         ui.with_layout(Layout::right_to_left(egui::Align::Center), |ui| {
          568                             ui.label(fl!(crate::LANGUAGE_LOADER, "new-file-height"));
          569                         });
          570                         ui.add(egui::Slider::new(&mut self.height, 2..=19));
          571                         ui.end_row();
          572                     });
          573 
          574                     if (self.width != self.font.size.width || self.height != self.font.size.height) && ui.button("Resize").clicked() {
          575                         message = to_message(self.resize_font());
          576                     }
          577                 });
          578 
          579                 ui.vertical(|ui| {
          580                     ui.heading(fl!(crate::LANGUAGE_LOADER, "font-editor-tile_area"));
          581                     let mut scale = unsafe { SETTINGS.get_scale() };
          582                     if self.buffer_view.lock().get_buffer().use_aspect_ratio() {
          583                         scale.y *= 1.35;
          584                     }
          585                     let opt = icy_engine_egui::TerminalOptions {
          586                         stick_to_bottom: false,
          587                         scale: Some(Vec2::new(2.0, 2.0)),
          588                         monitor_settings: unsafe { SETTINGS.monitor_settings.clone() },
          589                         marker_settings: unsafe { SETTINGS.marker_settings.clone() },
          590                         id: Some(Id::new(self.id + 20000)),
          591                         ..Default::default()
          592                     };
          593                     self.buffer_view.lock().get_caret_mut().set_is_visible(false);
          594                     let (_, _) = show_terminal_area(ui, self.buffer_view.clone(), opt);
          595                 });
          596             });
          597         });
          598 
          599         ui.label(fl!(crate::LANGUAGE_LOADER, "font-editor-table", length = (self.font.length - 1).to_string()));
          600         egui::ScrollArea::vertical().show(ui, |ui| {
          601             ui.horizontal_wrapped(|ui| {
          602                 for i in 0..self.font.length {
          603                     let ch = unsafe { char::from_u32_unchecked(i as u32) };
          604                     let mut style = DrawGlyphStyle::Normal;
          605                     if let Some(ch2) = self.selected_char_opt {
          606                         if ch == ch2 {
          607                             style = DrawGlyphStyle::Selected
          608                         }
          609                     }
          610                     let response = BitFontEditor::draw_glyph(ui, &self.font, style, ch);
          611                     if response.clicked() {
          612                         self.selected_char_opt = Some(ch);
          613                         self.update_tile_area();
          614                     }
          615 
          616                     response.on_hover_ui(|ui| {
          617                         ui.horizontal(|ui| {
          618                             ui.label(RichText::new(fl!(crate::LANGUAGE_LOADER, "font-view-char_label")).small());
          619                             ui.label(RichText::new(format!("{0}/0x{0:02X}", i)).small().color(Color32::WHITE));
          620                         });
          621                         ui.horizontal(|ui| {
          622                             ui.label(RichText::new(fl!(crate::LANGUAGE_LOADER, "font-view-ascii_label")).small());
          623                             ui.label(
          624                                 RichText::new(format!("'{0}'", unsafe { char::from_u32_unchecked(i as u32) }))
          625                                     .small()
          626                                     .color(Color32::WHITE),
          627                             );
          628                         });
          629                     });
          630                 }
          631             })
          632         });
          633 
          634         if message.is_none() && self.send_update_message {
          635             message = Some(Message::UpdateFont(Box::new((self.last_updated_font.clone(), self.font.clone()))));
          636             self.last_updated_font = self.font.clone();
          637             self.send_update_message = false;
          638         }
          639 
          640         message
          641     }
          642 
          643     fn get_bytes(&mut self, _path: &Path) -> TerminalResult<Vec<u8>> {
          644         self.font.to_psf2_bytes()
          645     }
          646 
          647     fn get_ansi_editor_mut(&mut self) -> Option<&mut AnsiEditor> {
          648         None
          649     }
          650 
          651     fn get_ansi_editor(&self) -> Option<&AnsiEditor> {
          652         None
          653     }
          654 
          655     fn inform_save(&mut self) {
          656         self.original_font = self.font.clone();
          657     }
          658 
          659     fn destroy(&self, gl: &glow::Context) -> Option<Message> {
          660         self.buffer_view.lock().destroy(gl);
          661         Some(Message::UpdateFont(Box::new((self.last_updated_font.clone(), self.original_font.clone()))))
          662     }
          663 }