kopia lustrzana https://github.com/inkstitch/inkstitch
192 wiersze
7.2 KiB
Python
192 wiersze
7.2 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: UTF-8 -*-
|
|
#
|
|
# Authors: see git history
|
|
#
|
|
# Copyright (c) 2023 Authors
|
|
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
|
|
|
import wx
|
|
import wx.adv
|
|
|
|
from ..i18n import _
|
|
from ..svg.tags import EMBROIDERABLE_TAGS
|
|
|
|
|
|
class GenerateSwatchesFrame(wx.Frame):
|
|
def __init__(self, *args, **kwargs):
|
|
self.extension = kwargs.pop("extension")
|
|
self.choices = kwargs.pop("choices")
|
|
wx.Frame.__init__(self, *args, **kwargs)
|
|
wx.Frame.__init__(self, None, wx.ID_ANY, _("Generate Swatches"), *args, **kwargs)
|
|
|
|
self.SetWindowStyle(wx.FRAME_FLOAT_ON_PARENT | wx.DEFAULT_FRAME_STYLE)
|
|
|
|
self.panel = wx.Panel(self, wx.ID_ANY)
|
|
|
|
main_sizer = wx.BoxSizer(wx.VERTICAL)
|
|
|
|
self.notebook = wx.Notebook(self.panel, wx.ID_ANY)
|
|
main_sizer.Add(self.notebook, 0, wx.ALL | wx.EXPAND, 10)
|
|
|
|
self.options = wx.Panel(self.notebook, wx.ID_ANY)
|
|
self.notebook.AddPage(self.options, _("Options"))
|
|
|
|
options_sizer = wx.BoxSizer(wx.VERTICAL)
|
|
|
|
grid_main_sizer = wx.FlexGridSizer(6, 2, 10, 10)
|
|
options_sizer.Add(grid_main_sizer, 0, wx.ALL, 10)
|
|
|
|
param_label = wx.StaticText(self.options, wx.ID_ANY, _("Param"))
|
|
grid_main_sizer.Add(param_label, 0, 0, 0)
|
|
|
|
self.param = wx.ComboBox(self.options, wx.ID_ANY, choices=[])
|
|
for choice in self.choices:
|
|
self.param.Append(choice.name, choice)
|
|
self.param.SetSelection(0)
|
|
grid_main_sizer.Add(self.param, 0, 0, 0)
|
|
|
|
start_value_label = wx.StaticText(self.options, wx.ID_ANY, _("Start Value"))
|
|
grid_main_sizer.Add(start_value_label, 0, 0, 0)
|
|
|
|
self.start_value = wx.SpinCtrlDouble(self.options, wx.ID_ANY, initial=2.5, min=0.0, max=500.0)
|
|
self.start_value.SetDigits(2)
|
|
grid_main_sizer.Add(self.start_value, 0, 0, 0)
|
|
|
|
step_label = wx.StaticText(self.options, wx.ID_ANY, _("Increase by"))
|
|
grid_main_sizer.Add(step_label, 0, 0, 0)
|
|
|
|
self.step = wx.SpinCtrlDouble(self.options, wx.ID_ANY, initial=0.5, min=0.01, max=500.0)
|
|
self.step.SetDigits(2)
|
|
grid_main_sizer.Add(self.step, 0, 0, 0)
|
|
|
|
cols_label = wx.StaticText(self.options, wx.ID_ANY, _("Columns"))
|
|
grid_main_sizer.Add(cols_label, 0, 0, 0)
|
|
|
|
self.columns = wx.SpinCtrl(self.options, wx.ID_ANY, "0", min=1, max=100)
|
|
grid_main_sizer.Add(self.columns, 0, 0, 0)
|
|
|
|
rows_label = wx.StaticText(self.options, wx.ID_ANY, _("Rows"))
|
|
grid_main_sizer.Add(rows_label, 0, 0, 0)
|
|
|
|
self.rows = wx.SpinCtrl(self.options, wx.ID_ANY, "0", min=1, max=100)
|
|
grid_main_sizer.Add(self.rows, 0, 0, 0)
|
|
|
|
spacing_label = wx.StaticText(self.options, wx.ID_ANY, _("Spacing"))
|
|
grid_main_sizer.Add(spacing_label, 0, 0, 0)
|
|
|
|
self.spacing = wx.SpinCtrlDouble(self.options, wx.ID_ANY, initial=5, min=0.0, max=100.0)
|
|
self.spacing.SetDigits(2)
|
|
grid_main_sizer.Add(self.spacing, 0, 0, 0)
|
|
|
|
self.info = wx.Panel(self.notebook, wx.ID_ANY)
|
|
self.notebook.AddPage(self.info, _("Help"))
|
|
|
|
info_sizer = wx.BoxSizer(wx.VERTICAL)
|
|
|
|
info_text_label = wx.StaticText(
|
|
self.info,
|
|
wx.ID_ANY,
|
|
_("This extension generates test swatches from a selection.\n"
|
|
"Test swatches help to find best stitch settings for your design.\n"
|
|
"Sew them out with the same thread and fabric as the final designs."),
|
|
style=wx.ALIGN_LEFT
|
|
)
|
|
info_text_label.Wrap(500)
|
|
info_sizer.Add(info_text_label, 0, wx.ALL, 8)
|
|
|
|
info_sizer.Add((20, 20), 0, 0, 0)
|
|
|
|
more_info_label = wx.StaticText(self.info, wx.ID_ANY, _("Get more information on our website"))
|
|
info_sizer.Add(more_info_label, 0, wx.ALL, 8)
|
|
|
|
self.help_link = wx.adv.HyperlinkCtrl(
|
|
self.info,
|
|
wx.ID_ANY,
|
|
_("https://inkstitch.org/docs/edit/#generate-test-swatches-from-selection"),
|
|
_("https://inkstitch.org/docs/edit/#generate-test-swatches-from-selection"),
|
|
style=wx.adv.HL_ALIGN_CENTRE
|
|
)
|
|
info_sizer.Add(self.help_link, 0, 0, 0)
|
|
|
|
button_sizer = wx.StdDialogButtonSizer()
|
|
main_sizer.Add(button_sizer, 1, wx.BOTTOM | wx.EXPAND, 10)
|
|
|
|
button_sizer.Add((0, 0), 1, 0, 0)
|
|
|
|
self.apply_button = wx.Button(self.panel, wx.ID_ANY, _("Apply"))
|
|
button_sizer.Add(self.apply_button, 0, wx.RIGHT, 10)
|
|
|
|
self.options.SetSizer(options_sizer)
|
|
self.info.SetSizer(info_sizer)
|
|
self.panel.SetSizer(main_sizer)
|
|
|
|
main_sizer.Fit(self)
|
|
self.Layout()
|
|
self.SetSizeHints(main_sizer.CalcMin())
|
|
|
|
self.param.Bind(wx.EVT_TEXT, self.on_text_input)
|
|
self.Bind(wx.EVT_BUTTON, self.apply_button_clicked, self.apply_button)
|
|
|
|
def on_text_input(self, event):
|
|
# this will allow us to catch manual text input, but
|
|
# we only want to catch it when we actually create the swatches
|
|
pass
|
|
|
|
def apply_button_clicked(self, event):
|
|
self.apply()
|
|
self.Destroy()
|
|
|
|
def apply(self):
|
|
num_cols = self.columns.GetValue()
|
|
num_rows = self.rows.GetValue()
|
|
spacing = self.spacing.GetValue()
|
|
|
|
start_value = self.start_value.GetValue()
|
|
step = self.step.GetValue()
|
|
|
|
choice_names = [choice.name for choice in self.choices]
|
|
if self.param.GetValue() not in choice_names:
|
|
# catch manual text input
|
|
param = self.param.GetValue()
|
|
if param.startswith("inkstitch:"):
|
|
param = param[10:]
|
|
else:
|
|
param = self.choices[self.param.GetSelection()].id
|
|
|
|
for element in self.extension.svg.selection:
|
|
dimensions = element.bounding_box()
|
|
param_value = start_value
|
|
for rows in range(0, num_rows):
|
|
for cols in range(0, num_cols):
|
|
new_element = element.duplicate()
|
|
translate_x = cols * dimensions.width + cols * spacing
|
|
translate_y = rows * dimensions.height + rows * spacing
|
|
new_element.transform.add_translate((translate_x, translate_y))
|
|
if new_element.TAG == "g":
|
|
for embroidery_element in new_element.iterdescendants(EMBROIDERABLE_TAGS):
|
|
# Since this won't effect functionality, we can simply ignore the fact
|
|
# that this will also set the value to patterns, guide lines etc.
|
|
self._set_param(embroidery_element, param, param_value)
|
|
else:
|
|
self._set_param(new_element, param, param_value)
|
|
param_value += step
|
|
# remove old element
|
|
element.delete()
|
|
|
|
def _set_param(self, element, param, value):
|
|
element.set(f'inkstitch:{ param }', value)
|
|
|
|
|
|
class GenerateSwatchesApp(wx.App):
|
|
def __init__(self, extension, choices):
|
|
self.extension = extension
|
|
self.choices = choices
|
|
super().__init__()
|
|
|
|
def OnInit(self):
|
|
self.frame = GenerateSwatchesFrame(extension=self.extension, choices=self.choices)
|
|
self.SetTopWindow(self.frame)
|
|
self.frame.Show()
|
|
return True
|