select_outline_dialog.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
---
select_outline_dialog.rs (5520B)
---
1 use eframe::{
2 egui::{self},
3 epaint::{Color32, Rect, Rounding, Vec2},
4 };
5 use egui_modal::Modal;
6 use i18n_embed_fl::fl;
7 use icy_engine::{BitFont, TheDrawFont};
8
9 use crate::{AnsiEditor, Message, ModalDialog, Settings, TerminalResult};
10
11 pub struct SelectOutlineDialog {
12 should_commit: bool,
13 selected_outline: usize,
14 font: BitFont,
15 }
16
17 impl Default for SelectOutlineDialog {
18 fn default() -> Self {
19 Self {
20 should_commit: false,
21 selected_outline: Settings::get_font_outline_style(),
22 font: BitFont::default(),
23 }
24 }
25 }
26
27 impl SelectOutlineDialog {
28 pub fn get_outline_style(&self) -> usize {
29 self.selected_outline
30 }
31
32 fn draw_outline_glyph(&mut self, ui: &mut egui::Ui, outline_style: usize) {
33 let scale = 1.;
34 let border = 4.0;
35
36 let (_id, stroke_rect) = ui.allocate_space(Vec2::new(
37 2. * border + scale * self.font.size.width as f32 * OUTLINE_WIDTH as f32,
38 2. * border + scale * self.font.size.height as f32 * OUTLINE_HEIGHT as f32,
39 ));
40
41 let painter = ui.painter_at(stroke_rect);
42 let s = self.font.size;
43 let mut col = if self.selected_outline == outline_style {
44 Color32::GRAY
45 } else {
46 Color32::DARK_GRAY
47 };
48 let bg_color = if self.selected_outline == outline_style {
49 Color32::DARK_BLUE
50 } else {
51 Color32::BLACK
52 };
53
54 if let Some(pos) = ui.input(|i| i.pointer.hover_pos()) {
55 if stroke_rect.contains(pos) {
56 if ui.input(|i| i.pointer.primary_clicked()) {
57 self.selected_outline = outline_style;
58 }
59 if ui.input(|i| i.pointer.button_double_clicked(egui::PointerButton::Primary)) {
60 self.selected_outline = outline_style;
61 self.should_commit = true;
62 }
63 col = Color32::WHITE;
64 }
65 }
66 painter.rect_filled(stroke_rect, Rounding::ZERO, bg_color);
67
68 for h in 0..OUTLINE_HEIGHT {
69 for w in 0..OUTLINE_WIDTH {
70 let ch = TheDrawFont::transform_outline(outline_style, OUTLINE_FONT_CHAR[w + h * OUTLINE_WIDTH]);
71 let ch = unsafe { char::from_u32_unchecked(ch as u32) };
72
73 let xs = w as f32 * scale * self.font.size.width as f32;
74 let ys = h as f32 * scale * self.font.size.height as f32;
75 if let Some(glyph) = self.font.get_glyph(ch) {
76 for y in 0..s.height {
77 for x in 0..s.width {
78 if glyph.data[y as usize] & (128 >> x) != 0 {
79 painter.rect_filled(
80 Rect::from_min_size(
81 egui::Pos2::new(
82 border + xs + stroke_rect.left() + x as f32 * scale,
83 border + ys + stroke_rect.top() + y as f32 * scale,
84 ),
85 Vec2::new(scale, scale),
86 ),
87 Rounding::ZERO,
88 col,
89 );
90 }
91 }
92 }
93 }
94 }
95 }
96 }
97
98 pub fn show_outline_ui(&mut self, ui: &mut egui::Ui, item_per_row: usize, spacing: Vec2) {
99 for style in 0..TheDrawFont::OUTLINE_STYLES / item_per_row {
100 ui.horizontal(|ui| {
101 ui.add_space(4.0);
102 for i in 0..item_per_row {
103 self.draw_outline_glyph(ui, style * item_per_row + i);
104 if i < item_per_row - 1 {
105 ui.add_space(spacing.x);
106 }
107 }
108 });
109 ui.end_row();
110 ui.add_space(spacing.y);
111 }
112 }
113 }
114
115 const OUTLINE_WIDTH: usize = 8;
116 const OUTLINE_HEIGHT: usize = 6;
117 const OUTLINE_FONT_CHAR: [u8; 48] = [
118 69, 65, 65, 65, 65, 65, 65, 70, 67, 79, 71, 66, 66, 72, 79, 68, 67, 79, 73, 65, 65, 74, 79, 68, 67, 79, 71, 66, 66, 72, 79, 68, 67, 79, 68, 64, 64, 67, 79,
119 68, 75, 66, 76, 64, 64, 75, 66, 76,
120 ];
121
122 impl ModalDialog for SelectOutlineDialog {
123 fn show(&mut self, ctx: &egui::Context) -> bool {
124 let mut result = false;
125 let modal = Modal::new(ctx, "select_outline_dialog");
126
127 modal.show(|ui| {
128 modal.title(ui, fl!(crate::LANGUAGE_LOADER, "select-outline-style-title"));
129
130 modal.frame(ui, |ui| {
131 ui.add_space(8.0);
132 self.show_outline_ui(ui, 4, Vec2::new(8.0, 8.0));
133 });
134
135 modal.buttons(ui, |ui| {
136 if ui.button(fl!(crate::LANGUAGE_LOADER, "new-file-ok")).clicked() {
137 self.should_commit = true;
138 result = true;
139 }
140 if ui.button(fl!(crate::LANGUAGE_LOADER, "new-file-cancel")).clicked() {
141 result = true;
142 }
143 });
144 });
145 modal.open();
146 result || self.should_commit
147 }
148
149 fn should_commit(&self) -> bool {
150 self.should_commit
151 }
152
153 fn commit(&self, _editor: &mut AnsiEditor) -> TerminalResult<Option<Message>> {
154 Settings::set_font_outline_style(self.selected_outline);
155 Ok(None)
156 }
157 }