Skip to content

Commit b7ebe44

Browse files
committed
Fix #65: Add Previous and Next buttons to sliders
This change adds previous and next buttons the FontGlyphsView slider. Controls: - Add generic Layout and LayoutManager - Add Toolbar and ToolbarLayoutManager - Add SliderView Converter: - Add generic TypeConverter base class. FontFamily: - Rename DefaultFontFamily to Defauilt - Rename FluentUIFontFamily to FluentUI GlyphsView: - Replace Slider with SliderView SkLabel: - Integrate FontFamily changes - Fix #endregion labels Slider: - Fix OnPropertyChanged implementation. - use Math.Clamp in ValueProperty coerceValue
1 parent 9ed33f7 commit b7ebe44

22 files changed

+1746
-35
lines changed

Controls/Layouts/Layout.cs

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
namespace GlyphViewer.Controls.Layouts;
2+
3+
/// <summary>
4+
/// Provides an abstract base <see cref="Layout"/> class.
5+
/// </summary>
6+
/// <typeparam name="I">The type of <see cref="LayoutInfo"/> to use to layout child items.</typeparam>
7+
public abstract class Layout<I> : Layout
8+
where I : LayoutInfo
9+
{
10+
#region Fields
11+
12+
readonly Dictionary<IView, I> _layoutInfo = new(ReferenceEqualityComparer.Instance);
13+
Size _measuredSize = Size.Zero;
14+
15+
#endregion Fields
16+
17+
/// <summary>
18+
/// Initializes a new instance of this class.
19+
/// </summary>
20+
protected Layout()
21+
{ }
22+
23+
#region Properties
24+
25+
/// <summary>
26+
/// Gets the <typeparamref name="I"/> <see cref="Info"/> for the specified <paramref name="view"/> view.
27+
/// </summary>
28+
/// <param name="view">The <see cref="IView"/> of information to retrieve.</param>
29+
/// <returns>The <typeparamref name="I"/> <see cref="Info"/>, if found; otherwise, a null reference.</returns>
30+
public I this[IView view]
31+
{
32+
get
33+
{
34+
_layoutInfo.TryGetValue(view, out I info);
35+
return info;
36+
}
37+
}
38+
39+
/// <summary>
40+
/// Enumerates the <typeparamref name="I"/> <see cref="LayoutInfo"/> for each view.
41+
/// </summary>
42+
/// <returns>An <see cref="IEnumerable{T}"/>.</returns>
43+
protected IEnumerable<I> Info
44+
{
45+
get => _layoutInfo.Values;
46+
}
47+
48+
#endregion Properties
49+
50+
#region Add
51+
52+
void AddView(IView view)
53+
{
54+
I info = CreateItemInfo(view);
55+
if (info is not null)
56+
{
57+
_layoutInfo.Add(view, info);
58+
OnItemAdded(info);
59+
}
60+
}
61+
62+
/// <summary>
63+
/// Creates an instance of <typeparamref name="I"/> <see cref="LayoutInfo"/>.
64+
/// </summary>
65+
/// <param name="view">The <see cref="IView"/> to arrange.</param>
66+
/// <returns>A new instance of a <typeparamref name="I"/> <see cref="LayoutInfo"/>.</returns>
67+
protected abstract I CreateItemInfo(IView view);
68+
69+
/// <summary>
70+
/// Overridden in the derived class when a <see cref="IView"/> is added.
71+
/// </summary>
72+
/// <param name="info">The <typeparamref name="I"/> for the added view.</param>
73+
protected virtual void OnItemAdded(I info)
74+
{
75+
}
76+
77+
#endregion Add
78+
79+
#region Remove
80+
81+
void RemoveView(IView view)
82+
{
83+
if (_layoutInfo.TryGetValue(view, out I info))
84+
{
85+
_layoutInfo.Remove(view);
86+
OnItemRemoved(info);
87+
info.Removed();
88+
}
89+
}
90+
91+
/// <summary>
92+
/// Overridden in the derived class when a <see cref="IView"/> is removed.
93+
/// </summary>
94+
/// <param name="info">The <typeparamref name="I"/> for the removed view.</param>
95+
protected virtual void OnItemRemoved(I info)
96+
{
97+
}
98+
99+
#endregion Remove
100+
101+
#region Find
102+
103+
/// <summary>
104+
/// Find the <typeparamref name="I"/> <see cref="LayoutInfo"/> for the item
105+
/// at the specified <paramref name="point"/>.
106+
/// </summary>
107+
/// <param name="point">The <see cref="Point"/> to query.</param>
108+
/// <returns>
109+
/// The <typeparamref name="I"/> <see cref="LayoutInfo"/> for the item
110+
/// at the specified <paramref name="point"/>; otherwise, a null reference.
111+
/// </returns>
112+
public I Find(Point point)
113+
{
114+
foreach (I info in _layoutInfo.Values)
115+
{
116+
if (info.Bounds.Contains(point))
117+
{
118+
return info;
119+
}
120+
}
121+
return null;
122+
}
123+
124+
/// <summary>
125+
/// Find the child <see cref="View"/> at the specified <paramref name="point"/>.
126+
/// </summary>
127+
/// <param name="point">The <see cref="Point"/> to query.</param>
128+
/// <returns>
129+
/// The <see cref="View"/> for the child at the specified <paramref name="point"/>;
130+
/// otherwise, a null reference.
131+
/// </returns>
132+
public View FindChild(Point point)
133+
{
134+
if (Find(point) is I info)
135+
{
136+
return info.View as View;
137+
}
138+
return null;
139+
}
140+
141+
#endregion Find
142+
143+
#region Overrides
144+
145+
/// <summary>
146+
/// Updates the size of an View.
147+
/// </summary>
148+
/// <param name="widthConstraint">The width that a parent element can allocate a child element.</param>
149+
/// <param name="heightConstraint">The height that a parent element can allocate a child element.</param>
150+
/// <returns>The desired Size for this element.</returns>
151+
protected override Size MeasureOverride(double widthConstraint, double heightConstraint)
152+
{
153+
bool needsMeasure = _measuredSize.Width != widthConstraint || _measuredSize.Height != heightConstraint;
154+
if (needsMeasure)
155+
{
156+
foreach (LayoutInfo info in _layoutInfo.Values)
157+
{
158+
info.View.InvalidateMeasure();
159+
}
160+
}
161+
else
162+
{
163+
foreach (LayoutInfo info in _layoutInfo.Values)
164+
{
165+
if (info.NeedsMeasure)
166+
{
167+
needsMeasure = true;
168+
break;
169+
}
170+
}
171+
}
172+
if (needsMeasure)
173+
{
174+
_measuredSize = base.MeasureOverride(widthConstraint, heightConstraint);
175+
}
176+
return _measuredSize;
177+
}
178+
179+
/// <summary>
180+
/// Adds an <see cref="IView"/> to the <see cref="Layout.Children"/> collection.
181+
/// </summary>
182+
/// <param name="index">The zero-based index to add.</param>
183+
/// <param name="view">The <see cref="IView"/> to add.</param>
184+
protected override sealed void OnAdd(int index, IView view)
185+
{
186+
base.OnAdd(index, view);
187+
AddView(view);
188+
InvalidateMeasure();
189+
}
190+
191+
/// <summary>
192+
/// Inserts an <see cref="IView"/> into the <see cref="Layout.Children"/> collection.
193+
/// </summary>
194+
/// <param name="index">The zero-based index to insert at.</param>
195+
/// <param name="view">The <see cref="IView"/> to add.</param>
196+
protected override sealed void OnInsert(int index, IView view)
197+
{
198+
base.OnInsert(index, view);
199+
AddView(view);
200+
InvalidateMeasure();
201+
}
202+
203+
/// <summary>
204+
/// Removes an <see cref="IView"/> from the <see cref="Layout.Children"/> collection.
205+
/// </summary>
206+
/// <param name="index">The zero-based index of the <see cref="IView"/> to remove.</param>
207+
/// <param name="view">The <see cref="IView"/> to remove.</param>
208+
protected override sealed void OnRemove(int index, IView view)
209+
{
210+
base.OnRemove(index, view);
211+
RemoveView(view);
212+
InvalidateMeasure();
213+
}
214+
215+
/// <summary>
216+
/// Replaces an <see cref="IView"/> in the <see cref="Layout.Children"/> collection.
217+
/// </summary>
218+
/// <param name="index">The zero-based index of the <see cref="IView"/> to update.</param>
219+
/// <param name="view">The <see cref="IView"/> to set.</param>
220+
/// <param name="oldView">The <see cref="IView"/> to replace.</param>
221+
protected override sealed void OnUpdate(int index, IView view, IView oldView)
222+
{
223+
base.OnUpdate(index, view, oldView);
224+
RemoveView(oldView);
225+
AddView(view);
226+
InvalidateMeasure();
227+
}
228+
229+
/// <summary>
230+
/// Removes all items from the <see cref="Layout.Children"/> collection.
231+
/// </summary>
232+
protected override sealed void OnClear()
233+
{
234+
base.OnClear();
235+
foreach (I info in _layoutInfo.Values)
236+
{
237+
RemoveView(info.View);
238+
}
239+
InvalidateMeasure();
240+
}
241+
242+
#endregion Overrides
243+
}

0 commit comments

Comments
 (0)