font_manager.rs - icy_draw - icy_draw is the successor to mystic draw. fork / mirror
 (HTM) git clone https://git.drkhsh.at/icy_draw.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       font_manager.rs (10712B)
       ---
            1 use std::sync::Arc;
            2 
            3 use crate::{AnsiEditor, Message, TerminalResult};
            4 use eframe::{
            5     egui::{self, Button, Sense, TextStyle, TopBottomPanel, WidgetText},
            6     epaint::{FontFamily, FontId, Rounding},
            7 };
            8 use egui_modal::Modal;
            9 use i18n_embed_fl::fl;
           10 
           11 pub struct FontManager {
           12     selected: usize,
           13     replace_with: usize,
           14     do_select: bool,
           15     buffer_view: Arc<eframe::epaint::mutex::Mutex<icy_engine_egui::BufferView>>,
           16     used_fonts: Vec<usize>,
           17 }
           18 
           19 impl FontManager {
           20     pub fn new(editor: &AnsiEditor) -> Self {
           21         let used_fonts = icy_engine::analyze_font_usage(editor.buffer_view.lock().get_buffer());
           22         Self {
           23             selected: 0,
           24             do_select: false,
           25             replace_with: 0,
           26             buffer_view: editor.buffer_view.clone(),
           27             used_fonts,
           28         }
           29     }
           30 
           31     fn update_used_fonts(&mut self) {
           32         let lock = &self.buffer_view.lock();
           33         self.used_fonts = icy_engine::analyze_font_usage(lock.get_buffer());
           34     }
           35 }
           36 
           37 impl crate::ModalDialog for FontManager {
           38     fn show(&mut self, ctx: &egui::Context) -> bool {
           39         let mut result = false;
           40         let modal = Modal::new(ctx, "manage_font_dialog");
           41         modal.show(|ui| {
           42             ui.set_height(320.);
           43             ui.set_width(600.);
           44 
           45             modal.title(ui, fl!(crate::LANGUAGE_LOADER, "manage-font-dialog-title"));
           46             modal.frame(ui, |ui| {
           47                 egui::CentralPanel::default().show_inside(ui, |ui| {
           48                     let row_height = 24.0;
           49                     ui.label(fl!(crate::LANGUAGE_LOADER, "manage-font-used_font_label"));
           50                     egui::ScrollArea::vertical().id_source("bitfont_scroll_area").show(ui, |ui| {
           51                         for (i, font) in self.buffer_view.lock().get_buffer().font_iter() {
           52                             let is_selected = *i == self.selected;
           53 
           54                             let (id, rect) = ui.allocate_space([ui.available_width(), row_height].into());
           55                             let response = ui.interact(rect, id, Sense::click());
           56                             if response.hovered() {
           57                                 ui.painter()
           58                                     .rect_filled(rect.expand(1.0), Rounding::same(4.0), ui.style().visuals.widgets.active.bg_fill);
           59                             } else if is_selected {
           60                                 ui.painter()
           61                                     .rect_filled(rect.expand(1.0), Rounding::same(4.0), ui.style().visuals.extreme_bg_color);
           62                             }
           63 
           64                             let font_id = FontId::new(12.0, FontFamily::Monospace);
           65                             let text: WidgetText = format!("{i:-3}.").into();
           66                             let galley = text.into_galley(ui, Some(false), f32::INFINITY, font_id.clone());
           67                             let size = galley.size();
           68                             let mut title_rect = rect;
           69                             title_rect.set_left(title_rect.left() + 4.0);
           70                             title_rect.set_top(title_rect.bottom() - size.y - 8.0);
           71                             let text_color = if is_selected {
           72                                 ui.style().visuals.strong_text_color()
           73                             } else {
           74                                 ui.style().visuals.text_color()
           75                             };
           76                             ui.painter().galley_with_override_text_color(
           77                                 egui::Align2::LEFT_TOP.align_size_within_rect(galley.size(), title_rect.shrink(4.0)).min,
           78                                 galley,
           79                                 text_color,
           80                             );
           81 
           82                             let font_id = TextStyle::Button.resolve(ui.style());
           83                             let text: WidgetText = font.name.clone().into();
           84                             let galley = text.into_galley(ui, Some(false), f32::INFINITY, font_id);
           85                             let mut title_rect = rect;
           86                             title_rect.set_left(title_rect.left() + 4.0 + size.x + 4.0);
           87                             ui.painter().galley_with_override_text_color(
           88                                 egui::Align2::LEFT_TOP.align_size_within_rect(galley.size(), title_rect.shrink(4.0)).min,
           89                                 galley,
           90                                 text_color,
           91                             );
           92 
           93                             let font_id = TextStyle::Button.resolve(ui.style());
           94                             let text: WidgetText = format!("{}x{}", font.size.width, font.size.height).into();
           95                             let galley = text.into_galley(ui, Some(false), f32::INFINITY, font_id);
           96                             let mut title_rect = rect;
           97                             title_rect.set_left(title_rect.left() + 399.0);
           98                             ui.painter().galley_with_override_text_color(
           99                                 egui::Align2::LEFT_TOP.align_size_within_rect(galley.size(), title_rect.shrink(4.0)).min,
          100                                 galley,
          101                                 text_color,
          102                             );
          103 
          104                             let font_id = TextStyle::Button.resolve(ui.style());
          105                             let text: WidgetText = if self.used_fonts.contains(i) {
          106                                 fl!(crate::LANGUAGE_LOADER, "manage-font-used_label")
          107                             } else {
          108                                 fl!(crate::LANGUAGE_LOADER, "manage-font-not_used_label")
          109                             }
          110                             .into();
          111                             let galley = text.into_galley(ui, Some(false), f32::INFINITY, font_id);
          112                             let mut title_rect = rect;
          113                             title_rect.set_left(title_rect.left() + 480.0);
          114                             ui.painter().galley_with_override_text_color(
          115                                 egui::Align2::LEFT_TOP.align_size_within_rect(galley.size(), title_rect.shrink(4.0)).min,
          116                                 galley,
          117                                 text_color,
          118                             );
          119 
          120                             if response.clicked() {
          121                                 self.selected = *i;
          122                             }
          123                         }
          124                     });
          125                 });
          126                 TopBottomPanel::bottom("font_manager_bottom_panel")
          127                     .exact_height(24.0)
          128                     .resizable(false)
          129                     .show_inside(ui, |ui| {
          130                         ui.add_space(8.0);
          131 
          132                         ui.horizontal(|ui| {
          133                             ui.label(fl!(crate::LANGUAGE_LOADER, "manage-font-replace_label"));
          134                             let mut tmp_str = self.replace_with.to_string();
          135                             ui.add(egui::TextEdit::singleline(&mut tmp_str).desired_width(80.0).char_limit(4));
          136                             if let Ok(new_width) = tmp_str.parse::<usize>() {
          137                                 self.replace_with = new_width;
          138                             } else {
          139                                 self.replace_with = 0;
          140                             }
          141                             let enabled = self.buffer_view.lock().get_buffer().get_font(self.replace_with).is_some();
          142                             if ui
          143                                 .add_enabled(enabled, Button::new(fl!(crate::LANGUAGE_LOADER, "manage-font-replace_font_button")))
          144                                 .clicked()
          145                             {
          146                                 if let Err(err) = self
          147                                     .buffer_view
          148                                     .lock()
          149                                     .get_edit_state_mut()
          150                                     .replace_font_usage(self.selected, self.replace_with)
          151                                 {
          152                                     log::error!("Error replacing font {}->{}: {err}", self.selected, self.replace_with);
          153                                 }
          154                                 self.update_used_fonts();
          155                                 self.selected = 0;
          156                                 self.replace_with = 0;
          157                                 self.do_select = true;
          158                             }
          159 
          160                             if ui
          161                                 .add_enabled(!enabled, Button::new(fl!(crate::LANGUAGE_LOADER, "manage-font-change_font_slot_button")))
          162                                 .clicked()
          163                             {
          164                                 if let Err(err) = self.buffer_view.lock().get_edit_state_mut().change_font_slot(self.selected, self.replace_with) {
          165                                     log::error!("Error change font {}->{}: {err}", self.selected, self.replace_with);
          166                                 }
          167                                 self.update_used_fonts();
          168                                 self.selected = 0;
          169                                 self.replace_with = 0;
          170                                 self.do_select = true;
          171                             }
          172                         });
          173                     });
          174             });
          175             ui.add_space(8.0);
          176             modal.buttons(ui, |ui| {
          177                 if ui.button(fl!(crate::LANGUAGE_LOADER, "new-file-ok")).clicked() {
          178                     result = true;
          179                 }
          180 
          181                 let copy_font_button = ui.add(Button::new(fl!(crate::LANGUAGE_LOADER, "manage-font-copy_font_button")));
          182                 let copy_font_button = copy_font_button.on_hover_ui(|ui| {
          183                     ui.label(fl!(crate::LANGUAGE_LOADER, "manage-font-copy_font_button-tooltip"));
          184                 });
          185 
          186                 if copy_font_button.clicked() {
          187                     let lock = &self.buffer_view.lock();
          188                     if let Some(font) = lock.get_buffer().get_font(self.selected) {
          189                         ui.output_mut(|o| o.copied_text = font.encode_as_ansi(self.selected));
          190                     }
          191                 }
          192                 let remove_font_button = &ui.add_enabled(self.selected > 0, Button::new(fl!(crate::LANGUAGE_LOADER, "manage-font-remove_font_button")));
          193                 if remove_font_button.clicked() {
          194                     if let Err(err) = self.buffer_view.lock().get_edit_state_mut().remove_font(self.selected) {
          195                         log::error!("Error removing font {}: {err}", self.selected);
          196                     }
          197                     self.update_used_fonts();
          198                     self.replace_with = 0;
          199                     self.do_select = true;
          200                 }
          201             });
          202         });
          203         modal.open();
          204         result
          205     }
          206 
          207     fn should_commit(&self) -> bool {
          208         self.do_select
          209     }
          210 
          211     fn commit(&self, _editor: &mut AnsiEditor) -> TerminalResult<Option<Message>> {
          212         Ok(None)
          213     }
          214 }