Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
TilePanelNavigationBehavior.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Windows;
5 using System.Windows.Controls;
6 using System.Windows.Controls.Primitives;
7 using System.Windows.Input;
8 using System.Windows.Media;
9 
10 using SiliconStudio.Presentation.Controls;
11 
12 namespace SiliconStudio.Presentation.Behaviors
13 {
14  public class TilePanelNavigationBehavior : DeferredBehaviorBase<VirtualizingTilePanel>
15  {
16  private Selector selector;
17 
18  protected override void OnAttachedOverride()
19  {
20  DependencyObject parent = AssociatedObject;
21  while (parent != null)
22  {
23  parent = VisualTreeHelper.GetParent(parent);
24  if (parent is Selector)
25  break;
26  }
27 
28  if (parent == null)
29  {
30  throw new InvalidOperationException("Unable to find a parent Selector to the associated VirtualizingTilePanel.");
31  }
32 
33  selector = (Selector)parent;
34 
35  selector.IsSynchronizedWithCurrentItem = true;
36  KeyboardNavigation.SetDirectionalNavigation(selector, KeyboardNavigationMode.None);
37 
38  selector.PreviewKeyDown += OnAssociatedObjectKeyDown;
39  }
40 
41  protected override void OnDetachingOverride()
42  {
43  selector.PreviewKeyDown -= OnAssociatedObjectKeyDown;
44  selector = null;
45  }
46 
47  private void OnAssociatedObjectKeyDown(object sender, KeyEventArgs e)
48  {
49  if (selector.SelectedIndex == -1 || selector.Items.Count == 0)
50  return;
51 
52  var window = Window.GetWindow(selector);
53  if (window == null)
54  return;
55 
56  // Find the currently focused element (logical focus)
57  var focusedElement = FocusManager.GetFocusedElement(window) as DependencyObject;
58  if (focusedElement == null)
59  return;
60 
61  // Because of virtualization, we have to find the container that correspond to the selected item (by its index)
62  var element = selector.ItemContainerGenerator.ContainerFromIndex(selector.SelectedIndex);
63  // focusedElement can be either the current selector or one of its item container
64  if (!ReferenceEquals(focusedElement, selector) && !ReferenceEquals(focusedElement, element))
65  {
66  // In this case, it means another control is focused, either a control out of scope, or an editing text box in the scope of the item container
67  return;
68  }
69 
70  bool moved;
71 
72  switch (e.Key)
73  {
74  case Key.Right:
75  moved = AssociatedObject.Orientation == Orientation.Vertical ? MoveToNextItem() : MoveToNextLineItem(1);
76  break;
77 
78  case Key.Left:
79  moved = AssociatedObject.Orientation == Orientation.Vertical ? MoveToPreviousItem() : MoveToPreviousLineItem(1);
80  break;
81 
82  case Key.Up:
83  moved = AssociatedObject.Orientation == Orientation.Vertical ? MoveToPreviousLineItem(1) : MoveToPreviousItem();
84  break;
85 
86  case Key.Down:
87  moved = AssociatedObject.Orientation == Orientation.Vertical ? MoveToNextLineItem(1) : MoveToNextItem();
88  break;
89 
90  case Key.PageUp:
91  if (AssociatedObject.Orientation == Orientation.Vertical)
92  {
93  var itemHeight = AssociatedObject.ItemSlotSize.Height + AssociatedObject.MinimumItemSpacing * 2.0f;
94  moved = MoveToPreviousLineItem((int)(AssociatedObject.ViewportHeight / itemHeight));
95  }
96  else
97  {
98  var itemWidth = AssociatedObject.ItemSlotSize.Width + AssociatedObject.MinimumItemSpacing * 2.0f;
99  moved = MoveToPreviousLineItem((int)(AssociatedObject.ViewportWidth / itemWidth));
100  }
101  break;
102 
103  case Key.PageDown:
104  if (AssociatedObject.Orientation == Orientation.Vertical)
105  {
106  var itemHeight = AssociatedObject.ItemSlotSize.Height + AssociatedObject.MinimumItemSpacing * 2.0f;
107  moved = MoveToNextLineItem((int)(AssociatedObject.ViewportHeight / itemHeight));
108  }
109  else
110  {
111  var itemWidth = AssociatedObject.ItemSlotSize.Width + AssociatedObject.MinimumItemSpacing * 2.0f;
112  moved = MoveToNextLineItem((int)(AssociatedObject.ViewportWidth / itemWidth));
113  }
114  break;
115 
116  case Key.Home:
117  moved = selector.Items.MoveCurrentToFirst();
118  break;
119 
120  case Key.End:
121  moved = selector.Items.MoveCurrentToLast();
122  break;
123 
124  default:
125  return;
126  }
127 
128  e.Handled = true;
129 
130  if (moved)
131  {
132  if (selector.SelectedIndex > -1)
133  {
134  AssociatedObject.ScrollToIndexedItem(selector.SelectedIndex);
135 
136  if (selector.ItemContainerGenerator != null && selector.SelectedItem != null)
137  {
138  var lbi = selector.ItemContainerGenerator.ContainerFromItem(selector.SelectedItem) as UIElement;
139  if (lbi != null)
140  lbi.Focus();
141  }
142  }
143  }
144  }
145 
146  private bool MoveToPreviousLineItem(int lineCount)
147  {
148  var moved = false;
149 
150  int newPos = selector.SelectedIndex - (AssociatedObject.ItemsPerLine * lineCount);
151 
152  if (newPos >= 0)
153  moved = selector.Items.MoveCurrentToPosition(newPos);
154 
155  return moved;
156  }
157 
158  private bool MoveToNextLineItem(int lineCount)
159  {
160  var moved = false;
161 
162  if (AssociatedObject.ItemCount > -1)
163  {
164  int newPos = selector.SelectedIndex + (AssociatedObject.ItemsPerLine * lineCount);
165 
166  if (newPos < AssociatedObject.ItemCount)
167  moved = selector.Items.MoveCurrentToPosition(newPos);
168  }
169  return moved;
170  }
171 
172  private bool MoveToPreviousItem()
173  {
174  bool moved = selector.Items.MoveCurrentToPrevious();
175  if (moved == false)
176  {
177  if (selector.SelectedItem == null)
178  selector.Items.MoveCurrentToFirst();
179  }
180  return moved;
181  }
182 
183  private bool MoveToNextItem()
184  {
185  bool moved = selector.Items.MoveCurrentToNext();
186  if (moved == false)
187  {
188  if (selector.SelectedItem == null)
189  selector.Items.MoveCurrentToLast();
190  }
191  return moved;
192  }
193  }
194 }
Android.Widget.Orientation Orientation
Definition: Section.cs:9