Skip to content

Commit 79106e4

Browse files
authored
feat: ToolBar controls (#2830)
1 parent 32edbc9 commit 79106e4

File tree

13 files changed

+1170
-954
lines changed

13 files changed

+1170
-954
lines changed

sources/editor/Stride.Core.Assets.Editor.Avalonia/Themes/PropertyViewTheme.axaml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<ControlTheme x:Key="PropertyExpanderTheme" TargetType="Expander">
88
<Setter Property="Padding" Value="10,0,0,0"/>
99
<Setter Property="Template">
10-
<ControlTemplate TargetType="Expander">
10+
<ControlTemplate>
1111
<Border BorderThickness="0" Margin="0" Padding="0"
1212
HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
1313
<ContentPresenter Content="{TemplateBinding Content}"
@@ -24,7 +24,7 @@
2424
<Setter Property="HorizontalAlignment" Value="Stretch"/>
2525
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
2626
<Setter Property="Template">
27-
<ControlTemplate TargetType="sd:PropertyView">
27+
<ControlTemplate>
2828
<Border Padding="{TemplateBinding Padding}"
2929
Background="{TemplateBinding Background}"
3030
BorderBrush="{TemplateBinding BorderBrush}"
@@ -52,7 +52,7 @@
5252
</TreeDataTemplate>
5353
</Setter>
5454
<Setter Property="Template">
55-
<ControlTemplate TargetType="sd:PropertyViewItem">
55+
<ControlTemplate>
5656
<Border BorderBrush="{TemplateBinding Border.BorderBrush}"
5757
BorderThickness="{TemplateBinding Border.BorderThickness}"
5858
IsVisible="{Binding IsVisible}">
@@ -63,9 +63,9 @@
6363
ContentTemplate="{TemplateBinding HeaderTemplate}"
6464
HorizontalAlignment="{TemplateBinding Control.HorizontalAlignment}"
6565
IsVisible="{sd:MultiBinding {Binding !$parent[sd:PropertyView].((caecp:SessionObjectPropertiesViewModel)DataContext).ShowOverridesOnly, FallbackValue={sd:True}},
66-
{Binding [IsOverridden]},
67-
{Binding ![HasBase]},
68-
Converter={sd:OrMulti}}"/>
66+
{Binding [IsOverridden]},
67+
{Binding ![HasBase]},
68+
Converter={sd:OrMulti}}"/>
6969
</Border>
7070
<Expander IsEnabled="True" IsExpanded="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"
7171
HorizontalAlignment="Stretch"
@@ -77,9 +77,9 @@
7777
ContentTemplate="{x:Static caev:PropertyViewHelper.FooterProviders}"
7878
HorizontalAlignment="{TemplateBinding Control.HorizontalAlignment}"
7979
IsVisible="{sd:MultiBinding {Binding !$parent[sd:PropertyView].((caecp:SessionObjectPropertiesViewModel)DataContext).ShowOverridesOnly, FallbackValue={sd:True}},
80-
{Binding [IsOverridden]},
81-
{Binding ![HasBase]},
82-
Converter={sd:OrMulti}}"/>
80+
{Binding [IsOverridden]},
81+
{Binding ![HasBase]},
82+
Converter={sd:OrMulti}}"/>
8383
</StackPanel>
8484
</Expander>
8585
</DockPanel>

sources/editor/Stride.Core.Assets.Editor/ViewModels/SessionViewModel.static.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public static SessionViewModel Instance
9898
actionService.Resize(200);
9999

100100
// And initialize the actions view model
101-
sessionViewModel.ActionHistory?.Initialize();
101+
sessionViewModel?.ActionHistory?.Initialize();
102102

103103
// Copy the result of the asset loading to the log panel.
104104
sessionViewModel?.AssetLog.AddLogger(LogKey.Get("Session"), sessionResult);

sources/editor/Stride.GameStudio.Avalonia/App.axaml

Lines changed: 5 additions & 128 deletions
Large diffs are not rendered by default.

sources/editor/Stride.GameStudio.Avalonia/Themes/DefaultStyles.axaml.cs

Lines changed: 0 additions & 15 deletions
This file was deleted.

sources/editor/Stride.GameStudio.Avalonia/Views/MainView.axaml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
<Grid RowDefinitions="Auto, *, 25"
3131
Background="Transparent">
32+
<!-- Menus -->
3233
<Menu Grid.Row="0" Grid.Column="0"
3334
VerticalAlignment="Top">
3435
<!-- File menu -->
@@ -86,6 +87,8 @@
8687
Command="{Binding CrashCommand}"/>
8788
</MenuItem>
8889
</Menu>
90+
91+
<!-- Session area -->
8992
<Grid Grid.Row="1"
9093
RowDefinitions="2*, 2, *">
9194
<Grid Grid.Row="0"
@@ -169,10 +172,12 @@
169172
</TabItem>
170173
<TabItem Header="References">
171174
<DockPanel>
172-
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
175+
<!-- Toolbar -->
176+
<sd:ToolBar DockPanel.Dock="Top">
173177
<ToggleButton IsChecked="{Binding !Session.References.ShowReferencers}" Content="{sd:LocalizeString References}" MinWidth="80"/>
174178
<ToggleButton IsChecked="{Binding Session.References.ShowReferencers}" Content="{sd:LocalizeString Referenced by}" MinWidth="80"/>
175-
</StackPanel>
179+
</sd:ToolBar>
180+
<!-- Asset references -->
176181
<Border DockPanel.Dock="Bottom"
177182
Padding="8,4">
178183
<TextBlock Text="{Binding Session.References.TypeCountersAsText}"
@@ -213,7 +218,7 @@
213218
</Grid>
214219
</Grid>
215220

216-
<!-- Status Bar -->
221+
<!-- Status bar -->
217222
<Grid Grid.Row="2"
218223
IsVisible="{Binding Session, Converter={sd:ObjectToBool}}"
219224
ColumnDefinitions="2*, Auto, *, Auto, *, 100">

sources/editor/Stride.GameStudio.Avalonia/Views/MainWindow.axaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@
1010
Icon="/Assets/GameStudio.ico"
1111
Title="{Binding Title}"
1212
Width="1280" Height="900">
13-
<gsvw:MainView />
13+
<gsvw:MainView />
1414
</Window>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net)
2+
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
3+
4+
using Avalonia;
5+
using Avalonia.Controls;
6+
using Avalonia.Layout;
7+
8+
namespace Stride.Core.Presentation.Avalonia.Controls;
9+
10+
public sealed class ToolBar : ItemsControl
11+
{
12+
/// <summary>
13+
/// Defines the <see cref="Orientation"/> property.
14+
/// </summary>
15+
public static readonly StyledProperty<Orientation> OrientationProperty =
16+
AvaloniaProperty.RegisterAttached<ToolBar, Orientation>(nameof(Orientation), typeof(ToolBar), coerce: CoerceOrientation);
17+
18+
private static Orientation CoerceOrientation(AvaloniaObject d, Orientation value)
19+
{
20+
ToolBarTray? toolBarTray = ((ToolBar)d).ToolBarTray;
21+
return toolBarTray?.Orientation ?? value;
22+
}
23+
24+
public Orientation Orientation
25+
{
26+
get => GetValue(OrientationProperty);
27+
}
28+
29+
private ToolBarTray? ToolBarTray => Parent as ToolBarTray;
30+
31+
protected override void OnInitialized()
32+
{
33+
base.OnInitialized();
34+
CoerceValue(OrientationProperty);
35+
}
36+
}
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net)
2+
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
3+
4+
using System.Collections.ObjectModel;
5+
using Avalonia;
6+
using Avalonia.Controls;
7+
using Avalonia.Layout;
8+
using Avalonia.Metadata;
9+
10+
namespace Stride.Core.Presentation.Avalonia.Controls;
11+
12+
public sealed class ToolBarTray : Control, IAddChild<ToolBar>
13+
{
14+
/// <summary>
15+
/// Defines the <see cref="Orientation"/> property.
16+
/// </summary>
17+
public static readonly StyledProperty<Orientation> OrientationProperty =
18+
AvaloniaProperty.Register<ToolBarTray, Orientation>(nameof(Orientation));
19+
20+
static ToolBarTray()
21+
{
22+
OrientationProperty.Changed.AddClassHandler<ToolBarTray>((tray, _) =>
23+
{
24+
foreach (var toolBar in tray.ToolBars)
25+
{
26+
toolBar.CoerceValue(ToolBar.OrientationProperty);
27+
}
28+
});
29+
}
30+
31+
private readonly ToolBarCollection toolBars;
32+
33+
public ToolBarTray()
34+
{
35+
toolBars = new ToolBarCollection(this);
36+
}
37+
38+
public Orientation Orientation
39+
{
40+
get => GetValue(OrientationProperty);
41+
set => SetValue(OrientationProperty, value);
42+
}
43+
44+
public Collection<ToolBar> ToolBars => toolBars;
45+
46+
void IAddChild<ToolBar>.AddChild(ToolBar child)
47+
{
48+
ToolBars.Add(child);
49+
}
50+
51+
// Note: for now follow a similar layouting than StackPanel
52+
protected override Size MeasureOverride(Size availableSize)
53+
{
54+
Size trayDesiredSize = new();
55+
Size toolBarConstraint = availableSize;
56+
bool isHorizontal = Orientation == Orientation.Horizontal;
57+
toolBarConstraint = isHorizontal
58+
? toolBarConstraint.WithWidth(double.PositiveInfinity)
59+
: toolBarConstraint.WithHeight(double.PositiveInfinity);
60+
61+
foreach (var toolBar in toolBars)
62+
{
63+
// Measure the toolbar
64+
toolBar.Measure(toolBarConstraint);
65+
var toolBarDesiredSize = toolBar.DesiredSize;
66+
67+
// Accumulate the size
68+
if (isHorizontal)
69+
{
70+
trayDesiredSize = trayDesiredSize.WithWidth(trayDesiredSize.Width + toolBarDesiredSize.Width);
71+
trayDesiredSize = trayDesiredSize.WithHeight(Math.Max(trayDesiredSize.Height, toolBarDesiredSize.Height));
72+
}
73+
else
74+
{
75+
trayDesiredSize = trayDesiredSize.WithWidth(Math.Max(trayDesiredSize.Width, toolBarDesiredSize.Width));
76+
trayDesiredSize = trayDesiredSize.WithHeight(trayDesiredSize.Height + toolBarDesiredSize.Height);
77+
}
78+
}
79+
80+
return trayDesiredSize;
81+
}
82+
83+
// Note: for now follow a similar layouting than StackPanel
84+
protected override Size ArrangeOverride(Size finalSize)
85+
{
86+
bool isHorizontal = Orientation == Orientation.Horizontal;
87+
Rect rcToolBar = new(finalSize);
88+
double previousDimension = 0.0;
89+
90+
foreach (var toolBar in toolBars)
91+
{
92+
if (!toolBar.IsVisible) continue;
93+
94+
if (isHorizontal)
95+
{
96+
rcToolBar = rcToolBar.WithX(rcToolBar.X + previousDimension);
97+
previousDimension = toolBar.DesiredSize.Width;
98+
rcToolBar = rcToolBar.WithWidth(previousDimension);
99+
rcToolBar = rcToolBar.WithHeight(Math.Max(finalSize.Height, toolBar.DesiredSize.Height));
100+
}
101+
else
102+
{
103+
rcToolBar = rcToolBar.WithY(rcToolBar.Y + previousDimension);
104+
previousDimension = toolBar.DesiredSize.Height;
105+
rcToolBar = rcToolBar.WithHeight(previousDimension);
106+
rcToolBar = rcToolBar.WithWidth(Math.Max(finalSize.Width, toolBar.DesiredSize.Width));
107+
}
108+
109+
toolBar.Arrange(rcToolBar);
110+
}
111+
112+
return finalSize;
113+
}
114+
115+
private sealed class ToolBarCollection : Collection<ToolBar>
116+
{
117+
private readonly ToolBarTray parent;
118+
119+
public ToolBarCollection(ToolBarTray parent)
120+
{
121+
this.parent = parent;
122+
}
123+
124+
protected override void ClearItems()
125+
{
126+
var count = Count;
127+
if (count > 0)
128+
{
129+
for (var i = 0; i < count; i++)
130+
{
131+
var toolBar = this[i];
132+
parent.VisualChildren.Remove(toolBar);
133+
parent.LogicalChildren.Remove(toolBar);
134+
}
135+
136+
parent.InvalidateMeasure();
137+
}
138+
139+
base.ClearItems();
140+
}
141+
142+
protected override void InsertItem(int index, ToolBar toolBar)
143+
{
144+
base.InsertItem(index, toolBar);
145+
146+
parent.LogicalChildren.Add(toolBar);
147+
parent.VisualChildren.Add(toolBar);
148+
149+
parent.InvalidateMeasure();
150+
}
151+
152+
protected override void RemoveItem(int index)
153+
{
154+
var toolBar = this[index];
155+
base.RemoveItem(index);
156+
157+
parent.VisualChildren.Remove(toolBar);
158+
parent.LogicalChildren.Remove(toolBar);
159+
160+
parent.InvalidateMeasure();
161+
}
162+
163+
protected override void SetItem(int index, ToolBar toolBar)
164+
{
165+
var currentToolBar = this[index];
166+
if (toolBar != currentToolBar)
167+
{
168+
base.SetItem(index, toolBar);
169+
170+
// remove current toolBar
171+
parent.VisualChildren.Remove(currentToolBar);
172+
parent.LogicalChildren.Remove(currentToolBar);
173+
174+
// add new toolBar
175+
parent.LogicalChildren.Add(toolBar);
176+
parent.VisualChildren.Add(toolBar);
177+
178+
parent.InvalidateMeasure();
179+
}
180+
}
181+
}
182+
}

0 commit comments

Comments
 (0)