diff --git a/Terminal.Gui/Application/ApplicationNavigation.cs b/Terminal.Gui/Application/ApplicationNavigation.cs
index d472eee13..20965adbf 100644
--- a/Terminal.Gui/Application/ApplicationNavigation.cs
+++ b/Terminal.Gui/Application/ApplicationNavigation.cs
@@ -62,6 +62,11 @@ public class ApplicationNavigation
}
}
+ //if (start.Border is { })
+ //{
+ // return IsInHierarchy (start.Border, view);
+ //}
+
return false;
}
diff --git a/Terminal.Gui/View/Adornment/Border.cs b/Terminal.Gui/View/Adornment/Border.cs
index 4fc92daed..de7390c9f 100644
--- a/Terminal.Gui/View/Adornment/Border.cs
+++ b/Terminal.Gui/View/Adornment/Border.cs
@@ -59,6 +59,7 @@ public class Border : Adornment
{
Parent = parent;
CanFocus = false;
+ TabStop = TabBehavior.TabGroup;
Application.GrabbingMouse += Application_GrabbingMouse;
Application.UnGrabbingMouse += Application_UnGrabbingMouse;
@@ -291,22 +292,22 @@ public class Border : Adornment
return true;
}
- if (!Parent!.Arrangement.HasFlag (ViewArrangement.Movable)
- && !Parent!.Arrangement.HasFlag (ViewArrangement.BottomResizable)
- && !Parent!.Arrangement.HasFlag (ViewArrangement.TopResizable)
- && !Parent!.Arrangement.HasFlag (ViewArrangement.LeftResizable)
- && !Parent!.Arrangement.HasFlag (ViewArrangement.RightResizable)
- )
- {
- return false;
- }
-
// BUGBUG: See https://github.com/gui-cs/Terminal.Gui/issues/3312
if (!_dragPosition.HasValue && mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed))
{
Parent.SetFocus ();
ApplicationOverlapped.BringOverlappedTopToFront ();
+ if (!Parent!.Arrangement.HasFlag (ViewArrangement.Movable)
+ && !Parent!.Arrangement.HasFlag (ViewArrangement.BottomResizable)
+ && !Parent!.Arrangement.HasFlag (ViewArrangement.TopResizable)
+ && !Parent!.Arrangement.HasFlag (ViewArrangement.LeftResizable)
+ && !Parent!.Arrangement.HasFlag (ViewArrangement.RightResizable)
+ )
+ {
+ return false;
+ }
+
// Only start grabbing if the user clicks in the Thickness area
// Adornment.Contains takes Parent SuperView=relative coords.
if (Contains (new (mouseEvent.Position.X + Parent.Frame.X + Frame.X, mouseEvent.Position.Y + Parent.Frame.Y + Frame.Y)))
@@ -930,11 +931,16 @@ public class Border : Adornment
private ViewArrangement _arranging;
- private Button? _arrangeButton;
+ private Button? _moveButton; // always top-left
+ private Button? _allSizeButton;
+ private Button? _leftSizeButton;
+ private Button? _rightSizeButton;
+ private Button? _topSizeButton;
+ private Button? _bottomSizeButton;
///
/// Starts "Arrange Mode" where can be moved and/or resized using the mouse
- /// or keyboard.
+ /// or keyboard. If is keyboard mode is enabled.
///
///
/// Arrange Mode is exited by the user pressing , , or by clicking
@@ -955,21 +961,231 @@ public class Border : Adornment
return false;
}
- Debug.Assert (_arrangeButton is null);
- _arrangeButton = new Button
+ // Add Commands and Keybindigs - Note it's ok these get added each time. KeyBindings are cleared in EndArrange()
+ AddArrangeModeKeyBindings ();
+
+ Application.MouseEvent += ApplicationOnMouseEvent;
+
+ // Create buttons for resizing and moving
+ if (Parent!.Arrangement.HasFlag (ViewArrangement.Movable))
{
- CanFocus = true,
- Width = 1,
- Height = 1,
- NoDecorations = true,
- NoPadding = true,
- ShadowStyle = ShadowStyle.None,
- Text = $"{Glyphs.Diamond}",
- };
- Add (_arrangeButton);
+ Debug.Assert (_moveButton is null);
- CanFocus = true;
+ _moveButton = new Button
+ {
+ Id = "moveButton",
+ CanFocus = true,
+ Width = 1,
+ Height = 1,
+ NoDecorations = true,
+ NoPadding = true,
+ ShadowStyle = ShadowStyle.None,
+ Text = $"{Glyphs.Diamond}",
+ Visible = false,
+ };
+ Add (_moveButton);
+ }
+ if (Parent!.Arrangement.HasFlag (ViewArrangement.Resizable))
+ {
+ Debug.Assert (_allSizeButton is null);
+
+ _allSizeButton = new Button
+ {
+ Id = "allSizeButton",
+ CanFocus = true,
+ Width = 1,
+ Height = 1,
+ NoDecorations = true,
+ NoPadding = true,
+ ShadowStyle = ShadowStyle.None,
+ Text = $"{Glyphs.Diamond}",
+ X = Pos.AnchorEnd (),
+ Y = Pos.AnchorEnd (),
+ Visible = false,
+ };
+ Add (_allSizeButton);
+ }
+
+ if (Parent!.Arrangement.HasFlag (ViewArrangement.TopResizable))
+ {
+ Debug.Assert (_topSizeButton is null);
+
+ _topSizeButton = new Button
+ {
+ Id = "topSizeButton",
+ CanFocus = true,
+ Width = 1,
+ Height = 1,
+ NoDecorations = true,
+ NoPadding = true,
+ ShadowStyle = ShadowStyle.None,
+ Text = $"{Glyphs.Diamond}",
+ X = Pos.Center () + Parent!.Margin.Thickness.Horizontal,
+ Y = 0,
+ Visible = false,
+ };
+ Add (_topSizeButton);
+ }
+
+ if (Parent!.Arrangement.HasFlag (ViewArrangement.RightResizable))
+ {
+ Debug.Assert (_rightSizeButton is null);
+
+ _rightSizeButton = new Button
+ {
+ Id = "rightSizeButton",
+ CanFocus = true,
+ Width = 1,
+ Height = 1,
+ NoDecorations = true,
+ NoPadding = true,
+ ShadowStyle = ShadowStyle.None,
+ Text = $"{Glyphs.Diamond}",
+ X = Pos.AnchorEnd (),
+ Y = Pos.Center () + Parent!.Margin.Thickness.Vertical,
+ Visible = false,
+ };
+ Add (_rightSizeButton);
+ }
+
+ if (Parent!.Arrangement.HasFlag (ViewArrangement.LeftResizable))
+ {
+ Debug.Assert (_leftSizeButton is null);
+
+ _leftSizeButton = new Button
+ {
+ Id = "leftSizeButton",
+ CanFocus = true,
+ Width = 1,
+ Height = 1,
+ NoDecorations = true,
+ NoPadding = true,
+ ShadowStyle = ShadowStyle.None,
+ Text = $"{Glyphs.Diamond}",
+ X = 0,
+ Y = Pos.Center () + Parent!.Margin.Thickness.Vertical,
+ Visible = false,
+ };
+ Add (_leftSizeButton);
+ }
+
+ if (Parent!.Arrangement.HasFlag (ViewArrangement.BottomResizable))
+ {
+ Debug.Assert (_bottomSizeButton is null);
+
+ _bottomSizeButton = new Button
+ {
+ Id = "bottomSizeButton",
+ CanFocus = true,
+ Width = 1,
+ Height = 1,
+ NoDecorations = true,
+ NoPadding = true,
+ ShadowStyle = ShadowStyle.None,
+ Text = $"{Glyphs.Diamond}",
+ X = Pos.Center () + Parent!.Margin.Thickness.Horizontal,
+ Y = Pos.AnchorEnd (),
+ Visible = false,
+ };
+ Add (_bottomSizeButton);
+ }
+
+
+ if (arrangement == ViewArrangement.Fixed)
+ {
+ // Keyboard mode
+ if (Parent!.Arrangement.HasFlag (ViewArrangement.Movable))
+ {
+ _arranging = ViewArrangement.Movable;
+ _moveButton!.Visible = true;
+ }
+
+ if (Parent!.Arrangement.HasFlag (ViewArrangement.Resizable))
+ {
+ _arranging = ViewArrangement.Resizable;
+ _allSizeButton!.Visible = true;
+ }
+ }
+ else
+ {
+ // Mouse mode
+ _arranging = arrangement;
+
+ switch (_arranging)
+ {
+ case ViewArrangement.Movable:
+ _moveButton!.Visible = true;
+ break;
+
+ case ViewArrangement.RightResizable | ViewArrangement.BottomResizable:
+ case ViewArrangement.Resizable:
+ _rightSizeButton!.Visible = true;
+ _bottomSizeButton!.Visible = true;
+ _allSizeButton!.X = Pos.AnchorEnd ();
+ _allSizeButton!.Y = Pos.AnchorEnd ();
+ _allSizeButton!.Visible = true;
+ break;
+
+ case ViewArrangement.LeftResizable:
+ _leftSizeButton!.Visible = true;
+ break;
+
+ case ViewArrangement.RightResizable:
+ _rightSizeButton!.Visible = true;
+ break;
+
+ case ViewArrangement.TopResizable:
+ _topSizeButton!.Visible = true;
+ break;
+
+ case ViewArrangement.BottomResizable:
+ _bottomSizeButton!.Visible = true;
+ break;
+
+ case ViewArrangement.LeftResizable | ViewArrangement.BottomResizable:
+ _rightSizeButton!.Visible = true;
+ _bottomSizeButton!.Visible = true;
+ _allSizeButton!.X = 0;
+ _allSizeButton!.Y = Pos.AnchorEnd ();
+ _allSizeButton!.Visible = true;
+ break;
+
+ case ViewArrangement.LeftResizable | ViewArrangement.TopResizable:
+ _leftSizeButton!.Visible = true;
+ _topSizeButton!.Visible = true;
+ break;
+
+ case ViewArrangement.RightResizable | ViewArrangement.TopResizable:
+ _rightSizeButton!.Visible = true;
+ _topSizeButton!.Visible = true;
+ _allSizeButton!.X = Pos.AnchorEnd ();
+ _allSizeButton!.Y = 0;
+ _allSizeButton!.Visible = true;
+
+ break;
+
+ }
+ }
+
+ if (_arranging != ViewArrangement.Fixed)
+ {
+ if (arrangement == ViewArrangement.Fixed)
+ {
+ // Keyboard mode - enable nav
+ CanFocus = true;
+ SetFocus ();
+ }
+ return true;
+ }
+
+ // Hack for now
+ EndArrange ();
+ return false;
+ }
+
+ private void AddArrangeModeKeyBindings ()
+ {
AddCommand (Command.Quit, EndArrange);
AddCommand (Command.Up,
@@ -1060,8 +1276,18 @@ public class Border : Adornment
return true;
});
- AddCommand (Command.Tab, Navigate);
- AddCommand (Command.BackTab, Navigate);
+ AddCommand (Command.Tab, () =>
+ {
+ AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
+
+ return true; // Always eat
+ });
+ AddCommand (Command.BackTab, () =>
+ {
+ AdvanceFocus (NavigationDirection.Backward, TabBehavior.TabStop);
+
+ return true; // Always eat
+ });
KeyBindings.Add (Key.Esc, KeyBindingScope.HotKey, Command.Quit);
KeyBindings.Add (Application.ArrangeKey, KeyBindingScope.HotKey, Command.Quit);
@@ -1072,113 +1298,6 @@ public class Border : Adornment
KeyBindings.Add (Key.Tab, KeyBindingScope.HotKey, Command.Tab);
KeyBindings.Add (Key.Tab.WithShift, KeyBindingScope.HotKey, Command.BackTab);
-
- Application.MouseEvent += ApplicationOnMouseEvent;
-
- if (arrangement == ViewArrangement.Fixed)
- {
- if (Parent!.Arrangement.HasFlag (ViewArrangement.Movable))
- {
- _arranging = ViewArrangement.Movable;
- _arrangeButton.X = 0;
- _arrangeButton.Y = 0;
- return true;
- }
-
- if (Parent!.Arrangement.HasFlag (ViewArrangement.Resizable))
- {
- _arranging = ViewArrangement.Resizable;
- _arrangeButton.X = Pos.AnchorEnd ();
- _arrangeButton.Y = Pos.AnchorEnd ();
-
- return true;
- }
- }
- else
- {
- _arranging = arrangement;
-
- switch (_arranging)
- {
- case ViewArrangement.Movable:
- _arrangeButton.X = 0;
- _arrangeButton.Y = 0;
- return true;
-
- case ViewArrangement.RightResizable | ViewArrangement.BottomResizable:
- case ViewArrangement.Resizable:
- _arrangeButton.X = Pos.AnchorEnd ();
- _arrangeButton.Y = Pos.AnchorEnd ();
- return true;
-
- case ViewArrangement.LeftResizable:
- _arrangeButton.X = 0;
- _arrangeButton.Y = Pos.Center () + Parent!.Margin.Thickness.Vertical;
- return true;
-
- case ViewArrangement.RightResizable:
- _arrangeButton.X = Pos.AnchorEnd ();
- _arrangeButton.Y = Pos.Center ();
- return true;
-
- case ViewArrangement.TopResizable:
- _arrangeButton.X = Pos.Center ();
- _arrangeButton.Y = 0;
- return true;
-
- case ViewArrangement.BottomResizable:
- _arrangeButton.X = Pos.Center ();
- _arrangeButton.Y = Pos.AnchorEnd ();
- return true;
-
- case ViewArrangement.LeftResizable | ViewArrangement.BottomResizable:
- _arrangeButton.X = 0;
- _arrangeButton.Y = Pos.AnchorEnd ();
-
- return true;
-
- case ViewArrangement.LeftResizable | ViewArrangement.TopResizable:
- _arrangeButton.X = 0;
- _arrangeButton.Y = 0;
-
- return true;
-
- case ViewArrangement.RightResizable | ViewArrangement.TopResizable:
- _arrangeButton.X = Pos.AnchorEnd (); ;
- _arrangeButton.Y = 0;
-
- return true;
-
- }
- }
-
- // Hack for now
- EndArrange ();
- return false;
-
- bool? Navigate ()
- {
- if (_arranging == ViewArrangement.Movable)
- {
- if (Parent!.Arrangement.HasFlag (ViewArrangement.Resizable))
- {
- _arranging = ViewArrangement.Resizable;
- _arrangeButton.X = Pos.AnchorEnd ();
- _arrangeButton.Y = Pos.AnchorEnd ();
- }
- }
- else if (_arranging == ViewArrangement.Resizable)
- {
- if (Parent!.Arrangement.HasFlag (ViewArrangement.Movable))
- {
- _arranging = ViewArrangement.Movable;
- _arrangeButton.X = 0;
- _arrangeButton.Y = 0;
- }
- }
-
- return true;
- }
}
private void ApplicationOnMouseEvent (object? sender, MouseEvent e)
@@ -1210,17 +1329,55 @@ public class Border : Adornment
Application.UngrabMouse ();
}
- CanFocus = false;
-
- if (_arrangeButton is { })
+ if (_moveButton is { })
{
- Remove (_arrangeButton);
- _arrangeButton.Dispose ();
- _arrangeButton = null;
+ Remove (_moveButton);
+ _moveButton.Dispose ();
+ _moveButton = null;
+ }
+
+ if (_allSizeButton is { })
+ {
+ Remove (_allSizeButton);
+ _allSizeButton.Dispose ();
+ _allSizeButton = null;
+ }
+
+ if (_leftSizeButton is { })
+ {
+ Remove (_leftSizeButton);
+ _leftSizeButton.Dispose ();
+ _leftSizeButton = null;
+ }
+
+ if (_rightSizeButton is { })
+ {
+ Remove (_rightSizeButton);
+ _rightSizeButton.Dispose ();
+ _rightSizeButton = null;
+ }
+
+ if (_topSizeButton is { })
+ {
+ Remove (_topSizeButton);
+ _topSizeButton.Dispose ();
+ _topSizeButton = null;
+ }
+
+ if (_bottomSizeButton is { })
+ {
+ Remove (_bottomSizeButton);
+ _bottomSizeButton.Dispose ();
+ _bottomSizeButton = null;
}
KeyBindings.Clear ();
+ if (CanFocus)
+ {
+ CanFocus = false;
+ }
+
return true;
}
diff --git a/Terminal.Gui/View/View.Drawing.cs b/Terminal.Gui/View/View.Drawing.cs
index 9827071f8..0a6e76e41 100644
--- a/Terminal.Gui/View/View.Drawing.cs
+++ b/Terminal.Gui/View/View.Drawing.cs
@@ -473,15 +473,16 @@ public partial class View // Drawing APIs
{
if (NeedsDisplay)
{
+ if (!CanBeVisible (this))
+ {
+ return;
+ }
+
if (SuperView is { })
{
Clear ();
}
- if (!CanBeVisible (this))
- {
- return;
- }
if (!string.IsNullOrEmpty (TextFormatter.Text))
{
diff --git a/Terminal.Gui/View/View.Navigation.cs b/Terminal.Gui/View/View.Navigation.cs
index 7aa658a16..d38d5c4f3 100644
--- a/Terminal.Gui/View/View.Navigation.cs
+++ b/Terminal.Gui/View/View.Navigation.cs
@@ -214,7 +214,33 @@ public partial class View // Focus and cross-view navigation management (TabStop
/// Gets the currently focused Subview of this view, or if nothing is focused.
public View? Focused
{
- get { return Subviews.FirstOrDefault (v => v.HasFocus); }
+ get
+ {
+ View? focused = Subviews.FirstOrDefault (v => v.HasFocus);
+
+ if (focused is { })
+ {
+ return focused;
+ }
+
+ // How about in Adornments?
+ if (Margin is { HasFocus:true })
+ {
+ return Margin;
+ }
+
+ if (Border is { HasFocus: true })
+ {
+ return Border;
+ }
+
+ if (Padding is { HasFocus: true })
+ {
+ return Padding;
+ }
+
+ return null;
+ }
}
/// Returns a value indicating if this View is currently on Top (Active)
@@ -384,7 +410,10 @@ public partial class View // Focus and cross-view navigation management (TabStop
return (false, false);
}
- if (CanFocus && SuperView is { CanFocus: false })
+ var thisAsAdornment = this as Adornment;
+ View? superViewOrParent = thisAsAdornment?.Parent ?? SuperView;
+
+ if (CanFocus && superViewOrParent is { CanFocus: false })
{
Debug.WriteLine ($@"WARNING: Attempt to FocusChanging where SuperView.CanFocus == false. {this}");
@@ -412,7 +441,7 @@ public partial class View // Focus and cross-view navigation management (TabStop
// Make sure superviews up the superview hierarchy have focus.
// Any of them may cancel gaining focus. In which case we need to back out.
- if (SuperView is { HasFocus: false } sv)
+ if (superViewOrParent is { HasFocus: false } sv)
{
(bool focusSet, bool svCancelled) = sv.SetHasFocusTrue (previousFocusedView, true);
@@ -422,20 +451,6 @@ public partial class View // Focus and cross-view navigation management (TabStop
}
}
- // Are we an Adornment?
- if (this is Adornment adornment)
- {
- if (adornment.Parent is { HasFocus: false } parent)
- {
- (bool focusSet, bool parentCancelled) = parent.SetHasFocusTrue (previousFocusedView, true);
-
- if (!focusSet)
- {
- return (false, parentCancelled);
- }
- }
- }
-
if (_hasFocus)
{
// Something else beat us to the change (likely a FocusChanged handler).
@@ -445,16 +460,7 @@ public partial class View // Focus and cross-view navigation management (TabStop
// By setting _hasFocus to true we definitively change HasFocus for this view.
// Get whatever peer has focus, if any
- View? focusedPeer = SuperView?.Focused;
-
- if (focusedPeer is null)
- {
- // Are we an Adornment?
- if (this is Adornment ad)
- {
- focusedPeer = ad.Parent?.Focused;
- }
- }
+ View? focusedPeer = superViewOrParent?.Focused;
_hasFocus = true;
@@ -481,6 +487,14 @@ public partial class View // Focus and cross-view navigation management (TabStop
previousFocusedView.SetHasFocusFalse (this);
}
+ if (previousFocusedView is { HasFocus: true })
+ {
+ if (previousFocusedView.SuperView is Adornment a)
+ {
+ previousFocusedView.SetHasFocusFalse (this);
+ }
+ }
+
if (Arrangement.HasFlag (ViewArrangement.Overlapped))
{
SuperView?.MoveSubviewToEnd (this);
@@ -570,43 +584,34 @@ public partial class View // Focus and cross-view navigation management (TabStop
throw new InvalidOperationException ("SetHasFocusFalse should not be called if the view does not have focus.");
}
+ var thisAsAdornment = this as Adornment;
+ View? superViewOrParent = thisAsAdornment?.Parent ?? SuperView;
+
// If newFocusedVew is null, we need to find the view that should get focus, and SetFocus on it.
if (!traversingDown && newFocusedView is null)
{
- if (SuperView?._previouslyMostFocused is { })
+ if (superViewOrParent?._previouslyMostFocused is { })
{
- if (SuperView?._previouslyMostFocused != this)
+ if (superViewOrParent?._previouslyMostFocused != this)
{
- SuperView?._previouslyMostFocused?.SetFocus ();
+ superViewOrParent?._previouslyMostFocused?.SetFocus ();
// The above will cause SetHasFocusFalse, so we can return
return;
}
- newFocusedView = SuperView?._previouslyMostFocused;
+
+ newFocusedView = superViewOrParent?._previouslyMostFocused;
}
- if (SuperView is { })
+ if (superViewOrParent is { })
{
- if (SuperView.AdvanceFocus (NavigationDirection.Forward, TabStop))
+ if (superViewOrParent.AdvanceFocus (NavigationDirection.Forward, TabStop))
{
// The above will cause SetHasFocusFalse, so we can return
return;
}
- newFocusedView = SuperView;
- }
- // Are we an Adornment?
- if (this is Adornment ad)
- {
- if (ad.Parent is {})
- {
- if (ad.Parent.RestoreFocus ())
- {
- // The above will cause SetHasFocusFalse, so we can return
- return;
- }
- newFocusedView = ad.Parent;
- }
+ newFocusedView = superViewOrParent;
}
if (Application.Navigation is { } && Application.Current is { })
@@ -645,6 +650,13 @@ public partial class View // Focus and cross-view navigation management (TabStop
bottom = bottom.SuperView;
}
+ if (bottom == this && bottom.SuperView is Adornment a)
+ {
+ a.SetHasFocusFalse (newFocusedView, true);
+ }
+
+ Debug.Assert (!mostFocused.WasDisposed);
+
_previouslyMostFocused = mostFocused;
}
@@ -654,7 +666,7 @@ public partial class View // Focus and cross-view navigation management (TabStop
NotifyFocusChanging (HasFocus, !HasFocus, newFocusedView, this);
// Get whatever peer has focus, if any
- View? focusedPeer = SuperView?.Focused;
+ View? focusedPeer = superViewOrParent?.Focused;
_hasFocus = false;
if (Application.Navigation is { })
@@ -663,7 +675,7 @@ public partial class View // Focus and cross-view navigation management (TabStop
if (appFocused is { } || appFocused == this)
{
- Application.Navigation.SetFocused (newFocusedView ?? SuperView);
+ Application.Navigation.SetFocused (newFocusedView ?? superViewOrParent);
}
}
@@ -675,9 +687,10 @@ public partial class View // Focus and cross-view navigation management (TabStop
return;
}
- if (SuperView is { })
+ if (superViewOrParent is { })
{
- SuperView._previouslyMostFocused = focusedPeer;
+ Debug.Assert(!focusedPeer.WasDisposed);
+ superViewOrParent._previouslyMostFocused = focusedPeer;
}
// Post-conditions - prove correctness
diff --git a/UnitTests/View/Navigation/SetFocusTests.cs b/UnitTests/View/Navigation/SetFocusTests.cs
index 3896e51cb..8dfd6375a 100644
--- a/UnitTests/View/Navigation/SetFocusTests.cs
+++ b/UnitTests/View/Navigation/SetFocusTests.cs
@@ -190,6 +190,115 @@ public class SetFocusTests () : TestsAllViews
Assert.False (subViewSubView3.HasFocus);
}
+
+ [Fact]
+ public void SetFocus_AdornmentSubView_SetFocus_Sets ()
+ {
+ var view = new View
+ {
+ Id = "view",
+ CanFocus = true
+ };
+
+ var subView = new View
+ {
+ Id = "subView",
+ CanFocus = true
+ };
+
+ view.Add (subView);
+
+ var borderSubView = new View
+ {
+ Id = "borderSubView",
+ CanFocus = true
+ };
+
+
+ var subViewSubView1 = new View
+ {
+ Id = "subViewSubView1",
+ CanFocus = true
+ };
+
+ var subViewSubView2 = new View
+ {
+ Id = "subViewSubView2",
+ CanFocus = true
+ };
+
+ var subViewSubView3 = new View
+ {
+ Id = "subViewSubView3",
+ CanFocus = true
+ };
+ borderSubView.Add (subViewSubView1, subViewSubView2, subViewSubView3);
+
+ view.Border.Add (borderSubView);
+
+ view.SetFocus ();
+ Assert.True (view.HasFocus);
+ Assert.True (subView.HasFocus);
+ Assert.False (borderSubView.HasFocus);
+
+ view.Border.CanFocus = true;
+ subViewSubView1.SetFocus ();
+ Assert.True (view.HasFocus);
+ Assert.False (subView.HasFocus);
+ Assert.True (borderSubView.HasFocus);
+ Assert.True (subViewSubView1.HasFocus);
+ Assert.False (subViewSubView2.HasFocus);
+ Assert.False (subViewSubView3.HasFocus);
+
+ view.Border.CanFocus = false;
+ Assert.True (view.HasFocus);
+ Assert.True (subView.HasFocus);
+ Assert.False (view.Border.HasFocus);
+ Assert.False (borderSubView.HasFocus);
+ Assert.False (subViewSubView1.HasFocus);
+ Assert.False (subViewSubView2.HasFocus);
+ Assert.False (subViewSubView3.HasFocus);
+
+ view.Border.CanFocus = true;
+ view.Border.SetFocus ();
+ Assert.True (view.HasFocus);
+ Assert.True (view.Border.HasFocus);
+ Assert.False (subView.HasFocus);
+ Assert.True (borderSubView.HasFocus);
+ Assert.True (subViewSubView1.HasFocus);
+ Assert.False (subViewSubView2.HasFocus);
+ Assert.False (subViewSubView3.HasFocus);
+
+ view.Border.CanFocus = false;
+ Assert.True (view.HasFocus);
+ Assert.True (subView.HasFocus);
+ Assert.False (view.Border.HasFocus);
+ Assert.False (borderSubView.HasFocus);
+ Assert.False (subViewSubView1.HasFocus);
+ Assert.False (subViewSubView2.HasFocus);
+ Assert.False (subViewSubView3.HasFocus);
+
+ view.Border.CanFocus = true;
+ subViewSubView1.SetFocus ();
+ Assert.True (view.HasFocus);
+ Assert.False (subView.HasFocus);
+ Assert.True (view.Border.HasFocus);
+ Assert.True (borderSubView.HasFocus);
+ Assert.True (subViewSubView1.HasFocus);
+ Assert.False (subViewSubView2.HasFocus);
+ Assert.False (subViewSubView3.HasFocus);
+
+ subView.SetFocus ();
+ Assert.True (view.HasFocus);
+ Assert.True (subView.HasFocus);
+ Assert.False (view.Border.HasFocus);
+ Assert.False (borderSubView.HasFocus);
+ Assert.False (subViewSubView1.HasFocus);
+ Assert.False (subViewSubView2.HasFocus);
+ Assert.False (subViewSubView3.HasFocus);
+ }
+
+
[Fact]
public void SetFocus_Peer_LeavesOther ()
{