URI: 
       Added tools. - 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
       ---
   DIR commit 26831819b399f8f8ec0e567e3f039debf870cab2
   DIR parent 2b3a2bd1ee9004994db51c3f3396738a03ccfe6e
  HTML Author: Mike Krueger <mkrueger@posteo.de>
       Date:   Sat, 10 Dec 2022 00:24:03 +0100
       
       Added tools.
       
       Switched to egui 0.2.0.
       
       Diffstat:
         M Cargo.toml                          |       6 +++---
         A data/icons/add.svg                  |       2 ++
         A data/icons/brush.svg                |       2 ++
         A data/icons/cursor.svg               |       2 ++
         A data/icons/delete.svg               |       2 ++
         A data/icons/down.svg                 |       2 ++
         A data/icons/dropper.svg              |       2 ++
         A data/icons/ellipse_filled.svg       |       2 ++
         A data/icons/ellipse_outline.svg      |       2 ++
         A data/icons/eraser.svg               |       2 ++
         A data/icons/fill.svg                 |       2 ++
         A data/icons/font.svg                 |       2 ++
         A data/icons/line.svg                 |       2 ++
         A data/icons/measure.svg              |       2 ++
         A data/icons/move.svg                 |       2 ++
         A data/icons/rectangle_filled.svg     |       2 ++
         A data/icons/rectangle_outline.svg    |       2 ++
         A data/icons/swap.svg                 |      40 +++++++++++++++++++++++++++++++
         A data/icons/up.svg                   |       2 ++
         M src/model/mod.rs                    |       7 +++++--
         A src/model/tool/brush_imp.rs         |     105 +++++++++++++++++++++++++++++++
         D src/model/tool/brush_tool.rs        |      25 -------------------------
         A src/model/tool/click_imp.rs         |      64 +++++++++++++++++++++++++++++++
         D src/model/tool/click_tool.rs        |      27 ---------------------------
         A src/model/tool/draw_ellipse_filled… |      81 ++++++++++++++++++++++++++++++
         A src/model/tool/draw_ellipse_imp.rs  |      87 +++++++++++++++++++++++++++++++
         A src/model/tool/draw_rectangle_fill… |      66 +++++++++++++++++++++++++++++++
         A src/model/tool/draw_rectangle_imp.… |      74 +++++++++++++++++++++++++++++++
         D src/model/tool/draw_shape_tool.rs   |      24 ------------------------
         A src/model/tool/erase_imp.rs         |      88 +++++++++++++++++++++++++++++++
         D src/model/tool/erase_tool.rs        |      16 ----------------
         A src/model/tool/fill_imp.rs          |      99 +++++++++++++++++++++++++++++++
         D src/model/tool/fill_tool.rs         |      15 ---------------
         A src/model/tool/flip_imp.rs          |      30 ++++++++++++++++++++++++++++++
         A src/model/tool/font_imp.rs          |     173 +++++++++++++++++++++++++++++++
         D src/model/tool/font_tool.rs         |     123 -------------------------------
         A src/model/tool/icons.rs             |      22 ++++++++++++++++++++++
         A src/model/tool/line_imp.rs          |     455 +++++++++++++++++++++++++++++++
         M src/model/tool/mod.rs               |     509 +++++++++++++++++++++++--------
         A src/model/tool/move_layer_imp.rs    |      33 +++++++++++++++++++++++++++++++
         D src/model/tool/paint_tool.rs        |      13 -------------
         A src/model/tool/pipette_imp.rs       |      20 ++++++++++++++++++++
         A src/model/tool/scan_lines.rs        |     346 +++++++++++++++++++++++++++++++
         D src/model/tool/select_tool.rs       |      75 -------------------------------
         M src/ui/main_window.rs               |      73 ++++++++++++++++++++++++++++++-
         M src/ui/mod.rs                       |       3 +++
         A src/ui/tool_switcher.rs             |      14 ++++++++++++++
       
       47 files changed, 2292 insertions(+), 455 deletions(-)
       ---
   DIR diff --git a/Cargo.toml b/Cargo.toml
       @@ -7,9 +7,9 @@ description = "An ansi drawing tool"
        # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
        
        [dependencies]
       -eframe = "0.19.0"
       -egui_extras = "0.19.0"
       -egui_glow = "0.19.0"
       +eframe = "0.20.0"
       +egui_extras = { version="0.20.0", features = ["svg"] }
       +egui_glow = "0.20.0"
        glow = "0.11.2"
        egui_dock = { git="https://github.com/Adanos020/egui_dock.git" }
        
   DIR diff --git a/data/icons/add.svg b/data/icons/add.svg
       @@ -0,0 +1 @@
       +<svg width="24" height="24" fill="#a8a8a8" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M11.883 3.007 12 3a1 1 0 0 1 .993.883L13 4v7h7a1 1 0 0 1 .993.883L21 12a1 1 0 0 1-.883.993L20 13h-7v7a1 1 0 0 1-.883.993L12 21a1 1 0 0 1-.993-.883L11 20v-7H4a1 1 0 0 1-.993-.883L3 12a1 1 0 0 1 .883-.993L4 11h7V4a1 1 0 0 1 .883-.993L12 3l-.117.007Z" fill="#a8a8a8"/></svg>
       +\ No newline at end of file
   DIR diff --git a/data/icons/brush.svg b/data/icons/brush.svg
       @@ -0,0 +1 @@
       +<svg xmlns="http://www.w3.org/2000/svg" id="mdi-brush" viewBox="0 0 24 24" fill="#a8a8a8"><path d="M20.71,4.63L19.37,3.29C19,2.9 18.35,2.9 17.96,3.29L9,12.25L11.75,15L20.71,6.04C21.1,5.65 21.1,5 20.71,4.63M7,14A3,3 0 0,0 4,17C4,18.31 2.84,19 2,19C2.92,20.22 4.5,21 6,21A4,4 0 0,0 10,17A3,3 0 0,0 7,14Z" /></svg>
       +\ No newline at end of file
   DIR diff --git a/data/icons/cursor.svg b/data/icons/cursor.svg
       @@ -0,0 +1 @@
       +<svg xmlns="http://www.w3.org/2000/svg" id="mdi-cursor-default" viewBox="0 0 24 24" fill="#a8a8a8"><path d="M13.64,21.97C13.14,22.21 12.54,22 12.31,21.5L10.13,16.76L7.62,18.78C7.45,18.92 7.24,19 7,19A1,1 0 0,1 6,18V3A1,1 0 0,1 7,2C7.24,2 7.47,2.09 7.64,2.23L7.65,2.22L19.14,11.86C19.57,12.22 19.62,12.85 19.27,13.27C19.12,13.45 18.91,13.57 18.7,13.61L15.54,14.23L17.74,18.96C18,19.46 17.76,20.05 17.26,20.28L13.64,21.97Z" /></svg>
       +\ No newline at end of file
   DIR diff --git a/data/icons/delete.svg b/data/icons/delete.svg
       @@ -0,0 +1 @@
       +<svg width="24" height="24" fill="#a8a8a8" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M21.5 6a1 1 0 0 1-.883.993L20.5 7h-.845l-1.231 12.52A2.75 2.75 0 0 1 15.687 22H8.313a2.75 2.75 0 0 1-2.737-2.48L4.345 7H3.5a1 1 0 0 1 0-2h5a3.5 3.5 0 1 1 7 0h5a1 1 0 0 1 1 1Zm-7.25 3.25a.75.75 0 0 0-.743.648L13.5 10v7l.007.102a.75.75 0 0 0 1.486 0L15 17v-7l-.007-.102a.75.75 0 0 0-.743-.648Zm-4.5 0a.75.75 0 0 0-.743.648L9 10v7l.007.102a.75.75 0 0 0 1.486 0L10.5 17v-7l-.007-.102a.75.75 0 0 0-.743-.648ZM12 3.5A1.5 1.5 0 0 0 10.5 5h3A1.5 1.5 0 0 0 12 3.5Z" fill="#a8a8a8"/></svg>
       +\ No newline at end of file
   DIR diff --git a/data/icons/down.svg b/data/icons/down.svg
       @@ -0,0 +1 @@
       +<svg width="24" height="24" fill="#a8a8a8" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M6.102 8c-1.074 0-1.648 1.265-.94 2.073l5.521 6.31a1.75 1.75 0 0 0 2.634 0l5.522-6.31c.707-.808.133-2.073-.94-2.073H6.101Z" fill="#a8a8a8"/></svg>
       +\ No newline at end of file
   DIR diff --git a/data/icons/dropper.svg b/data/icons/dropper.svg
       @@ -0,0 +1 @@
       +<svg width="24" height="24" fill="#a8a8a8" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M21.03 2.97a3.578 3.578 0 0 0-5.06 0L14 4.94l-.013-.013a1.75 1.75 0 0 0-2.475 0l-.585.586a1.75 1.75 0 0 0 0 2.474l.012.013-6.78 6.78a2.25 2.25 0 0 0-.659 1.591v.688l-1.28 2.347c-.836 1.533.841 3.21 2.374 2.374l2.347-1.28h.688a2.25 2.25 0 0 0 1.59-.659L16 13.061l.012.012a1.75 1.75 0 0 0 2.475 0l.586-.585a1.75 1.75 0 0 0 0-2.475L19.061 10l1.97-1.97a3.578 3.578 0 0 0 0-5.06ZM12 9.06 14.94 12l-6.78 6.78a.75.75 0 0 1-.531.22H6.75a.75.75 0 0 0-.359.092l-2.515 1.372a.234.234 0 0 1-.159.032.264.264 0 0 1-.138-.075.264.264 0 0 1-.075-.138.234.234 0 0 1 .033-.159l1.372-2.515A.75.75 0 0 0 5 17.25v-.879a.75.75 0 0 1 .22-.53L12 9.061Z" fill="#a8a8a8"/></svg>
       +\ No newline at end of file
   DIR diff --git a/data/icons/ellipse_filled.svg b/data/icons/ellipse_filled.svg
       @@ -0,0 +1 @@
       +<svg xmlns="http://www.w3.org/2000/svg" id="mdi-ellipse" viewBox="0 0 24 24" fill="#a8a8a8"><path d="M12,4C6.5,4 2,7.58 2,12C2,16.42 6.5,20 12,20C17.5,20 22,16.42 22,12C22,7.58 17.5,4 12,4Z" /></svg>
       +\ No newline at end of file
   DIR diff --git a/data/icons/ellipse_outline.svg b/data/icons/ellipse_outline.svg
       @@ -0,0 +1 @@
       +<svg xmlns="http://www.w3.org/2000/svg" id="mdi-ellipse-outline" viewBox="0 0 24 24" fill="#a8a8a8"><path d="M12,6C16.41,6 20,8.69 20,12C20,15.31 16.41,18 12,18C7.59,18 4,15.31 4,12C4,8.69 7.59,6 12,6M12,4C6.5,4 2,7.58 2,12C2,16.42 6.5,20 12,20C17.5,20 22,16.42 22,12C22,7.58 17.5,4 12,4Z" /></svg>
       +\ No newline at end of file
   DIR diff --git a/data/icons/eraser.svg b/data/icons/eraser.svg
       @@ -0,0 +1 @@
       +<svg width="24" height="24" fill="#a8a8a8" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m15.87 2.669 4.968 4.968a2.25 2.25 0 0 1 0 3.182l-8.681 8.68 6.097.001a.75.75 0 0 1 .744.648l.006.102a.75.75 0 0 1-.648.743l-.102.007-8.41.001a2.244 2.244 0 0 1-1.714-.655l-4.968-4.969a2.25 2.25 0 0 1 0-3.182l9.526-9.526a2.25 2.25 0 0 1 3.182 0Zm-4.172 15.09-5.955-5.956-1.506 1.467a.75.75 0 0 0 0 1.06l4.945 4.946a.75.75 0 0 0 1.06-.016l1.456-1.502Z" fill="#a8a8a8"/></svg>
       +\ No newline at end of file
   DIR diff --git a/data/icons/fill.svg b/data/icons/fill.svg
       @@ -0,0 +1 @@
       +<svg width="24" height="24" fill="#a8a8a8" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 2.25a.75.75 0 0 0-1.5 0V3.5a2.24 2.24 0 0 0-.841.53L2.78 10.91a2.25 2.25 0 0 0 0 3.182L7.66 18.97a2.25 2.25 0 0 0 3.182 0l6.879-6.879a2.25 2.25 0 0 0 0-3.182L12.84 4.03A2.24 2.24 0 0 0 12 3.5V2.25Zm-1.5 3.06v1.44a.75.75 0 0 0 1.5 0V5.31l4.659 4.66a.75.75 0 0 1 0 1.06l-.97.97H3.812l.029-.03L10.5 5.31ZM19.521 13.602a.874.874 0 0 0-1.542 0l-2.008 3.766C14.85 19.466 16.372 22 18.75 22s3.898-2.534 2.78-4.632l-2.009-3.766Z" fill="#a8a8a8"/></svg>
       +\ No newline at end of file
   DIR diff --git a/data/icons/font.svg b/data/icons/font.svg
       @@ -0,0 +1 @@
       +<svg width="24" height="24" fill="#a8a8a8" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M7 2a1 1 0 0 1 .94.658l2.882 7.926-1.11 2.798L9.209 12H4.792l-.852 2.342a1 1 0 0 1-1.88-.684l4.001-11A1 1 0 0 1 7.001 2Zm-1.48 8h2.962L7 5.926 5.519 10ZM15.368 6.528a1 1 0 0 0-1.86 0L8.151 20.022h-.15a1 1 0 1 0 0 2h.809a.89.89 0 0 0 .04 0H11a1 1 0 0 0 0-2h-.697L11.106 18h6.653l.8 2.023H18a1 1 0 0 0 0 2h2.014a.98.98 0 0 0 .035 0h.96a1 1 0 0 0 0-2h-.298L15.368 6.528ZM16.967 16H11.9l2.537-6.39 2.53 6.39Z" fill="#a8a8a8"/></svg>
       +\ No newline at end of file
   DIR diff --git a/data/icons/line.svg b/data/icons/line.svg
       @@ -0,0 +1 @@
       +<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4.382 14H4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2h-6.454l-1.316 1.314a3.25 3.25 0 0 1-1.362.813l-4.293 1.288a2 2 0 0 1-2.479-2.528L4.382 14Z" fill="#a8a8a8"/><path d="M18.648 2.944a3.218 3.218 0 0 1-.002 4.551l-7.123 7.111a2.25 2.25 0 0 1-.942.563l-4.294 1.289a1 1 0 0 1-1.239-1.265l1.362-4.228c.11-.34.298-.65.552-.902l7.132-7.122a3.22 3.22 0 0 1 4.554.003Z" fill="#a8a8a8"/></svg>
       +\ No newline at end of file
   DIR diff --git a/data/icons/measure.svg b/data/icons/measure.svg
       @@ -0,0 +1 @@
       +<svg width="24" height="24" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20.008 6.5a2.5 2.5 0 0 0-2.5-2.5h-11a2.5 2.5 0 0 0-2.5 2.5v4a1 1 0 1 0 2 0v-4a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 .5.5v4a1 1 0 1 0 2 0v-4Zm-1.8 13.207 2.5-2.5a1 1 0 0 0 0-1.414l-2.5-2.5a1 1 0 0 0-1.415 1.414l1.793 1.793-1.793 1.793a1 1 0 0 0 1.414 1.414ZM3.292 15.793a1 1 0 0 0 0 1.414l2.5 2.5a1 1 0 0 0 1.414-1.414L5.414 16.5l1.793-1.793a1 1 0 1 0-1.414-1.414l-2.5 2.5ZM13 16.5a1 1 0 1 0-2 0 1 1 0 0 0 2 0Zm-4-1a1 1 0 1 1 0 2H8a1 1 0 1 1 0-2h1Zm8 1a1 1 0 0 0-1-1h-1a1 1 0 1 0 0 2h1a1 1 0 0 0 1-1Z" fill="#a8a8a8"/></svg>
       +\ No newline at end of file
   DIR diff --git a/data/icons/move.svg b/data/icons/move.svg
       @@ -0,0 +1 @@
       +<svg width="24" height="24" fill="#a8a8a8" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M15.457 6.457a1 1 0 0 1-1.414 0L13 5.414V8.25a1 1 0 1 1-2 0V5.414L9.957 6.457a1 1 0 0 1-1.414-1.414l2.75-2.75a1 1 0 0 1 1.414 0l2.75 2.75a1 1 0 0 1 0 1.414ZM6.457 14.043a1 1 0 1 1-1.414 1.414l-2.75-2.75a1 1 0 0 1 0-1.414l2.75-2.75a1 1 0 0 1 1.414 1.414L5.414 11H8.25a1 1 0 1 1 0 2H5.414l1.043 1.043ZM18.957 15.457a1 1 0 0 1-1.414-1.414L18.586 13H15.75a1 1 0 1 1 0-2h2.836l-1.043-1.043a1 1 0 0 1 1.414-1.414l2.75 2.75a1 1 0 0 1 0 1.414l-2.75 2.75ZM11 18.586V15.75a1 1 0 1 1 2 0v2.836l1.043-1.043a1 1 0 0 1 1.414 1.414l-2.75 2.75a1 1 0 0 1-1.414 0l-2.75-2.75a1 1 0 1 1 1.414-1.414L11 18.586Z" fill="#a8a8a8"/></svg>
       +\ No newline at end of file
   DIR diff --git a/data/icons/rectangle_filled.svg b/data/icons/rectangle_filled.svg
       @@ -0,0 +1 @@
       +<svg width="24" height="24" fill="#a8a8a8" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M5.25 4A3.25 3.25 0 0 0 2 7.25v9.5A3.25 3.25 0 0 0 5.25 20h13.5A3.25 3.25 0 0 0 22 16.75v-9.5A3.25 3.25 0 0 0 18.75 4H5.25Z" fill="#a8a8a8"/></svg>
       +\ No newline at end of file
   DIR diff --git a/data/icons/rectangle_outline.svg b/data/icons/rectangle_outline.svg
       @@ -0,0 +1 @@
       +<svg width="24" height="24" fill="#a8a8a8" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M2 7.25A3.25 3.25 0 0 1 5.25 4h13.5A3.25 3.25 0 0 1 22 7.25v9.5A3.25 3.25 0 0 1 18.75 20H5.25A3.25 3.25 0 0 1 2 16.75v-9.5ZM5.25 5.5A1.75 1.75 0 0 0 3.5 7.25v9.5c0 .966.784 1.75 1.75 1.75h13.5a1.75 1.75 0 0 0 1.75-1.75v-9.5a1.75 1.75 0 0 0-1.75-1.75H5.25Z" fill="#a8a8a8"/></svg>
       +\ No newline at end of file
   DIR diff --git a/data/icons/swap.svg b/data/icons/swap.svg
       @@ -0,0 +1,40 @@
       +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
       +<svg
       +   width="24"
       +   height="24"
       +   fill="#a8a8a8"
       +   viewBox="0 0 24 24"
       +   version="1.1"
       +   id="svg4"
       +   sodipodi:docname="swap.svg"
       +   inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
       +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
       +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
       +   xmlns="http://www.w3.org/2000/svg"
       +   xmlns:svg="http://www.w3.org/2000/svg">
       +  <defs
       +     id="defs8" />
       +  <sodipodi:namedview
       +     id="namedview6"
       +     pagecolor="#ffffff"
       +     bordercolor="#000000"
       +     borderopacity="0.25"
       +     inkscape:showpageshadow="2"
       +     inkscape:pageopacity="0.0"
       +     inkscape:pagecheckerboard="0"
       +     inkscape:deskcolor="#d1d1d1"
       +     showgrid="false"
       +     inkscape:zoom="42.791667"
       +     inkscape:cx="11.988315"
       +     inkscape:cy="11.988315"
       +     inkscape:window-width="5120"
       +     inkscape:window-height="1299"
       +     inkscape:window-x="0"
       +     inkscape:window-y="32"
       +     inkscape:window-maximized="1"
       +     inkscape:current-layer="svg4" />
       +  <path
       +     d="m 7.2925838,3.292 a 1,1 0 1 1 1.414,1.414 L 6.4125838,7 h 7.0870002 a 4.5,4.5 0 0 1 4.5,4.5 v 7.086 l 2.293,-2.293 a 1.0002026,1.0002026 0 1 1 1.414,1.415 l -4,4 a 1,1 0 0 1 -1.415,0 l -4,-4 a 1.0005561,1.0005561 0 0 1 1.415,-1.415 l 2.293,2.293 V 11.5 a 2.5,2.5 0 0 0 -2.5,-2.5 H 6.4135838 l 2.293,2.293 a 1,1 0 1 1 -1.414,1.414 l -4,-4 a 1,1 0 0 1 0,-1.414 z"
       +     fill="#a8a8a8"
       +     id="path2" />
       +</svg>
   DIR diff --git a/data/icons/up.svg b/data/icons/up.svg
       @@ -0,0 +1 @@
       +<svg width="24" height="24" fill="#a8a8a8" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M6.102 16.981c-1.074 0-1.648-1.265-.94-2.073l5.521-6.31a1.75 1.75 0 0 1 2.634 0l5.522 6.31c.707.809.133 2.073-.94 2.073H6.101Z" fill="#a8a8a8"/></svg>
       +\ No newline at end of file
   DIR diff --git a/src/model/mod.rs b/src/model/mod.rs
       @@ -2,4 +2,7 @@
        #![allow(clippy::cast_sign_loss, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::too_many_lines, clippy::cast_lossless, clippy::cast_precision_loss)]
        
        mod editor;
       -pub use editor::*;
       -\ No newline at end of file
       +pub use editor::*;
       +
       +mod tool;
       +pub use tool::*;
       +\ No newline at end of file
   DIR diff --git a/src/model/tool/brush_imp.rs b/src/model/tool/brush_imp.rs
       @@ -0,0 +1,104 @@
       +use std::{cell::{RefCell}, rc::Rc};
       +use egui_extras::RetainedImage;
       +
       +use super::{ Tool, Editor, Position};
       +
       +pub enum BrushType {
       +    Shade,
       +    Solid,
       +    Color
       +}
       +
       +pub struct BrushTool {
       +    pub use_fore: bool,
       +    pub use_back: bool,
       +    pub size: i32,
       +    pub char_code: u16,
       +
       +    pub brush_type: BrushType
       +}
       +
       +impl BrushTool {
       +/* 
       +    fn paint_brush(&self, editor: &Rc<RefCell<Editor>>, pos: Position)
       +    {
       +        let mid = Position::from(-(self.size / 2), -(self.size / 2));
       +
       +        let center = pos + mid;
       +        let gradient = [176, 177, 178, 219];
       +        let mut editor = editor.borrow_mut();
       +        editor.begin_atomic_undo();
       +
       +        for y in 0..self.size {
       +            for x in 0..self.size {
       +                match self.brush_type {
       +                    BrushType::Shade => {    
       +                        let ch = editor.get_char_from_cur_layer(center + Position::from(x, y)).unwrap_or_default();
       +                       
       +                        let attribute= editor.caret.get_attribute();
       +
       +                        let mut char_code = gradient[0];
       +                        if ch.char_code == gradient[gradient.len() -1] {
       +                            char_code = gradient[gradient.len() -1];
       +                        } else {
       +                            for i in 0..gradient.len() - 1 {
       +                                if ch.char_code == gradient[i] {
       +                                    char_code = gradient[i + 1];
       +                                    break;
       +                                }
       +                            }
       +                        }
       +                        editor.set_char(center + Position::from(x, y), Some(crate::model::DosChar { 
       +                            char_code, 
       +                            attribute
       +                        }));
       +
       +                    },
       +                    BrushType::Solid => {
       +                        let attribute= editor.caret.get_attribute();
       +                        editor.set_char(center + Position::from(x, y), Some(crate::model::DosChar { char_code: self.char_code, attribute }));
       +                    },
       +                    BrushType::Color => {
       +                        let ch = editor.get_char_from_cur_layer(center + Position::from(x, y)).unwrap_or_default();
       +                        let mut attribute = ch.attribute;
       +
       +                        if self.use_fore {
       +                            attribute.set_foreground(editor.caret.get_attribute().get_foreground());
       +                        }
       +                        if self.use_back {
       +                            attribute.set_background(editor.caret.get_attribute().get_background());
       +                        }
       +
       +                        editor.set_char(center + Position::from(x, y), Some(crate::model::DosChar { 
       +                            char_code:ch.char_code, 
       +                            attribute
       +                        }));
       +                    },
       +                }
       +            }                
       +        }
       +        editor.end_atomic_undo();
       +
       +    }
       +    
       +*/
       +}
       +
       +impl Tool for BrushTool
       +{
       +    fn get_icon_name(&self) -> &'static RetainedImage { &super::icons::BRUSH_SVG }
       +    fn use_caret(&self) -> bool { false }
       +/* 
       +    fn handle_click(&mut self, editor: Rc<RefCell<Editor>>, button: u32, pos: Position) -> super::Event {
       +        if button == 1 {
       +            self.paint_brush(&editor, pos);
       +        }
       +        super::Event::None
       +    }
       +
       +    fn handle_drag(&self, editor: Rc<RefCell<Editor>>, _start: Position, cur: Position) -> super::Event
       +    {
       +        self.paint_brush(&editor, cur);
       +        super::Event::None
       +    }*/
       +}
       +\ No newline at end of file
   DIR diff --git a/src/model/tool/brush_tool.rs b/src/model/tool/brush_tool.rs
       @@ -1,24 +0,0 @@
       -use super::{Editor, Event, Position, Tool};
       -
       -pub struct BrushTool {}
       -
       -impl Tool for BrushTool
       -{
       -    fn get_icon_name(&self) -> &'static str { "edit-select" }
       -/* 
       -    fn add_tool_page(&self, window: &ApplicationWindow,parent: &mut gtk4::Box)
       -    {
       -        parent.append(&gtk4::Label::builder().label("BrushTool").build());
       -    }
       -    
       -    fn handle_click(&self, editor: &mut Editor, _button: u32, x: i32, y: i32) -> Event
       -    {
       -        editor.cursor.pos = Position::from(x, y);
       -        Event::None
       -    }
       -
       -    fn handle_drag(&self, _editor: &mut Editor, _start: Position, _cur: Position) -> Event
       -    {
       -        Event::None
       -    }*/
       -}
       -\ No newline at end of file
   DIR diff --git a/src/model/tool/click_imp.rs b/src/model/tool/click_imp.rs
       @@ -0,0 +1,64 @@
       +
       +use std::{rc::Rc, cell::RefCell};
       +
       +use egui_extras::RetainedImage;
       +
       +use crate::model::Selection;
       +
       +use super::{Editor, Event, Position, Tool};
       +
       +pub struct ClickTool {}
       +
       +impl Tool for ClickTool
       +{
       +    fn get_icon_name(&self) -> &'static RetainedImage { &super::icons::CURSOR_SVG }
       +/* 
       +    fn handle_click(&mut self, editor: Rc<RefCell<Editor>>, button: u32, pos: Position) -> Event {
       +        if button == 1 {
       +            editor.borrow_mut().set_caret_position(pos);
       +            editor.borrow_mut().cur_selection = None;
       +        }
       +        Event::None
       +    }
       +
       +    fn handle_drag(&self, editor: Rc<RefCell<Editor>>, start: Position, cur: Position) -> Event
       +    {
       +        let mut editor = editor.borrow_mut();
       +        let mut cur = cur;
       +        if start < cur {
       +            cur = cur + Position::from(1, 1);
       +        }
       +        if start == cur { 
       +            editor.cur_selection = None;
       +        } else {
       +            editor.cur_selection = Some(Selection { 
       +                rectangle: crate::model::Rectangle::from_pt(start, cur),
       +                is_preview: true,
       +                shape: crate::model::Shape::Rectangle
       +            });
       +        }
       +        editor.set_caret_position(cur);
       +        Event::None
       +    }
       +
       +    fn handle_drag_end(&self, editor: Rc<RefCell<Editor>>, start: Position, cur: Position) -> Event {
       +        let mut editor = editor.borrow_mut();
       +        let mut cur = cur;
       +        if start < cur {
       +            cur = cur + Position::from(1, 1);
       +        }
       +
       +        if start == cur { 
       +            editor.cur_selection = None;
       +        } else {
       +            editor.cur_selection = Some(Selection { 
       +                rectangle: crate::model::Rectangle::from_pt(start, cur),
       +                is_preview: false,
       +                shape: crate::model::Shape::Rectangle
       +            });
       +        }
       +        editor.set_caret_position(cur);
       +
       +        Event::None
       +    } */
       +}
   DIR diff --git a/src/model/tool/click_tool.rs b/src/model/tool/click_tool.rs
       @@ -1,27 +0,0 @@
       -
       -use std::{rc::Rc, cell::RefCell};
       -
       -use super::{Editor, Event, Position, Tool};
       -
       -
       -pub struct ClickTool {}
       -
       -impl Tool for ClickTool
       -{
       -    fn get_icon_name(&self) -> &'static str { "edit-select" }
       -/* 
       -    fn add_tool_page(&self, window: &ApplicationWindow,parent: &mut gtk4::Box)
       -    {
       -        parent.append(&gtk4::Label::builder().label("Click").build());
       -    }
       -*/
       -
       -
       -    fn handle_click(&self, editor: Rc<RefCell<Editor>>, button: u32, pos: Position) -> Event {
       -
       -        if button == 1 {
       -            editor.borrow_mut().cursor.pos = pos;
       -        }
       -        Event::None
       -    }
       -}
   DIR diff --git a/src/model/tool/draw_ellipse_filled_imp.rs b/src/model/tool/draw_ellipse_filled_imp.rs
       @@ -0,0 +1,81 @@
       +use icy_engine::TextAttribute;
       +
       +use super::{plot_point, DrawMode, Editor, Event, Plottable, Position, Tool, ScanLines };
       +use std::{
       +    cell::RefCell,
       +    rc::Rc,
       +};
       +
       +pub struct DrawEllipseFilledTool {
       +    pub draw_mode: DrawMode,
       +
       +    pub use_fore: bool,
       +    pub use_back: bool,
       +    pub attr: TextAttribute,
       +    pub char_code: u16,
       +}
       +
       +impl Plottable for DrawEllipseFilledTool {
       +    fn get_draw_mode(&self) -> DrawMode {
       +        self.draw_mode
       +    }
       +    fn get_use_fore(&self) -> bool {
       +        self.use_fore
       +    }
       +    fn get_use_back(&self) -> bool {
       +        self.use_back
       +    }
       +    fn get_char_code(&self) -> u16 {
       +        self.char_code
       +    }
       +}
       +
       +impl Tool for DrawEllipseFilledTool {
       +    fn get_icon_name(&self) -> &'static egui_extras::RetainedImage { &super::icons::ELLIPSE_FILLED_SVG }
       +
       +    fn use_caret(&self) -> bool {
       +        false
       +    }
       +    fn use_selection(&self) -> bool {
       +        false
       +    }
       +/*
       +    fn handle_drag(&self, editor: Rc<RefCell<Editor>>, start: Position, cur: Position) -> Event {
       +        if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +            layer.clear();
       +        }
       +
       +        let mut lines = ScanLines::new(1);
       +
       +        if start < cur {
       +            lines.add_ellipse(Rectangle::from_pt( start, cur));
       +        } else {
       +            lines.add_ellipse(Rectangle::from_pt(cur, start));
       +        }
       +
       +        let draw = move |rect: Rectangle| {
       +            for y in 0..rect.size.height {
       +                for x in 0..rect.size.width {
       +                    plot_point(&editor, self, Position::from(rect.start.x + x, rect.start.y + y));
       +                }
       +            }
       +        };
       +        lines.fill(draw);
       +        Event::None
       +    }
       +
       +    fn handle_drag_end(
       +        &self,
       +        editor: Rc<RefCell<Editor>>,
       +        start: Position,
       +        cur: Position,
       +    ) -> Event {
       +        let mut editor = editor.borrow_mut();
       +        if start == cur {
       +            editor.buf.remove_overlay();
       +        } else {
       +            editor.join_overlay();
       +        }
       +        Event::None
       +    } */
       +}
   DIR diff --git a/src/model/tool/draw_ellipse_imp.rs b/src/model/tool/draw_ellipse_imp.rs
       @@ -0,0 +1,87 @@
       +use icy_engine::TextAttribute;
       +
       +use super::{ DrawMode, Editor, Event, Plottable, Position, Tool, ScanLines};
       +use std::{
       +    cell::RefCell,
       +    rc::Rc,
       +};
       +
       +pub struct DrawEllipseTool {
       +    pub draw_mode: DrawMode,
       +
       +    pub use_fore: bool,
       +    pub use_back: bool,
       +    pub attr: TextAttribute,
       +    pub char_code: u16,
       +}
       +
       +impl Plottable for DrawEllipseTool {
       +    fn get_draw_mode(&self) -> DrawMode {
       +        self.draw_mode
       +    }
       +    fn get_use_fore(&self) -> bool {
       +        self.use_fore
       +    }
       +    fn get_use_back(&self) -> bool {
       +        self.use_back
       +    }
       +    fn get_char_code(&self) -> u16 {
       +        self.char_code
       +    }
       +}
       +
       +impl Tool for DrawEllipseTool {
       +    fn get_icon_name(&self) -> &'static egui_extras::RetainedImage { &super::icons::ELLIPSE_OUTLINE_SVG }
       +
       +    fn use_caret(&self) -> bool {
       +        false
       +    }
       +    fn use_selection(&self) -> bool {
       +        false
       +    }
       +/*
       +    fn handle_drag(&self, editor: Rc<RefCell<Editor>>, mut start: Position, mut cur: Position) -> Event {
       +        if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +            layer.clear();
       +        }
       +
       +        let mut lines = ScanLines::new(1);
       +
       +        if self.draw_mode == DrawMode::Line {
       +            start.y *= 2;
       +            cur.y *= 2;
       +        }
       +
       +        if start < cur {
       +            lines.add_ellipse(Rectangle::from_pt( start, cur));
       +        } else {
       +            lines.add_ellipse(Rectangle::from_pt(cur, start));
       +        }
       +
       +        let col = editor.borrow().caret.get_attribute().get_foreground();
       +        let draw = move |rect: Rectangle| {
       +            for y in 0..rect.size.height {
       +                for x in 0..rect.size.width {
       +                    set_half_block(&editor, Position::from(rect.start.x + x, rect.start.y + y ), col);
       +                }
       +            }
       +        };
       +        lines.outline(draw);
       +        Event::None
       +    }
       +
       +    fn handle_drag_end(
       +        &self,
       +        editor: Rc<RefCell<Editor>>,
       +        start: Position,
       +        cur: Position,
       +    ) -> Event {
       +        let mut editor = editor.borrow_mut();
       +        if start == cur {
       +            editor.buf.remove_overlay();
       +        } else {
       +            editor.join_overlay();
       +        }
       +        Event::None
       +    }*/
       +}
   DIR diff --git a/src/model/tool/draw_rectangle_filled_imp.rs b/src/model/tool/draw_rectangle_filled_imp.rs
       @@ -0,0 +1,66 @@
       +use icy_engine::TextAttribute;
       +
       +use super::{Editor, Event, Position, Tool, DrawMode, Plottable, plot_point, ScanLines};
       +use std::{
       +    cell::{RefCell},
       +    rc::Rc,
       +};
       +
       +pub struct DrawRectangleFilledTool {
       +    pub draw_mode: DrawMode,
       +
       +    pub use_fore: bool,
       +    pub use_back: bool,
       +    pub attr: TextAttribute,
       +    pub char_code: u16
       +}
       +
       +impl Plottable for DrawRectangleFilledTool {
       +    fn get_draw_mode(&self) -> DrawMode { self.draw_mode }
       +
       +    fn get_use_fore(&self) -> bool { self.use_fore }
       +    fn get_use_back(&self) -> bool { self.use_back }
       +    fn get_char_code(&self) -> u16 { self.char_code }
       +}
       +
       +impl Tool for DrawRectangleFilledTool {
       +    fn get_icon_name(&self) -> &'static egui_extras::RetainedImage { &super::icons::RECTANGLE_FILLED_SVG }
       +
       +    fn use_caret(&self) -> bool { false }
       +    fn use_selection(&self) -> bool { false }
       +/* 
       +    fn handle_drag(&self, editor: Rc<RefCell<Editor>>,  start: Position, cur: Position) -> Event {
       +        if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +            layer.clear();
       +        }
       +
       +        let mut lines = ScanLines::new(1);
       +        lines.add_rectangle(Rectangle::from_pt(start, cur));
       +
       +        let draw = move |rect: Rectangle| {
       +            for y in 0..rect.size.height {
       +                for x in 0..rect.size.width {
       +                    plot_point(&editor, self, Position::from(rect.start.x + x, rect.start.y + y));
       +                }
       +            }
       +        };
       +        lines.fill(draw);
       +
       +        Event::None
       +    }
       +
       +    fn handle_drag_end(
       +        &self,
       +        editor: Rc<RefCell<Editor>>,
       +        start: Position,
       +        cur: Position,
       +    ) -> Event {
       +        let mut editor = editor.borrow_mut();
       +        if start == cur {
       +            editor.buf.remove_overlay();
       +        } else {
       +            editor.join_overlay();
       +        }
       +        Event::None
       +    }*/
       +}
   DIR diff --git a/src/model/tool/draw_rectangle_imp.rs b/src/model/tool/draw_rectangle_imp.rs
       @@ -0,0 +1,74 @@
       +
       +use icy_engine::TextAttribute;
       +
       +use super::{Editor, Event, Position, Tool, DrawMode, Plottable, ScanLines};
       +use std::{
       +    cell::{RefCell},
       +    rc::Rc,
       +};
       +
       +pub struct DrawRectangleTool {
       +    pub draw_mode: DrawMode,
       +
       +    pub use_fore: bool,
       +    pub use_back: bool,
       +    pub attr: TextAttribute,
       +    pub char_code: u16
       +}
       +
       +impl Plottable for DrawRectangleTool {
       +    fn get_draw_mode(&self) -> DrawMode { self.draw_mode }
       +
       +    fn get_use_fore(&self) -> bool { self.use_fore }
       +    fn get_use_back(&self) -> bool { self.use_back }
       +    fn get_char_code(&self) -> u16 { self.char_code }
       +}
       +
       +impl Tool for DrawRectangleTool {
       +    fn get_icon_name(&self) -> &'static egui_extras::RetainedImage { &super::icons::RECTANGLE_OUTLINE_SVG }
       +    fn use_caret(&self) -> bool { false }
       +    fn use_selection(&self) -> bool { false }
       +/* 
       +    fn handle_drag(&self, editor: Rc<RefCell<Editor>>,  mut start: Position, mut cur: Position) -> Event {
       +        if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +            layer.clear();
       +        }
       +
       +        if self.draw_mode == DrawMode::Line {
       +            start.y *= 2;
       +            cur.y *= 2;
       +        }
       +
       +        let mut lines = ScanLines::new(1);
       +        lines.add_rectangle(Rectangle::from_pt(start, cur));
       +
       +        let col = editor.borrow().caret.get_attribute().get_foreground();
       +        let draw = move |rect: Rectangle| {
       +            for y in 0..rect.size.height {
       +                for x in 0..rect.size.width {
       +                    set_half_block(&editor, Position::from(rect.start.x + x, rect.start.y + y ), col);
       +                }
       +            }
       +        };
       +        lines.outline(draw);
       +
       +        Event::None
       +    }
       +
       +    fn handle_drag_end(
       +        &self,
       +        editor: Rc<RefCell<Editor>>,
       +        start: Position,
       +        cur: Position,
       +    ) -> Event {
       +        let mut editor = editor.borrow_mut();
       +        if start == cur {
       +            editor.buf.remove_overlay();
       +        } else {
       +            editor.join_overlay();
       +        }
       +        Event::None
       +    }
       +
       +    */
       +}
   DIR diff --git a/src/model/tool/draw_shape_tool.rs b/src/model/tool/draw_shape_tool.rs
       @@ -1,23 +0,0 @@
       -
       -use super::{Editor, Event, Position, Tool};
       -
       -
       -pub struct DrawShapeTool {}
       -
       -impl Tool for DrawShapeTool
       -{
       -    fn get_icon_name(&self) -> &'static str { "edit-select" }
       -
       -    /* 
       -    fn add_tool_page(&self, window: &ApplicationWindow,parent: &mut gtk4::Box)
       -    {
       -        parent.append(&gtk4::Label::builder().label("DrawShapeTool").build());
       -    }
       -
       -    fn handle_click(&self, editor: &mut Editor, _button: u32, x: i32, y: i32) -> Event
       -    {
       -        editor.cursor.pos = Position::from(x, y);
       -        Event::None
       -    }*/
       -
       -}
       -\ No newline at end of file
   DIR diff --git a/src/model/tool/erase_imp.rs b/src/model/tool/erase_imp.rs
       @@ -0,0 +1,88 @@
       +use std::{cell::{RefCell}, rc::Rc};
       +
       +use super::{ Tool, Editor, Position};
       +
       +pub enum EraseType {
       +    Shade,
       +    Solid
       +}
       +
       +pub struct EraseTool {
       +    pub size: i32,
       +    pub brush_type: EraseType
       +
       +}
       +impl EraseTool {
       +/* 
       +    fn paint_brush(&self, editor: &Rc<RefCell<Editor>>, pos: Position)
       +    {
       +        let mid = Position::from(-(self.size / 2), -(self.size / 2));
       +
       +        let center = pos + mid;
       +        let gradient = [ 219, 178, 177, 176, b' '];
       +        let mut editor = editor.borrow_mut();
       +        editor.begin_atomic_undo();
       +
       +        for y in 0..self.size {
       +            for x in 0..self.size {
       +                match self.brush_type {
       +                    EraseType::Shade => {    
       +                        let ch = editor.get_char_from_cur_layer(center + Position::from(x, y)).unwrap_or_default();
       +                       
       +                        let mut attribute= ch.attribute;
       +
       +                        let mut char_code = gradient[0];
       +                        let mut found = false;
       +                        if ch.char_code as u8 == gradient[gradient.len() -1] {
       +                            char_code = gradient[gradient.len() -1];
       +                            attribute = TextAttribute::DEFAULT;
       +                            found = true;
       +                        } else {
       +                            for i in 0..gradient.len() - 1 {
       +                                if ch.char_code as u8 == gradient[i] {
       +                                    char_code = gradient[i + 1];
       +                                    found = true;
       +                                    break;
       +                                }
       +                            }
       +                        }
       +
       +                        if found {
       +                            editor.set_char(center + Position::from(x, y), Some(crate::model::DosChar { 
       +                                char_code: char_code as u16, 
       +                                attribute
       +                            }));
       +                        }
       +                    },
       +                    EraseType::Solid => {
       +                        editor.set_char(center + Position::from(x, y), Some(crate::model::DosChar { char_code: b' ' as u16, attribute: TextAttribute::DEFAULT }));
       +                    }
       +                }
       +            }                
       +        }
       +        editor.end_atomic_undo();
       +
       +    }
       +    
       +*/
       +}
       +
       +impl Tool for EraseTool
       +{
       +    fn get_icon_name(&self) -> &'static egui_extras::RetainedImage { &super::icons::ERASER_SVG }
       +   
       +    fn use_caret(&self) -> bool { false }
       +/*
       +    fn handle_click(&mut self, editor: Rc<RefCell<Editor>>, button: u32, pos: Position) -> super::Event {
       +        if button == 1 {
       +            self.paint_brush(&editor, pos);
       +        }
       +        super::Event::None
       +    }
       +
       +    fn handle_drag(&self, editor: Rc<RefCell<Editor>>, _start: Position, cur: Position) -> super::Event
       +    {
       +        self.paint_brush(&editor, cur);
       +        super::Event::None
       +    }*/
       +}
   DIR diff --git a/src/model/tool/erase_tool.rs b/src/model/tool/erase_tool.rs
       @@ -1,16 +0,0 @@
       -
       -use super::{ Tool};
       -
       -
       -pub struct EraseTool {}
       -
       -impl Tool for EraseTool
       -{
       -    fn get_icon_name(&self) -> &'static str { "edit-select" }
       -
       -    /* 
       -    fn add_tool_page(&self, window: &ApplicationWindow,parent: &mut gtk4::Box)
       -    {
       -        parent.append(&gtk4::Label::builder().label("EraseTool").build());
       -    }*/
       -}
   DIR diff --git a/src/model/tool/fill_imp.rs b/src/model/tool/fill_imp.rs
       @@ -0,0 +1,98 @@
       +use std::{cell::{RefCell, RefMut}, rc::Rc, collections::{HashSet}};
       +
       +use icy_engine::TextAttribute;
       +
       +use super::{ Tool, Editor, Position, Event};
       +
       +pub struct FillTool {
       +    pub use_char : bool,
       +    pub use_fore : bool,
       +    pub use_back : bool,
       +
       +    pub attr: TextAttribute,
       +    pub char_code: u16
       +}
       +
       +// Fill with 
       +// Attribute, Fore/Back
       +// Character 
       +// Both
       +
       +impl Tool for FillTool
       +{
       +    fn get_icon_name(&self) -> &'static egui_extras::RetainedImage { &super::icons::FILL_SVG }
       +    fn use_caret(&self) -> bool { false }
       +   /*
       +    fn handle_click(&mut self, editor: Rc<RefCell<Editor>>, button: u32, pos: Position) -> Event {
       +        if button == 1 {
       +            let mut editor = editor.borrow_mut();
       +            if editor.cur_layer >= editor.buf.layers.len() as i32 { return Event::None; }
       +            let attr = editor.caret.get_attribute();
       +            let ch = editor.buf.get_char(pos);
       +            if self.use_back || self.use_fore || self.use_char {
       +                editor.begin_atomic_undo();
       +                let mut visited = HashSet::new();
       +                fill(&mut editor, &mut visited, attr, pos, ch,  DosChar{ char_code: self.char_code, attribute: attr });
       +                editor.end_atomic_undo();
       +
       +            }
       +        }
       +        Event::None
       +    }*/
       +}
       +/*
       +fn fill(editor: &mut RefMut<Editor>, visited: &mut HashSet<Position>, attribute: TextAttribute, pos: Position, opt_old_ch: Option<DosChar>, new_ch: DosChar) {
       +    if !editor.point_is_valid(pos) || !visited.insert(pos) {
       +        return;
       +    }
       +
       +    let cur_char = editor.buf.get_char(pos).unwrap_or_default();
       +    unsafe {
       +        if let Some(old_ch) = opt_old_ch {
       +            if FILL_TOOL.use_char && FILL_TOOL.use_fore && FILL_TOOL.use_back {
       +                if cur_char != old_ch || cur_char == new_ch {
       +                    return;
       +                }
       +            } else if FILL_TOOL.use_fore && FILL_TOOL.use_back {
       +                if cur_char.attribute != old_ch.attribute || cur_char.attribute == new_ch.attribute {
       +                    return;
       +                }
       +            } else if FILL_TOOL.use_char && FILL_TOOL.use_fore  {
       +                if cur_char.char_code != old_ch.char_code && cur_char.attribute.get_foreground() != old_ch.attribute.get_foreground() || 
       +                cur_char.char_code == new_ch.char_code && cur_char.attribute.get_foreground() == new_ch.attribute.get_foreground() {
       +                    return;
       +                }
       +            } else if FILL_TOOL.use_char && FILL_TOOL.use_back  {
       +                if cur_char.char_code != old_ch.char_code && cur_char.attribute.get_background() != old_ch.attribute.get_background() || 
       +                cur_char.char_code == new_ch.char_code && cur_char.attribute.get_background() == new_ch.attribute.get_background() {
       +                    return;
       +                }
       +            } else if FILL_TOOL.use_char {
       +                if cur_char.char_code != old_ch.char_code || cur_char.char_code == new_ch.char_code {
       +                    return;
       +                }
       +            } else if FILL_TOOL.use_fore  {
       +                if cur_char.attribute.get_foreground() != old_ch.attribute.get_foreground() || cur_char.attribute.get_foreground() == new_ch.attribute.get_foreground() {
       +                    return;
       +                }
       +            } else if FILL_TOOL.use_back {
       +                if cur_char.attribute.get_background() != old_ch.attribute.get_background()  || cur_char.attribute.get_background() == new_ch.attribute.get_background() {
       +                    return;
       +                }
       +            } else {
       +                panic!("should never happen!");
       +            }
       +           
       +        }
       +        let mut repl_ch = cur_char;
       +        if FILL_TOOL.use_char { repl_ch.char_code = new_ch.char_code; }
       +        if FILL_TOOL.use_fore { repl_ch.attribute.set_foreground(new_ch.attribute.get_foreground()) }
       +        if FILL_TOOL.use_back { repl_ch.attribute.set_background(new_ch.attribute.get_background()) }
       +
       +        editor.set_char(pos, Some(repl_ch));
       +    }
       +    fill(editor, visited, attribute, pos + Position::from(-1, 0), opt_old_ch, new_ch);
       +    fill(editor, visited, attribute, pos + Position::from(1, 0), opt_old_ch, new_ch);
       +    fill(editor, visited, attribute, pos + Position::from(    0, -1), opt_old_ch, new_ch);
       +    fill(editor, visited, attribute, pos + Position::from(0, 1), opt_old_ch, new_ch);
       +} */
       +\ No newline at end of file
   DIR diff --git a/src/model/tool/fill_tool.rs b/src/model/tool/fill_tool.rs
       @@ -1,14 +0,0 @@
       -use super::Tool;
       -
       -pub struct FillTool {}
       -
       -impl Tool for FillTool
       -{
       -    fn get_icon_name(&self) -> &'static str { "edit-select" }
       -
       -    /* 
       -    fn add_tool_page(&self, window: &ApplicationWindow,parent: &mut gtk4::Box)
       -    {
       -        parent.append(&gtk4::Label::builder().label("FillTool").build());
       -    }*/
       -}
       -\ No newline at end of file
   DIR diff --git a/src/model/tool/flip_imp.rs b/src/model/tool/flip_imp.rs
       @@ -0,0 +1,29 @@
       +
       +use std::{rc::Rc, cell::RefCell};
       +
       +use super::{Tool, Editor, Position, Event};
       +pub struct FlipTool {}
       +
       +impl Tool for FlipTool
       +{
       +    fn get_icon_name(&self) -> &'static egui_extras::RetainedImage { &super::icons::FILL_SVG }
       +    fn use_caret(&self) -> bool { false }
       +    fn use_selection(&self) -> bool { false }
       +    /*
       +    fn handle_click(&mut self, editor: Rc<RefCell<Editor>>, button: u32, pos: Position) -> Event {
       +        if button == 1 {
       +            let mut ch = editor.borrow().get_char(pos).unwrap_or_default();
       +
       +            if ch.char_code == 222 {
       +                ch.char_code = 221;
       +            } else if ch.char_code == 221 {
       +                ch.char_code = 219;
       +            } else { 
       +                ch.char_code = 222;
       +            }
       +            
       +            editor.borrow_mut().set_char(pos, Some(ch));
       +        }
       +        Event::None
       +    }*/
       +} //   [176, 177, 178, 219, 223, 220, 221, 222, 254, 250 ],
       +\ No newline at end of file
   DIR diff --git a/src/model/tool/font_imp.rs b/src/model/tool/font_imp.rs
       @@ -0,0 +1,172 @@
       +use std::{rc::Rc, cell::RefCell};
       +
       +use super::{Tool, MKey, Event, Editor, MKeyCode, MModifiers, Position};
       +use icy_engine::{TheDrawFont, Size};
       +use walkdir::{DirEntry, WalkDir};
       +pub struct FontTool {
       +    pub selected_font: i32,
       +    pub fonts: Vec<TheDrawFont>,
       +    pub sizes: Vec<Size<i32>>
       +}
       +
       +impl FontTool 
       +{
       +    pub fn get_selected_font(&self) -> Option<&TheDrawFont> {
       +        self.fonts.get(self.selected_font as usize)
       +    }
       +
       +    fn is_hidden(entry: &DirEntry) -> bool {
       +        entry.file_name()
       +             .to_str()
       +             .map_or(false, |s| s.starts_with('.'))
       +    }
       +  /* 
       +    pub fn load_fonts(&mut self)
       +    {
       +        if let Some(path) = unsafe { &WORKSPACE.settings.font_path } {
       +            let walker = WalkDir::new(path).into_iter();
       +            for entry in walker.filter_entry(|e| !FontTool::is_hidden(e)) {
       +                if let Err(e) = entry {
       +                    eprintln!("Can't load tdf font library: {}", e);
       +                    break;
       +                }
       +                let entry = entry.unwrap();
       +                let path = entry.path();
       +
       +                if path.is_dir() {
       +                    continue;
       +                }
       +                let extension = path.extension();
       +                if extension.is_none() { continue; }
       +                let extension = extension.unwrap().to_str();
       +                if extension.is_none() { continue; }
       +                let extension = extension.unwrap().to_lowercase();
       +
       +                if extension == "tdf" {
       +                    if let Some(font) = TheDrawFont::load(path) {
       +                        self.fonts.push(font);
       +                    }
       +                }
       +            }
       +        }
       +    }
       +
       +*/
       +}
       +
       +impl Tool for FontTool
       +{
       +    fn get_icon_name(&self) -> &'static egui_extras::RetainedImage { &super::icons::FONT_SVG }
       +    fn use_selection(&self) -> bool { false }
       +/* 
       +    fn handle_click(&mut self, editor: Rc<RefCell<Editor>>, button: u32, pos: Position) -> Event {
       +        if button == 1 {
       +            editor.borrow_mut().set_caret_position(pos);
       +        }
       +        let mut editor = editor.borrow_mut();
       +        self.sizes.clear();
       +        editor.cur_selection = None;
       +        Event::None
       +    }
       +
       +    fn handle_key(&mut self, editor: Rc<RefCell<Editor>>, key: MKey, _key_code: MKeyCode, modifier: MModifiers) -> Event
       +    {
       +        if self.selected_font < 0 || self.selected_font >= self.fonts.len() as i32 {
       +            return Event::None;
       +        }
       +        let font = &self.fonts[self.selected_font as usize];
       +        let pos = editor.borrow().get_caret_position();
       +        let mut editor = editor.borrow_mut();
       +
       +        match key {
       +            MKey::Down => {
       +                editor.set_caret(pos.x, pos.y + 1);
       +            }
       +            MKey::Up => {
       +                editor.set_caret(pos.x, pos.y - 1);
       +            }
       +            MKey::Left => {
       +                editor.set_caret(pos.x - 1, pos.y);
       +            }
       +            MKey::Right => {
       +                editor.set_caret(pos.x + 1, pos.y);
       +            }
       +            
       +            MKey::Home  => {
       +                if let MModifiers::Control = modifier {
       +                    for i in 0..editor.buf.width {
       +                        if !editor.get_char_from_cur_layer(pos.with_x(i as i32)).unwrap_or_default().is_transparent() {
       +                            editor.set_caret(i as i32, pos.y);
       +                            return Event::None;
       +                        }
       +                    }
       +                }
       +                editor.set_caret(0, pos.y);
       +            }
       +
       +            MKey::End => {
       +                if let MModifiers::Control = modifier {
       +                    for i in (0..editor.buf.width).rev()  {
       +                        if !editor.get_char_from_cur_layer(pos.with_x(i as i32)).unwrap_or_default().is_transparent() {
       +                            editor.set_caret(i as i32, pos.y);
       +                            return Event::None;
       +                        }
       +                    }
       +                }
       +                let w = editor.buf.width as i32;
       +                editor.set_caret(w - 1, pos.y);
       +            }
       +
       +            MKey::Return => {
       +                editor.set_caret(0,pos.y + font.get_font_height() as i32);
       +/* 
       +                if let Some(size) = self.sizes.last() {
       +                    editor.set_caret(0,pos.y + size.height as i32);
       +                } else {
       +                    editor.set_caret(0,pos.y + 1);
       +                }*/
       +                self.sizes.clear();
       +            }
       +
       +            MKey::Backspace => {
       +                let letter_size= self.sizes.pop().unwrap_or_else(|| Size::from(1,1));
       +                editor.cur_selection = None;
       +                let pos = editor.get_caret_position();
       +                if pos.x > 0 {
       +                    editor.set_caret_position(pos + Position::from(-(letter_size.width as i32), 0));
       +                    if editor.caret.insert_mode {
       +                        for i in pos.x..(editor.buf.width as i32 - (letter_size.width as i32)) {
       +                            let next = editor.get_char_from_cur_layer( Position::from(i + (letter_size.width as i32), pos.y));
       +                            editor.set_char(Position::from(i, pos.y), next);
       +                        }
       +                        let last_pos = Position::from(editor.buf.width as i32 - (letter_size.width as i32), pos.y);
       +                        editor.fill(Rectangle{ start: last_pos, size: letter_size }, Some(super::DosChar { char_code: b' ' as u16, attribute: TextAttribute::DEFAULT }));
       +                    } else {
       +                        let pos = editor.get_caret_position();
       +                        editor.fill(Rectangle{ start: pos, size: letter_size }, Some(super::DosChar { char_code: b' ' as u16, attribute: TextAttribute::DEFAULT }));
       +                    } 
       +                }
       +            }
       +
       +            MKey::Character(ch) => { 
       +                let c_pos = editor.get_caret_position();
       +                editor.begin_atomic_undo();
       +                let attr = editor.caret.get_attribute();
       +                let opt_size = font.render(&mut editor, c_pos, attr, ch as u8);
       +                if let Some(size) = opt_size  {
       +                    editor.set_caret(c_pos.x + size.width as i32 + font.spaces, c_pos.y);
       +                    let new_pos = editor.get_caret_position();
       +                    self.sizes.push(Size { width: (new_pos.x - c_pos.x), height: size.height });
       +                } else {
       +                    editor.type_key(ch);
       +                    self.sizes.push(Size::from(1, 1));
       +                }
       +                editor.end_atomic_undo();
       +            }
       +            _ => {}
       +        }
       +        Event::None
       +    }
       +
       +*/
       +}
       +\ No newline at end of file
   DIR diff --git a/src/model/tool/font_tool.rs b/src/model/tool/font_tool.rs
       @@ -1,122 +0,0 @@
       -use crate::model::TheDrawFont;
       -
       -use super::{Tool, Editor, Event, Position};
       -use walkdir::{DirEntry, WalkDir};
       -pub struct FontTool {
       -    pub selected_font: i32,
       -    pub fonts: Vec<TheDrawFont>
       -}
       -
       -impl FontTool 
       -{
       -    fn is_hidden(entry: &DirEntry) -> bool {
       -        entry.file_name()
       -             .to_str()
       -             .map(|s| s.starts_with("."))
       -             .unwrap_or(false)
       -    }
       -        
       -    pub fn load_fonts(&mut self)
       -    {
       -        let walker = WalkDir::new("/home/mkrueger/Dokumente/THEDRAWFONTS").into_iter();
       -        for entry in walker.filter_entry(|e| !FontTool::is_hidden(e)) {
       -             let entry = entry.unwrap();
       -             let path = entry.path();
       -
       -             if path.is_dir() {
       -                continue;
       -             }
       -             let extension = path.extension();
       -             if extension.is_none() { continue; }
       -             let extension = extension.unwrap().to_str();
       -             if extension.is_none() { continue; }
       -             let extension = extension.unwrap().to_lowercase();
       -
       -             if extension == "tdf" {
       -                if let Some(font) = TheDrawFont::load(path) {
       -                    self.fonts.push(font);
       -                }
       -            }
       -        }
       -
       -        println!("{} fonts read.", self.fonts.len());
       -    }
       -}
       -
       -impl Tool for FontTool
       -{
       -    fn get_icon_name(&self) -> &'static str { "edit-select" }
       -/*
       -    fn add_tool_page(&self, window: &ApplicationWindow,parent: &mut gtk4::Box)
       -    {
       -        crate::ui::add_font_tool_page(window, parent);
       -    }
       -    
       -    fn handle_click(&self, editor: &mut Editor, _button: u32, x: i32, y: i32) -> Event
       -    {
       -        editor.cursor.pos = Position::from(x, y);
       -        Event::None
       -    }
       -
       -    fn handle_key(&self, editor: &mut Editor, key: Key, _key_code: u32, _modifier: ModifierType) -> Event
       -    {
       -        if self.selected_font < 0 || self.selected_font >= self.fonts.len() as i32 {
       -            return Event::None;
       -        }
       -        let font = &self.fonts[self.selected_font as usize];
       -
       -        match key {
       -            Key::Down => {
       -                editor.set_cursor(editor.cursor.pos.x, editor.cursor.pos.y + 1);
       -            }
       -            Key::Up => {
       -                editor.set_cursor(editor.cursor.pos.x, editor.cursor.pos.y - 1);
       -            }
       -            Key::Left => {
       -                editor.set_cursor(editor.cursor.pos.x - 1, editor.cursor.pos.y);
       -            }
       -            Key::Right => {
       -                editor.set_cursor(editor.cursor.pos.x + 1, editor.cursor.pos.y);
       -            }
       -            
       -            Key::Page_Down |
       -            Key::Page_Up => {
       -                // TODO
       -            }
       -            
       -            Key::Home | Key::KP_Home => {
       -                editor.set_cursor(0, editor.cursor.pos.y);
       -            }
       -            
       -            Key::End | Key::KP_End => {
       -                editor.set_cursor(editor.buf.width as i32 - 1, editor.cursor.pos.y);
       -            }
       -
       -            Key::Return | Key::KP_Enter => {
       -                editor.set_cursor(0,editor.cursor.pos.y + font.get_font_height() as i32);
       -            }
       -
       -            _ => { 
       -                if let Some(key) = key.to_unicode() {
       -                    if key.len_utf8() == 1 {
       -                        let mut dst = [0];
       -                        key.encode_utf8(&mut dst);
       -
       -                        let width = font.render(&mut editor.buf, editor.cursor.pos, editor.cursor.attr, dst[0]);
       -                        if width > 0 {
       -                            editor.set_cursor(editor.cursor.pos.x + width + font.spaces, editor.cursor.pos.y);
       -                        } else {
       -                            editor.buf.set_char(editor.cursor.pos, crate::model::DosChar {
       -                                char_code: dst[0],
       -                                attribute: editor.cursor.attr,
       -                            });
       -                            editor.set_cursor(editor.cursor.pos.x + 1, editor.cursor.pos.y);
       -                        }
       -                    }
       -                }
       -            }
       -        }
       -        Event::None
       -    }*/
       -
       -}
       -\ No newline at end of file
   DIR diff --git a/src/model/tool/icons.rs b/src/model/tool/icons.rs
       @@ -0,0 +1,22 @@
       +use egui_extras::RetainedImage;
       +
       +lazy_static::lazy_static! {
       +    pub static ref ADD_SVG: RetainedImage = egui_extras::RetainedImage::from_svg_bytes("add.svg", include_bytes!("../../../data/icons/add.svg")).unwrap();
       +    pub static ref BRUSH_SVG: RetainedImage = egui_extras::RetainedImage::from_svg_bytes("brush.svg", include_bytes!("../../../data/icons/brush.svg")).unwrap();
       +    pub static ref CURSOR_SVG: RetainedImage = egui_extras::RetainedImage::from_svg_bytes("cursor.svg", include_bytes!("../../../data/icons/cursor.svg")).unwrap();
       +    pub static ref DELETE_SVG: RetainedImage = egui_extras::RetainedImage::from_svg_bytes("delete.svg", include_bytes!("../../../data/icons/delete.svg")).unwrap();
       +    pub static ref DOWN_SVG: RetainedImage = egui_extras::RetainedImage::from_svg_bytes("down.svg", include_bytes!("../../../data/icons/down.svg")).unwrap();
       +    pub static ref DROPPER_SVG: RetainedImage = egui_extras::RetainedImage::from_svg_bytes("dropper.svg", include_bytes!("../../../data/icons/dropper.svg")).unwrap();
       +    pub static ref ELLIPSE_FILLED_SVG: RetainedImage = egui_extras::RetainedImage::from_svg_bytes("ellipse_filled.svg", include_bytes!("../../../data/icons/ellipse_filled.svg")).unwrap();
       +    pub static ref ELLIPSE_OUTLINE_SVG: RetainedImage = egui_extras::RetainedImage::from_svg_bytes("ellipse_outline.svg", include_bytes!("../../../data/icons/ellipse_outline.svg")).unwrap();
       +    pub static ref ERASER_SVG: RetainedImage = egui_extras::RetainedImage::from_svg_bytes("eraser.svg", include_bytes!("../../../data/icons/eraser.svg")).unwrap();
       +    pub static ref FILL_SVG: RetainedImage = egui_extras::RetainedImage::from_svg_bytes("fill.svg", include_bytes!("../../../data/icons/fill.svg")).unwrap();
       +    pub static ref LINE_SVG: RetainedImage = egui_extras::RetainedImage::from_svg_bytes("line.svg", include_bytes!("../../../data/icons/line.svg")).unwrap();
       +    pub static ref FONT_SVG: RetainedImage = egui_extras::RetainedImage::from_svg_bytes("font.svg", include_bytes!("../../../data/icons/font.svg")).unwrap();
       +    pub static ref MOVE_SVG: RetainedImage = egui_extras::RetainedImage::from_svg_bytes("move.svg", include_bytes!("../../../data/icons/move.svg")).unwrap();
       +    pub static ref RECTANGLE_FILLED_SVG: RetainedImage = egui_extras::RetainedImage::from_svg_bytes("rectangle_filled.svg", include_bytes!("../../../data/icons/rectangle_filled.svg")).unwrap();
       +    pub static ref RECTANGLE_OUTLINE_SVG: RetainedImage = egui_extras::RetainedImage::from_svg_bytes("rectangle_outline.svg", include_bytes!("../../../data/icons/rectangle_outline.svg")).unwrap();
       +    pub static ref SWAP_SVG: RetainedImage = egui_extras::RetainedImage::from_svg_bytes("swap.svg", include_bytes!("../../../data/icons/swap.svg")).unwrap();
       +    pub static ref UP_SVG: RetainedImage = egui_extras::RetainedImage::from_svg_bytes("up.svg", include_bytes!("../../../data/icons/up.svg")).unwrap();
       +}
       +
   DIR diff --git a/src/model/tool/line_imp.rs b/src/model/tool/line_imp.rs
       @@ -0,0 +1,454 @@
       +use icy_engine::TextAttribute;
       +
       +use super::{Editor, Event, MKey, MKeyCode, MModifiers, Position, Tool, DrawMode, Plottable, plot_point};
       +use std::{cell::RefCell, rc::Rc};
       +
       +pub struct LineTool {
       +    pub draw_mode: DrawMode,
       +
       +    pub use_fore: bool,
       +    pub use_back: bool,
       +    pub attr: TextAttribute,
       +    pub char_code: u16,
       +
       +    pub old_pos: Position
       +}
       +
       +impl Plottable for LineTool {
       +    fn get_draw_mode(&self) -> DrawMode { self.draw_mode }
       +
       +    fn get_use_fore(&self) -> bool { self.use_fore }
       +    fn get_use_back(&self) -> bool { self.use_back }
       +    fn get_char_code(&self) -> u16 { self.char_code }
       +}
       +
       +const CORNER_UPPER_LEFT:i32 = 0;
       +const CORNER_UPPER_RIGHT:i32 = 1;
       +const CORNER_LOWER_LEFT:i32 = 2;
       +const CORNER_LOWER_RIGHT:i32 = 3;
       +
       +const HORIZONTAL_CHAR:i32 = 4;
       +const VERTICAL_CHAR:i32 = 5;
       +
       +const VERT_RIGHT_CHAR:i32 = 6;
       +const VERT_LEFT_CHAR:i32 = 7;
       +
       +const HORIZ_UP_CHAR:i32 = 8;
       +const HORIZ_DOWN_CHAR:i32 = 9;
       +
       +impl LineTool {
       +/*
       +    pub fn get_new_horiz_char(editor: &std::cell::RefMut<Editor>, new_char: u16, to_left: bool) -> i32
       +    {
       +        if new_char == editor.get_outline_char_code(VERTICAL_CHAR).unwrap() {
       +            if to_left { 
       +                VERT_RIGHT_CHAR 
       +            } else { 
       +                VERT_LEFT_CHAR 
       +            }
       +        } else if new_char == editor.get_outline_char_code(CORNER_LOWER_RIGHT).unwrap() || new_char == editor.get_outline_char_code(CORNER_LOWER_LEFT).unwrap() { 
       +            HORIZ_UP_CHAR
       +        } else if new_char == editor.get_outline_char_code(CORNER_UPPER_RIGHT).unwrap() || new_char == editor.get_outline_char_code(CORNER_UPPER_LEFT).unwrap() { 
       +            HORIZ_DOWN_CHAR
       +        } else {
       +            HORIZONTAL_CHAR
       +        }
       +    }
       +
       +    pub fn get_old_horiz_char(&self, editor: &std::cell::RefMut<Editor>, old_char: u16, to_left: bool) -> Option<u16>
       +    {
       +        let pos = editor.get_caret_position();
       +        if old_char == editor.get_outline_char_code(VERTICAL_CHAR).unwrap() {
       +            match self.old_pos.y.cmp(&pos.y) {
       +                std::cmp::Ordering::Greater => Some(editor.get_outline_char_code(if to_left {CORNER_UPPER_RIGHT} else { CORNER_UPPER_LEFT}).unwrap()),
       +                std::cmp::Ordering::Less => Some(editor.get_outline_char_code(if to_left {CORNER_LOWER_RIGHT} else { CORNER_LOWER_LEFT}).unwrap()),
       +                std::cmp::Ordering::Equal => None
       +            }
       +        } else if old_char == editor.get_outline_char_code(VERT_LEFT_CHAR).unwrap() || old_char == editor.get_outline_char_code(VERT_RIGHT_CHAR).unwrap()  {
       +            let cur =editor.get_cur_outline();
       +            if cur < 4  {
       +                let ck = Editor::get_outline_char_code_from(4, cur);
       +                Some(ck.unwrap())
       +            } else { None}
       +        } else {
       +            None
       +        }
       +    }
       +
       +    pub fn get_new_vert_char(editor: &std::cell::RefMut<Editor>, new_char: u16, to_left: bool) -> i32
       +    {
       +        if new_char == editor.get_outline_char_code(HORIZONTAL_CHAR).unwrap() {
       +            if to_left { 
       +                HORIZ_DOWN_CHAR 
       +            } else { 
       +                HORIZ_UP_CHAR 
       +            }
       +        } else if new_char == editor.get_outline_char_code(CORNER_LOWER_RIGHT).unwrap() || new_char == editor.get_outline_char_code(CORNER_LOWER_LEFT).unwrap() { 
       +            HORIZ_UP_CHAR
       +        } else if new_char == editor.get_outline_char_code(CORNER_UPPER_RIGHT).unwrap() || new_char == editor.get_outline_char_code(CORNER_UPPER_LEFT).unwrap() { 
       +            VERT_RIGHT_CHAR
       +        } else {
       +            VERTICAL_CHAR
       +        }
       +    }
       +
       +    pub fn get_old_vert_char(&self, editor: &std::cell::RefMut<Editor>, old_char: u16, to_left: bool) -> Option<u16>
       +    {
       +        let pos = editor.get_caret_position();
       +        if old_char == editor.get_outline_char_code(HORIZONTAL_CHAR).unwrap() {
       +            match self.old_pos.x.cmp(&pos.x) {
       +                std::cmp::Ordering::Greater => Some(editor.get_outline_char_code(if to_left {CORNER_LOWER_RIGHT} else { CORNER_UPPER_RIGHT}).unwrap()),
       +                std::cmp::Ordering::Less => Some(editor.get_outline_char_code(if to_left {CORNER_LOWER_LEFT} else { CORNER_UPPER_LEFT}).unwrap()),
       +                std::cmp::Ordering::Equal => None
       +            }
       +        } else if old_char == editor.get_outline_char_code(HORIZ_UP_CHAR).unwrap() || old_char == editor.get_outline_char_code(HORIZ_DOWN_CHAR).unwrap()  {
       +            if editor.get_cur_outline() < 4  {
       +                Some(Editor::get_outline_char_code_from(4, editor.get_cur_outline()).unwrap())
       +            } else { None}
       +        } else {
       +            None
       +        }
       +    }
       +
       +*/
       +}
       +
       +// block tools:
       +// copy/moxe
       +// fill, delete
       +impl Tool for LineTool {
       +    fn get_icon_name(&self) -> &'static egui_extras::RetainedImage { &super::icons::LINE_SVG }
       +    fn use_selection(&self) -> bool { false }
       +/*
       +    fn handle_key(
       +        &mut self,
       +        editor: Rc<RefCell<Editor>>,
       +        key: MKey,
       +        _key_code: MKeyCode,
       +        modifier: MModifiers,
       +    ) -> Event {
       +        let mut e = editor.borrow_mut();
       +        let old_pos = e.get_caret_position();
       +        match key {
       +            MKey::Down => {
       +                e.set_caret(old_pos.x, old_pos.y + 1);
       +            }
       +            MKey::Up => {
       +                e.set_caret(old_pos.x, old_pos.y - 1);
       +            }
       +            MKey::Left => {
       +                e.set_caret(old_pos.x - 1, old_pos.y);
       +            }
       +            MKey::Right => {
       +                e.set_caret(old_pos.x + 1, old_pos.y);
       +            }
       +
       +            _ => {
       +                if modifier.is_shift() || modifier.is_control() {
       +                    match key {
       +                        MKey::F1 => {
       +                            handle_outline_insertion(&mut e, modifier, 0);
       +                        }
       +                        MKey::F2 => {
       +                            handle_outline_insertion(&mut e, modifier, 1);
       +                        }
       +                        MKey::F3 => {
       +                            handle_outline_insertion(&mut e, modifier, 2);
       +                        }
       +                        MKey::F4 => {
       +                            handle_outline_insertion(&mut e, modifier, 3);
       +                        }
       +                        MKey::F5 => {
       +                            handle_outline_insertion(&mut e, modifier, 4);
       +                        }
       +                        MKey::F6 => {
       +                            handle_outline_insertion(&mut e, modifier, 5);
       +                        }
       +                        MKey::F7 => {
       +                            handle_outline_insertion(&mut e, modifier, 6);
       +                        }
       +                        MKey::F8 => {
       +                            handle_outline_insertion(&mut e, modifier, 7);
       +                        }
       +                        MKey::F9 => {
       +                            handle_outline_insertion(&mut e, modifier, 8);
       +                        }
       +                        MKey::F10 => {
       +                            handle_outline_insertion(&mut e, modifier, 9);
       +                        }
       +                        _ => {}
       +                    }
       +                }
       +            }
       +        }
       +
       +        let new_pos = e.get_caret_position();
       +        let new_char = e.get_char_from_cur_layer(new_pos).unwrap_or_default();
       +        let old_char = e.get_char_from_cur_layer(old_pos).unwrap_or_default();
       +
       +        let b = (new_pos.x - old_pos.x).signum();
       +        let a = (new_pos.y - old_pos.y).signum();
       +        if a == 1 || a == -1 {
       +            let c = LineTool::get_new_vert_char(&e, new_char.char_code, a == -1 );
       +            let char_code = e.get_outline_char_code(c).unwrap();
       +            let attribute = e.caret.get_attribute();
       +            e.set_char(
       +                new_pos,
       +                Some(crate::model::DosChar {
       +                    char_code,
       +                    attribute,
       +                }),
       +            );
       +
       +            if old_char.is_transparent() {
       +                let char_code = e.get_outline_char_code(HORIZONTAL_CHAR).unwrap();
       +                e.set_char(
       +                    old_pos,
       +                    Some(crate::model::DosChar {
       +                        char_code,
       +                        attribute,
       +                    }),
       +                );
       +            } else if let Some(char_code) = self.get_old_vert_char(&e, old_char.char_code, a == -1) {
       +                e.set_char(
       +                    old_pos,
       +                    Some(crate::model::DosChar {
       +                        char_code,
       +                        attribute,
       +                    }),
       +                );   
       +            }
       +        }
       +
       +        
       +        if b == 1 || b == -1 { // horizontal movement
       +            let c = LineTool::get_new_horiz_char(&e, new_char.char_code, b == -1 );
       +            let char_code = e.get_outline_char_code(c).unwrap();
       +            let attribute = e.caret.get_attribute();
       +            e.set_char(
       +                new_pos,
       +                Some(crate::model::DosChar {
       +                    char_code,
       +                    attribute,
       +                }),
       +            );
       +
       +            if old_char.is_transparent() {
       +                let char_code = e.get_outline_char_code(VERTICAL_CHAR).unwrap();
       +                e.set_char(
       +                    old_pos,
       +                    Some(crate::model::DosChar {
       +                        char_code,
       +                        attribute,
       +                    }),
       +                );
       +            } else if let Some(char_code) = self.get_old_horiz_char(&e, old_char.char_code, b == -1) {
       +                e.set_char(
       +                    old_pos,
       +                    Some(crate::model::DosChar {
       +                        char_code,
       +                        attribute,
       +                    }),
       +                );   
       +            }
       +        }
       +
       +        self.old_pos = old_pos;
       +        Event::None
       +    }
       +
       +    fn handle_click(&mut self, editor: Rc<RefCell<Editor>>, button: u32, pos: Position) -> Event {
       +        let mut editor = editor.borrow_mut();
       +        if button == 1 {
       +            std::borrow::BorrowMut::borrow_mut(&mut editor)
       +                .set_caret_position(pos);
       +        }
       +        Event::None
       +    }
       +
       +
       +    fn handle_drag(&self, editor: Rc<RefCell<Editor>>, start: Position, cur: Position) -> Event
       +    {
       +        if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +            layer.clear();
       +        }
       +
       +        let mut lines = ScanLines::new(1);
       +        if self.draw_mode == DrawMode::Line {
       +            lines.add_line(Position::from(start.x, start.y * 2), Position::from(cur.x, cur.y * 2));
       +            let col = editor.borrow().caret.get_attribute().get_foreground();
       +            let draw = move |rect: Rectangle| {
       +                for y in 0..rect.size.height {
       +                    for x in 0..rect.size.width {
       +                        set_half_block(&editor, Position::from(rect.start.x + x, rect.start.y + y ), col);
       +                    }
       +                }
       +            };
       +            lines.fill(draw);
       +        } else {
       +            lines.add_line(start, cur);
       +            let draw = move |rect: Rectangle| {
       +                for y in 0..rect.size.height {
       +                    for x in 0..rect.size.width {
       +                        plot_point(&editor, self, Position::from(rect.start.x + x, rect.start.y + y));
       +                    }
       +                }
       +            };
       +            lines.fill(draw);
       +        }
       +
       +        Event::None
       +    }
       +
       +    fn handle_drag_end(&self, editor: Rc<RefCell<Editor>>, start: Position, cur: Position) -> Event {
       +        let mut editor = editor.borrow_mut();
       +        if start == cur {
       +            editor.buf.remove_overlay();
       +        } else {
       +            editor.join_overlay();
       +        }
       +        Event::None
       +    }
       +}
       +
       +fn get_half_block(editor: &Rc<RefCell<Editor>>, pos: Position) -> (Position, i32, bool, bool, u8, u8, u8 ,u8, bool, u8, u8)
       +{
       +    let text_y = pos.y / 2;
       +    let is_top = pos.y % 2 == 0;
       +    let block = editor.borrow_mut().get_char(Position::from(pos.x, text_y)).unwrap_or_default();
       +
       +    let mut upper_block_color = 0;
       +    let mut lower_block_color = 0;
       +    let mut left_block_color = 0;
       +    let mut right_block_color = 0;
       +    let mut is_blocky = false;
       +    let mut is_vertically_blocky = false;
       +    match block.char_code {
       +        0 | 32 |255 => { upper_block_color = block.attribute.get_background(); lower_block_color = block.attribute.get_background(); is_blocky = true; }
       +        220 => { upper_block_color = block.attribute.get_background(); lower_block_color = block.attribute.get_foreground(); is_blocky = true; }
       +        223 => { upper_block_color = block.attribute.get_foreground(); lower_block_color = block.attribute.get_background(); is_blocky = true; }
       +        219 => { upper_block_color = block.attribute.get_foreground(); lower_block_color = block.attribute.get_foreground(); is_blocky = true; }
       +        221 => { left_block_color = block.attribute.get_foreground(); right_block_color = block.attribute.get_background(); is_vertically_blocky = true; }
       +        222 => { left_block_color = block.attribute.get_background(); right_block_color = block.attribute.get_foreground(); is_vertically_blocky = true; }
       +        _ => {
       +            if block.attribute.get_foreground() == block.attribute.get_background() {
       +                is_blocky = true;
       +                upper_block_color = block.attribute.get_foreground();
       +                lower_block_color = block.attribute.get_foreground();
       +            } else {
       +                is_blocky = false;
       +            }
       +        }
       +    }
       +    (
       +        pos, 
       +        text_y, 
       +        is_blocky, 
       +        is_vertically_blocky, 
       +        upper_block_color, 
       +        lower_block_color, 
       +        left_block_color, 
       +        right_block_color, 
       +        is_top, 
       +        block.attribute.get_foreground(), 
       +        block.attribute.get_background()
       +    )
       +}
       +
       +pub fn set_half_block(editor: &Rc<RefCell<Editor>>, pos: Position, col: u8) {
       +    let w = editor.borrow().buf.width as i32;
       +    let h = editor.borrow().buf.height as i32;
       +
       +    if pos.x < 0 || pos.x >= w || pos.y < 0 || pos.y >= h * 2 { return }
       +
       +    let (_, text_y, is_blocky, _, 
       +        upper_block_color, lower_block_color, _,  _, 
       +        is_top, _, block_back) = get_half_block(editor, pos);
       +    
       +        let pos = Position::from(pos.x, text_y);
       +        if is_blocky {
       +        if (is_top && lower_block_color == col) || (!is_top && upper_block_color == col) {
       +            if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +                layer.set_char(pos,Some(DosChar::from(219, TextAttribute::from_color(col, 0))));
       +            }
       +        } else if is_top {
       +            if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +                layer.set_char(pos,Some(DosChar::from(223, TextAttribute::from_color(col, lower_block_color))));
       +            }
       +        } else if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +            layer.set_char(pos,Some(DosChar::from(220, TextAttribute::from_color(col, upper_block_color))));
       +        }
       +    } else if is_top {
       +        if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +            layer.set_char(pos,Some(DosChar::from(223, TextAttribute::from_color(col, block_back))));
       +        }
       +    } else if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +        layer.set_char(pos,Some(DosChar::from(220, TextAttribute::from_color(col, block_back))));
       +    }
       +    optimize_block(editor ,Position::from(pos.x, text_y));
       +}
       +
       +
       +fn optimize_block(editor: &Rc<RefCell<Editor>>, pos: Position) {
       +    let block = if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +        layer.get_char(pos).unwrap_or_default()
       +    }  else {
       +        DosChar::new()
       +    };
       +
       +    if block.attribute.get_foreground() == 0 {
       +        if block.attribute.get_background() == 0 || block.char_code == 219 {
       +            if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +                layer.set_char(pos,Some(DosChar::new()));
       +            }
       +        } else {
       +            match block.char_code {
       +                220 => { 
       +                    if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +                        layer.set_char(pos,Some(DosChar::from(223, TextAttribute::from_color(block.attribute.get_background(), block.attribute.get_foreground()))));
       +                    }
       +                }
       +                223 => { 
       +                    if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +                        layer.set_char(pos,Some(DosChar::from(220, TextAttribute::from_color(block.attribute.get_background(), block.attribute.get_foreground()))));
       +                    }
       +                }
       +                _ => {}
       +            }
       +        }
       +    } else if block.attribute.get_foreground() < 8 && block.attribute.get_background() >= 8 {
       +        let (pos, _, is_blocky, is_vertically_blocky, 
       +            _, _, _,  _, 
       +            _, _, _) = get_half_block(editor, pos);
       +
       +        if is_blocky {
       +            match block.char_code {
       +                220 => { 
       +                    if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +                        layer.set_char(pos,Some(DosChar::from(223, TextAttribute::from_color(block.attribute.get_background(), block.attribute.get_foreground()))));
       +                    }
       +                }
       +                223 => { 
       +                    if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +                        layer.set_char(pos,Some(DosChar::from(220, TextAttribute::from_color(block.attribute.get_background(), block.attribute.get_foreground()))));
       +                    }
       +                }
       +                _ => {}
       +            }
       +        } else if is_vertically_blocky {
       +            match block.char_code {
       +                221 => { 
       +                    if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +                        layer.set_char(pos,Some(DosChar::from(222, TextAttribute::from_color(block.attribute.get_background(), block.attribute.get_foreground()))));
       +                    }
       +                }
       +                222 => { 
       +                    if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +                        layer.set_char(pos,Some(DosChar::from(221, TextAttribute::from_color(block.attribute.get_background(), block.attribute.get_foreground()))));
       +                    }
       +                }
       +                _ => {}
       +            }
       +        }
       +    }*/
       +}
       +\ No newline at end of file
   DIR diff --git a/src/model/tool/mod.rs b/src/model/tool/mod.rs
       @@ -1,164 +1,414 @@
       -use std::{rc::Rc, cell::RefCell};
       +use std::{rc::Rc, cell::{RefCell, RefMut}, cmp::{max, min}};
       +pub use super::{Editor, Event};
        
       -pub use super::{Editor, Event, Position};
       +pub mod brush_imp;
       +pub mod click_imp;
       +pub mod draw_rectangle_imp;
       +pub mod draw_ellipse_imp;
       +pub mod draw_rectangle_filled_imp;
       +pub mod draw_ellipse_filled_imp;
       +pub mod erase_imp;
       +pub mod fill_imp;
       +pub mod font_imp;
       +pub mod pipette_imp;
       +pub mod line_imp;
       +pub mod flip_imp;
       +pub mod move_layer_imp;
       +mod icons;
        
       -mod brush_tool;
       -mod click_tool;
       -mod draw_shape_tool;
       -mod erase_tool;
       -mod fill_tool;
       -mod font_tool;
       -mod paint_tool;
       -mod select_tool;
       +use egui_extras::RetainedImage;
       +use icy_engine::{Position, TextAttribute};
       +pub use scan_lines::*;
       +pub mod scan_lines;
        
       -pub trait Tool
       +#[derive(Copy, Clone, Debug)]
       + pub enum MKey {
       +    Character(u16),
       +    Down,
       +    Up,
       +    Left,
       +    Right,
       +    PageDown,
       +    PageUp,
       +    Home,
       +    End,
       +    Return,
       +    Delete,
       +    Insert,
       +    Backspace,
       +    Tab,
       +    Escape,
       +    F1,
       +    F2,
       +    F3,
       +    F4,
       +    F5,
       +    F6,
       +    F7,
       +    F8,
       +    F9,
       +    F10,
       +    F11,
       +    F12
       +}
       +
       +#[derive(Copy, Clone, Debug)]
       +pub enum MModifiers
       +{
       +    None,
       +    Shift,
       +    Alt,
       +    Control
       +}
       +
       +impl MModifiers
       +{
       +    pub fn is_shift(self) -> bool 
       +    {
       +        matches!(self, MModifiers::Shift)
       +    }
       +
       +    pub fn is_alt(self) -> bool 
       +    {
       +        matches!(self, MModifiers::Alt)
       +    }
       +
       +    pub fn is_control(self) -> bool 
       +    {
       +        matches!(self, MModifiers::Control)
       +    }
       +}
       +
       +#[derive(Copy, Clone, Debug)]
       +pub enum MKeyCode
        {
       -    fn get_icon_name(&self) -> &'static str;/* 
       -    fn add_tool_page(&self, window: &ApplicationWindow,parent: &mut gtk4::Box);
       +    Unknown,
       +    KeyI,
       +    KeyU,
       +    KeyY,
       +}
        
       -    fn handle_key(&self, editor: &mut Editor, key: Key, _key_code: u32, _modifier: ModifierType) -> Event
       +pub trait Tool
       +{
       +    fn get_icon_name(&self) -> &'static RetainedImage;
       +    
       +    fn use_caret(&self) -> bool { true }
       +    
       +    fn use_selection(&self) -> bool { true }
       +      /* 
       +    fn handle_key(&mut self, editor: Rc<RefCell<Editor>>, key: MKey, key_code: MKeyCode, modifier: MModifiers) -> Event
            {
       +        // TODO Keys:
       +
       +        // Tab - Next tab
       +        // Shift+Tab - Prev tab
       +
       +        // ctrl+pgup  - upper left corner
       +        // ctrl+pgdn  - lower left corner
       +        let pos = editor.borrow().get_caret_position();
       +        let mut editor = editor.borrow_mut();
                match key {
       -            Key::Down => {
       -                editor.set_cursor(editor.cursor.pos.x, editor.cursor.pos.y + 1);
       +            MKey::Down => {
       +                if let MModifiers::Control = modifier {
       +                    let fg = (editor.caret.get_attribute().get_foreground() + 14) % 16;
       +                    editor.caret.get_attribute().set_foreground(fg);
       +                } else {
       +                    editor.set_caret(pos.x, pos.y + 1);
       +                }
       +            }
       +            MKey::Up => {
       +                if let MModifiers::Control = modifier {
       +                    let fg = (editor.caret.get_attribute().get_foreground() + 1) % 16;
       +                    editor.caret.get_attribute().set_foreground(fg);
       +                } else {
       +                    editor.set_caret(pos.x, pos.y - 1);
       +                }
                    }
       -            Key::Up => {
       -                editor.set_cursor(editor.cursor.pos.x, editor.cursor.pos.y - 1);
       +            MKey::Left => {
       +                // TODO: ICE Colors
       +                if let MModifiers::Control = modifier {
       +                    let bg = (editor.caret.get_attribute().get_background() + 7) % 8;
       +                    editor.caret.get_attribute().set_background(bg);
       +                } else {
       +                    editor.set_caret(pos.x - 1, pos.y);
       +                }
                    }
       -            Key::Left => {
       -                editor.set_cursor(editor.cursor.pos.x - 1, editor.cursor.pos.y);
       +            MKey::Right => {
       +                // TODO: ICE Colors
       +                if let MModifiers::Control = modifier {
       +                    let bg = (editor.caret.get_attribute().get_background() + 1) % 8;
       +                    editor.caret.get_attribute().set_background(bg);
       +                } else {
       +                    editor.set_caret(pos.x + 1, pos.y);
       +                }
                    }
       -            Key::Right => {
       -                editor.set_cursor(editor.cursor.pos.x + 1, editor.cursor.pos.y);
       +            MKey::PageDown => {
       +                // TODO
       +                println!("pgdn");
                    }
       -            
       -            Key::Page_Down |
       -            
       -            Key::Page_Up => {
       +            MKey::PageUp => {
                        // TODO
       +                println!("pgup");
                    }
       -            
       -            Key::Home | Key::KP_Home => {
       -                editor.set_cursor(0, editor.cursor.pos.y);
       -            }
       -            
       -            Key::End | Key::KP_End => {
       -                editor.set_cursor(editor.buf.width as i32 - 1, editor.cursor.pos.y);
       -            }
       -
       -            Key::Return | Key::KP_Enter => {
       -                editor.set_cursor(0,editor.cursor.pos.y + 1);
       -            }
       -
       -            /*
       -            
       -                                                                    case SDLK_DELETE:
       -                                                                for (int i = caret.getLogicalX(); i < getCurrentBuffer()->getWidth(); ++i) {
       -                                                                        getCurrentBuffer()->getCharacter(caret.getLogicalY(), i) = getCurrentBuffer()->getCharacter(caret.getLogicalY(), i + 1);
       -                                                                        getCurrentBuffer()->getAttribute(caret.getLogicalY(), i) = getCurrentBuffer()->getAttribute(caret.getLogicalY(), i + 1);
       -                                                                }
       -                                                                getCurrentBuffer()->getCharacter(caret.getLogicalY(), getCurrentBuffer()->getWidth() - 1) = ' ';
       -                                                                getCurrentBuffer()->getAttribute(caret.getLogicalY(), getCurrentBuffer()->getWidth() - 1) = 7;
       -                                                                break;
       -                                                        case SDLK_INSERT:
       -                                                                caret.insertMode() = !caret.insertMode();
       -                                                                break;
       -                                                        case SDLK_BACKSPACE:
       -                                                                if (caret.getLogicalX()>0){
       -                                                                        if (caret.fontMode() && FontTyped && cpos > 0)  {
       -                                                                                caret.getX() -= CursorPos[cpos] - 1;
       -                                                                                for (a=0;a<=CursorPos[cpos];a++)
       -                                                                                for (b=0;b<=FontLibrary::getInstance().maxY;b++) {
       -                                                                                        getCurrentBuffer()->getCharacter(caret.getLogicalY() + b, caret.getLogicalX()+a) = getUndoBuffer()->getCharacter(caret.getLogicalY() + b, caret.getLogicalX()+a);
       -                                                                                        getCurrentBuffer()->getAttribute(caret.getLogicalY() + b, caret.getLogicalX()+a) = getUndoBuffer()->getAttribute(caret.getLogicalY() + b, caret.getLogicalX()+a);
       -                                                                                }
       -                                                                                cpos--;
       -                                                                        } else {        
       -                                                                                cpos=0;
       -                                                                                caret.getX()--;
       -                                                                                if (caret.insertMode()) {
       -                                                                                        for (int i = caret.getLogicalX(); i < getCurrentBuffer()->getWidth(); ++i) {
       -                                                                                                getCurrentBuffer()->getCharacter(caret.getLogicalY(), i) = getCurrentBuffer()->getCharacter(caret.getLogicalY(), i + 1);
       -                                                                                                getCurrentBuffer()->getAttribute(caret.getLogicalY(), i) = getCurrentBuffer()->getAttribute(caret.getLogicalY(), i + 1);
       -                                                                                        }
       -                                                                                        getCurrentBuffer()->getCharacter(caret.getLogicalY(), getCurrentBuffer()->getWidth() - 1) = ' ';
       -                                                                                        getCurrentBuffer()->getAttribute(caret.getLogicalY(), getCurrentBuffer()->getWidth() - 1) = 7;
       -                                                                                } else  {
       -                                                                                        getCurrentBuffer()->getCharacter(caret.getLogicalY(), getCurrentBuffer()->getWidth() - 1) = ' ';
       -                                                                                        getCurrentBuffer()->getAttribute(caret.getLogicalY(), getCurrentBuffer()->getWidth() - 1) = 7;
       -                                                                                } 
       -                                                                        }
       -                                                                }
       -                                                                break;
       -
       -            */
       -
       -            _ => { 
       -                if let Some(key) = key.to_unicode() {
       -                    
       -                    if key.len_utf8() == 1 {
       -                        let mut dst = [0];
       -                        key.encode_utf8(&mut dst);
       -                        
       -                        editor.buf.set_char(editor.cursor.pos, crate::model::DosChar {
       -                            char_code: dst[0],
       -                            attribute: editor.cursor.attr,
       -                        });
       -                        editor.set_cursor(editor.cursor.pos.x + 1, editor.cursor.pos.y);
       +
       +            MKey::Tab => {
       +                let tab_size = unsafe { crate::WORKSPACE.settings.tab_size } ;
       +                if let MModifiers::Control = modifier {
       +                    let tabs = max(0, (pos.x / tab_size) - 1);
       +                    let next_tab = tabs * tab_size;
       +                    editor.set_caret(next_tab, pos.y);
       +                } else {
       +                    let tabs = 1 + pos.x / tab_size;
       +                    let next_tab = min(editor.buf.width as i32 - 1, tabs * tab_size);
       +                    editor.set_caret(next_tab, pos.y);
       +                }
       +            }
       +            MKey::Home  => {
       +                if let MModifiers::Control = modifier {
       +                    for i in 0..editor.buf.width {
       +                        if !editor.get_char_from_cur_layer(pos.with_x(i as i32)).unwrap_or_default().is_transparent() {
       +                            editor.set_caret(i as i32, pos.y);
       +                            return Event::None;
       +                        }
                            }
                        }
       +                editor.set_caret(0, pos.y);
                    }
       -                /* 
       -                    a = event.key.keysym.unicode;
       -                    if (caret.fontMode() && a > 32 && a < 127) {
       -                         renderFontCharacter(a);
       -                    } else  {
       -                    if (caret.fontMode() && FontTyped) {
       -                        cpos++;
       -                        CursorPos[cpos]=2;
       +            MKey::End => {
       +                if let MModifiers::Control = modifier {
       +                    for i in (0..editor.buf.width).rev()  {
       +                        if !editor.get_char_from_cur_layer(pos.with_x(i as i32)).unwrap_or_default().is_transparent() {
       +                            editor.set_caret(i as i32, pos.y);
       +                            return Event::None;
       +                        }
       +                    }
       +                }
       +                let w = editor.buf.width as i32;
       +                editor.set_caret(w - 1, pos.y);
       +            }
       +            MKey::Return => {
       +                editor.set_caret(0,pos.y + 1);
       +            }
       +            MKey::Delete => {
       +                if editor.cur_selection.is_some() {
       +                    editor.delete_selection(); 
       +                } else {
       +                    let pos = editor.get_caret_position();
       +                    for i in pos.x..(editor.buf.width as i32 - 1) {
       +                        let next = editor.get_char_from_cur_layer( Position::from(i + 1, pos.y));
       +                        editor.set_char(Position::from(i, pos.y), next);
                            }
       -                    if (caret.eliteMode()) {
       -                        typeCharacter(translate(a)); 
       -                    } else {
       -                        typeCharacter(a);
       +                    let last_pos = Position::from(editor.buf.width as i32 - 1, pos.y);
       +                    editor.set_char(last_pos, None);
       +                }
       +            }
       +            MKey::Insert => {
       +                editor.caret.insert_mode = !editor.caret.insert_mode;
       +            }
       +            MKey::Backspace => {
       +                editor.cur_selection = None;
       +                let pos = editor.get_caret_position();
       +                if pos.x> 0 {
       +                   /* if (caret.fontMode() && FontTyped && cpos > 0)  {
       +                        caret.getX() -= CursorPos[cpos] - 1;
       +                        for (a=0;a<=CursorPos[cpos];a++)
       +                        for (b=0;b<=FontLibrary::getInstance().maxY;b++) {
       +                            getCurrentBuffer()->getCharacter(caret.getLogicalY() + b, caret.getLogicalX()+a) = getUndoBuffer()->getCharacter(caret.getLogicalY() + b, caret.getLogicalX()+a);
       +                            getCurrentBuffer()->getAttribute(caret.getLogicalY() + b, caret.getLogicalX()+a) = getUndoBuffer()->getAttribute(caret.getLogicalY() + b, caret.getLogicalX()+a);
       +                        }
       +                        cpos--;
       +                    } else {*/        
       +                        editor.set_caret_position(pos + Position::from(-1, 0));
       +                    if editor.caret.insert_mode {
       +                        for i in pos.x..(editor.buf.width as i32 - 1) {
       +                            let next = editor.get_char_from_cur_layer( Position::from(i + 1, pos.y));
       +                            editor.set_char(Position::from(i, pos.y), next);
       +                        }
       +                        let last_pos = Position::from(editor.buf.width as i32 - 1, pos.y);
       +                        editor.set_char(last_pos, None);
       +                    } else  {
       +                        let pos = editor.get_caret_position();
       +                        editor.set_char(pos, None);
       +                    } 
       +                }
       +            }
       +
       +            MKey::Character(ch) => { 
       +                editor.cur_selection = None;
       +                if let MModifiers::Alt = modifier {
       +                    match key_code { 
       +                        MKeyCode::KeyI => editor.insert_line(pos.y),
       +                        MKeyCode::KeyU => editor.pickup_color(pos),
       +                        MKeyCode::KeyY => editor.delete_line(pos.y),
       +                        MKeyCode::Unknown => {}
                            }
       -                */
       +                    return Event::None;
       +                }
       +
       +                editor.type_key(ch);
       +            }
       +
       +            MKey::F1 => {
       +                handle_outline_insertion(&mut editor, modifier, 0);
       +            }
       +            MKey::F2 => {
       +                handle_outline_insertion(&mut editor, modifier, 1);
       +            }
       +            MKey::F3 => {
       +                handle_outline_insertion(&mut editor, modifier, 2);
       +            }
       +            MKey::F4 => {
       +                handle_outline_insertion(&mut editor, modifier, 3);
       +            }
       +            MKey::F5 => {
       +                handle_outline_insertion(&mut editor, modifier, 4);
       +            }
       +            MKey::F6 => {
       +                handle_outline_insertion(&mut editor, modifier, 5);
       +            }
       +            MKey::F7 => {
       +                handle_outline_insertion(&mut editor, modifier, 6);
       +            }
       +            MKey::F8 => {
       +                handle_outline_insertion(&mut editor, modifier, 7);
       +            }
       +            MKey::F9 => {
       +                handle_outline_insertion(&mut editor, modifier, 8);
       +            }
       +            MKey::F10 => {
       +                handle_outline_insertion(&mut editor, modifier, 9);
       +            }
       +            MKey::Escape => {
       +                editor.cur_selection = None;
       +            }
       +            _ => {}
                }
                Event::None
            }
        
       -*/
       -fn handle_click(&self, _editor: Rc<RefCell<Editor>>, _button: u32, _pos: Position) -> Event {
       -    Event::None
       -}
       -/* 
       -    fn handle_drag_begin(&self, _editor: &mut Editor, _start: Position, _cur: Position) -> Event {
       +    fn handle_click(&mut self, _editor: Rc<RefCell<Editor>>, _button: u32, _pos: Position) -> Event {
                Event::None
            }
        
       -    fn handle_drag(&self, _editor: &mut Editor, _start: Position, _cur: Position) -> Event {
       +    fn handle_drag_begin(&mut self, _editor: Rc<RefCell<Editor>>, _start: Position, _cur: Position) -> Event {
                Event::None
            }
        
       -    fn handle_drag_end(&self, _editor: &mut Editor, _start: Position, _cur: Position) -> Event {
       +    fn handle_drag(&self, _editor: Rc<RefCell<Editor>>, _start: Position, _cur: Position) -> Event {
       +        Event::None
       +    }
       +
       +    fn handle_drag_end(&self, _editor: Rc<RefCell<Editor>>, _start: Position, _cur: Position) -> Event {
                Event::None
            }*/
        }
        
       -pub static mut FONT_TOOL: font_tool::FontTool = font_tool::FontTool { fonts: Vec::new(), selected_font: -1  };
       -pub static mut TOOLS: Vec<&dyn Tool> = Vec::new();
        
       -pub fn init_tools()
       +/*
       +fn handle_outline_insertion(editor: &mut RefMut<Editor>, modifier: MModifiers, outline: i32) {
       +    if let MModifiers::Control = modifier {
       +        editor.set_cur_outline(outline);
       +        return;
       +    }
       +
       +    if outline < 5 {
       +        if let MModifiers::Shift = modifier {
       +            editor.set_cur_outline(10 + outline);
       +            return;
       +        }
       +    }
       +    editor.cur_selection = None;
       +    let ch = editor.get_outline_char_code(outline);
       +    if let Ok(ch) = ch {
       +        editor.type_key(ch);
       +    }
       +} */
       +
       +#[derive(Clone, Copy, Debug, PartialEq)]
       +pub enum DrawMode {
       +    Line,
       +    Char,
       +    Shade,
       +    Colorize
       +}
       +
       +trait Plottable {
       +    fn get_draw_mode(&self) -> DrawMode;
       +
       +    fn get_use_fore(&self) -> bool;
       +    fn get_use_back(&self) -> bool;
       +    fn get_char_code(&self) -> u16;
       +}
       +
       +fn plot_point(editor: &Rc<RefCell<Editor>>, tool: &dyn Plottable, pos: Position)
        {
       -   /*  unsafe {
       -        FONT_TOOL.load_fonts();
       -        TOOLS.push(&click_tool::ClickTool {});
       -        TOOLS.push(&select_tool::SelectTool {});
       -        TOOLS.push(&paint_tool::PaintTool{});
       -        TOOLS.push(&brush_tool::BrushTool{});
       -        TOOLS.push(&erase_tool::EraseTool{});
       -        TOOLS.push(&draw_shape_tool::DrawShapeTool{});
       -        TOOLS.push(&fill_tool::FillTool{});
       -        TOOLS.push(&FONT_TOOL);
       +  /*   let ch = editor.borrow().get_char_from_cur_layer(pos).unwrap_or_default();
       +    let editor_attr = editor.borrow().caret.get_attribute();
       +    let mut attribute= ch.attribute;
       +    if tool.get_use_back() {
       +        attribute.set_background(editor_attr.get_background());
       +    }
       +    if tool.get_use_fore() {
       +        attribute.set_foreground(editor_attr.get_foreground());
       +    }
       +
       +    match tool.get_draw_mode() {
       +        DrawMode::Line => {
       +            if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +                layer.set_char(
       +                    pos,
       +                    Some(DosChar {
       +                        char_code: 219,
       +                        attribute,
       +                    }),
       +                );
       +            }
       +        },
       +        DrawMode::Char => {
       +            if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +                layer.set_char(
       +                    pos,
       +                    Some(DosChar {
       +                        char_code: tool.get_char_code(),
       +                        attribute,
       +                    }),
       +                );
       +            }
       +        },
       +        DrawMode::Shade => {
       +            let mut char_code = SHADE_GRADIENT[0];
       +            if ch.char_code == SHADE_GRADIENT[SHADE_GRADIENT.len() -1] {
       +                char_code = SHADE_GRADIENT[SHADE_GRADIENT.len() -1];
       +            } else {
       +                for i in 0..SHADE_GRADIENT.len() - 1 {
       +                    if ch.char_code == SHADE_GRADIENT[i] {
       +                        char_code = SHADE_GRADIENT[i + 1];
       +                        break;
       +                    }
       +                }
       +            }
       +            if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +                layer.set_char(
       +                    pos,
       +                    Some(DosChar {
       +                        char_code,
       +                        attribute,
       +                    }),
       +                );
       +            }
       +        }
       +        DrawMode::Colorize => {
       +            if let Some(layer) = editor.borrow_mut().get_overlay_layer() {
       +                layer.set_char(
       +                    pos,
       +                    Some(DosChar {
       +                        char_code: ch.char_code,
       +                        attribute,
       +                    }),
       +                );
       +            }
       +        }
            }*/
       -}
       -\ No newline at end of file
       +}
       +
       +pub static SHADE_GRADIENT: [u16;4] = [176, 177, 178, 219];
   DIR diff --git a/src/model/tool/move_layer_imp.rs b/src/model/tool/move_layer_imp.rs
       @@ -0,0 +1,32 @@
       +
       +use std::{rc::Rc, cell::RefCell};
       +
       +
       +use super::{Tool, Editor, Position, Event};
       +pub struct MoveLayer { pub pos: Position }
       +
       +impl Tool for MoveLayer
       +{
       +    fn get_icon_name(&self) -> &'static egui_extras::RetainedImage { &super::icons::MOVE_SVG }
       +    fn use_caret(&self) -> bool { false }
       +    fn use_selection(&self) -> bool { false }
       +
       +  /* 
       +    fn handle_drag_begin(&mut self, editor: Rc<RefCell<Editor>>, _start: Position, _cur: Position) -> Event {
       +        let mut editor = editor.borrow_mut();
       +        if let Some(layer) = editor.get_cur_layer() {
       +            self.pos = layer.get_offset();
       +        }
       +        Event::None
       +    }
       +
       +    fn handle_drag(&self, editor: Rc<RefCell<Editor>>, start: Position, cur: Position) -> Event
       +    {
       +        let mut editor = editor.borrow_mut();
       +        if let Some(layer) = editor.get_cur_layer_mut() {
       +            layer.set_offset(self.pos + cur - start);
       +        }
       +        Event::None
       +    }*/
       +
       +}
       +\ No newline at end of file
   DIR diff --git a/src/model/tool/paint_tool.rs b/src/model/tool/paint_tool.rs
       @@ -1,12 +0,0 @@
       -
       -use super::Tool;
       -pub struct PaintTool {}
       -
       -impl Tool for PaintTool
       -{
       -    fn get_icon_name(&self) -> &'static str { "edit-select" }
       - /*   fn add_tool_page(&self, window: &ApplicationWindow,parent: &mut gtk4::Box)
       -    {
       -        parent.append(&gtk4::Label::builder().label("Paint").build());
       -    }*/
       -}
       -\ No newline at end of file
   DIR diff --git a/src/model/tool/pipette_imp.rs b/src/model/tool/pipette_imp.rs
       @@ -0,0 +1,19 @@
       +use std::{rc::Rc, cell::RefCell};
       +
       +use super::{Tool, Editor, Position, Event};
       +pub struct PipetteTool {}
       +
       +impl Tool for PipetteTool
       +{
       +    fn get_icon_name(&self) -> &'static egui_extras::RetainedImage { &super::icons::DROPPER_SVG }
       +    fn use_caret(&self) -> bool { false }
       +    fn use_selection(&self) -> bool { false }
       +    /* 
       +    fn handle_click(&mut self, editor: Rc<RefCell<Editor>>, button: u32, pos: Position) -> Event {
       +        if button == 1 {
       +            let ch = editor.borrow().get_char(pos).unwrap_or_default();
       +            editor.borrow_mut().set_caret_attribute(ch.attribute);
       +        }
       +        Event::None
       +    }*/
       +}
       +\ No newline at end of file
   DIR diff --git a/src/model/tool/scan_lines.rs b/src/model/tool/scan_lines.rs
       @@ -0,0 +1,346 @@
       +use std::{collections::HashMap, cmp::{max, min}, f64::consts};
       +
       +use icy_engine::Rectangle;
       +
       +use super::Position;
       +
       +// Code from Pablodraw - I liked the approach and I needed a better ellipse drawing algorithm.
       +// translated from https://github.com/cwensley/pablodraw/blob/main/Source/Pablo/Drawing/ScanLines.cs
       +
       +pub struct ScanLines {
       +    line_thickness: i32,
       +    rows: HashMap<i32, ScanRow>,
       +}
       +
       +impl ScanLines {
       +    const RAD2DEG: f64 = 180.0 / consts::PI;
       +    // const deg2rad: f64 = consts::PI / 180.0;
       +
       +    pub fn add(&mut self, x: i32, y: i32) {
       +        if let Some(row) = self.rows.get_mut(&y) {
       +            row.add(x);
       +        } else {
       +            let mut row = ScanRow::new();
       +            row.add(x);
       +            self.rows.insert(y, row);
       +        }
       +    }
       +
       +    pub fn add_ellipse(&mut self, rectangle: Rectangle) {
       +        let mut rw = rectangle.size.width;
       +        let mut rh = rectangle.size.height;
       +
       +        if rw < 2 {  rw = 2; }
       +        if rh < 2 { rh = 2; }
       +
       +        if (rw % 2) == 0 { rw += 1; }
       +        if (rh % 2) == 0 { rh += 1; }
       +
       +        let mx = rectangle.start.x + rw / 2;
       +        let my = rectangle.start.y + rh / 2;
       +
       +        self.add_ellipse_internal(mx, my, rw / 2, rh / 2/*, 0, 360*/);
       +    }
       +
       +    fn add_ellipse_internal(&mut self, x: i32, y: i32, radius_x: i32, radius_y: i32/*, mut start_angle: i32, mut end_angle: i32*/) {
       +
       +        // check if valid angles
       +        //if start_angle > end_angle {
       +        //    std::mem::swap(&mut start_angle, &mut end_angle);
       +        //}
       +
       +        let radius_x = max(1, radius_x);
       +        let radius_y = max(1, radius_y);
       +
       +        let dx = radius_x * 2;
       +        let dy = radius_y * 2;
       +        let b1 = dy & 1;
       +        let mut stop_x = 4 * (1 - dx) * dy * dy;
       +        let mut stop_y = 4 * (b1 + 1) * dx * dx; // error increment
       +        let mut err = stop_x + stop_y + b1 * dx * dx; // error of 1 step
       +
       +        let mut xoffset = radius_x;
       +        let mut yoffset = 0;
       +        let inc_x = 8 * dx * dx;
       +        let inc_y = 8 * dy * dy;
       +
       +        let aspect = (radius_x as f64)  / (radius_y as f64);
       +
       +        // calculate horizontal fill angle
       +        let horizontal_angle = if radius_x < radius_y {
       +            90.0 - (45.0 * aspect)
       +        } else {
       +            45.0 / aspect
       +        };
       +        let horizontal_angle = horizontal_angle.round() as i32;
       +
       +        loop {
       +            let e2 = 2 * err;
       +            let angle = ((yoffset as f64 * aspect / (xoffset as f64)).atan() * ScanLines::RAD2DEG).round() as i32;
       +            self.symmetry_scan (x, y, /*start_angle, end_angle, */xoffset, yoffset/*, angle, angle <= horizontal_angle*/);
       +            if (angle - horizontal_angle).abs() < 1 {
       +                self.symmetry_scan (x, y, /*start_angle, end_angle,*/ xoffset, yoffset/*, angle, angle > horizontal_angle*/);
       +            }
       +
       +            if e2 <= stop_y {
       +                yoffset += 1;
       +                stop_y += inc_x;
       +                err += stop_y;
       +            }
       +            if e2 >= stop_x {
       +                xoffset -= 1;
       +                stop_x += inc_y;
       +                err += stop_x;
       +            }
       +            if xoffset < 0 {
       +                break;
       +            }
       +        }
       +
       +        xoffset += 1;
       +        while yoffset < radius_y {
       +            let angle = ((yoffset as f64 * aspect / (xoffset as f64)).atan() * ScanLines::RAD2DEG).round() as i32;
       +            self.symmetry_scan (x, y, /*start_angle, end_angle, */xoffset, yoffset/*, angle as i32, angle <= horizontal_angle*/);
       +            if angle == horizontal_angle {
       +                self.symmetry_scan (x, y, /*start_angle, end_angle,*/ xoffset, yoffset/*, angle as i32, angle > horizontal_angle*/);
       +            }
       +            yoffset += 1;
       +        }
       +    }
       +
       +    fn add_horizontal(&mut self, x: i32, y: i32, count: i32) {
       +        if count > 0 {
       +            for i in 0..count {
       +                self.add(x + i, y);
       +            }
       +        } else {
       +            for i in (0..count).rev() {
       +                self.add(x + i, y);
       +            }
       +        }
       +    }
       +
       +    /*fn add_vertical(&mut self, x: i32, y: i32, count: i32) {
       +        if count > 0 {
       +            for i in 0..count {
       +                self.add(x, y + i);
       +            }
       +        } else {
       +            for i in (0..count).rev() {
       +                self.add(x, y + i);
       +            }
       +        }
       +    }*/
       +
       +    pub fn fill<T>(&self, draw: T) where
       +        T: Fn(Rectangle),
       +    {
       +        for row in &self.rows {
       +            let (min, max) = row.1.get_min_max();
       +            draw(Rectangle::from_coords(min, *row.0, max, *row.0));
       +        }
       +    }
       +
       +   /* fn in_angle(angle: i32, start_angle: i32, end_angle: i32) -> bool {
       +        angle >= start_angle && angle <= end_angle
       +    }*/
       +
       +    /*pub fn is_drawn(&self, point: Position) -> bool {
       +        if let Some(row) = self.rows.get(&point.y) {
       +            row.points.contains(&point.x)
       +        } else {
       +            false
       +        }
       +    }*/
       +
       +    // simple https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
       +    // maybe worth to explore https://en.wikipedia.org/wiki/Xiaolin_Wu%27s_line_algorithm
       +    pub fn add_line(&mut self, mut pos0: Position, pos1: Position) {
       +        let dx = (pos1.x - pos0.x).abs();
       +        let sx = if pos0.x < pos1.x { 1 } else { -1 };
       +        let dy = -(pos1.y - pos0.y).abs();
       +        let sy = if pos0.y < pos1.y { 1 } else { -1 };
       +        let mut error = dx + dy;
       +        
       +        loop {
       +            self.add(pos0.x, pos0.y);
       +            
       +            if pos0.x == pos1.x && pos0.y == pos1.y { break; }
       +            let e2 = 2 * error;
       +            if e2 >= dy {
       +                if pos0.x == pos1.x { break; }
       +                error += dy;
       +                pos0.x += sx;
       +            }
       +            if e2 <= dx {
       +                if pos0.y == pos1.y { break; }
       +                error += dx;
       +                pos0.y += sy;
       +            }
       +        }
       +    }
       +
       +    pub fn add_rectangle(&mut self, rectangle: Rectangle)
       +    {
       +        for i in 0..rectangle.size.height {
       +            self.add_horizontal(rectangle.start.x, rectangle.start.y + i, rectangle.size.width);
       +        }
       +    }
       +
       +  /*  pub fn is_inside(&self, point: Position) -> bool {
       +        if let Some(row) = self.rows.get(&point.y) {
       +            let (min, max) = row.get_min_max();
       +            min <= point.x && point.x <= max
       +        } else {
       +            false
       +        }
       +    }*/
       +
       +    pub fn new(line_thickness: i32) -> Self {
       +        ScanLines {
       +            line_thickness,
       +            rows: HashMap::new(),
       +        }
       +    }
       +    pub fn outline<T>(&self, draw: T)
       +        where
       +            T: Fn(Rectangle)
       +    {
       +        let mut lastx = 0;
       +
       +        let mut rows = Vec::new();
       +
       +        for i in &self.rows {
       +            let (min, max) = i.1.get_min_max();
       +            rows.push((*i.0, min, max));
       +        }
       +        rows.sort_by(|x, y| x.0.cmp(&y.0));
       +        // trace min edge
       +        for i in 0..rows.len() {
       +            let row = rows[i];
       +
       +            let cur_y = row.0;
       +            let cur_x = row.1;
       +            let last = i == rows.len() - 1;
       +            let first = i == 0;
       +
       +            if !first && !last {
       +                let nextx = rows[i + 1].1;
       +                if cur_x < lastx {
       +                    draw(Rectangle::from_coords(cur_x, cur_y, lastx - 1, cur_y));
       +                } else if cur_x > lastx + 1 {
       +                    draw(Rectangle::from_coords(lastx + 1, cur_y - 1, cur_x - 1, cur_y - 1));
       +                    draw(Rectangle::from_coords(cur_x, cur_y, cur_x, cur_y));
       +                } else {
       +                    draw(Rectangle::from_coords(cur_x, cur_y, cur_x, cur_y));
       +                }
       +                if nextx > cur_x {
       +                    draw(Rectangle::from_coords(cur_x, cur_y, nextx - 1, cur_y));
       +                }
       +            }
       +            lastx = cur_x;
       +        }
       +
       +        // trace max edge
       +        for i in 0..rows.len() {
       +            let row = rows[i];
       +            let cur_y = row.0;
       +            let cur_x = row.2;
       +            let last = i == rows.len() - 1;
       +            let first = i == 0;
       +
       +            if !first && !last {
       +                let nextx = rows[i + 1].2;
       +                if cur_x > lastx {
       +                    draw(Rectangle::from_coords(lastx + 1, cur_y, cur_x, cur_y));
       +                } else if cur_x < lastx - 1 {
       +                    draw(Rectangle::from_coords(cur_x + 1, cur_y - 1, lastx - 1, cur_y - 1));
       +                    draw(Rectangle::from_coords(cur_x, cur_y, cur_x, cur_y));
       +                } else {
       +                    draw(Rectangle::from_coords(cur_x, cur_y, cur_x, cur_y));
       +                }
       +                if nextx < cur_x {
       +                    draw(Rectangle::from_coords(nextx + 1, cur_y, cur_x, cur_y));
       +                }
       +            }
       +            lastx = cur_x;
       +        }
       +
       +        // fill top/bottom
       +        let row = rows[0];
       +        draw(Rectangle::from_coords(row.1, row.0, row.2, row.0));
       +        let row = rows[rows.len() - 1];
       +        draw(Rectangle::from_coords(row.1, row.0, row.2, row.0));
       +    }
       +
       +    fn symmetry_scan(&mut self, x: i32, y: i32, /* start_angle: i32, end_angle: i32, */xoffset: i32, yoffset: i32/*, angle: i32, horizontal: bool*/) {
       +        if self.line_thickness == 1 {
       +            //if ScanLines::in_angle(angle, start_angle, end_angle) {
       +                self.add(x + xoffset, y - yoffset);
       +            //}
       +            //if ScanLines::in_angle(180 - angle, start_angle, end_angle) {
       +                self.add(x - xoffset, y - yoffset);
       +            //}
       +            //if ScanLines::in_angle(180 + angle, start_angle, end_angle) {
       +                self.add(x - xoffset, y + yoffset);
       +            //}
       +            //if ScanLines::in_angle(360 - angle, start_angle, end_angle) {
       +                self.add(x + xoffset, y + yoffset);
       +            //}
       +        } /*else {
       +            let offset = self.line_thickness / 2;
       +            if horizontal {
       +                if ScanLines::in_angle(angle, start_angle, end_angle) {
       +                    self.add_horizontal(x + xoffset - offset, y - yoffset, self.line_thickness);
       +                }
       +                if ScanLines::in_angle(180 - angle, start_angle, end_angle) {
       +                    self.add_horizontal(x - xoffset - offset, y - yoffset, self.line_thickness);
       +                }
       +                if ScanLines::in_angle(180 + angle, start_angle, end_angle) {
       +                    self.add_horizontal(x - xoffset - offset, y + yoffset, self.line_thickness);
       +                }
       +                if ScanLines::in_angle(360 - angle, start_angle, end_angle) {
       +                    self.add_horizontal(x + xoffset - offset, y + yoffset, self.line_thickness);
       +                }
       +            } else {
       +                if ScanLines::in_angle(angle, start_angle, end_angle) {
       +                    self.add_vertical(x + xoffset, y - yoffset - offset, self.line_thickness);
       +                }
       +                if ScanLines::in_angle(180 - angle, start_angle, end_angle) {
       +                    self.add_vertical(x - xoffset, y - yoffset - offset, self.line_thickness);
       +                }
       +                if ScanLines::in_angle(180 + angle, start_angle, end_angle) {
       +                    self.add_vertical(x - xoffset, y + yoffset - offset, self.line_thickness);
       +                }
       +                if ScanLines::in_angle(360 - angle, start_angle, end_angle) {
       +                    self.add_vertical(x + xoffset, y + yoffset - offset, self.line_thickness);
       +                }
       +            }
       +        }*/
       +    }
       +}
       +
       +struct ScanRow {
       +    pub points: Vec<i32>,
       +}
       +
       +impl ScanRow {
       +    pub fn new() -> Self {
       +        ScanRow {
       +            points: Vec::new(),
       +        }
       +    }
       +    pub fn get_min_max(&self) -> (i32, i32) {
       +        let mut min_point = i32::MAX;
       +        let mut max_point = i32::MIN;
       +
       +        for i in &self.points {
       +            min_point = min(min_point, *i);
       +            max_point = max(max_point, *i);
       +        }
       +        (min_point, max_point)
       +    }
       +    pub fn add(&mut self, x: i32) {
       +        self.points.push(x);
       +    }
       +}
   DIR diff --git a/src/model/tool/select_tool.rs b/src/model/tool/select_tool.rs
       @@ -1,75 +0,0 @@
       -
       -use super::{Editor, Event, Position, Tool};
       -
       -pub struct SelectTool {}
       -
       -impl Tool for SelectTool
       -{
       -    fn get_icon_name(&self) -> &'static str { "edit-select" }
       -
       -    /* 
       -    fn add_tool_page(&self, window: &ApplicationWindow,parent: &mut gtk4::Box)
       -    {
       -        parent.append(&gtk4::Label::builder().label("Select").build());
       -    }
       -
       -    fn handle_key(&self, editor: &mut Editor, key: Key, _key_code: u32, _modifier: ModifierType) -> Event
       -    {
       -        match key {
       -            Key::Down => {
       -                if editor.cur_selection.is_active {
       -                    editor.cur_selection.rectangle.start.y += 1;
       -                }
       -            }
       -            Key::Up => {
       -                if editor.cur_selection.is_active {
       -                    editor.cur_selection.rectangle.start.y -= 1;
       -                }
       -            }
       -            Key::Left => {
       -                if editor.cur_selection.is_active {
       -                    editor.cur_selection.rectangle.start.x -= 1;
       -                }
       -            }
       -            Key::Right => {
       -                if editor.cur_selection.is_active {
       -                    editor.cur_selection.rectangle.start.x += 1;
       -                }
       -            }
       -            Key::Escape => {
       -                editor.cur_selection.is_active = false;
       -            }
       -            _ => {}
       -        }
       -        Event::None
       -    }
       -
       -    fn handle_click(&self, editor: &mut Editor, button: u32, x: i32, y: i32) -> Event
       -    {
       -        if button == 3 {
       -            editor.cur_selection.is_active = false;
       -        } else {
       -            editor.cursor.pos = Position::from(x, y);
       -        }
       -        Event::None
       -    }
       -
       -    fn handle_drag(&self, editor: &mut Editor, start: Position, mut cur: Position) -> Event
       -    {
       -        if start < cur {
       -            cur = cur + Position::from(1, 1);
       -        }
       -        editor.cur_selection.rectangle = crate::model::Rectangle::from_pt(start, cur);
       -        editor.cur_selection.is_preview = true;
       -        editor.cur_selection.is_active = true;
       -
       -        Event::None
       -    }
       -
       -    fn handle_drag_end(&self, editor: &mut Editor, _start: Position, _cur: Position) -> Event {
       -        editor.cur_selection.is_preview = false;
       -        editor.cur_selection.is_active = true;
       -
       -        Event::None
       -    }*/
       -}
   DIR diff --git a/src/ui/main_window.rs b/src/ui/main_window.rs
       @@ -1,16 +1,19 @@
        use std::{path::PathBuf, fs, sync::Arc, time::Duration};
        
       -use eframe::egui::{self, menu, TopBottomPanel, SidePanel};
       +use eframe::{egui::{self, menu, TopBottomPanel, SidePanel}, epaint::ahash::HashMap};
        use egui_dock::{DockArea, Style,  Tree, Node};
       +use egui_extras::RetainedImage;
        use glow::Context;
        use icy_engine::{BitFont, Buffer};
        use rfd::FileDialog;
        
       -use crate::{Document, FontEditor};
       +use crate::{Document, FontEditor, model::Tool};
        
        use super::ansi_editor::AnsiEditor;
        
        pub struct MainWindow {
       +    pub tools: Vec<Box<dyn Tool>>,
       +    pub selected_tool: usize,
            tree: Tree<(String, Box<dyn Document>)>,
            gl: Arc<Context>
        }
       @@ -19,7 +22,70 @@ impl MainWindow {
            pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
                let tree = Tree::new(Vec::new());
        
       +        let mut tools: Vec<Box::<dyn Tool>> = Vec::new();
       +       
       +        tools.push(Box::new(crate::model::click_imp::ClickTool { }));
       +        tools.push(Box::new(crate::model::brush_imp::BrushTool {
       +            size: 3, 
       +            use_back: true,
       +            use_fore: true,
       +            brush_type: crate::model::brush_imp::BrushType::Shade,
       +            char_code: 176,
       +        }));
       +        tools.push(Box::new(crate::model::erase_imp::EraseTool { size: 3, brush_type: crate::model::erase_imp::EraseType::Shade }));
       +        tools.push(Box::new(crate::model::pipette_imp::PipetteTool { }));
       +        tools.push(Box::new(crate::model::line_imp::LineTool {
       +            draw_mode: crate::model::DrawMode::Line, 
       +            use_fore: true, 
       +            use_back: true, 
       +            attr: icy_engine::TextAttribute::default(), 
       +            char_code: 176,
       +            old_pos: icy_engine::Position { x: 0, y: 0 }
       +        }));
       +        tools.push(Box::new(crate::model::draw_rectangle_imp::DrawRectangleTool { 
       +            draw_mode: crate::model::DrawMode::Line, 
       +            use_fore: true, 
       +            use_back: true, 
       +            attr: icy_engine::TextAttribute::default(), 
       +            char_code: 176
       +        }));
       +
       +        tools.push(Box::new(crate::model::draw_rectangle_filled_imp::DrawRectangleFilledTool { 
       +            draw_mode: crate::model::DrawMode::Line, 
       +            use_fore: true, 
       +            use_back: true, 
       +            attr: icy_engine::TextAttribute::default(), 
       +            char_code: 176
       +        }));
       +        tools.push(Box::new(crate::model::draw_ellipse_imp::DrawEllipseTool {
       +            draw_mode: crate::model::DrawMode::Line, 
       +            use_fore: true, 
       +            use_back: true, 
       +            attr: icy_engine::TextAttribute::default(), 
       +            char_code: 176
       +        }));
       +
       +        tools.push(Box::new(crate::model::draw_ellipse_filled_imp::DrawEllipseFilledTool {
       +            draw_mode: crate::model::DrawMode::Line, 
       +            use_fore: true, 
       +            use_back: true, 
       +            attr: icy_engine::TextAttribute::default(), 
       +            char_code: 176
       +        }));
       +
       +        tools.push(Box::new(crate::model::fill_imp::FillTool {
       +            use_char: true,
       +            use_fore: true,
       +            use_back: true,
       +            char_code: 176,
       +            attr: icy_engine::TextAttribute::default()
       +        }));
       +
       +        tools.push(Box::new(crate::model::move_layer_imp::MoveLayer { pos: icy_engine::Position { x: 0, y: 0 } }));
       +
                let view = MainWindow {
       +            tools,
       +            selected_tool: 0,
                    tree,
                    gl: cc.gl.clone().unwrap()
                };
       @@ -54,6 +120,7 @@ impl MainWindow {
                self.tree.push_to_focused_leaf((full_path, Box::new(editor)));
        
            }
       +
        }
        
        
       @@ -109,6 +176,7 @@ impl eframe::App for MainWindow {
                        buffer_opt = t.1.get_buffer_view();
                    }
                    ui.add(crate::palette_editor_16(buffer_opt));
       +            crate::add_tool_switcher(ctx, ui, self);
                });
        
                DockArea::new(&mut self.tree)
       @@ -130,3 +198,4 @@ impl eframe::App for MainWindow {
                }
            }
        }
       +
   DIR diff --git a/src/ui/mod.rs b/src/ui/mod.rs
       @@ -13,4 +13,7 @@ pub use font_editor::*;
        mod palette_editor;
        pub use palette_editor::*;
        
       +mod tool_switcher;
       +pub use tool_switcher::*;
       +
        pub type TerminalResult<T> = Result<T, Box<dyn Error>>;
   DIR diff --git a/src/ui/tool_switcher.rs b/src/ui/tool_switcher.rs
       @@ -0,0 +1,14 @@
       +use eframe::{egui::{self, ImageButton}, epaint::Vec2};
       +use crate::MainWindow;
       +
       +pub fn add_tool_switcher(ctx: &egui::Context, ui: &mut egui::Ui, arg: &mut MainWindow) {
       +
       +    ui.horizontal_wrapped(|ui| {
       +        for i in 0..arg.tools.len() {
       +            let t = &arg.tools[i];
       +            if ui.add(ImageButton::new(t.get_icon_name().texture_id(ctx), Vec2::new(28., 28.)).selected(i == arg.selected_tool)).clicked() {
       +                arg.selected_tool = i;
       +            }
       +        }
       +    });
       +}