kopia lustrzana https://github.com/inkstitch/inkstitch
preset-related fixes (#3931)
* fix manually clicking pencil icon * update choices when loading presets * ignore hidden and disabled params when applying and creating presets * mark selection param changed when a dependent param is changed * don't immediately apply when clicking 'Use Last Settings' * define on_change_hook in __init__ * make adding, updating, and deleting presets clearer * only skip satin param for strokes thinner than 0.3mm when they have only one subpathpull/3944/head dev-build-kaalleen-stroke-to-satin-start
rodzic
28eaecabf2
commit
d22f9d86f4
|
|
@ -16,6 +16,7 @@ import wx
|
|||
from wx.lib.scrolledpanel import ScrolledPanel
|
||||
|
||||
from ..commands import is_command, is_command_symbol
|
||||
from ..debug.debug import debug
|
||||
from ..elements import (Clone, EmbroideryElement, FillStitch, SatinColumn,
|
||||
Stroke)
|
||||
from ..elements.clone import is_clone
|
||||
|
|
@ -52,11 +53,14 @@ class ParamsTab(ScrolledPanel):
|
|||
self.changed_inputs = set()
|
||||
self.dependent_tabs = []
|
||||
self.parent_tab = None
|
||||
self.param_inputs = {}
|
||||
self.param_name_to_input = {}
|
||||
self.input_to_param_name = {}
|
||||
self.param_name_to_param = {param.name: param for param in self.params}
|
||||
self.choice_widgets = defaultdict(list)
|
||||
self.dict_of_choices = {}
|
||||
self.paired_tab = None
|
||||
self.disable_notify_pair = False
|
||||
self.on_change_hook = None
|
||||
|
||||
toggles = [param for param in self.params if param.type == 'toggle']
|
||||
|
||||
|
|
@ -75,7 +79,7 @@ class ParamsTab(ScrolledPanel):
|
|||
wx.EVT_CHECKBOX, self.update_toggle_state)
|
||||
self.toggle_checkbox.Bind(wx.EVT_CHECKBOX, self.changed)
|
||||
|
||||
self.param_inputs[self.toggle.name] = self.toggle_checkbox
|
||||
self.param_name_to_input[self.toggle.name] = self.toggle_checkbox
|
||||
else:
|
||||
self.toggle = None
|
||||
|
||||
|
|
@ -105,8 +109,7 @@ class ParamsTab(ScrolledPanel):
|
|||
# So let's add the satin column param to the list of changed_inputs right away - even when they didn't actively
|
||||
# change it
|
||||
if self.toggle and self.toggle.name == 'satin_column':
|
||||
self.enable_change_indicator(self.toggle.name)
|
||||
self.changed_inputs.add(self.toggle_checkbox)
|
||||
self.param_changed(self.toggle.name)
|
||||
|
||||
self.update_enable_widgets()
|
||||
|
||||
|
|
@ -153,9 +156,9 @@ class ParamsTab(ScrolledPanel):
|
|||
else:
|
||||
selection = input.GetSelection()
|
||||
|
||||
param = self.inputs_to_params[input]
|
||||
param_name = self.input_to_param_name[input]
|
||||
|
||||
self.update_choice_widgets((param, selection))
|
||||
self.update_choice_widgets((param_name, selection))
|
||||
self.settings_grid.Layout()
|
||||
self.Fit()
|
||||
self.Layout()
|
||||
|
|
@ -196,7 +199,7 @@ class ParamsTab(ScrolledPanel):
|
|||
def set_toggle_state(self, value):
|
||||
if self.toggle_checkbox:
|
||||
self.toggle_checkbox.SetValue(value)
|
||||
self.changed_inputs.add(self.toggle_checkbox)
|
||||
self.param_changed(self.toggle.name)
|
||||
|
||||
def get_values(self):
|
||||
values = {}
|
||||
|
|
@ -214,24 +217,25 @@ class ParamsTab(ScrolledPanel):
|
|||
# because they're grayed out anyway.
|
||||
return values
|
||||
|
||||
for name, input in self.param_inputs.items():
|
||||
for name, input in self.param_name_to_input.items():
|
||||
if input in self.changed_inputs and input != self.toggle_checkbox:
|
||||
# there are two types of combo boxes:
|
||||
# 1. multiple values for the same param on selected elements - 2. param type
|
||||
# multiple values will be handled with the GetValue() method
|
||||
if name in self.dict_of_choices and self.dict_of_choices[name]['param'].type == 'combo':
|
||||
values[name] = input.GetClientData(input.GetSelection()).id
|
||||
elif isinstance(input, wx.Choice):
|
||||
values[name] = input.GetSelection()
|
||||
else:
|
||||
values[name] = input.GetValue()
|
||||
if input.IsEnabled() and input.IsShown():
|
||||
# there are two types of combo boxes:
|
||||
# 1. multiple values for the same param on selected elements - 2. param type
|
||||
# multiple values will be handled with the GetValue() method
|
||||
if name in self.dict_of_choices and self.dict_of_choices[name]['param'].type == 'combo':
|
||||
values[name] = input.GetClientData(input.GetSelection()).id
|
||||
elif isinstance(input, wx.Choice):
|
||||
values[name] = input.GetSelection()
|
||||
else:
|
||||
values[name] = input.GetValue()
|
||||
|
||||
return values
|
||||
|
||||
def on_reroll(self, event):
|
||||
if len(self.nodes) == 1:
|
||||
new_seed = str(randbelow(int(1e8)))
|
||||
input = self.param_inputs['random_seed']
|
||||
input = self.param_name_to_input['random_seed']
|
||||
input.SetValue(new_seed)
|
||||
self.changed_inputs.add(input)
|
||||
else:
|
||||
|
|
@ -247,7 +251,8 @@ class ParamsTab(ScrolledPanel):
|
|||
def apply(self):
|
||||
values = self.get_values()
|
||||
for node in self.nodes:
|
||||
if "satin_column" in values.keys() and values["satin_column"] is True and node.stroke_width < 0.3 * PIXELS_PER_MM:
|
||||
if ("satin_column" in values.keys() and values["satin_column"] is True and
|
||||
len(node.paths) == 1 and node.stroke_width < 0.3 * PIXELS_PER_MM):
|
||||
# when we apply satin columns, strokes (running stitches) are not rendered in the simulator
|
||||
# and we also don't want to set any of the chosen values to these elements as this may lead to unexpected rendering results
|
||||
continue
|
||||
|
|
@ -259,35 +264,61 @@ class ParamsTab(ScrolledPanel):
|
|||
|
||||
def changed(self, event):
|
||||
input = event.GetEventObject()
|
||||
self.changed_inputs.add(input)
|
||||
|
||||
param = self.inputs_to_params[input]
|
||||
self.enable_change_indicator(param)
|
||||
param_name = self.input_to_param_name[input]
|
||||
self.param_changed(param_name)
|
||||
event.Skip()
|
||||
|
||||
def param_changed(self, param_name):
|
||||
param = self.param_name_to_param[param_name]
|
||||
input = self.param_name_to_input[param_name]
|
||||
self.changed_inputs.add(input)
|
||||
self.enable_change_indicator(param_name)
|
||||
|
||||
# If they change a param enabled by a parent param, then we should
|
||||
# consider the parent param changed too. This ensures that all
|
||||
# selected embroidery elements get the effect of this param applied.
|
||||
# For example, if they change the meander pattern, we should ensure
|
||||
# that we're setting the fill type to meander on all selected elements.
|
||||
|
||||
debug.log(f"param_changed(): checking for parent params of {param.name} with selecT_items {param.select_items}")
|
||||
|
||||
for p in self.params:
|
||||
if p.enables is not None:
|
||||
if param.name in p.enables:
|
||||
self.param_changed(p.name)
|
||||
|
||||
if param.select_items:
|
||||
for choice_name, choice_value in param.select_items:
|
||||
debug.log(f"forcing changed on parent select item: {choice_name}")
|
||||
self.param_changed(choice_name)
|
||||
|
||||
if self.on_change_hook:
|
||||
self.on_change_hook(self)
|
||||
|
||||
def load_preset(self, preset):
|
||||
preset_data = preset.get(self.name, {})
|
||||
|
||||
# print(self.param_inputs, '\n\n', preset_data.items(), file=sys.stderr)
|
||||
|
||||
for name, value in preset_data.items():
|
||||
if name in self.param_inputs:
|
||||
if name in self.param_name_to_input:
|
||||
if name in self.dict_of_choices and self.dict_of_choices[name]['param'].type == 'combo':
|
||||
param = self.dict_of_choices[name]["param"]
|
||||
self.param_inputs[name].SetSelection(self.get_combo_value_index(value, param.options, param.default))
|
||||
elif isinstance(self.param_inputs[name], wx.Choice):
|
||||
self.param_inputs[name].SetSelection(int(value))
|
||||
self.param_name_to_input[name].SetSelection(self.get_combo_value_index(value, param.options, param.default))
|
||||
elif isinstance(self.param_name_to_input[name], wx.Choice):
|
||||
self.param_name_to_input[name].SetSelection(int(value))
|
||||
else:
|
||||
input = self.param_inputs[name]
|
||||
input = self.param_name_to_input[name]
|
||||
if name == "satin_column" and input.Label == _('Running stitch along paths'):
|
||||
value = not value
|
||||
input.SetValue(value)
|
||||
self.changed_inputs.add(self.param_inputs[name])
|
||||
self.changed_inputs.add(self.param_name_to_input[name])
|
||||
self.enable_change_indicator(name)
|
||||
|
||||
self.update_toggle_state()
|
||||
self.update_enable_widgets()
|
||||
self.update_choice_widgets()
|
||||
self.settings_grid.Layout()
|
||||
self.Fit()
|
||||
self.Layout()
|
||||
|
||||
def save_preset(self, storage):
|
||||
storage[self.name] = self.get_values()
|
||||
|
|
@ -371,9 +402,9 @@ class ParamsTab(ScrolledPanel):
|
|||
if event is None:
|
||||
for param in self.params:
|
||||
if param.enables is not None:
|
||||
value = self.param_inputs[param.name].GetValue()
|
||||
value = self.param_name_to_input[param.name].GetValue()
|
||||
for item in param.enables:
|
||||
enable_input = self.param_inputs[item]
|
||||
enable_input = self.param_name_to_input[item]
|
||||
enable_input.Enable(value)
|
||||
enable_input.GetPrevSibling().Enable(value)
|
||||
else:
|
||||
|
|
@ -385,7 +416,7 @@ class ParamsTab(ScrolledPanel):
|
|||
if param.enables is not None:
|
||||
value = input.GetValue()
|
||||
for item in param.enables:
|
||||
enable_input = self.param_inputs[item]
|
||||
enable_input = self.param_name_to_input[item]
|
||||
enable_input.Enable(value)
|
||||
enable_input.GetPrevSibling().Enable(value)
|
||||
|
||||
|
|
@ -472,7 +503,7 @@ class ParamsTab(ScrolledPanel):
|
|||
input = wx.TextCtrl(self, wx.ID_ANY, value=str(value))
|
||||
input.Bind(wx.EVT_TEXT, self.changed)
|
||||
|
||||
self.param_inputs[param.name] = input
|
||||
self.param_name_to_input[param.name] = input
|
||||
|
||||
if param.type == 'random_seed':
|
||||
col4 = wx.Button(self, wx.ID_ANY, _("Re-roll"))
|
||||
|
|
@ -490,7 +521,7 @@ class ParamsTab(ScrolledPanel):
|
|||
self.settings_grid.Add(input, flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.EXPAND, border=10)
|
||||
self.settings_grid.Add(col4, flag=wx.ALIGN_CENTER_VERTICAL)
|
||||
|
||||
self.inputs_to_params = {v: k for k, v in self.param_inputs.items()}
|
||||
self.input_to_param_name.update({v: k for k, v in self.param_name_to_input.items()})
|
||||
|
||||
box.Add(self.settings_grid, proportion=1, flag=wx.ALL | wx.EXPAND, border=10)
|
||||
|
||||
|
|
@ -500,20 +531,20 @@ class ParamsTab(ScrolledPanel):
|
|||
|
||||
self.Layout()
|
||||
|
||||
def create_change_indicator(self, param):
|
||||
def create_change_indicator(self, param_name):
|
||||
indicator = wx.Button(self, style=wx.BORDER_NONE |
|
||||
wx.BU_NOTEXT, size=(28, 28))
|
||||
indicator.SetToolTip(
|
||||
_('Click to force this parameter to be saved when you click "Apply and Quit"'))
|
||||
indicator.Bind(
|
||||
wx.EVT_BUTTON, lambda event: self.enable_change_indicator(param))
|
||||
wx.EVT_BUTTON, lambda event: self.param_changed(param_name))
|
||||
|
||||
self.param_change_indicators[param] = indicator
|
||||
self.param_change_indicators[param_name] = indicator
|
||||
return indicator
|
||||
|
||||
def enable_change_indicator(self, param):
|
||||
self.param_change_indicators[param].SetBitmapLabel(self.pencil_icon)
|
||||
self.param_change_indicators[param].SetToolTip(
|
||||
def enable_change_indicator(self, param_name):
|
||||
self.param_change_indicators[param_name].SetBitmapLabel(self.pencil_icon)
|
||||
self.param_change_indicators[param_name].SetToolTip(
|
||||
_('This parameter will be saved when you click "Apply and Quit"'))
|
||||
|
||||
# end of class SatinPane
|
||||
|
|
@ -672,7 +703,6 @@ class SettingsPanel(wx.Panel):
|
|||
|
||||
def use_last(self, event):
|
||||
self.presets_panel.load_preset("__LAST__")
|
||||
self.apply(event)
|
||||
|
||||
def close(self):
|
||||
self.simulator.stop()
|
||||
|
|
|
|||
|
|
@ -102,9 +102,12 @@ class PresetsPanel(wx.Panel):
|
|||
json.dump(presets, presets_file)
|
||||
|
||||
def update_preset_list(self):
|
||||
current_preset = self.preset_chooser.GetValue().strip()
|
||||
preset_names = list(self._load_presets().keys())
|
||||
preset_names = [preset for preset in preset_names if not self.is_hidden(preset)]
|
||||
self.preset_chooser.SetItems(sorted(preset_names))
|
||||
if current_preset in preset_names:
|
||||
self.preset_chooser.SetValue(current_preset)
|
||||
|
||||
def is_hidden(self, preset_name):
|
||||
return self.HIDDEN_PRESET_RE.match(preset_name)
|
||||
|
|
@ -141,6 +144,11 @@ class PresetsPanel(wx.Panel):
|
|||
|
||||
self.store_preset(preset_name, self.parent.get_preset_data())
|
||||
|
||||
if overwrite:
|
||||
info_dialog(self, _('Preset "%s" updated.') % preset_name)
|
||||
else:
|
||||
info_dialog(self, _('Preset "%s" added.') % preset_name)
|
||||
|
||||
event.Skip()
|
||||
|
||||
def overwrite_preset(self, event):
|
||||
|
|
@ -178,4 +186,6 @@ class PresetsPanel(wx.Panel):
|
|||
self.update_preset_list()
|
||||
self.preset_chooser.SetValue("")
|
||||
|
||||
info_dialog(self, _('Preset "%s" deleted.') % preset_name)
|
||||
|
||||
event.Skip()
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue