Skip to content

Commit

Permalink
add basic code
Browse files Browse the repository at this point in the history
  • Loading branch information
NaBian committed Jun 13, 2022
1 parent 6207684 commit eb2779f
Show file tree
Hide file tree
Showing 9 changed files with 501 additions and 1 deletion.
274 changes: 274 additions & 0 deletions src/Shared/HandyControl_Shared/Controls/Ribbon/Ribbon.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using HandyControl.Data;

namespace HandyControl.Controls
{
[TemplatePart(Name = TabHeaderItemsControl, Type = typeof(ItemsControl))]
public class Ribbon : Selector
{
private const string TabHeaderItemsControl = "PART_TabHeaderItemsControl";

private ItemsControl _tabHeaderItemsControl;

private readonly ObservableCollection<object> _tabHeaderItemsSource = new();

public Ribbon()
{
ItemContainerGenerator.StatusChanged += OnItemContainerGeneratorStatusChanged;

AddHandler(SelectableItem.SelectedEvent, new RoutedEventHandler(OnTabHeaderSelected));
}

private void OnTabHeaderSelected(object sender, RoutedEventArgs e)
{
if (_tabHeaderItemsControl == null)
{
return;
}

if (e.OriginalSource is not RibbonTabHeader tabHeader)
{
return;
}

var selectedIndex = _tabHeaderItemsControl.ItemContainerGenerator.IndexFromContainer(tabHeader);
var currentSelectedIndex = SelectedIndex;

if (currentSelectedIndex < 0 || SelectedIndex != selectedIndex)
{
SelectedIndex = selectedIndex;
}
}

private static readonly DependencyPropertyKey SelectedContentPropertyKey =
DependencyProperty.RegisterReadOnly("SelectedContent", typeof(object), typeof(Ribbon),
new FrameworkPropertyMetadata((object) null));

public static readonly DependencyProperty SelectedContentProperty =
SelectedContentPropertyKey.DependencyProperty;

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public object SelectedContent
{
get => GetValue(SelectedContentProperty);
internal set => SetValue(SelectedContentPropertyKey, value);
}

public static readonly DependencyProperty IsMinimizedProperty = DependencyProperty.Register(nameof(IsMinimized),
typeof(bool), typeof(Ribbon),
new PropertyMetadata(ValueBoxes.FalseBox, OnIsMinimizedChanged, CoerceIsMinimized));

private static object CoerceIsMinimized(DependencyObject d, object basevalue)
{
var num = (bool) basevalue ? 1 : 0;
var ribbon = (Ribbon) d;
return num != 0 && ribbon.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated ? ValueBoxes.FalseBox : basevalue;
}

private static void OnIsMinimizedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{

}

public bool IsMinimized
{
get => (bool) GetValue(IsMinimizedProperty);
set => SetValue(IsMinimizedProperty, ValueBoxes.BooleanBox(value));
}

public static readonly DependencyProperty IsDropDownOpenProperty =
DependencyProperty.Register(nameof(IsDropDownOpen), typeof(bool), typeof(Ribbon),
new PropertyMetadata(ValueBoxes.FalseBox, OnIsDropDownOpenChanged, CoerceIsDropDownOpen));

private static object CoerceIsDropDownOpen(DependencyObject d, object basevalue)
{
return ValueBoxes.FalseBox;
}

private static void OnIsDropDownOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{

}

public bool IsDropDownOpen
{
get => (bool) GetValue(IsDropDownOpenProperty);
set => SetValue(IsDropDownOpenProperty, ValueBoxes.BooleanBox(value));
}

public override void OnApplyTemplate()
{
base.OnApplyTemplate();

_tabHeaderItemsControl = GetTemplateChild(TabHeaderItemsControl) as ItemsControl;
if (_tabHeaderItemsControl is {ItemsSource: null})
{
_tabHeaderItemsControl.ItemsSource = _tabHeaderItemsSource;
}

UpdateSelectedContent();
}

protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
{
base.OnItemsChanged(e);

if (e.Action == NotifyCollectionChangedAction.Remove ||
e.Action == NotifyCollectionChangedAction.Replace ||
e.Action == NotifyCollectionChangedAction.Reset)
{
InitializeSelection();
}

if ((ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated || e.Action != NotifyCollectionChangedAction.Move) &&
e.Action != NotifyCollectionChangedAction.Remove)
{
return;
}

RefreshHeaderCollection();
}

protected override DependencyObject GetContainerForItemOverride() => new RibbonTab();

protected override bool IsItemItsOwnContainerOverride(object item) => item is RibbonTab;

private void OnItemContainerGeneratorStatusChanged(object sender, EventArgs e)
{
if (ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
{
return;
}

CoerceValue(Ribbon.IsMinimizedProperty);
InitializeSelection();
RefreshHeaderCollection();
}

private int GetFirstVisibleTabIndex()
{
var count = Items.Count;
for (var index = 0; index < count; ++index)
{
if (ItemContainerGenerator.ContainerFromIndex(index) is RibbonTab {IsVisible: true})
{
return index;
}
}

return -1;
}

private void InitializeSelection()
{
if (SelectedIndex >= 0 || Items.Count <= 0)
{
return;
}

var firstVisibleTabIndex = GetFirstVisibleTabIndex();
if (firstVisibleTabIndex < 0)
{
return;
}

SelectedIndex = firstVisibleTabIndex;
}

private static bool EqualsEx(object o1, object o2)
{
try
{
return Equals(o1, o2);
}
catch (InvalidCastException)
{
return false;
}
}

private RibbonTab GetSelectedRibbonTab()
{
var selectedItem = SelectedItem;
if (selectedItem != null)
{
if (selectedItem is not RibbonTab ribbonTab)
{
ribbonTab = ItemContainerGenerator.ContainerFromIndex(SelectedIndex) as RibbonTab;

if (ribbonTab == null || !EqualsEx(selectedItem, ItemContainerGenerator.ItemFromContainer(ribbonTab)))
{
ribbonTab = ItemContainerGenerator.ContainerFromItem(selectedItem) as RibbonTab;
}
}

return ribbonTab;
}

return null;
}

private void UpdateSelectedContent()
{
if (SelectedIndex < 0)
{
SelectedContent = null;
return;
}

var ribbonTab = GetSelectedRibbonTab();
if (ribbonTab == null)
{
return;
}

var visualParent = VisualTreeHelper.GetParent(ribbonTab) as FrameworkElement;

//seitem
}

private static object CreateDefaultHeaderObject() => new SingleSpaceObject();

private void RefreshHeaderCollection()
{
var itemsCount = Items.Count;
for (var index = 0; index < itemsCount; ++index)
{
object header = null;
if (ItemContainerGenerator.ContainerFromIndex(index) is RibbonTab ribbonTab)
{
header = ribbonTab.Header;
}

header ??= CreateDefaultHeaderObject();

if (index >= _tabHeaderItemsSource.Count)
{
_tabHeaderItemsSource.Add(header);
}
else
{
_tabHeaderItemsSource[index] = header;
}
}

var headerCount = _tabHeaderItemsSource.Count;
for (var index = 0; index < headerCount - itemsCount; ++index)
{
_tabHeaderItemsSource.RemoveAt(itemsCount);
}
}

private class SingleSpaceObject
{
public override string ToString() => " ";
}
}
}
27 changes: 27 additions & 0 deletions src/Shared/HandyControl_Shared/Controls/Ribbon/RibbonGroup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Windows;
using System.Windows.Controls;
using HandyControl.Data;

namespace HandyControl.Controls
{
public class RibbonGroup : HeaderedItemsControl
{
public static readonly DependencyProperty ShowLauncherButtonProperty = DependencyProperty.Register(
"ShowLauncherButton", typeof(bool), typeof(RibbonGroup), new PropertyMetadata(ValueBoxes.FalseBox));

public bool ShowLauncherButton
{
get => (bool) GetValue(ShowLauncherButtonProperty);
set => SetValue(ShowLauncherButtonProperty, value);
}

public static readonly DependencyProperty ShowSplitterProperty = DependencyProperty.Register(
"ShowSplitter", typeof(bool), typeof(RibbonGroup), new PropertyMetadata(ValueBoxes.TrueBox));

public bool ShowSplitter
{
get => (bool) GetValue(ShowSplitterProperty);
set => SetValue(ShowSplitterProperty, value);
}
}
}
22 changes: 22 additions & 0 deletions src/Shared/HandyControl_Shared/Controls/Ribbon/RibbonTab.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Windows;
using System.Windows.Controls;
using HandyControl.Data;

namespace HandyControl.Controls
{
public class RibbonTab : HeaderedItemsControl
{
public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register(
"IsSelected", typeof(bool), typeof(RibbonTab), new PropertyMetadata(ValueBoxes.FalseBox));

public bool IsSelected
{
get => (bool) GetValue(IsSelectedProperty);
set => SetValue(IsSelectedProperty, value);
}

protected override DependencyObject GetContainerForItemOverride() => new RibbonGroup();

protected override bool IsItemItsOwnContainerOverride(object item) => item is RibbonGroup;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace HandyControl.Controls
{
public class RibbonTabHeader : SelectableItem
{

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Windows;
using System.Windows.Controls;

namespace HandyControl.Controls
{
public class RibbonTabHeaderItemsControl : ItemsControl
{
protected override DependencyObject GetContainerForItemOverride() => new RibbonTabHeader();

protected override bool IsItemItsOwnContainerOverride(object item) => item is RibbonTabHeader;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace HandyControl.Controls
{
public class RibbonTabHeadersPanel : SimpleStackPanel
{

}
}
9 changes: 9 additions & 0 deletions src/Shared/HandyControl_Shared/HandyControl_Shared.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@
<Compile Include="$(MSBuildThisFileDirectory)Controls\PropertyGrid\PropertyItem.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\PropertyGrid\PropertyItemsControl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\PropertyGrid\PropertyResolver.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Ribbon\Ribbon.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Ribbon\RibbonGroup.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Ribbon\RibbonTab.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Ribbon\RibbonTabHeader.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Ribbon\RibbonTabHeaderItemsControl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Ribbon\RibbonTabHeadersPanel.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Screenshot\Screenshot.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Other\Sprite.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Block\ToggleBlock.cs" />
Expand Down Expand Up @@ -385,6 +391,9 @@
<None Include="$(MSBuildThisFileDirectory)Themes\Styles\ElementGroup.xaml">
<SubType>Designer</SubType>
</None>
<Page Include="$(MSBuildThisFileDirectory)Themes\Styles\Ribbon.xaml">
<SubType>Designer</SubType>
</Page>
<None Include="$(MSBuildThisFileDirectory)Themes\XamlCombine.exe" />
<Page Include="$(MSBuildThisFileDirectory)Themes\Basic\Colors\Colors.xaml">
<SubType>Designer</SubType>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}"/>
<Setter Property="Background" Value="{DynamicResource RegionBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource TitleBrush}"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="{StaticResource DefaultControlPadding}"/>
<Setter Property="MinHeight" Value="{StaticResource DefaultControlHeight}"/>
Expand Down
Loading

0 comments on commit eb2779f

Please sign in to comment.