diff options
| author | Lex Neva <lexelby@users.noreply.github.com> | 2024-08-08 09:43:36 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-08 09:43:36 -0400 |
| commit | 47ad76f513846a8501f84c057b28a146031859b6 (patch) | |
| tree | 0d29cb0f87473f925c07f9b58949357ae1cf141d | |
| parent | 17b88ce2c14a0802e18e90d8dd142224013dfb15 (diff) | |
Show page in simulator (#3120)
* add exception logging helpers
* wip
* show page and drop shadow from SVG
* allow toggling page
* add page icon
* add dark mode icon
* showpageshadow
* refresh after background change (fix for macOS)
* fix params sim background
* try a native GraphicsBrush for windows
* show page button in standalone simulator only and adapt shadow color
* remove doubled line
---------
Co-authored-by: Kaalleen <reni@allenka.de>
| -rw-r--r-- | icons/page.png | bin | 0 -> 3191 bytes | |||
| -rw-r--r-- | icons/page.svg | 97 | ||||
| -rw-r--r-- | icons/page_dark.png | bin | 0 -> 3145 bytes | |||
| -rw-r--r-- | lib/debug/debug.py | 13 | ||||
| -rw-r--r-- | lib/extensions/simulator.py | 29 | ||||
| -rw-r--r-- | lib/gui/simulator/drawing_panel.py | 56 | ||||
| -rw-r--r-- | lib/gui/simulator/simulator_panel.py | 4 | ||||
| -rw-r--r-- | lib/gui/simulator/simulator_window.py | 3 | ||||
| -rw-r--r-- | lib/gui/simulator/view_panel.py | 17 |
9 files changed, 217 insertions, 2 deletions
diff --git a/icons/page.png b/icons/page.png Binary files differnew file mode 100644 index 00000000..34cea16c --- /dev/null +++ b/icons/page.png diff --git a/icons/page.svg b/icons/page.svg new file mode 100644 index 00000000..55eebeae --- /dev/null +++ b/icons/page.svg @@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + width="256" + height="256" + viewBox="0 0 256 256" + id="svg8375" + version="1.1" + inkscape:version="1.3 (1:1.3+202307231459+0e150ed6c4)" + sodipodi:docname="page.svg" + inkscape:export-filename="page.png" + inkscape:export-xdpi="96" + inkscape:export-ydpi="96" + 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" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <defs + id="defs8377"> + <filter + style="color-interpolation-filters:sRGB;" + inkscape:label="Blur" + id="filter2" + x="-0.10779408" + y="-0.10779408" + width="1.2155882" + height="1.2155882"> + <feGaussianBlur + stdDeviation="4 4" + result="fbSourceGraphic" + id="feGaussianBlur2" /> + <feColorMatrix + result="fbSourceGraphicAlpha" + in="fbSourceGraphic" + values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0" + id="feColorMatrix2" /> + <feGaussianBlur + id="feGaussianBlur3" + stdDeviation="6 6" + result="blur" + in="fbSourceGraphic" /> + </filter> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.979899" + inkscape:cx="94.449262" + inkscape:cy="142.68405" + inkscape:document-units="mm" + inkscape:current-layer="layer1" + showgrid="false" + units="mm" + inkscape:window-width="1366" + inkscape:window-height="705" + inkscape:window-x="-4" + inkscape:window-y="-4" + inkscape:window-maximized="1" + inkscape:showpageshadow="2" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" /> + <metadata + id="metadata8380"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <path + id="rect1-3" + style="stroke-width:0.755906;stroke-linejoin:round;filter:url(#filter2)" + d="M 31.662572,29.484143 H 254.30931 V 252.13088 H 31.662572 Z" + sodipodi:nodetypes="ccccc" + transform="matrix(0.91809316,0,0,0.91809316,8.0575784,8.0575784)" /> + <path + id="rect1" + style="fill:#ffffff;stroke:#000000;stroke-width:5;stroke-linejoin:round;stroke-dasharray:none" + d="M 20,18 H 217.95764 V 215.95764 H 20 Z" + sodipodi:nodetypes="ccccc" /> + </g> +</svg> diff --git a/icons/page_dark.png b/icons/page_dark.png Binary files differnew file mode 100644 index 00000000..89257dc0 --- /dev/null +++ b/icons/page_dark.png diff --git a/lib/debug/debug.py b/lib/debug/debug.py index ab5132e4..d96dd36d 100644 --- a/lib/debug/debug.py +++ b/lib/debug/debug.py @@ -5,6 +5,7 @@ import atexit # to save svg file on exit import time # to measure time of code block, use time.monotonic() instead of time.time() +import traceback from datetime import datetime from contextlib import contextmanager # to measure time of with block @@ -246,6 +247,18 @@ class Debug(object): if self.enabled: self.raw_log("completed %s, duration = %s", label, time.monotonic() - start) + def log_exception(self): + if self.enabled: + self.raw_log(traceback.format_exc()) + + @contextmanager + def log_exceptions(self): + try: + yield + except Exception: + self.log_exception() + raise + # global debug object debug = Debug() diff --git a/lib/extensions/simulator.py b/lib/extensions/simulator.py index 69f74b02..af793f03 100644 --- a/lib/extensions/simulator.py +++ b/lib/extensions/simulator.py @@ -7,6 +7,7 @@ import wx from ..gui.simulator import SimulatorWindow from ..stitch_plan import stitch_groups_to_stitch_plan +from ..svg import convert_length from ..utils.svg_data import get_pagecolor from .base import InkstitchExtension @@ -37,5 +38,33 @@ class Simulator(InkstitchExtension): app.SetTopWindow(simulator) simulator.Show() simulator.load(stitch_plan) + simulator.set_page_specs(self.get_page_specs(stitch_plan)) simulator.go() app.MainLoop() + + def get_page_specs(self, stitch_plan): + svg = self.document.getroot() + width = svg.get('width', 0) + height = svg.get('height', 0) + page_color = "white" + desk_color = "white" + border_color = "black" + show_page_shadow = "true" + + named_view = svg.namedview + if named_view is not None: + page_color = named_view.get('pagecolor', page_color) + desk_color = named_view.get('inkscape:deskcolor', desk_color) + border_color = named_view.get('bordercolor', border_color) + show_page_shadow = named_view.get('inkscape:showpageshadow', show_page_shadow) in ['true', 'yes', 'y', '1', '2'] + + return { + "width": convert_length(width), + "height": convert_length(height), + "x": stitch_plan.bounding_box[0], + "y": stitch_plan.bounding_box[1], + "page_color": page_color, + "desk_color": desk_color, + "border_color": border_color, + "show_page_shadow": show_page_shadow + } diff --git a/lib/gui/simulator/drawing_panel.py b/lib/gui/simulator/drawing_panel.py index 9b705716..0d1b0afe 100644 --- a/lib/gui/simulator/drawing_panel.py +++ b/lib/gui/simulator/drawing_panel.py @@ -7,6 +7,7 @@ import time import wx from numpy import split +from ...debug.debug import debug from ...i18n import _ from ...svg import PIXELS_PER_MM from ...utils.settings import global_settings @@ -59,6 +60,9 @@ class DrawingPanel(wx.Panel): self.width = 0 self.height = 0 self.loaded = False + self.page_specs = {} + self.show_page = True + self.background_color = None # desired simulation speed in stitches per second self.speed = 16 @@ -122,6 +126,34 @@ class DrawingPanel(wx.Panel): self.draw_stitches(canvas) self.draw_scale(canvas) + def draw_page(self, canvas): + self._update_background_color() + + if not self.page_specs or not self.show_page: + return + + with debug.log_exceptions(): + border_color = wx.Colour(self.page_specs['border_color']) + if self.page_specs['show_page_shadow']: + canvas.SetPen(wx.TRANSPARENT_PEN) + canvas.SetBrush(canvas.CreateBrush(wx.Brush(wx.Colour(border_color.Red(), border_color.Green(), border_color.Blue(), alpha=65)))) + canvas.DrawRoundedRectangle( + (-self.page_specs['x'] + 4) * self.PIXEL_DENSITY, (-self.page_specs['y'] + 4) * self.PIXEL_DENSITY, + self.page_specs['width'] * self.PIXEL_DENSITY, self.page_specs['height'] * self.PIXEL_DENSITY, + 1 * self.PIXEL_DENSITY + ) + + pen = canvas.CreatePen( + wx.GraphicsPenInfo(wx.Colour(border_color)).Width(1 * self.PIXEL_DENSITY).Join(wx.JOIN_MITER) + ) + canvas.SetPen(pen) + canvas.SetBrush(wx.Brush(wx.Colour(self.background_color or self.page_specs['page_color']))) + + canvas.DrawRectangle( + -self.page_specs['x'] * self.PIXEL_DENSITY, -self.page_specs['y'] * self.PIXEL_DENSITY, + self.page_specs['width'] * self.PIXEL_DENSITY, self.page_specs['height'] * self.PIXEL_DENSITY + ) + def draw_stitches(self, canvas): canvas.BeginLayer(1) @@ -130,6 +162,8 @@ class DrawingPanel(wx.Panel): transform.Scale(self.zoom / self.PIXEL_DENSITY, self.zoom / self.PIXEL_DENSITY) canvas.SetTransform(transform) + self.draw_page(canvas) + stitch = 0 last_stitch = None @@ -252,6 +286,28 @@ class DrawingPanel(wx.Panel): if hasattr(self.view_panel, 'info_panel'): self.view_panel.info_panel.update() + def set_page_specs(self, page_specs): + self.SetBackgroundColour(page_specs['desk_color']) + self.page_specs = page_specs + + def set_background_color(self, color): + self.background_color = color + # this refresh is necessary for macOS + self.Refresh() + + def _update_background_color(self): + if not self.page_specs: + self.SetBackgroundColour(self.background_color or "#FFFFFF") + else: + if self.show_page: + self.SetBackgroundColour(self.page_specs['desk_color']) + else: + self.SetBackgroundColour(self.background_color or self.page_specs['page_color']) + + def set_show_page(self, show_page): + self.show_page = show_page + self._update_background_color() + def choose_zoom_and_pan(self, event=None): # ignore if EVT_SIZE fired before we load the stitch plan if not self.width and not self.height and event is not None: diff --git a/lib/gui/simulator/simulator_panel.py b/lib/gui/simulator/simulator_panel.py index 593b551a..1cea9214 100644 --- a/lib/gui/simulator/simulator_panel.py +++ b/lib/gui/simulator/simulator_panel.py @@ -30,6 +30,7 @@ class SimulatorPanel(wx.Panel): self.cp.set_drawing_panel(self.dp) self.vp.set_drawing_panel(self.dp) self.vp.set_background_color(wx.Colour(background_color)) + self.dp.set_background_color(wx.Colour(background_color)) dvSizer = wx.BoxSizer(wx.HORIZONTAL) @@ -93,3 +94,6 @@ class SimulatorPanel(wx.Panel): def clear(self): self.dp.clear() self.cp.clear() + + def set_page_specs(self, page_specs): + self.dp.set_page_specs(page_specs) diff --git a/lib/gui/simulator/simulator_window.py b/lib/gui/simulator/simulator_window.py index 2318041b..6ddc6f33 100644 --- a/lib/gui/simulator/simulator_window.py +++ b/lib/gui/simulator/simulator_window.py @@ -53,3 +53,6 @@ class SimulatorWindow(wx.Frame): def go(self): self.panel.go() + + def set_page_specs(self, page_specs): + self.panel.set_page_specs(page_specs) diff --git a/lib/gui/simulator/view_panel.py b/lib/gui/simulator/view_panel.py index 9cfe3331..27a89352 100644 --- a/lib/gui/simulator/view_panel.py +++ b/lib/gui/simulator/view_panel.py @@ -56,6 +56,13 @@ class ViewPanel(ScrolledPanel): self.btnBackgroundColor.SetToolTip(_("Change background color")) self.btnBackgroundColor.Bind(wx.EVT_COLOURPICKER_CHANGED, self.on_update_background_color) + if not self.detach_callback: + self.btnPage = wx.BitmapToggleButton(self, -1, style=self.button_style) + self.btnPage.Bind(wx.EVT_TOGGLEBUTTON, self.toggle_page) + self.btnPage.SetValue(True) + self.btnPage.SetBitmap(self.control_panel.load_icon('page')) + self.btnPage.SetToolTip(_('Show page')) + self.btnSettings = wx.BitmapToggleButton(self, -1, style=self.button_style) self.btnSettings.SetToolTip(_('Open settings dialog')) self.btnSettings.SetBitmap(self.control_panel.load_icon('settings')) @@ -94,6 +101,8 @@ class ViewPanel(ScrolledPanel): settings_sizer = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, _("Settings")), wx.VERTICAL) settings_inner_sizer = wx.BoxSizer(wx.VERTICAL) settings_inner_sizer.Add(self.btnBackgroundColor, 0, wx.EXPAND | wx.ALL, 2) + if not self.detach_callback: + settings_inner_sizer.Add(self.btnPage, 0, wx.EXPAND | wx.ALL, 2) settings_inner_sizer.Add(self.btnSettings, 0, wx.EXPAND | wx.ALL, 2) if self.detach_callback: settings_inner_sizer.Add(self.btnDetachSimulator, 0, wx.ALL, 2) @@ -109,11 +118,10 @@ class ViewPanel(ScrolledPanel): def on_update_background_color(self, event): self.set_background_color(event.Colour) + self.drawing_panel.set_background_color(event.Colour) def set_background_color(self, color): self.btnBackgroundColor.SetColour(color) - self.drawing_panel.SetBackgroundColour(color) - self.drawing_panel.Refresh() def on_toggle_npp_shortcut(self, event): self.btnNpp.SetValue(not self.btnNpp.GetValue()) @@ -122,6 +130,11 @@ class ViewPanel(ScrolledPanel): def toggle_npp(self, event): self.drawing_panel.Refresh() + def toggle_page(self, event): + debug.log("toggle page") + self.drawing_panel.set_show_page(self.btnPage.GetValue()) + self.drawing_panel.Refresh() + def on_marker_button(self, marker_type, event): self.control_panel.slider.enable_marker_list(marker_type, event.GetEventObject().GetValue()) if marker_type == 'jump': |
