Pārlūkot izejas kodu

WIP: Modify Focus logic to properly deal with ViewArrangement.Overlapped.

Tig 1 gadu atpakaļ
vecāks
revīzija
ca4d10b509

+ 5 - 4
Terminal.Gui/View/Adornment/Border.cs

@@ -279,10 +279,11 @@ public class Border : Adornment
             return true;
         }
 
-        if (!Parent.CanFocus)
-        {
-            return false;
-        }
+        // BUGBUG: Shouldn't non-focusable views be draggable??
+        //if (!Parent.CanFocus)
+        //{
+        //    return false;
+        //}
 
         if (!Parent.Arrangement.HasFlag (ViewArrangement.Movable))
         {

+ 12 - 1
Terminal.Gui/View/ViewArrangement.cs

@@ -53,7 +53,18 @@ public enum ViewArrangement
     /// <remarks>
     ///     If <see cref="Movable"/> is also set, the top will not be resizable.
     /// </remarks>
-    Resizable = LeftResizable | RightResizable | TopResizable | BottomResizable
+    Resizable = LeftResizable | RightResizable | TopResizable | BottomResizable,
+
+    /// <summary>
+    ///    The view overlap other views.
+    /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         When set, Tab and Shift-Tab will be constrained to the subviews of the view (normally, they will navigate to the next/prev view in the next/prev Tabindex).
+    ///         Use Ctrl-Tab (Ctrl-PageDown) / Ctrl-Shift-Tab (Ctrl-PageUp) to move between overlapped views.
+    ///     </para>
+    /// </remarks>
+    Overlapped = 32
 }
 public partial class View
 {

+ 51 - 11
Terminal.Gui/View/ViewSubViews.cs

@@ -672,7 +672,7 @@ public partial class View
     /// <summary>
     ///     Focuses the last focusable view in <see cref="View.TabIndexes"/> if one exists. If there are no views in <see cref="View.TabIndexes"/> then the focus is set to the view itself.
     /// </summary>
-    public void FocusFirst ()
+    public void FocusFirst (bool overlapped = false)
     {
         if (!CanBeVisible (this))
         {
@@ -686,7 +686,7 @@ public partial class View
             return;
         }
 
-        foreach (View view in _tabIndexes)
+        foreach (View view in _tabIndexes.Where (v => !overlapped || v.Arrangement.HasFlag (ViewArrangement.Overlapped)))
         {
             if (view.CanFocus && view._tabStop && view.Visible && view.Enabled)
             {
@@ -700,7 +700,7 @@ public partial class View
     /// <summary>
     ///     Focuses the last focusable view in <see cref="View.TabIndexes"/> if one exists. If there are no views in <see cref="View.TabIndexes"/> then the focus is set to the view itself.
     /// </summary>
-    public void FocusLast ()
+    public void FocusLast (bool overlapped = false)
     {
         if (!CanBeVisible (this))
         {
@@ -714,15 +714,11 @@ public partial class View
             return;
         }
 
-        for (int i = _tabIndexes.Count; i > 0;)
+        foreach (View view in _tabIndexes.Where (v => !overlapped || v.Arrangement.HasFlag (ViewArrangement.Overlapped)).Reverse ())
         {
-            i--;
-
-            View v = _tabIndexes [i];
-
-            if (v.CanFocus && v._tabStop && v.Visible && v.Enabled)
+            if (view.CanFocus && view._tabStop && view.Visible && view.Enabled)
             {
-                SetFocus (v);
+                SetFocus (view);
 
                 return;
             }
@@ -777,6 +773,18 @@ public partial class View
             {
                 Focused.SetHasFocus (false, w);
 
+                // If the focused view is overlapped don't focus on the next if it's not overlapped.
+                if (Focused.Arrangement.HasFlag (ViewArrangement.Overlapped) && !w.Arrangement.HasFlag (ViewArrangement.Overlapped))
+                {
+                    return false;
+                }
+
+                // If the focused view is not overlapped and the next is, skip it
+                if (!Focused.Arrangement.HasFlag (ViewArrangement.Overlapped) && w.Arrangement.HasFlag (ViewArrangement.Overlapped))
+                {
+                   continue;
+                }
+
                 if (w.CanFocus && w._tabStop && w.Visible && w.Enabled)
                 {
                     w.FocusLast ();
@@ -788,9 +796,19 @@ public partial class View
             }
         }
 
+        // There's no prev view in tab indexes.
         if (Focused is { })
         {
+            // Leave Focused
             Focused.SetHasFocus (false, this);
+
+            if (Focused.Arrangement.HasFlag (ViewArrangement.Overlapped))
+            {
+                FocusLast (true);
+                return true;
+            }
+
+            // Signal to caller no next view was found
             Focused = null;
         }
 
@@ -798,7 +816,7 @@ public partial class View
     }
 
     /// <summary>
-    ///     Focuses the previous view in <see cref="View.TabIndexes"/>. If there is no previous view, the focus is set to the view itself.
+    ///     Focuses the next view in <see cref="View.TabIndexes"/>. If there is no next view, the focus is set to the view itself.
     /// </summary>
     /// <returns><see langword="true"/> if next was focused, <see langword="false"/> otherwise.</returns>
     public bool FocusNext ()
@@ -844,6 +862,18 @@ public partial class View
             {
                 Focused.SetHasFocus (false, w);
 
+                // If the focused view is overlapped don't focus on the next if it's not overlapped.
+                if (Focused.Arrangement.HasFlag (ViewArrangement.Overlapped) && !w.Arrangement.HasFlag (ViewArrangement.Overlapped))
+                {
+                    return false;
+                }
+
+                // If the focused view is not overlapped and the next is, skip it
+                if (!Focused.Arrangement.HasFlag (ViewArrangement.Overlapped) && w.Arrangement.HasFlag (ViewArrangement.Overlapped))
+                {
+                    continue;
+                }
+
                 if (w.CanFocus && w._tabStop && w.Visible && w.Enabled)
                 {
                     w.FocusFirst ();
@@ -855,9 +885,19 @@ public partial class View
             }
         }
 
+        // There's no next view in tab indexes.
         if (Focused is { })
         {
+            // Leave Focused
             Focused.SetHasFocus (false, this);
+
+            if (Focused.Arrangement.HasFlag (ViewArrangement.Overlapped))
+            {
+                FocusFirst (true);
+                return true;
+            }
+
+            // Signal to caller no next view was found
             Focused = null;
         }
 

+ 61 - 190
UICatalog/Scenarios/ViewExperiments.cs

@@ -18,233 +18,104 @@ public class ViewExperiments : Scenario
             Title = GetQuitKeyAndName ()
         };
 
-        var containerLabel = new Label
+        var view = new View
         {
-            X = 0,
-            Y = 0,
+            X = 2,
+            Y = 2,
+            Height = Dim.Auto (),
+            Width = Dim.Auto (),
+            Title = "View1",
+            ColorScheme = Colors.ColorSchemes ["Base"],
+            Id = "View1",
+            CanFocus = true, // Can't drag without this? BUGBUG
+            Arrangement = ViewArrangement.Movable | ViewArrangement.Overlapped
+        };
 
-            Width = Dim.Fill (),
-            Height = 3
+        Button button = new ()
+        {
+            Title = "Button_1",
         };
-        app.Add (containerLabel);
+        view.Add (button);
 
-        var view = new View
+        button = new ()
         {
-            X = 2,
-            Y = Pos.Bottom (containerLabel),
-            Height = Dim.Fill (2),
-            Width = Dim.Fill (2),
-            Title = "View with 2xMargin, 2xBorder, & 2xPadding",
-            ColorScheme = Colors.ColorSchemes ["Base"],
-            Id = "DaView"
+            Y = Pos.Bottom (button),
+            Title = "Button_2",
         };
+        view.Add (button);
 
         //app.Add (view);
 
-        view.Margin.Thickness = new (2, 2, 2, 2);
+        view.Margin.Thickness = new (0);
         view.Margin.ColorScheme = Colors.ColorSchemes ["Toplevel"];
         view.Margin.Data = "Margin";
-        view.Border.Thickness = new (3);
-        view.Border.LineStyle = LineStyle.Single;
+        view.Border.Thickness = new (1);
+        view.Border.LineStyle = LineStyle.Double;
         view.Border.ColorScheme = view.ColorScheme;
         view.Border.Data = "Border";
-        view.Padding.Thickness = new (2);
+        view.Padding.Thickness = new (0);
         view.Padding.ColorScheme = Colors.ColorSchemes ["Error"];
         view.Padding.Data = "Padding";
 
-        var window1 = new Window
+        var view2 = new View
         {
-            X = 2,
-            Y = 3,
-            Height = 7,
-            Width = 17,
-            Title = "Window 1",
-            Text = "Window #2",
-            TextAlignment = Alignment.Center
-        };
-
-        window1.Margin.Thickness = new (0);
-        window1.Margin.ColorScheme = Colors.ColorSchemes ["Toplevel"];
-        window1.Margin.Data = "Margin";
-        window1.Border.Thickness = new (1);
-        window1.Border.LineStyle = LineStyle.Single;
-        window1.Border.ColorScheme = view.ColorScheme;
-        window1.Border.Data = "Border";
-        window1.Padding.Thickness = new (0);
-        window1.Padding.ColorScheme = Colors.ColorSchemes ["Error"];
-        window1.Padding.Data = "Padding";
-
-        view.Add (window1);
-
-        var window2 = new Window
-        {
-            X = Pos.Right (window1) + 1,
-            Y = 3,
-            Height = 5,
-            Width = 37,
-            Title = "Window2",
-            Text = "Window #2 (Right(window1)+1",
-            TextAlignment = Alignment.Center
-        };
-
-        //view3.InitializeFrames ();
-        window2.Margin.Thickness = new (1, 1, 0, 0);
-        window2.Margin.ColorScheme = Colors.ColorSchemes ["Toplevel"];
-        window2.Margin.Data = "Margin";
-        window2.Border.Thickness = new (1, 1, 1, 1);
-        window2.Border.LineStyle = LineStyle.Single;
-        window2.Border.ColorScheme = view.ColorScheme;
-        window2.Border.Data = "Border";
-        window2.Padding.Thickness = new (1, 1, 0, 0);
-        window2.Padding.ColorScheme = Colors.ColorSchemes ["Error"];
-        window2.Padding.Data = "Padding";
-
-        view.Add (window2);
-
-        var view4 = new View
-        {
-            X = Pos.Right (window2) + 1,
-            Y = 3,
-            Height = 5,
-            Width = 37,
-            Title = "View4",
-            Text = "View #4 (Right(window2)+1",
-            TextAlignment = Alignment.Center
-        };
-
-        //view4.InitializeFrames ();
-        view4.Margin.Thickness = new (0, 0, 1, 1);
-        view4.Margin.ColorScheme = Colors.ColorSchemes ["Toplevel"];
-        view4.Margin.Data = "Margin";
-        view4.Border.Thickness = new (1, 1, 1, 1);
-        view4.Border.LineStyle = LineStyle.Single;
-        view4.Border.ColorScheme = view.ColorScheme;
-        view4.Border.Data = "Border";
-        view4.Padding.Thickness = new (0, 0, 1, 1);
-        view4.Padding.ColorScheme = Colors.ColorSchemes ["Error"];
-        view4.Padding.Data = "Padding";
-
-        view.Add (view4);
-
-        var view5 = new View
-        {
-            X = Pos.Right (view4) + 1,
-            Y = 3,
-            Height = Dim.Fill (2),
-            Width = Dim.Fill (),
-            Title = "View5",
-            Text = "View #5 (Right(view4)+1 Fill",
-            TextAlignment = Alignment.Center
-        };
-
-        //view5.InitializeFrames ();
-        view5.Margin.Thickness = new (0, 0, 0, 0);
-        view5.Margin.ColorScheme = Colors.ColorSchemes ["Toplevel"];
-        view5.Margin.Data = "Margin";
-        view5.Border.Thickness = new (1, 1, 1, 1);
-        view5.Border.LineStyle = LineStyle.Single;
-        view5.Border.ColorScheme = view.ColorScheme;
-        view5.Border.Data = "Border";
-        view5.Padding.Thickness = new (0, 0, 0, 0);
-        view5.Padding.ColorScheme = Colors.ColorSchemes ["Error"];
-        view5.Padding.Data = "Padding";
-
-        view.Add (view5);
-
-        var label = new Label { Text = "AutoSize true; 1;1:", X = 1, Y = 1 };
-        view.Add (label);
-
-        var edit = new TextField
-        {
-            Text = "Right (label)",
-            X = Pos.Right (label),
-            Y = 1,
-            Width = 15,
-            Height = 1
+            X = Pos.Right (view),
+            Y = Pos.Bottom (view),
+            Height = Dim.Auto (),
+            Width = Dim.Auto (),
+            Title = "View2",
+            ColorScheme = Colors.ColorSchemes ["Base"],
+            Id = "View2",
+            CanFocus = true, // Can't drag without this? BUGBUG
+            Arrangement = ViewArrangement.Movable | ViewArrangement.Overlapped
         };
-        view.Add (edit);
 
-        edit = new()
-        {
-            Text = "Right (edit) + 1",
-            X = Pos.Right (edit) + 1,
-            Y = 1,
-            Width = 20,
-            Height = 1
-        };
-        view.Add (edit);
 
-        var label50 = new View
+        button = new ()
         {
-            Title = "Border Inherit Demo",
-            Text = "Center();50%",
-            X = Pos.Center (),
-            Y = Pos.Percent (50),
-            Width = 30,
-            TextAlignment = Alignment.Center
+            Title = "Button_3",
         };
-        label50.Border.Thickness = new (1, 3, 1, 1);
-        label50.Height = 5;
-        view.Add (label50);
+        view2.Add (button);
 
-        edit = new()
+        button = new ()
         {
-            Text = "0 + Percent(50);70%",
-            X = 0 + Pos.Percent (50),
-            Y = Pos.Percent (70),
-            Width = 30,
-            Height = 1
+            Y = Pos.Bottom (button),
+            Title = "Button_4",
         };
-        view.Add (edit);
-
-        edit = new() { Text = "AnchorEnd ();AnchorEnd ()", X = Pos.AnchorEnd (), Y = Pos.AnchorEnd (), Width = 30, Height = 1 };
-        view.Add (edit);
-
-        edit = new()
+        view2.Add (button);
+
+        view2.Add (button);
+        view2.Margin.Thickness = new (0);
+        view2.Margin.ColorScheme = Colors.ColorSchemes ["Toplevel"];
+        view2.Margin.Data = "Margin";
+        view2.Border.Thickness = new (1);
+        view2.Border.LineStyle = LineStyle.Double;
+        view2.Border.ColorScheme = view2.ColorScheme;
+        view2.Border.Data = "Border";
+        view2.Padding.Thickness = new (0);
+        view2.Padding.ColorScheme = Colors.ColorSchemes ["Error"];
+        view2.Padding.Data = "Padding";
+
+        button = new ()
         {
-            Text = "Left;AnchorEnd (2)",
-            X = 0,
-            Y = Pos.AnchorEnd (2),
-            Width = 30,
-            Height = 1
+            X = Pos.AnchorEnd (),
+            Y = Pos.AnchorEnd (),
+            Title = "Button_5",
         };
-        view.Add (edit);
-
-        view.LayoutComplete += (s, e) =>
-                               {
-                                   containerLabel.Text =
-                                       $"Container.Frame: {
-                                           app.Frame
-                                       } .Bounds: {
-                                           app.Viewport
-                                       }\nView.Frame: {
-                                           view.Frame
-                                       } .Viewport: {
-                                           view.Viewport
-                                       } .viewportOffset: {
-                                           view.GetViewportOffsetFromFrame ()
-                                       }\n .Padding.Frame: {
-                                           view.Padding.Frame
-                                       } .Padding.Viewport: {
-                                           view.Padding.Viewport
-                                       }";
-                               };
-
-        view.X = Pos.Center ();
 
         var editor = new AdornmentsEditor
         {
             X = 0,
-            Y = Pos.Bottom (containerLabel),
+            Y = 0,
             AutoSelectViewToEdit = true
         };
 
         app.Add (editor);
-        view.X = 36;
+        view.X = 34;
         view.Y = 4;
-        view.Width = Dim.Fill ();
-        view.Height = Dim.Fill ();
         app.Add (view);
+        app.Add (view2);
+        app.Add (button);
 
         Application.Run (app);
         app.Dispose ();