Browse Source

Updated conceptual API documentation; added mouse.md

Tig 1 năm trước cách đây
mục cha
commit
6b80b23340

+ 10 - 9
Terminal.Gui/View/ViewScrolling.cs

@@ -74,34 +74,35 @@ public partial class View
     public event EventHandler<SizeChangedEventArgs> ContentSizeChanged;
 
     /// <summary>
-    ///     Converts a content-relative location to a screen-relative location.
+    ///     Converts a Content-relative location to a Screen-relative location.
     /// </summary>
-    /// <param name="location"></param>
-    /// <returns>The screen-relative location.</returns>
+    /// <param name="location">The Content-relative location.</param>
+    /// <returns>The Screen-relative location.</returns>
     public Point ContentToScreen (in Point location)
     {
-        // Translate to Viewport
+        // Subtract the ViewportOffsetFromFrame to get the Viewport-relative location.
         Point viewportOffset = GetViewportOffsetFromFrame ();
         Point contentRelativeToViewport = location;
         contentRelativeToViewport.Offset (-Viewport.X, -Viewport.Y);
 
-        // Translate to Frame (our SuperView's Viewport-relative coordinates)
+        // Translate to Screen-Relative (our SuperView's Viewport-relative coordinates)
         Rectangle screen = ViewportToScreen (new (contentRelativeToViewport, Size.Empty));
 
         return screen.Location;
     }
 
-    /// <summary>Converts a screen-relative coordinate to a Content-relative coordinate.</summary>
+    /// <summary>Converts a Screen-relative coordinate to a Content-relative coordinate.</summary>
     /// <remarks>
-    ///     Content-relative means relative to the top-left corner of the view's Content.
+    ///     Content-relative means relative to the top-left corner of the view's Content, which is
+    ///     always at <c>0, 0</c>.
     /// </remarks>
     /// <param name="x">Column relative to the left side of the Content.</param>
     /// <param name="y">Row relative to the top of the Content</param>
     /// <returns>The coordinate relative to this view's Content.</returns>
-    public Point ScreenToContent (int x, int y)
+    public Point ScreenToContent (in Point location)
     {
         Point viewportOffset = GetViewportOffsetFromFrame ();
-        Point screen = ScreenToFrame (x, y);
+        Point screen = ScreenToFrame (location.X, location.Y);
         screen.Offset (Viewport.X - viewportOffset.X, Viewport.Y - viewportOffset.Y);
 
         return screen;

+ 50 - 0
UICatalog/Scenarios/Coordinates.cs

@@ -0,0 +1,50 @@
+using Terminal.Gui;
+
+namespace UICatalog.Scenarios;
+
+[ScenarioMetadata ("Coordinates", "Demonstrates Screen, Frame, Content, and Viewport coordinates.")]
+[ScenarioCategory ("Layout")]
+public sealed class Coordinates : Scenario
+{
+    public override void Main ()
+    {
+        // Init
+        Application.Init ();
+
+        // Setup - Create a top-level application window and configure it.
+        Window app = new ()
+        {
+            Title = $"Application/Screen",
+            BorderStyle = LineStyle.HeavyDotted
+        };
+
+        View frame = new ()
+        {
+            Title = "",
+            Text = "Content - Location (0 0), Size: (54, 14)",
+            X = 3,
+            Y = 3,
+            Width = 60,
+            Height = 20,
+            ColorScheme = new ColorScheme (new Attribute (Color.Black, Color.White))
+        };
+        frame.Margin.Thickness = new (1);
+        frame.Margin.ColorScheme = new ColorScheme (new Attribute (Color.Black, Color.BrightRed));
+        frame.Margin.Add (new Label () { Title = "Margin - Frame-Relative Location (0,0)" });
+        frame.Border.LineStyle = LineStyle.None;
+        frame.Border.Thickness = new (1);
+        frame.Border.ColorScheme = new ColorScheme (new Attribute (Color.Black, Color.BrightGreen));
+        frame.Border.Add (new Label () { Title = "Border - Frame-Relative Location (1,1)" });
+        frame.Padding.Thickness = new (1);
+        frame.Padding.ColorScheme = new ColorScheme (new Attribute (Color.Black, Color.BrightYellow));
+        frame.Padding.Add (new Label () { Title = "Padding - Frame-Relative Location (2,2)" });
+
+        app.Add (frame);
+        // Run - Start the application.
+        Application.Run (app);
+        app.Dispose ();
+
+        // Shutdown - Calling Application.Shutdown is required.
+        Application.Shutdown ();
+    }
+}

+ 1 - 1
UnitTests/View/MouseTests.cs

@@ -532,7 +532,7 @@ public class MouseTests (ITestOutputHelper output)
         int enablingHighlight = 0;
         int disablingHighlight = 0;
         view.Highlight += View_Highlight;
-        bool inViewport = view.Bounds.Contains (x, 0);
+        bool inViewport = view.Viewport.Contains (x, 0);
 
         // Start at 0,0 ; in viewport
         view.NewMouseEvent (new () { X = 0, Flags = MouseFlags.Button1Pressed });

+ 30 - 1
docfx/docs/drawing.md

@@ -1,6 +1,35 @@
 # Drawing (Text and Color)
 
-Terminal.Gui supports color on all platforms, including Windows, Mac, and Linux. The default colors are 24-bit RGB colors, but the library will gracefully degrade to 16-colors if the terminal does not support 24-bit color, and black and white if the terminal does not support 16-colors.
+Terminal.Gui provides a set of APIs for formatting text, line drawing, and character-based graphing. The fundamental concept is a `Cell` which ocupises a particular row and column in the terminal. A Cell includes the character (glyph) that should be rendred by the terminal, and attributes that indicate how the glphy should be rendered (e.g. the foreground and background color).
+
+Color is supported on all platforms, including Windows, Mac, and Linux. The default colors are 24-bit RGB colors, but the library will gracefully degrade to 16-colors if the terminal does not support 24-bit color, and black and white if the terminal does not support 16-colors.
+
+## View Drawing API
+
+A `View` will typically draw text when the [OnDrawContent](~/api/Terminal.Gui.View.yml#Terminal_Gui_View_OnDrawContent_) is called (or the `DrawContent` event is received). 
+
+Outputing text directly involves:
+
+a) Moving the draw cursor using the `Move` API.
+b) Setting the attributes using `SetAttribute`.
+c) Outputting glyphs by calling `AddRune` or `AddStr`
+
+Outputting formatted text involves:
+
+a) Adding the text to a `TextFormatter` object.
+b) Setting formatting options, such as `TextFormatter.TextAlignment`.
+c) calling `TextFormatter.Draw` 
+
+Line drawing is accomplished using the `LineCanvas` API:
+
+a) Add the lines via `LineCanvas.Add`.
+b) Either render the line canvas via `LineCanvas.Draw` or let the `View` do so automatically (which enables automatic line joining across Views).
+
+## Coordinate System for Drawing
+
+The `View` draw APIs, including the `OnDrawContent` method, the `DrawContent` event, and the `View.Move` method, all take coordinates specified in *Viewport-Relative* coordinates. That is, `0, 0` is the top-left cell visible to the user.
+
+See [Layout](layout.html) for more details of the Terminal.Gui coordinate system.
 
 ## Cell
 

+ 1 - 1
docfx/docs/keyboard.md

@@ -1,6 +1,6 @@
 # Keyboard Events
 
-## Tenets for Terminal.Gui Key Bindings (Unless you know better ones...)
+## Tenets for Terminal.Gui Keyboard Handling (Unless you know better ones...)
 
 Tenets higher in the list have precedence over tenets lower in the list.
 

+ 53 - 31
docfx/docs/layout.md

@@ -1,42 +1,63 @@
 # Layout
 
-Terminal.Gui v2 supports the following View layout systems (controlled by the [View.LayoutStyle](~/api/Terminal.Gui.LayoutStyle.yml)):
+Terminal.Gui provides a rich system for how `View` objects are laid our relative to each other. The layout system also defines how coordinates are specified.
 
-* **Absolute** - Used to have the View positioned exactly in a location, with a fixed size. Absolute layout is accomplished by constructing a View with an argument of type [Rect](~/api/Terminal.Gui.Rect.yml) or directly changing the `Frame` property on the View.
-* **Computed** - The Computed Layout system provides automatic aligning of Views with other Views, automatic centering, and automatic sizing. To use Computed layout set the 
- `X`, `Y`, `Width` and `Height` properties after the object has been created. Views laid out using the Computed Layout system can be resized with the mouse or keyboard, enabling tiled window managers and dynamic terminal UIs.
-* **Overlapped** - New in V2 (But not yet) - Overlapped layout enables views to be positioned on top of each other. Overlapped Views are movable and sizable with both the keyboard and the mouse.
+## Dealing with coordinates
 
-Examples:
+The coordinate systems in Terminal.Gui are:
 
-```csharp
+* `Screen` - Describes the dimensions and characteristcs of the underlying terminal. Currently Terminal.Gui only supports applications that run "full-screen", meaning they fill the entire terminal when running. As the user resizes their terminal, the `Screen` changes size and a Terminal.Gui applicaiton will be resized to fit. *Screen-Relative* means an origin (`0, 0`) at the top-left corner of the terminal. `ConsoleDriver`s operate exclusively on *Screen-Relative* coordinates.
+* `Application` - The dimensions and charactersistcs of the application. Because only full-screen apps are currently supported, `Application` is effectively the same as `Screen` from a layout perspective. *Application-Relative* currently means an origin (`0, 0`) at the top-left corner of the terminal. `Applicaiton.Top` is a `View` who's top-left corner is fixed at the *Application.Relative* coordinate of (`0, 0`) and who's size is the same as the size of the `Screen`.
+* `View Frame` - A rectangle at a particular point, and of a particular size, within another `View`, referred to as the `Superview`. *Frame-Relative* means a coordinate is relative to the top-left corner of the View in question. `View.FrameToScreen ()` and `View.ScreenToFrame ()` are helper methods for translating a *Frame-Relative* coordinate to a *Screen-Relative* coordinate and vice-versa.
+* `View Content` - A rectangle, with an origin of (`0, 0`) and size (defined by `View.ContentSize`) where the View's content exists. *Content-Relative* means a coordinate is relative to the top-left corner of the content, which is always (`0,0`). `View.ContentToScreen ()` and `View.ScreenToContent ()` are helper methods for translating a *Content-Relative* coordinate to a *Screen-Relative* coordinate and vice-versa.
+* `Viewport` - A *Contnet-Relative* rectangle representing the subset of the View's content that is visible to the user. If `View.ContentSize` is larger than the Viewport, scrolling is enabled. *Viewport-Relative* means a coordinate that is bound by (`0,0`) and the size of the inner-rectangle of the View's `Padding`. The View drawing primitives (e.g. `View.Move`) take *Viewport-Relative* coordinates; `Move (0, 0)` means the `Cell` in the top-left corner of the inner rectangle of `Padding`. `View.ViewportToScreen ()` and `View.ScreenToViewport ()` are helper methods for translating a *Viewport-Relative* coordinate to a *Screen-Relative* coordinate and vice-versa. To convert a *Viewport-Relative* coordinate to a *Content-Relative* coordinate, simply subtract `Viewport.X` and/or `Viewport.Y` from the *Content-Relative* coordinate. To convert a *Viewport-Relative* coordinate to a *Frame-Relative* coordinate, subtract the point returned by `View.GetViewportOffsetFromFrame`.
+
+## The Viewport
+
+The Viewport (`View.Viewport`) is a rectangle describing a sub-set of the View's content. It is a "portal" into the content. The `Viewport.Location` is relative to the top-left corner of the inner rectangle of `View.Padding`. If `Viewport.Size` is the same as `View.ContentSize`, `Viewport.Location` will be `0,0`. Non-zero values for the location indicate the visible area is offset into the View's content area, enabling scrolling. Making `Viewport.Location` positive, moves the Viewport down and to the right in the content. If the location values are negative, it means the `Viewport` is positioned above and to the left of the content.
+
+## Layout
+
+Terminal.Gui provides a rich sytem for how views are laid out relative to each other. **Computed Layout** means the position and size of a View is declared to be computed by the layout engine. **Absolute Layout** means the position and size of a View is explicitly declared by the develeper to be an absolute value. The position of a view is set by setting the `X` and `Y` properties, which are of time [Pos](~/api/Terminal.Gui.Pos.yml). The size is set via that `Width` and `Height` properties, which are of type [Dim](~/api/Terminal.Gui.Dim.yml).
+
+**Computed Layout** supports dynamic console apps where UI elements (Views) adjust layout as the terminal resizes or other Views change size or position. The X, Y, Width, and Height properties are Dim and Pos objects that dynamically update the position of a view.
+
+**Absolute Layout** requires specifying coordinates and sizes of Views explicitly, and the View will typically stay in a fixed position and size.
+
+```cs
 // Absolute layout using a provided rectangle
-var label1 = new Label (new Rect (1, 1, 20, 1), "Hello")
+var label1 = new Label () { X = 1, Y = 2, Width = 3, Height = 4, Title = "Absolute")
 
 // Computed Layout
-var label2 = new Label ("Hello") {
-    X = Pos.Right (label2),
+var label2 = new Label () {
+    Title = "Computed",
+    X = Pos.Right (otherView),
     Y = Pos.Center (),
     Width = Dim.Fill (),
-    Height = 1
+    Height = Dim.Percent (50)
 };
 
 ```
 
-When using *Computed Layout* the `X` and `Y` properties are of type [Pos](~/api/Terminal.Gui.Pos.yml) and the `Width` and `Height` properties are of type [Dim](~/api/Terminal.Gui.Dim.yml) both of which can be created implicitly from integer values.
+The `Frame` property is a rectangle that provides the current location and size of the view relative to the View's `Superview`'s Content area. 
+
+The `View.LayoutStyle` property can be used to determine how the View is treated. If the style is `Absolute`, the `X`, `Y`, `Width`, and `Height` objects are all absolute values. If the style is `Computed`, one or more of the `X`, `Y`, `Width`, and `Height` objects describe a computed value.
 
 ## The `Pos` Type
 
-The `Pos` type on `X` and `Y` offers a few options:
-* Absolute position, by passing an integer
-* Percentage of the parent's view size - `Pos.Percent(n)`
-* Anchored from the end of the dimension - `AnchorEnd(int margin=0)`
-* Centered, using `Center()`
-* Reference the Left (X), Top (Y), Bottom, Right positions of another view
+The [Pos](~/api/Terminal.Gui.Pos.yml) is the type of `View.X` and `View.Y` and supports the following sub-types:
+
+* Absolute position, by passing an integer - `Pos.Absolute(n)`.
+* Percentage of the parent's view size - `Pos.Percent(percent)`.
+* Anchored from the end of the dimension - `Pos.AnchorEnd(margin)`.
+* Centered, using `Pos.Center()`.
+* The `Pos.Left(otherView)`, `Pos.Top(otherView)`, `Pos.Bottom(otherView)`, `Pos.Right(otherView)` positions of another view.
 
-The `Pos` values can be added or subtracted, like this:
+All `Pos` coordinates are relative to the Superview's content area.
 
-```csharp
+`Pos` values can be combined using addition or subtraction:
+
+```cs
 // Set the X coordinate to 10 characters left from the center
 view.X = Pos.Center () - 10;
 
@@ -46,28 +67,29 @@ anotherView.X = AnchorEnd (10);
 anotherView.Width = 9;
 
 myView.X = Pos.X (view);
-myView.Y = Pos.Bottom (anotherView);
+myView.Y = Pos.Bottom (anotherView) + 5;
 ```
-
 ## The `Dim` Type
 
-The `Dim` type is used for the `Width` and `Height` properties on the View and offers
-the following options:
+The [Dim](~/api/Terminal.Gui.Dim.yml) is the type of `View.Width` and `View.Height` and supports the following sub-types:
 
-* Absolute size, by passing an integer
-* Percentage of the parent's view size - `Dim.Percent(n)`
-* Fill to the end - `Dim.Fill ()`
-* Reference the Width or Height of another view
+* Absolute size, by passing an integer - `Dim.Absolute(n)`.
+* Percentage of the Superview's Content Area  - `Dim.Percent(percent)`.
+* Fill to the end of the Superview's Content Area - `Dim.Fill ()`.
+* Reference the Width or Height of another view - `Dim.Width (otherView)`, `Dim.Height (otherView)`.
+* An arbitrary function - `Dim.Function(fn)`
+* Automatic size based on the View's content (either Subviews or Text) - `Dim.Auto()`
 
-Like, `Pos`, objects of type `Dim` can be added an subtracted, like this:
+All `Dim` dimensions are relative to the Superview's content area.
 
+Like, `Pos`, objects of type `Dim` can be combined using addition or subtraction, like this:
 
-```csharp
+```cs
 // Set the Width to be 10 characters less than filling 
 // the remaining portion of the screen
 view.Width = Dim.Fill () - 10;
 
 view.Height = Dim.Percent(20) - 1;
 
-anotherView.Height = Dim.Height (view)+1
+anotherView.Height = Dim.Height (view) + 1;
 ```

+ 27 - 0
docfx/docs/mouse.md

@@ -0,0 +1,27 @@
+# Mouse API
+
+## Tenets for Terminal.Gui Mouse Handling (Unless you know better ones...)
+
+Tenets higher in the list have precedence over tenets lower in the list.
+
+* **Keyboard Required; Mouse Optional** - Terminal users expect full functionality without having to pick up the mouse. At the same time they love being able to use the mouse when it makes sense to do so. We strive to ensure anything that can be done with the keyboard is also possible with the mouse. We avoid features that are only useable with the mouse.
+
+* **Be Consistent With the User's Platform** - Users get to choose the platform they run *Terminal.Gui* apps on and those apps should respond to mouse input in a way that is consistent with the platform. For example, on Windows ???
+
+## Mouse APIs
+
+At the core of *Terminal.Gui*'s mouse API is the *[MouseEvent](~/api/Terminal.Gui.MouseEvent.yml)* class. The `MouseEvent` class provides a platform-independent abstraction for common mouse events. Every mouse event can be fully described in a `MouseEvent` instance, and most of the mouse-related APIs are simply helper functions for decoding a `MouseEvent`.
+
+When the user does something with the mouse, the `ConsoleDriver` maps the platform-specific mouse event into a `MouseEvent` and calls `Application.OnMouseEvent`. Then, `Application.OnMouseEvent` determines which `View` the event should go to. The `View.OnMouseEvent` method can be overridden or the `View.MouseEvent` event can be subscribed to, to handle the low-level mouse event. If the low-level event is not handled by a view, `Appliation` will then call the appropriate high-level helper APIs. For example, if the user double-clicks the mouse, `View.OnMouseClick` will be called/`View.MouseClick` will be fired with the event arguments indicating which mouse button was double-clicked. 
+
+## Mouse Button and Movement Concepts
+
+* **Down** - Indicates the user pushed a mouse button down.
+* **Pressed** - Indicates the mouse button is down; for example if the mouse was pressed down and remains down for a period of time.
+* **Released** - Indicates the user released a mouse button.
+* **Clicked** - Indicates the user pressed then released the mouse button while over a particular View. 
+* **Moved** - Indicates the mouse moved to a new location since the last mouse event.
+
+## **[Global Mouse Handling](~/api/Terminal.Gui.Application.yml#Terminal_Gui_Application_MouseEvent)**
+
+The `Application.MouseEvent` event can be used if an application wishes to recieve all mouse events.

+ 5 - 3
docfx/docs/toc.yml

@@ -8,15 +8,17 @@
   href: views.md
 - name: Configuration
   href: config.md
-- name: Drawing (Text and Color)
+- name: Drawing (Text, Lines, and Color)
   href: drawing.md
 - name: Cross-platform Driver Model
   href: drivers.md
 - name: Keyboard Event Processing
   href: keyboard.md
-- name: Abosolute, Computed, and Overlapped Layout
+- name: Mouse Event Processing
+  href: mouse.md
+- name: The View Layout Engine
   href: layout.md
-- name: Event Processing and the Application Main Loop
+- name: Mutli-Tasking and Application Main Loop
   href: mainloop.md
 - name: TableView Deep Dive
   href: tableview.md