summaryrefslogtreecommitdiff
path: root/lib/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'lib/extensions')
-rw-r--r--lib/extensions/__init__.py2
-rw-r--r--lib/extensions/base.py12
-rw-r--r--lib/extensions/cleanup.py4
-rw-r--r--lib/extensions/params.py81
-rw-r--r--lib/extensions/selection_to_guide_line.py67
5 files changed, 145 insertions, 21 deletions
diff --git a/lib/extensions/__init__.py b/lib/extensions/__init__.py
index b6e0d1d1..933720c9 100644
--- a/lib/extensions/__init__.py
+++ b/lib/extensions/__init__.py
@@ -39,6 +39,7 @@ from .print_pdf import Print
from .remove_embroidery_settings import RemoveEmbroiderySettings
from .reorder import Reorder
from .selection_to_pattern import SelectionToPattern
+from .selection_to_guide_line import SelectionToGuideLine
from .simulator import Simulator
from .stitch_plan_preview import StitchPlanPreview
from .zip import Zip
@@ -52,6 +53,7 @@ __all__ = extensions = [StitchPlanPreview,
Zip,
Flip,
SelectionToPattern,
+ SelectionToGuideLine,
ObjectCommands,
ObjectCommandsToggleVisibility,
LayerCommands,
diff --git a/lib/extensions/base.py b/lib/extensions/base.py
index 75a07c5a..56385458 100644
--- a/lib/extensions/base.py
+++ b/lib/extensions/base.py
@@ -10,7 +10,6 @@ from collections.abc import MutableMapping
import inkex
from lxml import etree
-from lxml.etree import Comment
from stringcase import snakecase
from ..commands import is_command, layer_commands
@@ -20,8 +19,7 @@ from ..i18n import _
from ..patterns import is_pattern
from ..svg import generate_unique_id
from ..svg.tags import (CONNECTOR_TYPE, EMBROIDERABLE_TAGS, INKSCAPE_GROUPMODE,
- NOT_EMBROIDERABLE_TAGS, SVG_CLIPPATH_TAG, SVG_DEFS_TAG,
- SVG_GROUP_TAG, SVG_MASK_TAG)
+ NOT_EMBROIDERABLE_TAGS, SVG_DEFS_TAG, SVG_GROUP_TAG)
SVG_METADATA_TAG = inkex.addNS("metadata", "svg")
@@ -131,10 +129,6 @@ class InkstitchExtension(inkex.Effect):
def descendants(self, node, selected=False, troubleshoot=False): # noqa: C901
nodes = []
-
- if node.tag == Comment:
- return []
-
element = EmbroideryElement(node)
if element.has_command('ignore_object'):
@@ -147,9 +141,7 @@ class InkstitchExtension(inkex.Effect):
if (node.tag in EMBROIDERABLE_TAGS or node.tag == SVG_GROUP_TAG) and element.get_style('display', 'inline') is None:
return []
- # defs, masks and clippaths can contain embroiderable elements
- # but should never be rendered directly.
- if node.tag in [SVG_DEFS_TAG, SVG_MASK_TAG, SVG_CLIPPATH_TAG]:
+ if node.tag == SVG_DEFS_TAG:
return []
# command connectors with a fill color set, will glitch into the elements list
diff --git a/lib/extensions/cleanup.py b/lib/extensions/cleanup.py
index a38818b8..ae95041b 100644
--- a/lib/extensions/cleanup.py
+++ b/lib/extensions/cleanup.py
@@ -5,7 +5,7 @@
from inkex import NSS, Boolean, errormsg
-from ..elements import Fill, Stroke
+from ..elements import AutoFill, Stroke
from ..i18n import _
from .base import InkstitchExtension
@@ -38,7 +38,7 @@ class Cleanup(InkstitchExtension):
return
for element in self.elements:
- if (isinstance(element, Fill) and self.rm_fill and element.shape.area < self.fill_threshold):
+ if (isinstance(element, AutoFill) and self.rm_fill and element.shape.area < self.fill_threshold):
element.node.getparent().remove(element.node)
count += 1
if (isinstance(element, Stroke) and self.rm_stroke and
diff --git a/lib/extensions/params.py b/lib/extensions/params.py
index c96b9691..8021d5d7 100644
--- a/lib/extensions/params.py
+++ b/lib/extensions/params.py
@@ -7,15 +7,15 @@
import os
import sys
-from collections import defaultdict
+from collections import defaultdict,namedtuple
from copy import copy
-from itertools import groupby
+from itertools import groupby,zip_longest
import wx
from wx.lib.scrolledpanel import ScrolledPanel
from ..commands import is_command, is_command_symbol
-from ..elements import (AutoFill, Clone, EmbroideryElement, Fill, Polyline,
+from ..elements import (AutoFill, Clone, EmbroideryElement, Polyline,
SatinColumn, Stroke)
from ..elements.clone import is_clone
from ..gui import PresetsPanel, SimulatorPreview, WarningPanel
@@ -25,6 +25,14 @@ from ..utils import get_resource_dir
from .base import InkstitchExtension
+#ChoiceWidgets = namedtuple("ChoiceWidgets", "param widget last_initialized_choice")
+
+
+
+def grouper(iterable_obj, count, fillvalue=None):
+ args = [iter(iterable_obj)] * count
+ return zip_longest(*args, fillvalue=fillvalue)
+
class ParamsTab(ScrolledPanel):
def __init__(self, *args, **kwargs):
self.params = kwargs.pop('params', [])
@@ -38,6 +46,8 @@ class ParamsTab(ScrolledPanel):
self.dependent_tabs = []
self.parent_tab = None
self.param_inputs = {}
+ self.choice_widgets = defaultdict(list)
+ self.dict_of_choices = {}
self.paired_tab = None
self.disable_notify_pair = False
@@ -113,6 +123,19 @@ class ParamsTab(ScrolledPanel):
if event:
event.Skip()
+ def update_choice_state(self, event=None):
+ input = event.GetEventObject()
+ selection = input.GetSelection()
+
+ param = self.inputs_to_params[input]
+
+ self.update_choice_widgets((param, selection))
+ self.settings_grid.Layout()
+ self.Layout()
+
+ if event:
+ event.Skip()
+
def pair_changed(self, value):
# print self.name, "pair_changed", value
new_value = not value
@@ -245,7 +268,30 @@ class ParamsTab(ScrolledPanel):
# end wxGlade
pass
- def __do_layout(self):
+ #choice tuple is None or contains ("choice widget param name", "actual selection")
+ def update_choice_widgets(self, choice_tuple = None):
+ if choice_tuple == None: #update all choices
+ for choice in self.dict_of_choices.values():
+ self.update_choice_widgets((choice["param"].name, choice["widget"].GetSelection()))
+ else:
+ choice = self.dict_of_choices[choice_tuple[0]]
+ last_selection = choice["last_initialized_choice"]
+ current_selection = choice["widget"].GetSelection()
+ if last_selection != -1 and last_selection != current_selection: #Hide the old widgets
+ for widget in self.choice_widgets[(choice["param"].name, last_selection)]:
+ widget.Hide()
+ #self.settings_grid.Detach(widget)
+
+ #choice_index = self.settings_grid.GetChildren().index(self.settings_grid.GetItem(choice["widget"])) #TODO: is there a better way to get the index in the sizer?
+ for widgets in grouper(self.choice_widgets[choice_tuple], 4):
+ widgets[0].Show(True)
+ widgets[1].Show(True)
+ widgets[2].Show(True)
+ widgets[3].Show(True)
+ choice["last_initialized_choice"] = current_selection
+
+ def __do_layout(self, only_settings_grid=False):
+
# just to add space around the settings
box = wx.BoxSizer(wx.VERTICAL)
@@ -266,14 +312,20 @@ class ParamsTab(ScrolledPanel):
box.Add(toggle_sizer, proportion=0, flag=wx.BOTTOM, border=10)
for param in self.params:
- self.settings_grid.Add(self.create_change_indicator(param.name), proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-
+ col1 = self.create_change_indicator(param.name)
description = wx.StaticText(self, label=param.description)
description.SetToolTip(param.tooltip)
+
+ if param.select_items != None:
+ col1.Hide()
+ description.Hide()
+ for item in param.select_items:
+ self.choice_widgets[item].extend([col1, description])
+ #else:
+ self.settings_grid.Add(col1, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
self.settings_grid.Add(description, proportion=1, flag=wx.EXPAND | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.TOP, border=5)
if param.type == 'boolean':
-
if len(param.values) > 1:
input = wx.CheckBox(self, style=wx.CHK_3STATE)
input.Set3StateValue(wx.CHK_UNDETERMINED)
@@ -287,6 +339,8 @@ class ParamsTab(ScrolledPanel):
input = wx.Choice(self, wx.ID_ANY, choices=param.options)
input.SetSelection(int(param.values[0]))
input.Bind(wx.EVT_CHOICE, self.changed)
+ input.Bind(wx.EVT_CHOICE, self.update_choice_state)
+ self.dict_of_choices[param.name] = {"param": param, "widget": input, "last_initialized_choice": 1}
elif len(param.values) > 1:
input = wx.ComboBox(self, wx.ID_ANY, choices=sorted(str(value) for value in param.values), style=wx.CB_DROPDOWN)
input.Bind(wx.EVT_COMBOBOX, self.changed)
@@ -298,13 +352,22 @@ class ParamsTab(ScrolledPanel):
self.param_inputs[param.name] = input
+ col4 = wx.StaticText(self, label=param.unit or "")
+
+ if param.select_items != None:
+ input.Hide()
+ col4.Hide()
+ for item in param.select_items:
+ self.choice_widgets[item].extend([input, col4])
+ #else:
self.settings_grid.Add(input, proportion=1, flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND | wx.LEFT, border=40)
- self.settings_grid.Add(wx.StaticText(self, label=param.unit or ""), proportion=1, flag=wx.ALIGN_CENTER_VERTICAL)
+ self.settings_grid.Add(col4, proportion=1, flag=wx.ALIGN_CENTER_VERTICAL)
self.inputs_to_params = {v: k for k, v in self.param_inputs.items()}
box.Add(self.settings_grid, proportion=1, flag=wx.ALL, border=10)
self.SetSizer(box)
+ self.update_choice_widgets()
self.Layout()
@@ -521,7 +584,7 @@ class Params(InkstitchExtension):
else:
if element.get_style("fill", 'black') and not element.get_style("fill-opacity", 1) == "0":
classes.append(AutoFill)
- classes.append(Fill)
+ #classes.append(Fill)
if element.get_style("stroke") is not None:
classes.append(Stroke)
if element.get_style("stroke-dasharray") is None:
diff --git a/lib/extensions/selection_to_guide_line.py b/lib/extensions/selection_to_guide_line.py
new file mode 100644
index 00000000..85a44bb1
--- /dev/null
+++ b/lib/extensions/selection_to_guide_line.py
@@ -0,0 +1,67 @@
+# Authors: see git history
+#
+# Copyright (c) 2021 Authors
+# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
+
+import inkex
+from lxml import etree
+
+from ..i18n import _
+from ..svg.tags import SVG_PATH_TAG, SVG_POLYLINE_TAG, SVG_DEFS_TAG
+from .base import InkstitchExtension
+
+
+class SelectionToGuideLine(InkstitchExtension):
+
+ def effect(self):
+ if not self.get_elements():
+ return
+
+ if not self.svg.selected:
+ inkex.errormsg(_("Please select one object to be marked as a guide line."))
+ return
+
+ if len(self.get_nodes())!=1:
+ inkex.errormsg(_("Please select only one object to be marked as a guide line."))
+ return
+
+ for guide_line in self.get_nodes():
+ if guide_line.tag in (SVG_PATH_TAG, SVG_POLYLINE_TAG):
+ self.set_marker(guide_line)
+
+ def set_marker(self, node):
+ xpath = ".//marker[@id='inkstitch-guide-line-marker']"
+ guide_line_marker = self.document.xpath(xpath)
+
+ if not guide_line_marker:
+ # get or create def element
+ defs = self.document.find(SVG_DEFS_TAG)
+ if defs is None:
+ defs = etree.SubElement(self.document, SVG_DEFS_TAG)
+
+ # insert marker
+ marker = """<marker
+ refX="10"
+ refY="5"
+ orient="auto"
+ id="inkstitch-guide-line-marker">
+ <g
+ id="inkstitch-guide-line-group">
+ <path
+ style="fill:#fafafa;stroke:#ff00ff;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0;stroke-opacity:1;fill-opacity:0.8;"
+ d="M 10.12911,5.2916678 A 4.8374424,4.8374426 0 0 1 5.2916656,10.12911 4.8374424,4.8374426 0 0 1 0.45422399,5.2916678 4.8374424,4.8374426 0 0 1 5.2916656,0.45422399 4.8374424,4.8374426 0 0 1 10.12911,5.2916678 Z"
+ id="inkstitch-guide-line-marker-circle" />
+ <path
+ style="fill:none;stroke:#ff00ff;stroke-width:0.4;stroke-linecap:round;stroke-miterlimit:4;"
+ id="inkstitch-guide-line-marker-spiral"
+ d="M 4.9673651,5.7245662 C 4.7549848,5.7646159 4.6247356,5.522384 4.6430021,5.3419847 4.6765851,5.0103151 5.036231,4.835347 5.3381858,4.8987426 5.7863901,4.9928495 6.0126802,5.4853625 5.9002872,5.9065088 5.7495249,6.4714237 5.1195537,6.7504036 4.5799191,6.5874894 3.898118,6.3816539 3.5659013,5.6122905 3.7800789,4.9545192 4.0402258,4.1556558 4.9498996,3.7699484 5.7256318,4.035839 6.6416744,4.3498087 7.0810483,5.4003986 6.7631909,6.2939744 6.395633,7.3272552 5.2038143,7.8204128 4.1924535,7.4503931 3.0418762,7.0294421 2.4948761,5.6961604 2.9171752,4.567073 3.3914021,3.2991406 4.8663228,2.6982592 6.1130974,3.1729158 7.4983851,3.7003207 8.1531869,5.3169977 7.6260947,6.6814205 7.0456093,8.1841025 5.2870784,8.8928844 3.8050073,8.3132966 2.1849115,7.6797506 1.4221671,5.7793073 2.0542715,4.1796074 2.7408201,2.4420977 4.7832541,1.6253548 6.5005435,2.310012 8.3554869,3.0495434 9.2262638,5.2339874 8.4890181,7.0688861 8.4256397,7.2266036 8.3515789,7.379984 8.2675333,7.5277183" />
+ </g>
+ </marker>""" # noqa: E501
+ defs.append(etree.fromstring(marker))
+
+ # attach marker to node
+ style = node.get('style') or ''
+ style = style.split(";")
+ style = [i for i in style if not i.startswith('marker-start')]
+ style.append('marker-start:url(#inkstitch-guide-line-marker)')
+ node.set('style', ";".join(style))