Extract SliceSettings popover code for reuse in validation errors

- Issue MatterHackers/MCCentral#4878
This commit is contained in:
John Lewin 2019-01-22 13:23:22 -08:00
parent f2e8a9d4ec
commit 67e72aec57
2 changed files with 103 additions and 94 deletions

View file

@ -48,6 +48,11 @@ namespace MatterHackers.MatterControl.CustomWidgets
private Color hoverColor;
private bool fullRowSelect;
private GuiWidget settingsLabel;
private Popover popoverBubble = null;
private static Popover activePopover = null;
private SystemWindow systemWindow = null;
protected ImageWidget imageWidget;
public GuiWidget ActionWidget { get; set; }
@ -56,6 +61,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
{
using (this.LayoutLock())
{
this.HelpText = helpText;
this.theme = theme;
this.fullRowSelect = fullRowSelect;
@ -119,12 +125,15 @@ namespace MatterHackers.MatterControl.CustomWidgets
};
}
public string HelpText { get; protected set; }
public ArrowDirection ArrowDirection { get; set; } = ArrowDirection.Right;
public override void AddChild(GuiWidget childToAdd, int indexInChildrenList = -1)
{
if (fullRowSelect)
{
childToAdd.Selectable = false;
childToAdd.Selectable = false;
}
base.AddChild(childToAdd, indexInChildrenList);
@ -136,10 +145,20 @@ namespace MatterHackers.MatterControl.CustomWidgets
set => base.BackgroundColor = value;
}
public override void OnLoad(EventArgs args)
{
systemWindow = this.Parents<SystemWindow>().FirstOrDefault();
base.OnLoad(args);
}
public override void OnMouseEnterBounds(MouseEventArgs mouseEvent)
{
mouseInBounds = true;
this.Invalidate();
this.ShowPopover(this);
base.OnMouseEnterBounds(mouseEvent);
}
@ -148,7 +167,89 @@ namespace MatterHackers.MatterControl.CustomWidgets
mouseInBounds = false;
this.Invalidate();
if (popoverBubble != null)
{
// Allow a moment to elapse to determine if the mouse is within the bubble or has returned to this control, close otherwise
UiThread.RunOnIdle(() =>
{
// Skip close if we are FirstWidgetUnderMouse
if (this.FirstWidgetUnderMouse)
{
// Often we get OnMouseLeaveBounds when the mouse is still within bounds (as child mouse events are processed)
// If the mouse is in bounds of this widget, abort the popover close below
return;
}
// Close the popover as long as it doesn't contain the mouse
if (!popoverBubble.ContainsFirstUnderMouseRecursive())
{
// Close any active popover bubble
popoverBubble?.Close();
}
}, 1);
}
base.OnMouseLeaveBounds(mouseEvent);
}
protected virtual void ExtendPopover(SliceSettingsPopover popover)
{
}
protected void ShowPopover(SettingsRow settingsRow)
{
// Only display popovers when we're the active widget, exit if we're not first under mouse
if (systemWindow == null
|| !this.ContainsFirstUnderMouseRecursive())
{
return;
}
int arrowOffset = (int)(settingsRow.Height / 2);
var popover = new SliceSettingsPopover(this.ArrowDirection, new BorderDouble(15, 10), 7, arrowOffset)
{
HAnchor = HAnchor.Fit,
VAnchor = VAnchor.Fit,
TagColor = theme.ResolveColor(AppContext.Theme.BackgroundColor, AppContext.Theme.AccentMimimalOverlay.WithAlpha(50)),
};
popover.AddChild(new WrappedTextWidget(settingsRow.HelpText, pointSize: theme.DefaultFontSize - 1, textColor: AppContext.Theme.TextColor)
{
Width = 400 * GuiWidget.DeviceScale,
HAnchor = HAnchor.Fit,
});
bool alignLeft = (this.ArrowDirection == ArrowDirection.Right);
// after a certain amount of time make the popover close (just like a tool tip)
double closeSeconds = Math.Max(1, (settingsRow.HelpText.Length / 50.0)) * 5;
this.ExtendPopover(popover);
activePopover?.Close();
activePopover = popover;
systemWindow.ShowPopover(
new MatePoint(settingsRow)
{
Mate = new MateOptions(alignLeft ? MateEdge.Left : MateEdge.Right, MateEdge.Top),
AltMate = new MateOptions(alignLeft ? MateEdge.Left : MateEdge.Right, MateEdge.Bottom),
Offset = new RectangleDouble(12, 0, 12, 0)
},
new MatePoint(popover)
{
Mate = new MateOptions(alignLeft ? MateEdge.Right : MateEdge.Left, MateEdge.Top),
AltMate = new MateOptions(alignLeft ? MateEdge.Left : MateEdge.Right, MateEdge.Bottom),
//Offset = new RectangleDouble(12, 0, 12, 0)
},
secondsToClose: closeSeconds);
popoverBubble = popover;
}
}
}

View file

@ -78,8 +78,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
private SettingsContext settingsContext;
public string HelpText { get; }
private PrinterConfig printer;
private SliceSettingData settingData;
@ -88,8 +86,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
private GuiWidget restoreArea;
private GuiWidget restoreButton = null;
private Popover popoverBubble = null;
private SystemWindow systemWindow = null;
private ValidationWrapper validationWrapper;
public SliceSettingsRow(PrinterConfig printer, SettingsContext settingsContext, SliceSettingData settingData, ThemeConfig theme, bool fullRowSelect = false)
@ -98,7 +94,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
this.printer = printer;
this.settingData = settingData;
this.settingsContext = settingsContext;
this.HelpText = settingData.HelpText;
using (this.LayoutLock())
{
@ -271,54 +266,12 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
base.OnClick(mouseEvent);
}
public override void OnLoad(EventArgs args)
{
systemWindow = this.Parents<SystemWindow>().FirstOrDefault();
base.OnLoad(args);
}
public ArrowDirection ArrowDirection { get; set; } = ArrowDirection.Right;
public UIField UIField { get; internal set; }
public override void OnMouseEnterBounds(MouseEventArgs mouseEvent)
protected override void ExtendPopover(SliceSettingsPopover popover)
{
this.ShowPopover(this);
base.OnMouseEnterBounds(mouseEvent);
}
private void ShowPopover(SliceSettingsRow settingsRow)
{
// Only display popovers when we're the active widget, exit if we're not first under mouse
if (systemWindow == null
|| !this.ContainsFirstUnderMouseRecursive())
{
return;
}
int arrowOffset = (int)(settingsRow.Height / 2);
var popover = new SliceSettingsPopover(this.ArrowDirection, new BorderDouble(15, 10), 7, arrowOffset)
{
HAnchor = HAnchor.Fit,
VAnchor = VAnchor.Fit,
TagColor = theme.ResolveColor(AppContext.Theme.BackgroundColor, AppContext.Theme.AccentMimimalOverlay.WithAlpha(50)),
};
popover.AddChild(new WrappedTextWidget(settingsRow.HelpText, pointSize: theme.DefaultFontSize - 1, textColor: AppContext.Theme.TextColor)
{
Width = 400 * GuiWidget.DeviceScale,
HAnchor = HAnchor.Fit,
});
bool alignLeft = (this.ArrowDirection == ArrowDirection.Right);
string mapsTo = "";
// after a certain amount of time make the popover close (just like a tool tip)
double closeSeconds = Math.Max(1, (settingsRow.HelpText.Length / 50.0)) * 5;
if (printer.EngineMappingsMatterSlice.MappedSettings.FirstOrDefault(m => m.CanonicalSettingsName == settingData.SlicerConfigName) is AsPercentOfReferenceOrDirect percentReference)
{
mapsTo = " -> " + percentReference.ExportedName;
@ -412,54 +365,9 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
Margin = new BorderDouble(top: 10)
});
#endif
activePopover?.Close();
activePopover = popover;
systemWindow.ShowPopover(
new MatePoint(settingsRow)
{
Mate = new MateOptions(alignLeft ? MateEdge.Left : MateEdge.Right, MateEdge.Top),
AltMate = new MateOptions(alignLeft ? MateEdge.Left : MateEdge.Right, MateEdge.Bottom),
Offset = new RectangleDouble(12, 0, 12, 0)
},
new MatePoint(popover)
{
Mate = new MateOptions(alignLeft ? MateEdge.Right : MateEdge.Left, MateEdge.Top),
AltMate = new MateOptions(alignLeft ? MateEdge.Left : MateEdge.Right, MateEdge.Bottom),
//Offset = new RectangleDouble(12, 0, 12, 0)
},
secondsToClose: closeSeconds);
popoverBubble = popover;
}
public override void OnMouseLeaveBounds(MouseEventArgs mouseEvent)
{
if (popoverBubble != null)
{
// Allow a moment to elapse to determine if the mouse is withing the bubble or has returned to this control, close otherwise
UiThread.RunOnIdle(() =>
{
// Skip close if we are FirstWidgetUnderMouse
if (this.FirstWidgetUnderMouse)
{
// Often we get OnMouseLeaveBounds when the mouse is still within bounds (as child mouse events are processed)
// If the mouse is in bounds of this widget, abort the popover close below
return;
}
// Close the popover as long as it doesn't contain the mouse
if (!popoverBubble.ContainsFirstUnderMouseRecursive())
{
// Close any active popover bubble
popoverBubble?.Close();
}
}, 1);
}
base.OnMouseLeaveBounds(mouseEvent);
}
public void UpdateStyle()
{