| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- // Copyright (c) The Perspex Project. All rights reserved.
- // Licensed under the MIT license. See licence.md file in the project root for full license information.
- using System;
- using System.Collections;
- using System.Linq;
- using System.Reactive.Linq;
- using System.Threading.Tasks;
- using Perspex.Animation;
- using Perspex.Controls.Generators;
- using Perspex.Controls.Primitives;
- using Perspex.Controls.Templates;
- using Perspex.Controls.Utils;
- namespace Perspex.Controls.Presenters
- {
- /// <summary>
- /// Displays pages inside an <see cref="ItemsControl"/>.
- /// </summary>
- public class DeckPresenter : Control, IItemsPresenter
- {
- /// <summary>
- /// Defines the <see cref="Items"/> property.
- /// </summary>
- public static readonly PerspexProperty<IEnumerable> ItemsProperty =
- ItemsControl.ItemsProperty.AddOwner<DeckPresenter>();
- /// <summary>
- /// Defines the <see cref="ItemsPanel"/> property.
- /// </summary>
- public static readonly PerspexProperty<ITemplate<IPanel>> ItemsPanelProperty =
- ItemsControl.ItemsPanelProperty.AddOwner<DeckPresenter>();
- /// <summary>
- /// Defines the <see cref="SelectedIndex"/> property.
- /// </summary>
- public static readonly PerspexProperty<int> SelectedIndexProperty =
- SelectingItemsControl.SelectedIndexProperty.AddOwner<DeckPresenter>();
- /// <summary>
- /// Defines the <see cref="Transition"/> property.
- /// </summary>
- public static readonly PerspexProperty<IPageTransition> TransitionProperty =
- Deck.TransitionProperty.AddOwner<DeckPresenter>();
- private bool _createdPanel;
- private IItemContainerGenerator _generator;
- /// <summary>
- /// Initializes static members of the <see cref="DeckPresenter"/> class.
- /// </summary>
- static DeckPresenter()
- {
- SelectedIndexProperty.Changed.AddClassHandler<DeckPresenter>(x => x.SelectedIndexChanged);
- }
- /// <summary>
- /// Gets the <see cref="IItemContainerGenerator"/> used to generate item container
- /// controls.
- /// </summary>
- public IItemContainerGenerator ItemContainerGenerator
- {
- get
- {
- if (_generator == null)
- {
- var i = TemplatedParent as ItemsControl;
- _generator = i?.ItemContainerGenerator ?? new ItemContainerGenerator(this);
- }
- return _generator;
- }
- set
- {
- if (_generator != null)
- {
- throw new InvalidOperationException("ItemContainerGenerator is already set.");
- }
- _generator = value;
- }
- }
- /// <summary>
- /// Gets or sets the items to display.
- /// </summary>
- public IEnumerable Items
- {
- get { return GetValue(ItemsProperty); }
- set { SetValue(ItemsProperty, value); }
- }
- /// <summary>
- /// Gets or sets the panel used to display the pages.
- /// </summary>
- public ITemplate<IPanel> ItemsPanel
- {
- get { return GetValue(ItemsPanelProperty); }
- set { SetValue(ItemsPanelProperty, value); }
- }
- /// <summary>
- /// Gets or sets the index of the selected page.
- /// </summary>
- public int SelectedIndex
- {
- get { return GetValue(SelectedIndexProperty); }
- set { SetValue(SelectedIndexProperty, value); }
- }
- /// <summary>
- /// Gets the panel used to display the pages.
- /// </summary>
- public IPanel Panel
- {
- get;
- private set;
- }
- /// <summary>
- /// Gets or sets a transition to use when switching pages.
- /// </summary>
- public IPageTransition Transition
- {
- get { return GetValue(TransitionProperty); }
- set { SetValue(TransitionProperty, value); }
- }
- /// <inheritdoc/>
- public override sealed void ApplyTemplate()
- {
- if (!_createdPanel)
- {
- CreatePanel();
- }
- }
- /// <summary>
- /// Creates the <see cref="Panel"/>.
- /// </summary>
- private void CreatePanel()
- {
- var logicalHost = this.FindReparentingHost();
- ClearVisualChildren();
- Panel = ItemsPanel.Build();
- Panel.SetValue(TemplatedParentProperty, TemplatedParent);
- AddVisualChild(Panel);
- if (logicalHost != null)
- {
- ((IReparentingControl)Panel).ReparentLogicalChildren(
- logicalHost,
- logicalHost.LogicalChildren);
- }
- _createdPanel = true;
- var task = MoveToPage(-1, SelectedIndex);
- }
- /// <summary>
- /// Moves to the selected page, animating if a <see cref="Transition"/> is set.
- /// </summary>
- /// <param name="fromIndex">The index of the old page.</param>
- /// <param name="toIndex">The index of the new page.</param>
- /// <returns>A task tracking the animation.</returns>
- private async Task MoveToPage(int fromIndex, int toIndex)
- {
- var generator = ItemContainerGenerator;
- IControl from = null;
- IControl to = null;
- if (fromIndex != -1)
- {
- from = generator.ContainerFromIndex(fromIndex);
- }
- if (toIndex != -1)
- {
- var item = Items.Cast<object>().ElementAt(toIndex);
- to = generator.CreateContainers(toIndex, new[] { item }, null).FirstOrDefault();
- if (to != null)
- {
- Panel.Children.Add(to);
- }
- }
- if (Transition != null)
- {
- await Transition.Start((Visual)from, (Visual)to, fromIndex < toIndex);
- }
- if (from != null)
- {
- Panel.Children.Remove(from);
- generator.RemoveContainers(fromIndex, new[] { from });
- }
- }
- /// <summary>
- /// Called when the <see cref="SelectedIndex"/> property changes.
- /// </summary>
- /// <param name="e">The event args.</param>
- private void SelectedIndexChanged(PerspexPropertyChangedEventArgs e)
- {
- if (Panel != null)
- {
- var task = MoveToPage((int)e.OldValue, (int)e.NewValue);
- }
- }
- }
- }
|