Skip to content

Commit

Permalink
Adding start screen as mentioned in #242
Browse files Browse the repository at this point in the history
  • Loading branch information
batzen committed Jan 10, 2016
1 parent 015924f commit c6573a9
Show file tree
Hide file tree
Showing 17 changed files with 378 additions and 55 deletions.
39 changes: 34 additions & 5 deletions Fluent.Ribbon.Showcase/TestContent.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,30 @@
Visibility="Visible" />
</Fluent:Ribbon.ContextualGroups>

<Fluent:Ribbon.StartScreen>
<Fluent:StartScreen x:Name="startScreen">
<Fluent:StartScreenTabControl>
<Fluent:StartScreenTabControl.LeftContent>
<StackPanel Orientation="Vertical">
<Label Content="Fluent.Ribbon"
FontSize="48"
Foreground="{DynamicResource BackstageFontBrush}" />
</StackPanel>
</Fluent:StartScreenTabControl.LeftContent>

<Fluent:StartScreenTabControl.RightContent>
<StackPanel Orientation="Vertical">
<TextBlock VerticalAlignment="Center"
HorizontalAlignment="Center">You can close the start screen by either clicking the button below or by pressing ESC</TextBlock>
<Fluent:Button HorizontalAlignment="Center"
LargeIcon="pack://application:,,,/Fluent.Ribbon.Showcase;component/Images/Exit.png"
IsDefinitive="True">Close start screen</Fluent:Button>
</StackPanel>
</Fluent:StartScreenTabControl.RightContent>
</Fluent:StartScreenTabControl>
</Fluent:StartScreen>
</Fluent:Ribbon.StartScreen>

<Fluent:Ribbon.Menu>
<Grid>
<!--Backstage items can be keytipped-->
Expand Down Expand Up @@ -355,10 +379,10 @@
Target="{Binding ElementName=RedoButton}" />
</Fluent:Ribbon.QuickAccessItems>

<Fluent:RibbonTabItem x:Name="homeTabItem"
Header="Home"
KeyTip="H"
ToolTip="Regular Tool Tip">
<Fluent:RibbonTabItem x:Name="homeTabItem"
Header="Home"
KeyTip="H"
ToolTip="Regular Tool Tip">
<Fluent:RibbonGroupBox Icon="pack://application:,,,/Fluent.Ribbon.Showcase;component/Images/Default.png"
KeyTip="T10"
x:Name="C"
Expand Down Expand Up @@ -411,7 +435,12 @@
Name="UseApplicationMenu"
Size="Middle">
Use application menu
</Fluent:ToggleButton>
</Fluent:ToggleButton>
<Fluent:Button Name="ShowStartScreen"
Size="Middle"
Click="ShowStartScreen_OnClick">
Show start screen
</Fluent:Button>
</Fluent:RibbonGroupBox>

<Fluent:RibbonGroupBox Header="Window options">
Expand Down
6 changes: 6 additions & 0 deletions Fluent.Ribbon.Showcase/TestContent.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,12 @@ private void OpenModalRibbonWindow_OnClick(object sender, RoutedEventArgs e)
{
new TestWindow().ShowDialog();
}

private void ShowStartScreen_OnClick(object sender, RoutedEventArgs e)
{
this.startScreen.Shown = false;
this.startScreen.IsOpen = true;
}
}

public class TestRoutedCommand
Expand Down
76 changes: 57 additions & 19 deletions Fluent.Ribbon/Controls/Backstage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ public class Backstage : RibbonControl

#region Properties

#region IsOpen

/// <summary>
/// Gets or sets whether backstage is shown
/// </summary>
Expand Down Expand Up @@ -151,8 +149,6 @@ private static void OnIsOpenChanged(DependencyObject d, DependencyPropertyChange
}
}

#endregion

#region Content

/// <summary>
Expand Down Expand Up @@ -264,31 +260,33 @@ private void Click()
private double savedWindowWidth = double.NaN;
private double savedWindowHeight = double.NaN;

// Opens backstage on an Adorner layer
private void Show()
/// <summary>
/// Shows the <see cref="Backstage"/>
/// </summary>
protected virtual bool Show()
{
// don't open the backstage while in design mode
if (DesignerProperties.GetIsInDesignMode(this))
{
return;
return false;
}

if (this.IsLoaded == false)
{
this.Loaded += this.OnDelayedShow;
return;
return false;
}

if (this.Content == null)
{
return;
return false;
}

this.CreateAndAttachBackstageAdorner();

this.ShowAdorner();

var ribbon = this.FindRibbon();
var ribbon = this.GetParentRibbon();
if (ribbon != null)
{
ribbon.TabControl.IsDropDownOpen = false;
Expand Down Expand Up @@ -336,6 +334,8 @@ private void Show()

var content = this.Content as IInputElement;
content?.Focus();

return true;
}

private void ShowAdorner()
Expand Down Expand Up @@ -414,16 +414,38 @@ private void CreateAndAttachBackstageAdorner()
if (topLevelElement == null)
{
return;
}
}

this.adorner = new BackstageAdorner(topLevelElement, this);
var layer = this.GetAdornerLayer();

var layer = AdornerLayer.GetAdornerLayer(this);
this.adorner = new BackstageAdorner(topLevelElement, this);
layer.Add(this.adorner);

layer.CommandBindings.Add(new CommandBinding(RibbonCommands.OpenBackstage, HandleOpenBackstageCommandExecuted));
}

private AdornerLayer GetAdornerLayer()
{
var layer = AdornerLayer.GetAdornerLayer(this);

if (layer == null)
{
var parentVisual = this.Parent as Visual ?? this.GetParentRibbon();

if (parentVisual != null)
{
layer = AdornerLayer.GetAdornerLayer(parentVisual);
}
}

if (layer == null)
{
throw new Exception($"AdornerLayer could not be found for {this}.");
}

return layer;
}

private static void HandleOpenBackstageCommandExecuted(object sender, ExecutedRoutedEventArgs args)
{
var target = ((BackstageAdorner)args.Source).Backstage;
Expand Down Expand Up @@ -451,11 +473,13 @@ private void OnDelayedShow(object sender, EventArgs args)

// Delaying show so everthing can load properly.
// If we don't run this in the background setting IsOpen=true on application start we don't have access to the Bastage from the BackstageTabControl.
this.RunInDispatcherAsync(this.Show, DispatcherPriority.Background);
this.RunInDispatcherAsync(() => this.Show(), DispatcherPriority.Background);
}

// Hide backstage
private void Hide()
/// <summary>
/// Hides the <see cref="Backstage"/>
/// </summary>
protected virtual void Hide()
{
this.Loaded -= this.OnDelayedShow;

Expand All @@ -472,7 +496,7 @@ private void Hide()

this.HideAdorner();

var ribbon = this.FindRibbon();
var ribbon = this.GetParentRibbon();
if (ribbon != null)
{
ribbon.TabControl.HighlightSelectedItem = true;
Expand Down Expand Up @@ -522,8 +546,11 @@ private void Hide()
this.collapsedElements.Clear();
}

// Finds underlying ribbon control
private Ribbon FindRibbon()
/// <summary>
/// Get the parent <see cref="Ribbon"/>.
/// </summary>
/// <returns>The found <see cref="Ribbon"/> or <c>null</c> of no parent <see cref="Ribbon"/> could be found.</returns>
protected Ribbon GetParentRibbon()
{
DependencyObject item = this;

Expand All @@ -533,6 +560,17 @@ private Ribbon FindRibbon()
item = VisualTreeHelper.GetParent(item);
}

if (item == null)
{
item = this;

while (item != null &&
item is Ribbon == false)
{
item = LogicalTreeHelper.GetParent(item);
}
}

return (Ribbon)item;
}

Expand Down
44 changes: 31 additions & 13 deletions Fluent.Ribbon/Controls/Ribbon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -450,16 +450,19 @@ public UIElement Menu
/// This enables animation, styling, binding, etc...
/// </summary>
public static readonly DependencyProperty MenuProperty =
DependencyProperty.Register("Menu", typeof(UIElement), typeof(Ribbon), new UIPropertyMetadata(null, OnApplicationMenuChanged));
DependencyProperty.Register(nameof(Menu), typeof(UIElement), typeof(Ribbon), new UIPropertyMetadata(null, AddOrRemoveLogicalChildOnPropertyChanged));

static void OnApplicationMenuChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
#endregion

public UIElement StartScreen
{
Ribbon ribbon = (Ribbon)d;
if (e.OldValue != null) ribbon.RemoveLogicalChild(e.OldValue);
if (e.NewValue != null) ribbon.AddLogicalChild(e.NewValue);
get { return (UIElement)this.GetValue(StartScreenProperty); }
set { this.SetValue(StartScreenProperty, value); }
}

#endregion
// Using a DependencyProperty as the backing store for StartScreen. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StartScreenProperty =
DependencyProperty.Register(nameof(StartScreen), typeof(UIElement), typeof(UIElement), new UIPropertyMetadata(null, AddOrRemoveLogicalChildOnPropertyChanged));

/// <summary>
/// Window title
Expand All @@ -474,17 +477,13 @@ public string Title
/// Using a DependencyProperty as the backing store for Title. This enables animation, styling, binding, etc...
/// </summary>
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(Ribbon), new UIPropertyMetadata("", OnTitleChanged));
DependencyProperty.Register(nameof(Title), typeof(string), typeof(Ribbon), new UIPropertyMetadata(string.Empty, OnTitleChanged));

private static void OnTitleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ribbon = d as Ribbon;
var ribbon = (Ribbon)d;

if (ribbon != null
&& ribbon.TitleBar != null)
{
ribbon.TitleBar.InvalidateMeasure();
}
ribbon?.TitleBar?.InvalidateMeasure();
}

/// <summary>
Expand Down Expand Up @@ -559,6 +558,20 @@ private static void OnSelectedTabIndexChanged(DependencyObject d, DependencyProp
}
}

private static void AddOrRemoveLogicalChildOnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ribbon = (Ribbon)d;
if (e.OldValue != null)
{
ribbon.RemoveLogicalChild(e.OldValue);
}

if (e.NewValue != null)
{
ribbon.AddLogicalChild(e.NewValue);
}
}

/// <summary>
/// Gets the first visible TabItem
/// </summary>
Expand Down Expand Up @@ -836,6 +849,11 @@ protected override IEnumerator LogicalChildren
yield return this.Menu;
}

if (this.StartScreen != null)
{
yield return this.StartScreen;
}

if (this.quickAccessToolBar != null)
{
yield return this.quickAccessToolBar;
Expand Down
67 changes: 67 additions & 0 deletions Fluent.Ribbon/Controls/StartScreen.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
namespace Fluent
{
using System.Windows;

/// <summary>
/// Represents the container for the <see cref="StartScreenTabControl"/>.
/// </summary>
public class StartScreen : Backstage
{
private bool previousTitleBarIsCollapsed;

/// <summary>
/// Indicates whether the <see cref="StartScreen"/> has aleaady been shown or not.
/// </summary>
public bool Shown
{
get { return (bool)this.GetValue(ShownProperty); }
set { this.SetValue(ShownProperty, value); }
}

/// <summary>
/// <see cref="DependencyProperty"/> for <see cref="Shown"/>.
/// </summary>
public static readonly DependencyProperty ShownProperty =
DependencyProperty.Register(nameof(Shown), typeof(bool), typeof(StartScreen), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, null));

static StartScreen()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(StartScreen), new FrameworkPropertyMetadata(typeof(StartScreen)));
}

/// <summary>
/// Shows the <see cref="StartScreen"/>.
/// </summary>
protected override bool Show()
{
var ribbon = this.GetParentRibbon();

if (ribbon?.TitleBar != null)
{
this.previousTitleBarIsCollapsed = ribbon.TitleBar.IsCollapsed;
ribbon.TitleBar.IsCollapsed = true;
}

if (this.Shown)
{
return false;
}

return this.Shown = base.Show();
}

/// <summary>
/// Hides the <see cref="StartScreen"/>.
/// </summary>
protected override void Hide()
{
base.Hide();

var ribbon = this.GetParentRibbon();
if (ribbon?.TitleBar != null)
{
ribbon.TitleBar.IsCollapsed = this.previousTitleBarIsCollapsed;
}
}
}
}
Loading

0 comments on commit c6573a9

Please sign in to comment.