summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLex Neva <lexelby@users.noreply.github.com>2024-08-08 09:43:36 -0400
committerGitHub <noreply@github.com>2024-08-08 09:43:36 -0400
commit47ad76f513846a8501f84c057b28a146031859b6 (patch)
tree0d29cb0f87473f925c07f9b58949357ae1cf141d
parent17b88ce2c14a0802e18e90d8dd142224013dfb15 (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.pngbin0 -> 3191 bytes
-rw-r--r--icons/page.svg97
-rw-r--r--icons/page_dark.pngbin0 -> 3145 bytes
-rw-r--r--lib/debug/debug.py13
-rw-r--r--lib/extensions/simulator.py29
-rw-r--r--lib/gui/simulator/drawing_panel.py56
-rw-r--r--lib/gui/simulator/simulator_panel.py4
-rw-r--r--lib/gui/simulator/simulator_window.py3
-rw-r--r--lib/gui/simulator/view_panel.py17
9 files changed, 217 insertions, 2 deletions
diff --git a/icons/page.png b/icons/page.png
new file mode 100644
index 00000000..34cea16c
--- /dev/null
+++ b/icons/page.png
Binary files differ
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
new file mode 100644
index 00000000..89257dc0
--- /dev/null
+++ b/icons/page_dark.png
Binary files differ
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':