Extract settings field generation into individual classes

This commit is contained in:
John Lewin 2017-08-29 14:03:02 +03:00
parent 90d0b74244
commit 39fcb70e23
17 changed files with 1402 additions and 705 deletions

View file

@ -292,7 +292,22 @@
<Compile Include="SetupWizard\SetupWizardTroubleshooting.cs" />
<Compile Include="SetupWizard\SetupWizardWifi.cs" />
<Compile Include="SetupWizard\WizardWindow.cs" />
<Compile Include="SlicerConfiguration\UIFields\DoubleField.cs" />
<Compile Include="SlicerConfiguration\UIFields\DoubleOrPercentField.cs" />
<Compile Include="SlicerConfiguration\UIFields\IntOrMmField.cs" />
<Compile Include="SlicerConfiguration\UIFields\CheckboxField.cs" />
<Compile Include="SlicerConfiguration\UIFields\MultilineStringField.cs" />
<Compile Include="SlicerConfiguration\UIFields\ComPortField.cs" />
<Compile Include="SlicerConfiguration\UIFields\ListField.cs" />
<Compile Include="SlicerConfiguration\UIFields\HardwarePresetField.cs" />
<Compile Include="SlicerConfiguration\UIFields\Offset2Field.cs" />
<Compile Include="SlicerConfiguration\UIFields\Vector2Field.cs" />
<Compile Include="SlicerConfiguration\UIFields\StringField.cs" />
<Compile Include="SlicerConfiguration\UIFields\OffsetField.cs" />
<Compile Include="SlicerConfiguration\UIFields\IntField.cs" />
<Compile Include="SlicerConfiguration\UIFields\PositiveDoubleField.cs" />
<Compile Include="SlicerConfiguration\SettingsContext.cs" />
<Compile Include="SlicerConfiguration\UIFields\ISettingsField.cs" />
<Compile Include="SlicerConfiguration\Settings\GCodeMacro.cs" />
<Compile Include="SlicerConfiguration\Settings\ProfileMigrations.cs" />
<Compile Include="SlicerConfiguration\Settings\ProfileManager.cs" />

View file

@ -79,9 +79,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
private bool isPrimarySettingsView { get; set; }
PrinterConnection printerConnection;
static SliceSettingsWidget()
{
}
private EventHandler unregisterEvents;
public SliceSettingsWidget(PrinterConnection printerConnection, List<PrinterSettingsLayer> layerCascade = null, NamedSettingsLayers viewFilter = NamedSettingsLayers.All)
{
@ -127,6 +125,27 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
RebuildSliceSettingsTabs();
ActiveSliceSettings.SettingChanged.RegisterEvent(
(s, e) =>
{
if (e is StringEventArgs stringEvent)
{
string settingsKey = stringEvent.Data;
if (allFields.TryGetValue(settingsKey, out ISettingsField field))
{
string currentValue = settingsContext.GetValue(settingsKey);
if (field.Value != currentValue
|| settingsKey == "com_port")
{
field.Value = currentValue;
field.OnValueChanged(currentValue);
field.UpdateStyle();
}
}
}
},
ref unregisterEvents);
this.AnchorAll();
}
@ -291,8 +310,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
}
}
private EventHandler unregisterEvents;
public override void OnClosed(ClosedEventArgs e)
{
unregisterEvents?.Invoke(this, null);
@ -411,12 +428,12 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
topToBottomSettings.AddChild(
CreateSettingInfoUIControls(
printerConnection,
settingData,
settingsContext,
viewFilter,
copyIndex,
isPrimarySettingsView,
ref tabIndexForItem));
settingData,
settingsContext,
viewFilter,
copyIndex,
isPrimarySettingsView,
ref tabIndexForItem));
if (showHelpControls)
{
@ -608,6 +625,12 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
private static GuiWidget GetExtraSettingsWidget(SliceSettingData settingData)
{
// List elements contain list values in the field which normally contains label details, skip generation of invalid labels
if (settingData.DataEditType == SliceSettingData.DataEditTypes.LIST)
{
return null;
}
var nameHolder = new GuiWidget()
{
HAnchor = HAnchor.Stretch,
@ -622,52 +645,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
private class SettingsRow : FlowLayoutWidget
{
public string SettingsKey { get; set; }
public string SettingsValue { get; set; }
private EventHandler unregisterEvents;
/// <summary>
/// Gets or sets the delegate to be invoked when the settings values need to be refreshed. The implementation should
/// take the passed in text value and update its editor to reflect the latest value
/// </summary>
public Action<string> ValueChanged { get; set; }
public Action UpdateStyle { get; set; }
public SettingsRow(SettingsContext settingsContext)
{
Margin = new BorderDouble(0, 2);
Padding = new BorderDouble(3);
HAnchor = HAnchor.Stretch;
ActiveSliceSettings.SettingChanged.RegisterEvent((s, e) =>
{
if (((StringEventArgs)e).Data == SettingsKey)
{
string setting = settingsContext.GetValue(SettingsKey);
if (SettingsValue != setting
|| SettingsKey == "com_port")
{
SettingsValue = setting;
ValueChanged?.Invoke(setting);
}
UpdateStyle?.Invoke();
}
}, ref unregisterEvents);
}
public override void OnClosed(ClosedEventArgs e)
{
unregisterEvents?.Invoke(this, null);
base.OnClosed(e);
}
public void RefreshValue(SettingsContext settingsContext)
{
string latestValue = settingsContext.GetValue(this.SettingsKey);
SettingsValue = latestValue;
UpdateStyle?.Invoke();
ValueChanged?.Invoke(latestValue);
}
}
private static readonly RGBA_Bytes materialSettingBackgroundColor = new RGBA_Bytes(255, 127, 0, 108);
@ -739,7 +717,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
return dataArea;
}
public static GuiWidget CreateSettingControl(PrinterConnection printerConnection, string sliceSettingsKey, bool isPrimarySettingsView, ref int tabIndex)
public GuiWidget CreateSettingControl(PrinterConnection printerConnection, string sliceSettingsKey, bool isPrimarySettingsView, ref int tabIndex)
{
return CreateSettingInfoUIControls(
printerConnection,
@ -751,7 +729,9 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
ref tabIndex);
}
private static GuiWidget CreateSettingInfoUIControls(
Dictionary<string, ISettingsField> allFields = new Dictionary<string, ISettingsField>();
private GuiWidget CreateSettingInfoUIControls(
PrinterConnection printerConnection,
SliceSettingData settingData,
SettingsContext settingsContext,
@ -782,17 +762,21 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
Width = settingData.ShowAsOverride ? 30 * GuiWidget.DeviceScale : 0,
};
var settingsRow = new SettingsRow(settingsContext)
var settingsRow = new SettingsRow()
{
SettingsKey = settingData.SlicerConfigName,
SettingsValue = sliceSettingValue,
Margin = new BorderDouble(0, 2),
Padding = new BorderDouble(3),
HAnchor = HAnchor.Stretch
};
settingsRow.AddChild(nameArea);
settingsRow.AddChild(dataArea);
settingsRow.AddChild(unitsArea);
settingsRow.AddChild(restoreArea);
settingsRow.Name = settingData.SlicerConfigName + " Edit Field";
ISettingsField field = null;
if (!PrinterSettings.KnownSettings.Contains(settingData.SlicerConfigName))
{
// the setting we think we are adding is not in the known settings it may have been deprecated
@ -805,675 +789,70 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
{
int intEditWidth = (int)(60 * GuiWidget.DeviceScale + .5);
int doubleEditWidth = (int)(60 * GuiWidget.DeviceScale + .5);
int vectorXYEditWidth = (int)(60 * GuiWidget.DeviceScale + .5);
int multiLineEditHeight = (int)(120 * GuiWidget.DeviceScale + .5);
if (settingData.DataEditType != SliceSettingData.DataEditTypes.MULTI_LINE_TEXT)
{
nameArea.AddChild(new WrappedTextWidget(settingData.PresentationName.Localize(), pointSize: 10, textColor: ActiveTheme.Instance.PrimaryTextColor));
//nameArea.AddChild(new TextWidget(settingData.PresentationName.Localize(), pointSize: 10, textColor: ActiveTheme.Instance.PrimaryTextColor));
}
switch (settingData.DataEditType)
{
case SliceSettingData.DataEditTypes.INT:
{
FlowLayoutWidget content = new FlowLayoutWidget();
int currentValue;
int.TryParse(sliceSettingValue, out currentValue);
var intEditWidget = new MHNumberEdit(currentValue, pixelWidth: intEditWidth, tabIndex: tabIndexForItem++)
{
ToolTipText = settingData.HelpText,
SelectAllOnFocus = true,
Name = settingData.PresentationName + " Edit",
};
intEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
{
settingsContext.SetValue(settingData.SlicerConfigName, ((NumberEdit)sender).Value.ToString());
settingsRow.UpdateStyle();
};
content.AddChild(intEditWidget);
unitsArea.AddChild(GetExtraSettingsWidget(settingData));
if (settingData.QuickMenuSettings.Count > 0)
{
dataArea.AddChild(CreateQuickMenu(settingData, settingsContext, content, intEditWidget.ActuallNumberEdit.InternalTextEditWidget));
}
else
{
dataArea.AddChild(content);
}
settingsRow.ValueChanged = (text) =>
{
intEditWidget.Text = text;
};
}
field = new IntField();
break;
case SliceSettingData.DataEditTypes.DOUBLE:
{
double currentValue;
double.TryParse(sliceSettingValue, out currentValue);
var doubleEditWidget = new MHNumberEdit(currentValue, allowNegatives: true, allowDecimals: true, pixelWidth: doubleEditWidth, tabIndex: tabIndexForItem++)
{
ToolTipText = settingData.HelpText,
SelectAllOnFocus = true
};
doubleEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
{
settingsContext.SetValue(settingData.SlicerConfigName, ((NumberEdit)sender).Value.ToString());
settingsRow.UpdateStyle();
};
dataArea.AddChild(doubleEditWidget);
unitsArea.AddChild(GetExtraSettingsWidget(settingData));
settingsRow.ValueChanged = (text) =>
{
double currentValue2 = 0;
double.TryParse(text, out currentValue2);
doubleEditWidget.ActuallNumberEdit.Value = currentValue2;
};
}
field = new DoubleField();
break;
case SliceSettingData.DataEditTypes.POSITIVE_DOUBLE:
{
const string multiValuesAreDiffernt = "-";
FlowLayoutWidget content = new FlowLayoutWidget();
var doubleEditWidget = new MHNumberEdit(0, allowDecimals: true, pixelWidth: doubleEditWidth, tabIndex: tabIndexForItem++)
{
ToolTipText = settingData.HelpText,
Name = settingData.PresentationName + " Textbox",
SelectAllOnFocus = true
};
double currentValue;
bool ChangesMultipleOtherSettings = settingData.SetSettingsOnChange.Count > 0;
if (ChangesMultipleOtherSettings)
{
bool allTheSame = true;
string setting = settingsContext.GetValue(settingData.SetSettingsOnChange[0]["TargetSetting"]);
for (int i = 1; i < settingData.SetSettingsOnChange.Count; i++)
{
string nextSetting = settingsContext.GetValue(settingData.SetSettingsOnChange[i]["TargetSetting"]);
if (setting != nextSetting)
{
allTheSame = false;
break;
}
}
if (allTheSame && setting.EndsWith("mm"))
{
double.TryParse(setting.Substring(0, setting.Length - 2), out currentValue);
doubleEditWidget.ActuallNumberEdit.Value = currentValue;
}
else
{
doubleEditWidget.ActuallNumberEdit.InternalNumberEdit.Text = multiValuesAreDiffernt;
}
}
else // just set the setting normally
{
double.TryParse(sliceSettingValue, out currentValue);
doubleEditWidget.ActuallNumberEdit.Value = currentValue;
}
doubleEditWidget.ActuallNumberEdit.InternalTextEditWidget.MarkAsStartingState();
doubleEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
{
NumberEdit numberEdit = (NumberEdit)sender;
// If this setting sets other settings, then do that.
if (ChangesMultipleOtherSettings
&& numberEdit.Text != multiValuesAreDiffernt)
{
{
settingsContext.SetValue(settingData.SetSettingsOnChange[0]["TargetSetting"], numberEdit.Value.ToString() + "mm");
}
}
// also always save to the local setting
settingsContext.SetValue(settingData.SlicerConfigName, numberEdit.Value.ToString());
settingsRow.UpdateStyle();
};
content.AddChild(doubleEditWidget);
unitsArea.AddChild(GetExtraSettingsWidget(settingData));
if (settingData.QuickMenuSettings.Count > 0)
{
dataArea.AddChild(CreateQuickMenu(settingData, settingsContext, content, doubleEditWidget.ActuallNumberEdit.InternalTextEditWidget));
}
else
{
dataArea.AddChild(content);
}
settingsRow.ValueChanged = (text) =>
{
double currentValue2 = 0;
double.TryParse(text, out currentValue2);
doubleEditWidget.ActuallNumberEdit.Value = currentValue2;
};
}
field = new PositiveDoubleField();
break;
case SliceSettingData.DataEditTypes.OFFSET:
{
double currentValue;
double.TryParse(sliceSettingValue, out currentValue);
var doubleEditWidget = new MHNumberEdit(currentValue, allowDecimals: true, allowNegatives: true, pixelWidth: doubleEditWidth, tabIndex: tabIndexForItem++)
{
ToolTipText = settingData.HelpText,
SelectAllOnFocus = true
};
doubleEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
{
settingsContext.SetValue(settingData.SlicerConfigName, ((NumberEdit)sender).Value.ToString());
settingsRow.UpdateStyle();
};
dataArea.AddChild(doubleEditWidget);
unitsArea.AddChild(GetExtraSettingsWidget(settingData));
settingsRow.ValueChanged = (text) =>
{
double currentValue2;
double.TryParse(text, out currentValue2);
doubleEditWidget.ActuallNumberEdit.Value = currentValue2;
};
}
field = new OffsetField();
break;
case SliceSettingData.DataEditTypes.DOUBLE_OR_PERCENT:
{
FlowLayoutWidget content = new FlowLayoutWidget();
var stringEdit = new MHTextEditWidget(sliceSettingValue, pixelWidth: doubleEditWidth - 2, tabIndex: tabIndexForItem++)
{
ToolTipText = settingData.HelpText,
SelectAllOnFocus = true
};
stringEdit.ActualTextEditWidget.EditComplete += (sender, e) =>
{
var textEditWidget = (TextEditWidget)sender;
string text = textEditWidget.Text.Trim();
bool isPercent = text.Contains("%");
if (isPercent)
{
text = text.Substring(0, text.IndexOf("%"));
}
double result;
double.TryParse(text, out result);
text = result.ToString();
if (isPercent)
{
text += "%";
}
textEditWidget.Text = text;
settingsContext.SetValue(settingData.SlicerConfigName, textEditWidget.Text);
settingsRow.UpdateStyle();
};
stringEdit.ActualTextEditWidget.InternalTextEditWidget.AllSelected += (sender, e) =>
{
// select everything up to the % (if present)
InternalTextEditWidget textEditWidget = (InternalTextEditWidget)sender;
int percentIndex = textEditWidget.Text.IndexOf("%");
if (percentIndex != -1)
{
textEditWidget.SetSelection(0, percentIndex - 1);
}
};
content.AddChild(stringEdit);
unitsArea.AddChild(GetExtraSettingsWidget(settingData));
if (settingData.QuickMenuSettings.Count > 0)
{
dataArea.AddChild(CreateQuickMenu(settingData, settingsContext, content, stringEdit.ActualTextEditWidget.InternalTextEditWidget));
}
else
{
dataArea.AddChild(content);
}
settingsRow.ValueChanged = (text) =>
{
stringEdit.Text = text;
};
}
field = new DoubleOrPercentField();
break;
case SliceSettingData.DataEditTypes.INT_OR_MM:
{
FlowLayoutWidget content = new FlowLayoutWidget();
var stringEdit = new MHTextEditWidget(sliceSettingValue, pixelWidth: doubleEditWidth - 2, tabIndex: tabIndexForItem++)
{
ToolTipText = settingData.HelpText,
SelectAllOnFocus = true
};
string startingText = stringEdit.Text;
stringEdit.ActualTextEditWidget.EditComplete += (sender, e) =>
{
TextEditWidget textEditWidget = (TextEditWidget)sender;
// only validate when we lose focus
if (!textEditWidget.ContainsFocus)
{
string text = textEditWidget.Text;
text = text.Trim();
bool isMm = text.Contains("mm");
if (isMm)
{
text = text.Substring(0, text.IndexOf("mm"));
}
double result;
double.TryParse(text, out result);
text = result.ToString();
if (isMm)
{
text += "mm";
}
else
{
result = (int)result;
text = result.ToString();
}
textEditWidget.Text = text;
startingText = stringEdit.Text;
}
settingsContext.SetValue(settingData.SlicerConfigName, textEditWidget.Text);
settingsRow.UpdateStyle();
// make sure we are still looking for the final validation before saving.
if (textEditWidget.ContainsFocus)
{
UiThread.RunOnIdle(() =>
{
string currentText = textEditWidget.Text;
int cursorIndex = textEditWidget.InternalTextEditWidget.CharIndexToInsertBefore;
textEditWidget.Text = startingText;
textEditWidget.InternalTextEditWidget.MarkAsStartingState();
textEditWidget.Text = currentText;
textEditWidget.InternalTextEditWidget.CharIndexToInsertBefore = cursorIndex;
});
}
};
stringEdit.ActualTextEditWidget.InternalTextEditWidget.AllSelected += (sender, e) =>
{
// select everything up to the mm (if present)
InternalTextEditWidget textEditWidget = (InternalTextEditWidget)sender;
int mMIndex = textEditWidget.Text.IndexOf("mm");
if (mMIndex != -1)
{
textEditWidget.SetSelection(0, mMIndex - 1);
}
};
content.AddChild(stringEdit);
unitsArea.AddChild(GetExtraSettingsWidget(settingData));
if (settingData.QuickMenuSettings.Count > 0)
{
dataArea.AddChild(CreateQuickMenu(settingData, settingsContext, content, stringEdit.ActualTextEditWidget.InternalTextEditWidget));
}
else
{
dataArea.AddChild(content);
}
settingsRow.ValueChanged = (text) =>
{
stringEdit.Text = text;
};
}
field = new IntOrMmField();
break;
case SliceSettingData.DataEditTypes.CHECK_BOX:
{
var checkBoxWidget = new CheckBox("")
{
Name = settingData.PresentationName + " Checkbox",
ToolTipText = settingData.HelpText,
VAnchor = VAnchor.Bottom,
TextColor = ActiveTheme.Instance.PrimaryTextColor,
Checked = sliceSettingValue == "1"
};
checkBoxWidget.Click += (sender, e) =>
{
// SetValue should only be called when the checkbox is clicked. If this code makes its way into checkstatechanged
// we end up adding a key back into the dictionary after we call .ClearValue, resulting in the blue override bar reappearing after
// clearing a useroverride with the red x
settingsContext.SetValue(settingData.SlicerConfigName, checkBoxWidget.Checked ? "1" : "0");
};
checkBoxWidget.CheckedStateChanged += (s, e) =>
{
// Linked settings should be updated in all cases (user clicked checkbox, user clicked clear)
foreach (var setSettingsData in settingData.SetSettingsOnChange)
{
string targetValue;
if (setSettingsData.TryGetValue(checkBoxWidget.Checked ? "OnValue" : "OffValue", out targetValue))
{
settingsContext.SetValue(setSettingsData["TargetSetting"], targetValue);
}
}
settingsRow.UpdateStyle();
};
dataArea.AddChild(checkBoxWidget);
settingsRow.ValueChanged = (text) =>
{
checkBoxWidget.Checked = text == "1";
};
}
field = new CheckboxField();
break;
case SliceSettingData.DataEditTypes.STRING:
{
var stringEdit = new MHTextEditWidget(sliceSettingValue, pixelWidth: settingData.ShowAsOverride ? 120 : 200, tabIndex: tabIndexForItem++)
{
Name = settingData.PresentationName + " Edit",
};
stringEdit.ToolTipText = settingData.HelpText;
stringEdit.ActualTextEditWidget.EditComplete += (sender, e) =>
{
settingsContext.SetValue(settingData.SlicerConfigName, ((TextEditWidget)sender).Text);
settingsRow.UpdateStyle();
};
dataArea.AddChild(stringEdit);
settingsRow.ValueChanged = (text) =>
{
stringEdit.Text = text;
};
}
field = new StringField();
break;
case SliceSettingData.DataEditTypes.MULTI_LINE_TEXT:
{
string convertedNewLines = sliceSettingValue.Replace("\\n", "\n");
var stringEdit = new MHTextEditWidget(convertedNewLines, pixelWidth: 320, pixelHeight: multiLineEditHeight, multiLine: true, tabIndex: tabIndexForItem++, typeFace: ApplicationController.MonoSpacedTypeFace)
{
HAnchor = HAnchor.Stretch,
};
stringEdit.DrawFromHintedCache();
stringEdit.ActualTextEditWidget.EditComplete += (sender, e) =>
{
settingsContext.SetValue(settingData.SlicerConfigName, ((TextEditWidget)sender).Text.Replace("\n", "\\n"));
settingsRow.UpdateStyle();
};
nameArea.HAnchor = HAnchor.Absolute;
nameArea.Width = 0;
dataArea.AddChild(stringEdit);
dataArea.HAnchor = HAnchor.Stretch;
settingsRow.ValueChanged = (text) =>
{
stringEdit.Text = text.Replace("\\n", "\n");
};
}
field = new MultilineStringField();
break;
case SliceSettingData.DataEditTypes.COM_PORT:
{
// TODO: Conditionally opt out on Android
EventHandler localUnregisterEvents = null;
bool canChangeComPort = !printerConnection.PrinterIsConnected && printerConnection.CommunicationState != CommunicationStates.AttemptingToConnect;
// The COM_PORT control is unique in its approach to the SlicerConfigName. It uses "com_port" settings name to
// bind to a context that will place it in the SliceSetting view but it binds its values to a machine
// specific dictionary key that is not exposed in the UI. At runtime we lookup and store to '<machinename>_com_port'
// ensuring that a single printer can be shared across different devices and we'll select the correct com port in each case
var selectableOptions = new DropDownList("None".Localize(), maxHeight: 200)
{
ToolTipText = settingData.HelpText,
Margin = new BorderDouble(),
Name = "Serial Port Dropdown",
// Prevent droplist interaction when connected
Enabled = canChangeComPort,
TextColor = canChangeComPort ? ActiveTheme.Instance.PrimaryTextColor : new RGBA_Bytes(ActiveTheme.Instance.PrimaryTextColor, 150),
BorderColor = canChangeComPort ? ActiveTheme.Instance.SecondaryTextColor : new RGBA_Bytes(ActiveTheme.Instance.SecondaryTextColor, 150),
};
selectableOptions.Click += (s, e) =>
{
AddComMenuItems(settingData, settingsContext, settingsRow, selectableOptions);
};
AddComMenuItems(settingData, settingsContext, settingsRow, selectableOptions);
dataArea.AddChild(selectableOptions);
settingsRow.ValueChanged = (text) =>
{
// Lookup the machine specific comport value rather than the passed in text value
selectableOptions.SelectedLabel = ActiveSliceSettings.Instance.Helpers.ComPort();
};
// Prevent droplist interaction when connected
printerConnection.CommunicationStateChanged.RegisterEvent((s, e) =>
{
canChangeComPort = !printerConnection.PrinterIsConnected && printerConnection.CommunicationState != CommunicationStates.AttemptingToConnect;
selectableOptions.Enabled = canChangeComPort;
selectableOptions.TextColor = canChangeComPort ? ActiveTheme.Instance.PrimaryTextColor : new RGBA_Bytes(ActiveTheme.Instance.PrimaryTextColor, 150);
selectableOptions.BorderColor = canChangeComPort ? ActiveTheme.Instance.SecondaryTextColor : new RGBA_Bytes(ActiveTheme.Instance.SecondaryTextColor, 150);
}, ref localUnregisterEvents);
// Release event listener on close
selectableOptions.Closed += (s, e) =>
{
localUnregisterEvents?.Invoke(null, null);
};
}
field = new ComPortField();
break;
case SliceSettingData.DataEditTypes.LIST:
{
var selectableOptions = new DropDownList("None".Localize(), maxHeight: 200)
{
ToolTipText = settingData.HelpText,
Margin = new BorderDouble()
};
foreach (string listItem in settingData.ExtraSettings.Split(','))
{
MenuItem newItem = selectableOptions.AddItem(listItem);
if (newItem.Text == sliceSettingValue)
{
selectableOptions.SelectedLabel = sliceSettingValue;
}
newItem.Selected += (sender, e) =>
{
MenuItem menuItem = ((MenuItem)sender);
settingsContext.SetValue(settingData.SlicerConfigName, menuItem.Text);
settingsRow.UpdateStyle();
};
}
dataArea.AddChild(selectableOptions);
settingsRow.ValueChanged = (text) =>
{
selectableOptions.SelectedLabel = text;
};
}
field = new ListField();
break;
case SliceSettingData.DataEditTypes.HARDWARE_PRESENT:
{
var checkBoxWidget = new CheckBox("")
{
Name = settingData.PresentationName + " Checkbox",
ToolTipText = settingData.HelpText,
VAnchor = VAnchor.Bottom,
TextColor = ActiveTheme.Instance.PrimaryTextColor,
Checked = sliceSettingValue == "1"
};
checkBoxWidget.Click += (sender, e) =>
{
bool isChecked = ((CheckBox)sender).Checked;
settingsContext.SetValue(settingData.SlicerConfigName, isChecked ? "1" : "0");
settingsRow.UpdateStyle();
};
dataArea.AddChild(checkBoxWidget);
settingsRow.ValueChanged = (text) =>
{
checkBoxWidget.Checked = text == "1";
};
}
field = new HardwarePresetField();
break;
case SliceSettingData.DataEditTypes.VECTOR2:
{
string[] xyValueStrings = sliceSettingValue.Split(',');
if (xyValueStrings.Length != 2)
{
xyValueStrings = new string[] { "0", "0" };
}
double currentXValue;
double.TryParse(xyValueStrings[0], out currentXValue);
var xEditWidget = new MHNumberEdit(currentXValue, allowDecimals: true, pixelWidth: vectorXYEditWidth, tabIndex: tabIndexForItem++)
{
ToolTipText = settingData.HelpText,
SelectAllOnFocus = true
};
double currentYValue;
double.TryParse(xyValueStrings[1], out currentYValue);
var yEditWidget = new MHNumberEdit(currentYValue, allowDecimals: true, pixelWidth: vectorXYEditWidth, tabIndex: tabIndexForItem++)
{
ToolTipText = settingData.HelpText,
SelectAllOnFocus = true,
Margin = new BorderDouble(20, 0, 0, 0),
};
xEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
{
settingsContext.SetValue(settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "," + yEditWidget.ActuallNumberEdit.Value.ToString());
settingsRow.UpdateStyle();
};
dataArea.AddChild(xEditWidget);
dataArea.AddChild(new TextWidget("X", pointSize: 10, textColor: ActiveTheme.Instance.PrimaryTextColor)
{
VAnchor = VAnchor.Center,
Margin = new BorderDouble(5, 0),
});
yEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
{
settingsContext.SetValue(settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "," + yEditWidget.ActuallNumberEdit.Value.ToString());
settingsRow.UpdateStyle();
};
dataArea.AddChild(yEditWidget);
var yLabel = new GuiWidget()
{
VAnchor = VAnchor.Fit | VAnchor.Center,
Padding = new BorderDouble(5, 0),
HAnchor = HAnchor.Stretch,
};
yLabel.AddChild(new WrappedTextWidget("Y", pointSize: 9, textColor: ActiveTheme.Instance.PrimaryTextColor));
unitsArea.AddChild(yLabel);
settingsRow.ValueChanged = (text) =>
{
double currentValue2;
string[] xyValueStrings2 = text.Split(',');
if (xyValueStrings2.Length != 2)
{
xyValueStrings2 = new string[] { "0", "0" };
}
double.TryParse(xyValueStrings2[0], out currentValue2);
xEditWidget.ActuallNumberEdit.Value = currentValue2;
double.TryParse(xyValueStrings2[1], out currentValue2);
yEditWidget.ActuallNumberEdit.Value = currentValue2;
};
}
field = new Vector2Field();
break;
case SliceSettingData.DataEditTypes.OFFSET2:
field = new Offset2Field();
if (field is Offset2Field offset2)
{
Vector2 offset = ActiveSliceSettings.Instance.Helpers.ExtruderOffset(extruderIndex);
var xEditWidget = new MHNumberEdit(offset.x, allowDecimals: true, allowNegatives: true, pixelWidth: vectorXYEditWidth, tabIndex: tabIndexForItem++)
{
ToolTipText = settingData.HelpText,
SelectAllOnFocus = true,
};
var yEditWidget = new MHNumberEdit(offset.y, allowDecimals: true, allowNegatives: true, pixelWidth: vectorXYEditWidth, tabIndex: tabIndexForItem++)
{
ToolTipText = settingData.HelpText,
SelectAllOnFocus = true,
Margin = new BorderDouble(20, 0, 0, 0),
};
xEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
{
int extruderIndexLocal = extruderIndex;
SaveCommaSeparatedIndexSetting(extruderIndexLocal, settingsContext, settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "x" + yEditWidget.ActuallNumberEdit.Value.ToString());
settingsRow.UpdateStyle();
};
dataArea.AddChild(xEditWidget);
dataArea.AddChild(new TextWidget("X", pointSize: 10, textColor: ActiveTheme.Instance.PrimaryTextColor)
{
VAnchor = VAnchor.Center,
Margin = new BorderDouble(5, 0),
});
yEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
{
int extruderIndexLocal = extruderIndex;
SaveCommaSeparatedIndexSetting(extruderIndexLocal, settingsContext, settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "x" + yEditWidget.ActuallNumberEdit.Value.ToString());
settingsRow.UpdateStyle();
};
dataArea.AddChild(yEditWidget);
var yLabel = new GuiWidget()
{
Padding = new BorderDouble(5, 0),
HAnchor = HAnchor.Stretch,
VAnchor = VAnchor.Fit | VAnchor.Center,
};
yLabel.AddChild(new WrappedTextWidget("Y", pointSize: 9, textColor: ActiveTheme.Instance.PrimaryTextColor));
unitsArea.AddChild(yLabel);
settingsRow.ValueChanged = (text) =>
{
Vector2 offset2 = ActiveSliceSettings.Instance.Helpers.ExtruderOffset(extruderIndex);
xEditWidget.ActuallNumberEdit.Value = offset2.x;
yEditWidget.ActuallNumberEdit.Value = offset2.y;
};
offset2.ExtruderIndex = extruderIndex;
}
break;
@ -1499,7 +878,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
{
// Revert the user override
settingsContext.ClearValue(settingData.SlicerConfigName);
settingsRow.RefreshValue(settingsContext);
};
restoreArea.AddChild(restoreButton);
@ -1583,6 +961,22 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
}
};
if (field != null)
{
allFields.Add(settingData.SlicerConfigName, field);
field.Value = sliceSettingValue;
this.PrepareRow(
field,
field.Create(settingsContext, settingData, tabIndexForItem++),
dataArea,
unitsArea,
settingData);
field.UpdateStyle = settingsRow.UpdateStyle;
}
// Invoke the UpdateStyle implementation
settingsRow.UpdateStyle();
@ -1612,24 +1006,14 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
return settingsRow;
}
private static void AddComMenuItems(SliceSettingData settingData, SettingsContext settingsContext, SettingsRow settingsRow, DropDownList selectableOptions)
private void PrepareRow(ISettingsField field, GuiWidget content, GuiWidget dataArea, GuiWidget unitsArea, SliceSettingData settingData)
{
selectableOptions.MenuItems.Clear();
string machineSpecificComPortValue = ActiveSliceSettings.Instance.Helpers.ComPort();
foreach (string listItem in FrostedSerialPort.GetPortNames())
{
MenuItem newItem = selectableOptions.AddItem(listItem);
if (newItem.Text == machineSpecificComPortValue)
{
selectableOptions.SelectedLabel = machineSpecificComPortValue;
}
dataArea.AddChild(content);
newItem.Selected += (sender, e) =>
{
MenuItem menuItem = ((MenuItem)sender);
settingsContext.SetComPort(menuItem.Text);
settingsRow.UpdateStyle();
};
var extraInfo = GetExtraSettingsWidget(settingData);
if (extraInfo != null)
{
unitsArea.AddChild(extraInfo);
}
}
@ -1697,7 +1081,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
return totalContent;
}
private static void SaveCommaSeparatedIndexSetting(int extruderIndexLocal, SettingsContext settingsContext, string slicerConfigName, string newSingleValue)
public static void SaveCommaSeparatedIndexSetting(int extruderIndexLocal, SettingsContext settingsContext, string slicerConfigName, string newSingleValue)
{
string[] settings = settingsContext.GetValue(slicerConfigName).Split(',');
if (settings.Length > extruderIndexLocal)
@ -1726,11 +1110,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
string newValue = string.Join(",", settings);
settingsContext.SetValue(slicerConfigName, newValue);
}
public override void OnDraw(Graphics2D graphics2D)
{
base.OnDraw(graphics2D);
}
}
internal class SliceSettingListControl : ScrollableWidget

View file

@ -0,0 +1,83 @@
/*
Copyright (c) 2017, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using MatterHackers.Agg.UI;
namespace MatterHackers.MatterControl.SlicerConfiguration
{
public class CheckboxField : ISettingsField
{
private CheckBox checkBoxWidget;
public Action UpdateStyle { get; set; }
public string Value { get; set; }
public GuiWidget Create(SettingsContext settingsContext, SliceSettingData settingData, int tabIndex)
{
checkBoxWidget = new CheckBox("")
{
Name = settingData.PresentationName + " Checkbox",
ToolTipText = settingData.HelpText,
VAnchor = VAnchor.Bottom,
TextColor = ActiveTheme.Instance.PrimaryTextColor,
Checked = this.Value == "1"
};
checkBoxWidget.Click += (sender, e) =>
{
// SetValue should only be called when the checkbox is clicked. If this code makes its way into checkstatechanged
// we end up adding a key back into the dictionary after we call .ClearValue, resulting in the blue override bar reappearing after
// clearing a user override with the red x
settingsContext.SetValue(settingData.SlicerConfigName, checkBoxWidget.Checked ? "1" : "0");
};
checkBoxWidget.CheckedStateChanged += (s, e) =>
{
// Linked settings should be updated in all cases (user clicked checkbox, user clicked clear)
foreach (var setSettingsData in settingData.SetSettingsOnChange)
{
string targetValue;
if (setSettingsData.TryGetValue(checkBoxWidget.Checked ? "OnValue" : "OffValue", out targetValue))
{
settingsContext.SetValue(setSettingsData["TargetSetting"], targetValue);
}
}
this.UpdateStyle();
};
return checkBoxWidget;
}
public void OnValueChanged(string text)
{
checkBoxWidget.Checked = text == "1";
}
}
}

View file

@ -0,0 +1,120 @@
/*
Copyright (c) 2017, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.PrinterCommunication;
using MatterHackers.SerialPortCommunication.FrostedSerial;
namespace MatterHackers.MatterControl.SlicerConfiguration
{
public class ComPortField : ISettingsField
{
private DropDownList selectableOptions;
public Action UpdateStyle { get; set; }
public string Value { get; set; }
public GuiWidget Create(SettingsContext settingsContext, SliceSettingData settingData, int tabIndex)
{
EventHandler unregisterEvents = null;
bool canChangeComPort = !PrinterConnection.Instance.PrinterIsConnected && PrinterConnection.Instance.CommunicationState != CommunicationStates.AttemptingToConnect;
// The COM_PORT control is unique in its approach to the SlicerConfigName. It uses "com_port" settings name to
// bind to a context that will place it in the SliceSetting view but it binds its values to a machine
// specific dictionary key that is not exposed in the UI. At runtime we lookup and store to '<machinename>_com_port'
// ensuring that a single printer can be shared across different devices and we'll select the correct com port in each case
selectableOptions = new DropDownList("None".Localize(), maxHeight: 200)
{
ToolTipText = settingData.HelpText,
Margin = new BorderDouble(),
Name = "Serial Port Dropdown",
// Prevent droplist interaction when connected
Enabled = canChangeComPort,
TextColor = canChangeComPort ? ActiveTheme.Instance.PrimaryTextColor : new RGBA_Bytes(ActiveTheme.Instance.PrimaryTextColor, 150),
BorderColor = canChangeComPort ? ActiveTheme.Instance.SecondaryTextColor : new RGBA_Bytes(ActiveTheme.Instance.SecondaryTextColor, 150),
};
selectableOptions.Click += (s, e) =>
{
AddComMenuItems(settingData, settingsContext, selectableOptions);
};
AddComMenuItems(settingData, settingsContext, selectableOptions);
// Prevent droplist interaction when connected
PrinterConnection.Instance.CommunicationStateChanged.RegisterEvent((s, e) =>
{
canChangeComPort = !PrinterConnection.Instance.PrinterIsConnected && PrinterConnection.Instance.CommunicationState != CommunicationStates.AttemptingToConnect;
selectableOptions.Enabled = canChangeComPort;
selectableOptions.TextColor = canChangeComPort ? ActiveTheme.Instance.PrimaryTextColor : new RGBA_Bytes(ActiveTheme.Instance.PrimaryTextColor, 150);
selectableOptions.BorderColor = canChangeComPort ? ActiveTheme.Instance.SecondaryTextColor : new RGBA_Bytes(ActiveTheme.Instance.SecondaryTextColor, 150);
}, ref unregisterEvents);
// Release event listener on close
selectableOptions.Closed += (s, e) =>
{
unregisterEvents?.Invoke(null, null);
};
return selectableOptions;
}
public void OnValueChanged(string text)
{
// Lookup the machine specific comport value rather than the passed in text value
selectableOptions.SelectedLabel = ActiveSliceSettings.Instance.Helpers.ComPort();
}
private void AddComMenuItems(SliceSettingData settingData, SettingsContext settingsContext, DropDownList selectableOptions)
{
selectableOptions.MenuItems.Clear();
string machineSpecificComPortValue = ActiveSliceSettings.Instance.Helpers.ComPort();
foreach (string listItem in FrostedSerialPort.GetPortNames())
{
MenuItem newItem = selectableOptions.AddItem(listItem);
if (newItem.Text == machineSpecificComPortValue)
{
selectableOptions.SelectedLabel = machineSpecificComPortValue;
}
newItem.Selected += (sender, e) =>
{
MenuItem menuItem = ((MenuItem)sender);
settingsContext.SetComPort(menuItem.Text);
this.UpdateStyle();
};
}
}
}
}

View file

@ -0,0 +1,69 @@
/*
Copyright (c) 2017, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using MatterHackers.Agg.UI;
namespace MatterHackers.MatterControl.SlicerConfiguration
{
public class DoubleField : ISettingsField
{
public static int DoubleEditWidth = (int)(60 * GuiWidget.DeviceScale + .5);
public Action UpdateStyle { get; set; }
public string Value { get; set; }
private MHNumberEdit doubleEditWidget;
public GuiWidget Create(SettingsContext settingsContext, SliceSettingData settingData, int tabIndex)
{
double.TryParse(this.Value, out double currentValue);
doubleEditWidget = new MHNumberEdit(currentValue, allowNegatives: true, allowDecimals: true, pixelWidth: DoubleEditWidth, tabIndex: tabIndex)
{
ToolTipText = settingData.HelpText,
SelectAllOnFocus = true
};
doubleEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
{
settingsContext.SetValue(settingData.SlicerConfigName, ((NumberEdit)sender).Value.ToString());
this.UpdateStyle();
};
return doubleEditWidget;
}
public void OnValueChanged(string text)
{
double.TryParse(text, out double currentValue);
doubleEditWidget.ActuallNumberEdit.Value = currentValue;
}
}
}

View file

@ -0,0 +1,99 @@
/*
Copyright (c) 2017, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using MatterHackers.Agg.UI;
namespace MatterHackers.MatterControl.SlicerConfiguration
{
public class DoubleOrPercentField : ISettingsField
{
public Action UpdateStyle { get; set; }
private MHTextEditWidget editWidget;
public string Value { get; set; }
public GuiWidget Create(SettingsContext settingsContext, SliceSettingData settingData, int tabIndex)
{
editWidget = new MHTextEditWidget(this.Value, pixelWidth: DoubleField.DoubleEditWidth - 2, tabIndex: tabIndex)
{
ToolTipText = settingData.HelpText,
SelectAllOnFocus = true
};
editWidget.ActualTextEditWidget.EditComplete += (sender, e) =>
{
var textEditWidget = (TextEditWidget)sender;
string text = textEditWidget.Text.Trim();
bool isPercent = text.Contains("%");
if (isPercent)
{
text = text.Substring(0, text.IndexOf("%"));
}
double result;
double.TryParse(text, out result);
text = result.ToString();
if (isPercent)
{
text += "%";
}
textEditWidget.Text = text;
settingsContext.SetValue(settingData.SlicerConfigName, textEditWidget.Text);
this.UpdateStyle();
};
editWidget.ActualTextEditWidget.InternalTextEditWidget.AllSelected += (sender, e) =>
{
// select everything up to the % (if present)
InternalTextEditWidget textEditWidget = (InternalTextEditWidget)sender;
int percentIndex = textEditWidget.Text.IndexOf("%");
if (percentIndex != -1)
{
textEditWidget.SetSelection(0, percentIndex - 1);
}
};
if (settingData.QuickMenuSettings.Count > 0)
{
return SliceSettingsWidget.CreateQuickMenu(settingData, settingsContext, editWidget, editWidget.ActualTextEditWidget.InternalTextEditWidget);
}
else
{
return editWidget;
}
}
public void OnValueChanged(string text)
{
editWidget.Text = text;
}
}
}

View file

@ -0,0 +1,70 @@
/*
Copyright (c) 2017, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using MatterHackers.Agg.UI;
namespace MatterHackers.MatterControl.SlicerConfiguration
{
public class HardwarePresetField : ISettingsField
{
private CheckBox checkBoxWidget;
public Action UpdateStyle { get; set; }
public string Value { get; set; }
public GuiWidget Create(SettingsContext settingsContext, SliceSettingData settingData, int tabIndex)
{
checkBoxWidget = new CheckBox("")
{
Name = settingData.PresentationName + " Checkbox",
ToolTipText = settingData.HelpText,
VAnchor = VAnchor.Bottom,
TextColor = ActiveTheme.Instance.PrimaryTextColor,
Checked = this.Value == "1"
};
checkBoxWidget.Click += (sender, e) =>
{
bool isChecked = ((CheckBox)sender).Checked;
settingsContext.SetValue(settingData.SlicerConfigName, isChecked ? "1" : "0");
this.UpdateStyle();
};
return checkBoxWidget;
}
public void OnValueChanged(string text)
{
checkBoxWidget.Checked = text == "1";
}
}
}

View file

@ -0,0 +1,45 @@
/*
Copyright (c) 2017, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using MatterHackers.Agg.UI;
namespace MatterHackers.MatterControl.SlicerConfiguration
{
public interface ISettingsField
{
void OnValueChanged(string text);
Action UpdateStyle { get; set; }
string Value { get; set; }
GuiWidget Create(SettingsContext settingsContext, SliceSettingData settingData, int tabIndex);
}
}

View file

@ -0,0 +1,76 @@
/*
Copyright (c) 2017, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using MatterHackers.Agg.UI;
namespace MatterHackers.MatterControl.SlicerConfiguration
{
public class IntField : ISettingsField
{
private readonly int intEditWidth = (int)(60 * GuiWidget.DeviceScale + .5);
public Action UpdateStyle { get; set; }
public string Value { get; set; }
private MHNumberEdit intEditWidget;
public GuiWidget Create(SettingsContext settingsContext, SliceSettingData settingData, int tabIndex)
{
int.TryParse(this.Value, out int currentValue);
intEditWidget = new MHNumberEdit(currentValue, pixelWidth: intEditWidth, tabIndex: tabIndex)
{
ToolTipText = settingData.HelpText,
SelectAllOnFocus = true,
Name = settingData.PresentationName + " Edit",
};
intEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
{
settingsContext.SetValue(settingData.SlicerConfigName, ((NumberEdit)sender).Value.ToString());
this.UpdateStyle();
};
if (settingData.QuickMenuSettings.Count > 0)
{
return SliceSettingsWidget.CreateQuickMenu(settingData, settingsContext, intEditWidget, intEditWidget.ActuallNumberEdit.InternalTextEditWidget);
}
else
{
return intEditWidget;
}
}
public void OnValueChanged(string text)
{
intEditWidget.Text = text;
}
}
}

View file

@ -0,0 +1,125 @@
/*
Copyright (c) 2017, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using MatterHackers.Agg.UI;
namespace MatterHackers.MatterControl.SlicerConfiguration
{
public class IntOrMmField : ISettingsField
{
private MHTextEditWidget editWidget;
public Action UpdateStyle { get; set; }
public string Value { get; set; }
public GuiWidget Create(SettingsContext settingsContext, SliceSettingData settingData, int tabIndex)
{
editWidget = new MHTextEditWidget(this.Value, pixelWidth: DoubleField.DoubleEditWidth - 2, tabIndex: tabIndex)
{
ToolTipText = settingData.HelpText,
SelectAllOnFocus = true
};
string startingText = editWidget.Text;
editWidget.ActualTextEditWidget.EditComplete += (sender, e) =>
{
TextEditWidget textEditWidget = (TextEditWidget)sender;
// only validate when we lose focus
if (!textEditWidget.ContainsFocus)
{
string text = textEditWidget.Text;
text = text.Trim();
bool isMm = text.Contains("mm");
if (isMm)
{
text = text.Substring(0, text.IndexOf("mm"));
}
double result;
double.TryParse(text, out result);
text = result.ToString();
if (isMm)
{
text += "mm";
}
else
{
result = (int)result;
text = result.ToString();
}
textEditWidget.Text = text;
startingText = editWidget.Text;
}
settingsContext.SetValue(settingData.SlicerConfigName, textEditWidget.Text);
this.UpdateStyle();
// make sure we are still looking for the final validation before saving.
if (textEditWidget.ContainsFocus)
{
UiThread.RunOnIdle(() =>
{
string currentText = textEditWidget.Text;
int cursorIndex = textEditWidget.InternalTextEditWidget.CharIndexToInsertBefore;
textEditWidget.Text = startingText;
textEditWidget.InternalTextEditWidget.MarkAsStartingState();
textEditWidget.Text = currentText;
textEditWidget.InternalTextEditWidget.CharIndexToInsertBefore = cursorIndex;
});
}
};
editWidget.ActualTextEditWidget.InternalTextEditWidget.AllSelected += (sender, e) =>
{
// select everything up to the mm (if present)
InternalTextEditWidget textEditWidget = (InternalTextEditWidget)sender;
int mMIndex = textEditWidget.Text.IndexOf("mm");
if (mMIndex != -1)
{
textEditWidget.SetSelection(0, mMIndex - 1);
}
};
if (settingData.QuickMenuSettings.Count > 0)
{
return SliceSettingsWidget.CreateQuickMenu(settingData, settingsContext, editWidget, editWidget.ActualTextEditWidget.InternalTextEditWidget);
}
else
{
return editWidget;
}
}
public void OnValueChanged(string text)
{
editWidget.Text = text;
}
}
}

View file

@ -0,0 +1,78 @@
/*
Copyright (c) 2017, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
using MatterHackers.Localizations;
namespace MatterHackers.MatterControl.SlicerConfiguration
{
public class ListField : ISettingsField
{
private DropDownList selectableOptions;
public Action UpdateStyle { get; set; }
public string Value { get; set; }
public GuiWidget Create(SettingsContext settingsContext, SliceSettingData settingData, int tabIndex)
{
selectableOptions = new DropDownList("None".Localize(), maxHeight: 200)
{
ToolTipText = settingData.HelpText,
Margin = new BorderDouble()
};
foreach (string listItem in settingData.ExtraSettings.Split(','))
{
MenuItem newItem = selectableOptions.AddItem(listItem);
if (newItem.Text == this.Value)
{
selectableOptions.SelectedLabel = this.Value;
}
newItem.Selected += (sender, e) =>
{
MenuItem menuItem = ((MenuItem)sender);
settingsContext.SetValue(settingData.SlicerConfigName, menuItem.Text);
this.UpdateStyle();
};
}
return selectableOptions;
}
public void OnValueChanged(string text)
{
selectableOptions.SelectedLabel = text;
}
}
}

View file

@ -0,0 +1,68 @@
/*
Copyright (c) 2017, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using MatterHackers.Agg.UI;
namespace MatterHackers.MatterControl.SlicerConfiguration
{
public class MultilineStringField : ISettingsField
{
private readonly int multiLineEditHeight = (int)(120 * GuiWidget.DeviceScale + .5);
private MHTextEditWidget editWidget;
public Action UpdateStyle { get; set; }
public string Value { get; set; }
public GuiWidget Create(SettingsContext settingsContext, SliceSettingData settingData, int tabIndex)
{
string convertedNewLines = this.Value.Replace("\\n", "\n");
editWidget = new MHTextEditWidget(convertedNewLines, pixelWidth: 320, pixelHeight: multiLineEditHeight, multiLine: true, tabIndex: tabIndex, typeFace: ApplicationController.MonoSpacedTypeFace)
{
HAnchor = HAnchor.Stretch,
};
editWidget.DrawFromHintedCache();
editWidget.ActualTextEditWidget.EditComplete += (sender, e) =>
{
settingsContext.SetValue(settingData.SlicerConfigName, ((TextEditWidget)sender).Text.Replace("\n", "\\n"));
this.UpdateStyle();
};
return editWidget;
}
public void OnValueChanged(string text)
{
editWidget.Text = text.Replace("\\n", "\n");
}
}
}

View file

@ -0,0 +1,100 @@
/*
Copyright (c) 2017, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
using MatterHackers.VectorMath;
namespace MatterHackers.MatterControl.SlicerConfiguration
{
public class Offset2Field : ISettingsField
{
private MHNumberEdit xEditWidget;
private MHNumberEdit yEditWidget;
public Action UpdateStyle { get; set; }
public string Value { get; set; }
public int ExtruderIndex { get; set; } = 0;
public GuiWidget Create(SettingsContext settingsContext, SliceSettingData settingData, int tabIndex)
{
var container = new FlowLayoutWidget();
Vector2 offset = ActiveSliceSettings.Instance.Helpers.ExtruderOffset(0);
xEditWidget = new MHNumberEdit(offset.x, allowDecimals: true, allowNegatives: true, pixelWidth: Vector2Field.VectorXYEditWidth, tabIndex: tabIndex)
{
ToolTipText = settingData.HelpText,
SelectAllOnFocus = true,
};
xEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
{
SliceSettingsWidget.SaveCommaSeparatedIndexSetting(this.ExtruderIndex, settingsContext, settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "x" + yEditWidget.ActuallNumberEdit.Value.ToString());
this.UpdateStyle();
};
container.AddChild(new TextWidget("X:", pointSize: 10, textColor: ActiveTheme.Instance.PrimaryTextColor)
{
VAnchor = VAnchor.Center,
Margin = new BorderDouble(5, 0),
});
container.AddChild(xEditWidget);
yEditWidget = new MHNumberEdit(offset.y, allowDecimals: true, allowNegatives: true, pixelWidth: Vector2Field.VectorXYEditWidth, tabIndex: tabIndex)
{
ToolTipText = settingData.HelpText,
SelectAllOnFocus = true
};
yEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
{
SliceSettingsWidget.SaveCommaSeparatedIndexSetting(this.ExtruderIndex, settingsContext, settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "x" + yEditWidget.ActuallNumberEdit.Value.ToString());
this.UpdateStyle();
};
container.AddChild(new TextWidget("Y:", pointSize: 10, textColor: ActiveTheme.Instance.PrimaryTextColor)
{
VAnchor = VAnchor.Center,
Margin = new BorderDouble(15, 0, 5, 0),
});
container.AddChild(yEditWidget);
return container;
}
public void OnValueChanged(string text)
{
Vector2 offset2 = ActiveSliceSettings.Instance.Helpers.ExtruderOffset(this.ExtruderIndex);
xEditWidget.ActuallNumberEdit.Value = offset2.x;
yEditWidget.ActuallNumberEdit.Value = offset2.y;
}
}
}

View file

@ -0,0 +1,68 @@
/*
Copyright (c) 2017, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using MatterHackers.Agg.UI;
namespace MatterHackers.MatterControl.SlicerConfiguration
{
public class OffsetField : ISettingsField
{
private MHNumberEdit editWidget;
public Action UpdateStyle { get; set; }
public string Value { get; set; }
public GuiWidget Create(SettingsContext settingsContext, SliceSettingData settingData, int tabIndex)
{
double.TryParse(this.Value, out double currentValue);
editWidget = new MHNumberEdit(currentValue, allowDecimals: true, allowNegatives: true, pixelWidth: DoubleField.DoubleEditWidth, tabIndex: tabIndex)
{
ToolTipText = settingData.HelpText,
SelectAllOnFocus = true
};
editWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
{
settingsContext.SetValue(settingData.SlicerConfigName, ((NumberEdit)sender).Value.ToString());
this.UpdateStyle();
};
return editWidget;
}
public void OnValueChanged(string text)
{
double.TryParse(text, out double currentValue);
editWidget.ActuallNumberEdit.Value = currentValue;
}
}
}

View file

@ -0,0 +1,120 @@
/*
Copyright (c) 2017, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using MatterHackers.Agg.UI;
namespace MatterHackers.MatterControl.SlicerConfiguration
{
public class PositiveDoubleField : ISettingsField
{
private MHNumberEdit doubleEditWidget;
public Action UpdateStyle { get; set; }
public string Value { get; set; }
public GuiWidget Create(SettingsContext settingsContext, SliceSettingData settingData, int tabIndex)
{
const string multiValuesAreDiffernt = "-";
doubleEditWidget = new MHNumberEdit(0, allowDecimals: true, pixelWidth: DoubleField.DoubleEditWidth, tabIndex: tabIndex)
{
ToolTipText = settingData.HelpText,
Name = settingData.PresentationName + " Textbox",
SelectAllOnFocus = true
};
double currentValue;
bool ChangesMultipleOtherSettings = settingData.SetSettingsOnChange.Count > 0;
if (ChangesMultipleOtherSettings)
{
bool allTheSame = true;
string setting = settingsContext.GetValue(settingData.SetSettingsOnChange[0]["TargetSetting"]);
for (int i = 1; i < settingData.SetSettingsOnChange.Count; i++)
{
string nextSetting = settingsContext.GetValue(settingData.SetSettingsOnChange[i]["TargetSetting"]);
if (setting != nextSetting)
{
allTheSame = false;
break;
}
}
if (allTheSame && setting.EndsWith("mm"))
{
double.TryParse(setting.Substring(0, setting.Length - 2), out currentValue);
doubleEditWidget.ActuallNumberEdit.Value = currentValue;
}
else
{
doubleEditWidget.ActuallNumberEdit.InternalNumberEdit.Text = multiValuesAreDiffernt;
}
}
else // just set the setting normally
{
double.TryParse(this.Value, out currentValue);
doubleEditWidget.ActuallNumberEdit.Value = currentValue;
}
doubleEditWidget.ActuallNumberEdit.InternalTextEditWidget.MarkAsStartingState();
doubleEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
{
NumberEdit numberEdit = (NumberEdit)sender;
// If this setting sets other settings, then do that.
if (ChangesMultipleOtherSettings
&& numberEdit.Text != multiValuesAreDiffernt)
{
{
settingsContext.SetValue(settingData.SetSettingsOnChange[0]["TargetSetting"], numberEdit.Value.ToString() + "mm");
}
}
// also always save to the local setting
settingsContext.SetValue(settingData.SlicerConfigName, numberEdit.Value.ToString());
this.UpdateStyle();
};
if (settingData.QuickMenuSettings.Count > 0)
{
return SliceSettingsWidget.CreateQuickMenu(settingData, settingsContext, doubleEditWidget, doubleEditWidget.ActuallNumberEdit.InternalTextEditWidget);
}
else
{
return doubleEditWidget;
}
}
public void OnValueChanged(string text)
{
double.TryParse(text, out double currentValue);
doubleEditWidget.ActuallNumberEdit.Value = currentValue;
}
}
}

View file

@ -0,0 +1,65 @@
/*
Copyright (c) 2017, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using MatterHackers.Agg.UI;
namespace MatterHackers.MatterControl.SlicerConfiguration
{
public class StringField : ISettingsField
{
private MHTextEditWidget editWidget;
public Action UpdateStyle { get; set; }
public string Value { get; set; }
public GuiWidget Create(SettingsContext settingsContext, SliceSettingData settingData, int tabIndex)
{
editWidget = new MHTextEditWidget(this.Value, pixelWidth: settingData.ShowAsOverride ? 120 : 200, tabIndex: tabIndex)
{
Name = settingData.PresentationName + " Edit",
};
editWidget.ToolTipText = settingData.HelpText;
editWidget.ActualTextEditWidget.EditComplete += (sender, e) =>
{
settingsContext.SetValue(settingData.SlicerConfigName, ((TextEditWidget)sender).Text);
this.UpdateStyle();
};
return editWidget;
}
public void OnValueChanged(string text)
{
editWidget.Text = text;
}
}
}

View file

@ -0,0 +1,117 @@
/*
Copyright (c) 2017, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
namespace MatterHackers.MatterControl.SlicerConfiguration
{
public class Vector2Field : ISettingsField
{
public static readonly int VectorXYEditWidth = (int)(60 * GuiWidget.DeviceScale + .5);
private MHNumberEdit yEditWidget;
private MHNumberEdit xEditWidget;
public Action UpdateStyle { get; set; }
public string Value { get; set; }
public GuiWidget Create(SettingsContext settingsContext, SliceSettingData settingData, int tabIndex)
{
var container = new FlowLayoutWidget();
string[] xyValueStrings = this.Value.Split(',');
if (xyValueStrings.Length != 2)
{
xyValueStrings = new string[] { "0", "0" };
}
double.TryParse(xyValueStrings[0], out double currentXValue);
xEditWidget = new MHNumberEdit(currentXValue, allowDecimals: true, pixelWidth: VectorXYEditWidth, tabIndex: tabIndex)
{
ToolTipText = settingData.HelpText,
SelectAllOnFocus = true
};
xEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
{
settingsContext.SetValue(settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "," + yEditWidget.ActuallNumberEdit.Value.ToString());
this.UpdateStyle();
};
container.AddChild(new TextWidget("X:", pointSize: 10, textColor: ActiveTheme.Instance.PrimaryTextColor)
{
VAnchor = VAnchor.Center,
Margin = new BorderDouble(5, 0),
});
container.AddChild(xEditWidget);
double.TryParse(xyValueStrings[1], out double currentYValue);
yEditWidget = new MHNumberEdit(currentYValue, allowDecimals: true, pixelWidth: VectorXYEditWidth, tabIndex: tabIndex)
{
ToolTipText = settingData.HelpText,
SelectAllOnFocus = true,
};
yEditWidget.ActuallNumberEdit.EditComplete += (sender, e) =>
{
settingsContext.SetValue(settingData.SlicerConfigName, xEditWidget.ActuallNumberEdit.Value.ToString() + "," + yEditWidget.ActuallNumberEdit.Value.ToString());
this.UpdateStyle();
};
container.AddChild(new TextWidget("Y:", pointSize: 10, textColor: ActiveTheme.Instance.PrimaryTextColor)
{
VAnchor = VAnchor.Center,
Margin = new BorderDouble(15, 0, 5, 0),
});
container.AddChild(yEditWidget);
return container;
}
public void OnValueChanged(string text)
{
string[] xyValueStrings2 = text.Split(',');
if (xyValueStrings2.Length != 2)
{
xyValueStrings2 = new string[] { "0", "0" };
}
double.TryParse(xyValueStrings2[0], out double currentValue);
xEditWidget.ActuallNumberEdit.Value = currentValue;
double.TryParse(xyValueStrings2[1], out currentValue);
yEditWidget.ActuallNumberEdit.Value = currentValue;
}
}
}