palette_editor.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
       ---
       palette_editor.rs (8837B)
       ---
            1 use crate::{Message, SWAP_SVG};
            2 use eframe::egui::{self, Sense};
            3 use eframe::epaint::{Color32, Pos2, Rect, Rounding, Stroke, Vec2};
            4 use icy_engine::{Palette, TextAttribute};
            5 use std::cmp::min;
            6 
            7 pub fn palette_switcher(_ctx: &egui::Context, ui: &mut egui::Ui, caret_attr: &TextAttribute, palette: &Palette) -> Option<Message> {
            8     let mut result = None;
            9 
           10     let height = 62.0;
           11     let (id, rect) = ui.allocate_space(Vec2::new(height, height));
           12     let response = ui.interact(rect, id, Sense::click());
           13     let painter = ui.painter_at(rect);
           14 
           15     let rect_height = height * 0.618;
           16 
           17     painter.rect_filled(
           18         Rect::from_min_size(
           19             Pos2::new(height - rect_height, height - rect_height) + rect.left_top().to_vec2(),
           20             Vec2::new(rect_height, rect_height),
           21         ),
           22         Rounding::ZERO,
           23         Color32::BLACK,
           24     );
           25 
           26     painter.rect_filled(
           27         Rect::from_min_size(
           28             Pos2::new(height - rect_height + 1., height - rect_height + 1.) + rect.left_top().to_vec2(),
           29             Vec2::new(rect_height - 2., rect_height - 2.),
           30         ),
           31         Rounding::ZERO,
           32         Color32::WHITE,
           33     );
           34 
           35     let (r, g, b) = palette.get_rgb(caret_attr.get_background());
           36     painter.rect_filled(
           37         Rect::from_min_size(
           38             Pos2::new(height - rect_height + 2., height - rect_height + 2.) + rect.left_top().to_vec2(),
           39             Vec2::new(rect_height - 4., rect_height - 4.),
           40         ),
           41         Rounding::ZERO,
           42         Color32::from_rgb(r, g, b),
           43     );
           44 
           45     painter.rect_filled(
           46         Rect::from_min_size(Pos2::new(0., 0.) + rect.left_top().to_vec2(), Vec2::new(rect_height, rect_height)),
           47         Rounding::ZERO,
           48         Color32::BLACK,
           49     );
           50 
           51     painter.rect_filled(
           52         Rect::from_min_size(Pos2::new(1., 1.) + rect.left_top().to_vec2(), Vec2::new(rect_height - 2., rect_height - 2.)),
           53         Rounding::ZERO,
           54         Color32::WHITE,
           55     );
           56 
           57     let (r, g, b) = palette.get_rgb(caret_attr.get_foreground());
           58     painter.rect_filled(
           59         Rect::from_min_size(Pos2::new(2., 2.) + rect.left_top().to_vec2(), Vec2::new(rect_height - 4., rect_height - 4.)),
           60         Rounding::ZERO,
           61         Color32::from_rgb(r, g, b),
           62     );
           63 
           64     let s_rect_height = height * 0.382;
           65     let rh = s_rect_height / 1.8;
           66     let (r, g, b) = palette.get_rgb(7);
           67 
           68     let overlap = 2.0;
           69 
           70     painter.rect_filled(
           71         Rect::from_min_size(Pos2::new(rh - overlap, height - rh - overlap) + rect.left_top().to_vec2(), Vec2::new(rh, rh)),
           72         Rounding::ZERO,
           73         Color32::from_rgb(r ^ 0xFF, g ^ 0xFF, b ^ 0xFF),
           74     );
           75 
           76     painter.rect_filled(
           77         Rect::from_min_size(
           78             Pos2::new(rh - overlap + 1., height - rh - overlap + 1.) + rect.left_top().to_vec2(),
           79             Vec2::new(rh - 2., rh - 2.),
           80         ),
           81         Rounding::ZERO,
           82         Color32::from_rgb(r, g, b),
           83     );
           84 
           85     let (r, g, b) = palette.get_rgb(0);
           86     painter.rect_filled(
           87         Rect::from_min_size(
           88             Pos2::new(overlap, height - 2. * rh + 2. + overlap) + rect.left_top().to_vec2(),
           89             Vec2::new(rh, rh),
           90         ),
           91         Rounding::ZERO,
           92         Color32::from_rgb(r ^ 0xFF, g ^ 0xFF, b ^ 0xFF),
           93     );
           94 
           95     painter.rect_filled(
           96         Rect::from_min_size(
           97             Pos2::new(1. + overlap, height - 2. * rh + 3. + overlap) + rect.left_top().to_vec2(),
           98             Vec2::new(rh - 2., rh - 2.),
           99         ),
          100         Rounding::ZERO,
          101         Color32::from_rgb(r, g, b),
          102     );
          103     let mut tex_id = SWAP_SVG.clone();
          104     tex_id = tex_id.tint(Color32::WHITE);
          105     tex_id.paint_at(
          106         ui,
          107         Rect::from_min_size(
          108             Pos2::new(rect_height + 1., 0.) + rect.left_top().to_vec2(),
          109             Vec2::new(s_rect_height, s_rect_height),
          110         ),
          111     );
          112 
          113     if let Some(hp) = response.hover_pos() {
          114         let pos = hp.to_vec2() - rect.left_top().to_vec2();
          115 
          116         if response.clicked() {
          117             if pos.x > rect_height && pos.y < rect_height {
          118                 result = Some(Message::ToggleColor);
          119             }
          120 
          121             if pos.x < rect_height && pos.y > rect_height {
          122                 result = Some(Message::SwitchToDefaultColor);
          123             }
          124         }
          125     }
          126     result
          127 }
          128 
          129 pub fn palette_editor_16(
          130     ui: &mut egui::Ui,
          131     caret_attr: &TextAttribute,
          132     palette: &Palette,
          133     ice_mode: icy_engine::IceMode,
          134     font_mode: icy_engine::FontMode,
          135 ) -> Option<Message> {
          136     let mut result = None;
          137 
          138     ui.horizontal(|ui| {
          139         ui.add_space(4.0);
          140         let right_border = 4.0;
          141         let items_per_row = if palette.len() < 64 { 8 } else { 16 };
          142 
          143         let upper_limit = (palette.len() as f32 / items_per_row as f32).ceil() as usize * items_per_row;
          144 
          145         let height = (ui.available_width() - right_border) / items_per_row as f32;
          146 
          147         let (id, stroke_rect) = ui.allocate_space(Vec2::new(
          148             ui.available_width() - right_border,
          149             height * upper_limit as f32 / items_per_row as f32,
          150         ));
          151 
          152         let mut response = ui.interact(stroke_rect, id, Sense::click());
          153         let painter = ui.painter_at(stroke_rect);
          154 
          155         for i in 0..upper_limit {
          156             let (r, g, b) = palette.get_rgb(i as u32);
          157             painter.rect_filled(
          158                 Rect::from_min_size(
          159                     Pos2::new(
          160                         stroke_rect.left() + (i % items_per_row) as f32 * height,
          161                         stroke_rect.top() + (i / items_per_row) as f32 * height,
          162                     ),
          163                     Vec2::new(height, height),
          164                 ),
          165                 Rounding::ZERO,
          166                 Color32::from_rgb(r, g, b),
          167             );
          168         }
          169 
          170         let marker_len = height / 3.;
          171         // paint fg marker
          172         let stroke = Stroke::new(1., Color32::WHITE);
          173         let origin = Pos2::new(
          174             stroke_rect.left() + (caret_attr.get_foreground() % items_per_row as u32) as f32 * height,
          175             stroke_rect.top() + (caret_attr.get_foreground() / items_per_row as u32) as f32 * height,
          176         );
          177         painter.line_segment([origin, origin + Vec2::new(marker_len, 0.)], stroke);
          178         painter.line_segment([origin, origin + Vec2::new(0., marker_len)], stroke);
          179         for i in 0..marker_len as usize {
          180             painter.line_segment([origin + Vec2::new(i as f32, 0.), origin + Vec2::new(0., i as f32)], stroke);
          181         }
          182         let stroke = Stroke::new(1., Color32::GRAY);
          183         painter.line_segment([origin, origin + Vec2::new(marker_len, 0.)], stroke);
          184         painter.line_segment([origin, origin + Vec2::new(0., marker_len)], stroke);
          185         painter.line_segment([origin + Vec2::new(marker_len, 0.), origin + Vec2::new(0., marker_len)], stroke);
          186 
          187         // paint bg marker
          188         let stroke = Stroke::new(1., Color32::WHITE);
          189         let origin = Pos2::new(
          190             stroke_rect.left() + (1 + caret_attr.get_background() % items_per_row as u32) as f32 * height,
          191             stroke_rect.top() + (1 + caret_attr.get_background() / items_per_row as u32) as f32 * height,
          192         );
          193         painter.line_segment([origin, origin - Vec2::new(marker_len, 0.)], stroke);
          194         painter.line_segment([origin, origin - Vec2::new(0., marker_len)], stroke);
          195         for i in 0..marker_len as usize {
          196             painter.line_segment([origin - Vec2::new(i as f32, 0.), origin - Vec2::new(0., i as f32)], stroke);
          197         }
          198         let stroke = Stroke::new(1., Color32::GRAY);
          199         painter.line_segment([origin, origin - Vec2::new(marker_len, 0.)], stroke);
          200         painter.line_segment([origin, origin - Vec2::new(0., marker_len)], stroke);
          201         painter.line_segment([origin - Vec2::new(marker_len, 0.), origin - Vec2::new(0., marker_len)], stroke);
          202 
          203         if let Some(hp) = response.hover_pos() {
          204             let pos = (hp.to_vec2() - stroke_rect.left_top().to_vec2()) / Vec2::new(height, height);
          205             let color = min(palette.len() as u32 - 1, pos.x as u32 + pos.y as u32 * items_per_row as u32);
          206 
          207             if response.hovered() {
          208                 response = response.on_hover_ui(|ui| {
          209                     let col = palette.get_color(color);
          210                     let (r, g, b) = col.get_rgb();
          211                     if let Some(title) = &col.name {
          212                         ui.label(title);
          213                     }
          214                     ui.label(format!("#{:02X}{:02X}{:02X}", r, g, b));
          215                 });
          216             }
          217 
          218             if response.clicked() {
          219                 if color < 8 || font_mode.has_high_fg_colors() || palette.len() > 16 {
          220                     result = Some(Message::SetForeground(color));
          221                 }
          222                 response.mark_changed();
          223             }
          224             if response.secondary_clicked() {
          225                 if color < 8 || ice_mode.has_high_bg_colors() || palette.len() > 16 {
          226                     result = Some(Message::SetBackground(color));
          227                 }
          228                 response.mark_changed();
          229             }
          230         }
          231     });
          232     result
          233 }