diff --git a/.gitignore b/.gitignore index b46551486..1929d8960 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,7 @@ packages # User-specific files *.user -docfx/api \ No newline at end of file +docfx/api + +#git merge files +*.orig \ No newline at end of file diff --git a/Example/demo.cs b/Example/demo.cs index 7f81d9e98..0e431422a 100644 --- a/Example/demo.cs +++ b/Example/demo.cs @@ -30,7 +30,7 @@ static class Demo { throw new NotImplementedException (); } - public override void Redraw (Rect region) + public override void Redraw (Rect bounds) { //Point pos = new Point (region.X, region.Y); Driver.SetAttribute (ColorScheme.Focus); @@ -53,7 +53,7 @@ static class Demo { { } - public override void Redraw (Rect region) + public override void Redraw (Rect bounds) { Driver.SetAttribute (ColorScheme.Focus); var f = Frame; @@ -520,7 +520,7 @@ static class Demo { //Application.UseSystemConsole = true; - Application.Init (); + Application.Init(); var top = Application.Top; @@ -638,7 +638,7 @@ static class Demo { var bottom2 = new Label ("This should go on the bottom of another top-level!"); top.Add (bottom2); - Application.Loaded += (sender, e) => { + top.LayoutComplete += (sender, e) => { bottom.X = win.X; bottom.Y = Pos.Bottom (win) - Pos.Top (win) - margin; bottom2.X = Pos.Left (win); diff --git a/Terminal.Gui/Core/Application.cs b/Terminal.Gui/Core/Application.cs index 3c41d67db..ca42eb848 100644 --- a/Terminal.Gui/Core/Application.cs +++ b/Terminal.Gui/Core/Application.cs @@ -434,7 +434,7 @@ namespace Terminal.Gui { Current = toplevel; Driver.PrepareToRun (MainLoop, ProcessKeyEvent, ProcessKeyDownEvent, ProcessKeyUpEvent, ProcessMouseEvent); if (toplevel.LayoutStyle == LayoutStyle.Computed) - toplevel.RelativeLayout (new Rect (0, 0, Driver.Cols, Driver.Rows)); + toplevel.SetRelativeLayout (new Rect (0, 0, Driver.Cols, Driver.Rows)); toplevel.LayoutSubviews (); Loaded?.Invoke (null, new ResizedEventArgs () { Rows = Driver.Rows, Cols = Driver.Cols }); toplevel.WillPresent (); @@ -481,6 +481,7 @@ namespace Terminal.Gui { if (closeDriver) { MainLoop = null; Driver.End (); + Driver = null; } _initialized = false; @@ -670,7 +671,7 @@ namespace Terminal.Gui { Driver.Clip = full; foreach (var t in toplevels) { t.PositionToplevels (); - t.RelativeLayout (full); + t.SetRelativeLayout (full); t.LayoutSubviews (); } Refresh (); diff --git a/Terminal.Gui/Core/ConsoleDriver.cs b/Terminal.Gui/Core/ConsoleDriver.cs index fb3015893..72bd854b1 100644 --- a/Terminal.Gui/Core/ConsoleDriver.cs +++ b/Terminal.Gui/Core/ConsoleDriver.cs @@ -562,7 +562,7 @@ namespace Terminal.Gui { const char bottomChar = clearChar; #endif /// - /// Draws a frame for a window with padding aand n optional visible border inside the padding. + /// Draws a frame for a window with padding and an optional visible border inside the padding. /// /// Screen relative region where the frame will be drawn. /// Number of columns to pad on the left (if 0 the border will not appear on the left). @@ -724,7 +724,7 @@ namespace Terminal.Gui { // DrawFrame assumes the border is always at least one row/col thick // DrawWindowFrame assumes a padding of 0 means NO padding and no frame DrawWindowFrame (new Rect (region.X, region.Y, region.Width, region.Height), - padding + 1, padding + 1, padding + 1, padding + 1, fill: fill); + padding + 1, padding + 1, padding + 1, padding + 1, border: false, fill: fill); } diff --git a/Terminal.Gui/Core/Toplevel.cs b/Terminal.Gui/Core/Toplevel.cs index 3386d7f03..4e2c6ca1d 100644 --- a/Terminal.Gui/Core/Toplevel.cs +++ b/Terminal.Gui/Core/Toplevel.cs @@ -13,19 +13,18 @@ namespace Terminal.Gui { /// /// /// - /// Toplevels can be modally executing views, and they return control - /// to the caller when the "Running" property is set to false, or - /// by calling + /// Toplevels can be modally executing views, started by calling . + /// They return control to the caller when has + /// been called (which sets the property to false). /// /// - /// There will be a toplevel created for you on the first time use - /// and can be accessed from the property , - /// but new toplevels can be created and ran on top of it. To run, create the - /// toplevel and then invoke with the - /// new toplevel. + /// A Toplevel is created when an application initialzies Terminal.Gui by callling . + /// The application Toplevel can be accessed via . Additional Toplevels can be created + /// and run (e.g. s. To run a Toplevel, create the and + /// call . /// /// - /// TopLevels can also opt-in to more sophisticated initialization + /// Toplevels can also opt-in to more sophisticated initialization /// by implementing . When they do /// so, the and /// methods will be called @@ -33,27 +32,29 @@ namespace Terminal.Gui { /// If first-run-only initialization is preferred, the /// can be implemented too, in which case the /// methods will only be called if - /// is . This allows proper View inheritance hierarchies + /// is . This allows proper inheritance hierarchies /// to override base class layout code optimally by doing so only on first run, /// instead of on every run. /// /// public class Toplevel : View { /// - /// Gets or sets whether the Mainloop for this is running or not. Setting - /// this property to false will cause the MainLoop to exit. + /// Gets or sets whether the for this is running or not. /// + /// + /// Setting this property directly is discouraged. Use instead. + /// public bool Running { get; set; } /// - /// Fired once the Toplevel's MainLoop has started it's first iteration. + /// Fired once the Toplevel's has started it's first iteration. /// Subscribe to this event to perform tasks when the has been laid out and focus has been set. /// changes. A Ready event handler is a good place to finalize initialization after calling `(topLevel)`. /// public event EventHandler Ready; /// - /// Called from Application.RunLoop after the has entered it's first iteration of the loop. + /// Called from after the has entered it's first iteration of the loop. /// internal virtual void OnReady () { @@ -70,7 +71,7 @@ namespace Terminal.Gui { } /// - /// Initializes a new instance of the class with Computed layout, defaulting to full screen. + /// Initializes a new instance of the class with layout, defaulting to full screen. /// public Toplevel () : base () { @@ -85,7 +86,7 @@ namespace Terminal.Gui { } /// - /// Convenience factory method that creates a new toplevel with the current terminal dimensions. + /// Convenience factory method that creates a new Toplevel with the current terminal dimensions. /// /// The create. public static Toplevel Create () @@ -109,12 +110,12 @@ namespace Terminal.Gui { public bool Modal { get; set; } /// - /// Check id current toplevel has menu bar + /// Gets or sets the menu for this Toplevel /// public MenuBar MenuBar { get; set; } /// - /// Check id current toplevel has status bar + /// Gets or sets the status bar for this Toplevel /// public StatusBar StatusBar { get; set; } @@ -256,18 +257,18 @@ namespace Terminal.Gui { } /// - public override void Redraw (Rect region) + public override void Redraw (Rect bounds) { Application.CurrentView = this; if (IsCurrentTop || this == Application.Top) { if (NeedDisplay != null && !NeedDisplay.IsEmpty) { Driver.SetAttribute (Colors.TopLevel.Normal); - Clear (region); + Clear (Frame); Driver.SetAttribute (Colors.Base.Normal); } foreach (var view in Subviews) { - if (view.Frame.IntersectsWith (region)) { + if (view.Frame.IntersectsWith (bounds)) { view.SetNeedsLayout (); view.SetNeedsDisplay (view.Bounds); } @@ -280,7 +281,7 @@ namespace Terminal.Gui { } /// - /// This method is invoked by Application.Begin as part of the Application.Run after + /// Invoked by as part of the after /// the views have been laid out, and before the views are drawn for the first time. /// public virtual void WillPresent () diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index b426a9a06..1d50cfe5b 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -20,7 +20,7 @@ namespace Terminal.Gui { /// /// Determines the LayoutStyle for a view, if Absolute, during LayoutSubviews, the - /// value from the Frame will be used, if the value is Computer, then the Frame + /// value from the Frame will be used, if the value is Computed, then the Frame /// will be updated from the X, Y Pos objects and the Width and Height Dim objects. /// public enum LayoutStyle { @@ -41,68 +41,73 @@ namespace Terminal.Gui { /// /// /// - /// The View defines the base functionality for user interface elements in Terminal/gui.cs. Views + /// The View defines the base functionality for user interface elements in Terminal.Gui. Views /// can contain one or more subviews, can respond to user input and render themselves on the screen. /// /// - /// Views can either be created with an absolute position, by calling the constructor that takes a - /// Rect parameter to specify the absolute position and size (the Frame of the View) or by setting the - /// X, Y, Width and Height properties on the view. Both approaches use coordinates that are relative - /// to the container they are being added to. + /// Views supports two layout styles: Absolute or Computed. The choice as to which layout style is used by the View + /// is determined when the View is initizlied. To create a View using Absolute layout, call a constructor that takes a + /// Rect parameter to specify the absolute position and size (the View.)/. To create a View + /// using Computed layout use a constructor that does not take a Rect parametr and set the X, Y, Width and Height + /// properties on the view. Both approaches use coordinates that are relative to the container they are being added to. /// /// - /// When you do not specify a Rect frame you can use the more flexible - /// Dim and Pos objects that can dynamically update the position of a view. + /// To switch between Absolute and Computed layout, use the property. + /// + /// + /// Computed layout is more flexible and supports dynamic console apps where controls 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. /// The X and Y properties are of type /// and you can use either absolute positions, percentages or anchor /// points. The Width and Height properties are of type /// and can use absolute position, /// percentages and anchors. These are useful as they will take - /// care of repositioning your views if your view's frames are resized - /// or if the terminal size changes. + /// care of repositioning views when view's frames are resized or + /// if the terminal size changes. /// /// - /// When you specify the Rect parameter to a view, you are setting the LayoutStyle to Absolute, and the - /// view will always stay in the position that you placed it. To change the position change the - /// Frame property to the new position. + /// Absolute layout requires specifying coordiantes and sizes of Views explicitly, and the + /// View will typcialy stay in a fixed position and size. To change the position and size use the + /// property. /// /// - /// Subviews can be added to a View by calling the Add method. The container of a view is the - /// Superview. + /// Subviews (child views) can be added to a View by calling the method. + /// The container of a View can be accessed with the property. /// /// - /// Developers can call the SetNeedsDisplay method on the view to flag a region or the entire view + /// The method flags a region or the entire view /// as requiring to be redrawn. /// /// - /// Views have a ColorScheme property that defines the default colors that subviews + /// Views have a property that defines the default colors that subviews /// should use for rendering. This ensures that the views fit in the context where /// they are being used, and allows for themes to be plugged in. For example, the /// default colors for windows and toplevels uses a blue background, while it uses /// a white background for dialog boxes and a red background for errors. /// /// - /// If a ColorScheme is not set on a view, the result of the ColorScheme is the - /// value of the SuperView and the value might only be valid once a view has been - /// added to a SuperView, so your subclasses should not rely on ColorScheme being - /// set at construction time. + /// Subclasses should not rely on being + /// set at construction time. If a is not set on a view, the view will inherit the + /// value from its and the value might only be valid once a view has been + /// added to a SuperView. /// /// - /// Using ColorSchemes has the advantage that your application will work both + /// By using applications will work both /// in color as well as black and white displays. /// /// - /// Views that are focusable should implement the PositionCursor to make sure that - /// the cursor is placed in a location that makes sense. Unix terminals do not have + /// Views that are focusable should implement the to make sure that + /// the cursor is placed in a location that makes sense. Unix terminals do not have /// a way of hiding the cursor, so it can be distracting to have the cursor left at /// the last focused view. So views should make sure that they place the cursor /// in a visually sensible place. /// /// - /// The metnod LayoutSubviews is invoked when the size or layout of a view has + /// The method is invoked when the size or layout of a view has /// changed. The default processing system will keep the size and dimensions - /// for views that use the LayoutKind.Absolute, and will recompute the - /// frames for the vies that use LayoutKind.Computed. + /// for views that use the , and will recompute the + /// frames for the vies that use . /// /// public class View : Responder, IEnumerable { @@ -111,17 +116,18 @@ namespace Terminal.Gui { Backward } + // container == SuperView View container = null; View focused = null; Direction focusDirection; /// - /// Event fired when the view get focus. + /// Event fired when the view gets focus. /// public event EventHandler Enter; /// - /// Event fired when the view lost focus. + /// Event fired when the view looses focus. /// public event EventHandler Leave; @@ -131,7 +137,7 @@ namespace Terminal.Gui { public event EventHandler MouseEnter; /// - /// Event fired when the view loses mouse event for the last time. + /// Event fired when the view receives a mouse event for the last time. /// public event EventHandler MouseLeave; @@ -173,13 +179,14 @@ namespace Terminal.Gui { internal Rect NeedDisplay { get; private set; } = Rect.Empty; - // The frame for the object + // The frame for the object. Superview relative. Rect frame; /// /// Gets or sets an identifier for the view; /// /// The identifier. + /// The id should be unique across all Views that share a SuperView. public ustring Id { get; set; } = ""; /// @@ -192,7 +199,7 @@ namespace Terminal.Gui { } /// - /// Gets or sets a value indicating whether this want mouse position reports. + /// Gets or sets a value indicating whether this wants mouse position reports. /// /// true if want mouse position reports; otherwise, false. public virtual bool WantMousePositionReports { get; set; } = false; @@ -201,13 +208,19 @@ namespace Terminal.Gui { /// Gets or sets a value indicating whether this want continuous button pressed event. /// public virtual bool WantContinuousButtonPressed { get; set; } = false; + /// - /// Gets or sets the frame for the view. + /// Gets or sets the frame for the view. The frame is relative to the . /// /// The frame. /// + /// + /// Change the Frame when using the layout style to move or resize views. + /// + /// /// Altering the Frame of a view will trigger the redrawing of the - /// view as well as the redrawing of the affected regions in the superview. + /// view as well as the redrawing of the affected regions in the . + /// /// public virtual Rect Frame { get => frame; @@ -236,9 +249,9 @@ namespace Terminal.Gui { LayoutStyle layoutStyle; /// - /// Controls how the view's Frame is computed during the LayoutSubviews method, if Absolute, then - /// LayoutSubviews does not change the Frame properties, otherwise the Frame is updated from the - /// values in X, Y, Width and Height properties. + /// Controls how the View's is computed during the LayoutSubviews method, if the style is set to , + /// LayoutSubviews does not change the . If the style is the is updated using + /// the , , , and properties. /// /// The layout style. public LayoutStyle LayoutStyle { @@ -250,7 +263,7 @@ namespace Terminal.Gui { } /// - /// The bounds represent the View-relative rectangle used for this view. Updates to the Bounds update the Frame, and has the same side effects as updating the frame. + /// The bounds represent the View-relative rectangle used for this view. Updates to the Bounds update the , and has the same side effects as updating the . /// /// The bounds. public Rect Bounds { @@ -262,10 +275,12 @@ namespace Terminal.Gui { Pos x, y; /// - /// Gets or sets the X position for the view (the column). This is only used when the LayoutStyle is Computed, if the - /// LayoutStyle is set to Absolute, this value is ignored. + /// Gets or sets the X position for the view (the column). Only used whe is . /// /// The X Position. + /// + /// If is changing this property has no effect and its value is indeterminate. + /// public Pos X { get => x; set { @@ -275,10 +290,12 @@ namespace Terminal.Gui { } /// - /// Gets or sets the Y position for the view (line). This is only used when the LayoutStyle is Computed, if the - /// LayoutStyle is set to Absolute, this value is ignored. + /// Gets or sets the Y position for the view (the row). Only used whe is . /// /// The y position (line). + /// + /// If is changing this property has no effect and its value is indeterminate. + /// public Pos Y { get => y; set { @@ -290,10 +307,12 @@ namespace Terminal.Gui { Dim width, height; /// - /// Gets or sets the width for the view. This is only used when the LayoutStyle is Computed, if the - /// LayoutStyle is set to Absolute, this value is ignored. + /// Gets or sets the width of the view. Only used whe is . /// /// The width. + /// + /// If is changing this property has no effect and its value is indeterminate. + /// public Dim Width { get => width; set { @@ -303,10 +322,10 @@ namespace Terminal.Gui { } /// - /// Gets or sets the height for the view. This is only used when the LayoutStyle is Computed, if the - /// LayoutStyle is set to Absolute, this value is ignored. + /// Gets or sets the height of the view. Only used whe is . /// /// The height. + /// If is changing this property has no effect and its value is indeterminate. public Dim Height { get => height; set { @@ -322,11 +341,14 @@ namespace Terminal.Gui { public View SuperView => container; /// - /// Initializes a new instance of the class with the absolute - /// dimensions specified in the frame. If you want to have Views that can be positioned with - /// Pos and Dim properties on X, Y, Width and Height, use the empty constructor. + /// Initializes a new instance of a class with the absolute + /// dimensions specified in the frame parameter. /// /// The region covered by this view. + /// + /// This constructor intitalize a View with a of . Use to + /// initialize a View with of + /// public View (Rect frame) { this.Frame = frame; @@ -335,10 +357,15 @@ namespace Terminal.Gui { } /// - /// Initializes a new instance of the class and sets the - /// view up for Computed layout, which will use the values in X, Y, Width and Height to - /// compute the View's Frame. + /// Initializes a new instance of class. /// + /// + /// Use , , , and properties to dynamically control the size and location of the view. + /// + /// + /// This constructor intitalize a View with a of . + /// Use , , , and properties to dynamically control the size and location of the view. + /// public View () { CanFocus = false; @@ -346,8 +373,7 @@ namespace Terminal.Gui { } /// - /// Invoke to flag that this view needs to be redisplayed, by any code - /// that alters the state of the view. + /// Sets a flag indicating this view needs to be redisplayed because its state has changed. /// public void SetNeedsDisplay () { @@ -367,9 +393,9 @@ namespace Terminal.Gui { } /// - /// Flags the specified rectangle region on this view as needing to be repainted. + /// Flags the view-relative region on this View as needing to be repainted. /// - /// The region that must be flagged for repaint. + /// The view-relative region that must be flagged for repaint. public void SetNeedsDisplay (Rect region) { if (NeedDisplay == null || NeedDisplay.IsEmpty) @@ -397,7 +423,7 @@ namespace Terminal.Gui { internal bool childNeedsDisplay; /// - /// Flags this view for requiring the children views to be repainted. + /// Indicates that any child views (in the list) need to be repainted. /// public void ChildNeedsDisplay () { @@ -407,9 +433,10 @@ namespace Terminal.Gui { } /// - /// Adds a subview to this view. + /// Adds a subview (child) to this view. /// /// + /// The Views that have been added to this view can be retrieved via the property. See also /// public virtual void Add (View view) { @@ -426,9 +453,12 @@ namespace Terminal.Gui { } /// - /// Adds the specified views to the view. + /// Adds the specified views (children) to the view. /// /// Array of one or more views (can be optional parameter). + /// + /// The Views that have been added to this view can be retrieved via the property. See also + /// public void Add (params View [] views) { if (views == null) @@ -438,10 +468,8 @@ namespace Terminal.Gui { } /// - /// Removes all the widgets from this container. + /// Removes all subviews (children) added via or from this View. /// - /// - /// public virtual void RemoveAll () { if (subviews == null) @@ -453,7 +481,7 @@ namespace Terminal.Gui { } /// - /// Removes a widget from this container. + /// Removes a subview added via or from this View. /// /// /// @@ -573,27 +601,30 @@ namespace Terminal.Gui { } /// - /// Clears the specified rectangular region with the current color + /// Clears the specified region with the current color. /// - public void Clear (Rect r) + /// + /// + /// The screen-relative region to clear. + public void Clear (Rect regionScreen) { - var h = r.Height; - var w = r.Width; - for (int line = r.Y; line < r.Y + h; line++) { - Driver.Move (r.X, line); + var h = regionScreen.Height; + var w = regionScreen.Width; + for (int line = regionScreen.Y; line < regionScreen.Y + h; line++) { + Driver.Move (regionScreen.X, line); for (int col = 0; col < w; col++) Driver.AddRune (' '); } } /// - /// Converts the (col,row) position from the view into a screen (col,row). The values are clamped to (0..ScreenDim-1) + /// Converts a view-relative (col,row) position to a screen-relative position (col,row). The values are optionally clamped to the screen dimensions. /// - /// View-based column. - /// View-based row. - /// Absolute column, display relative. - /// Absolute row, display relative. - /// Whether to clip the result of the ViewToScreen method, if set to true, the rcol, rrow values are clamped to the screen dimensions. + /// View-relative column. + /// View-relative row. + /// Absolute column; screen-relative. + /// Absolute row; screen-relative. + /// Whether to clip the result of the ViewToScreen method, if set to true, the rcol, rrow values are clamped to the screen (terminal) dimensions (0..TerminalDim-1). internal void ViewToScreen (int col, int row, out int rcol, out int rrow, bool clipped = true) { // Computes the real row, col relative to the screen. @@ -614,7 +645,7 @@ namespace Terminal.Gui { } /// - /// Converts a point from screen coordinates into the view coordinate space. + /// Converts a point from screen-relative coordinates to view-relative coordinates. /// /// The mapped point. /// X screen-coordinate point. @@ -629,66 +660,72 @@ namespace Terminal.Gui { } } - // Converts a rectangle in view coordinates to screen coordinates. - internal Rect RectToScreen (Rect rect) + /// + /// Converts a region in view-relative coordinates to screen-relative coordinates. + /// + internal Rect ViewToScreen (Rect region) { - ViewToScreen (rect.X, rect.Y, out var x, out var y, clipped: false); - return new Rect (x, y, rect.Width, rect.Height); + ViewToScreen (region.X, region.Y, out var x, out var y, clipped: false); + return new Rect (x, y, region.Width, region.Height); } // Clips a rectangle in screen coordinates to the dimensions currently available on the screen - internal Rect ScreenClip (Rect rect) + internal Rect ScreenClip (Rect regionScreen) { - var x = rect.X < 0 ? 0 : rect.X; - var y = rect.Y < 0 ? 0 : rect.Y; - var w = rect.X + rect.Width >= Driver.Cols ? Driver.Cols - rect.X : rect.Width; - var h = rect.Y + rect.Height >= Driver.Rows ? Driver.Rows - rect.Y : rect.Height; + var x = regionScreen.X < 0 ? 0 : regionScreen.X; + var y = regionScreen.Y < 0 ? 0 : regionScreen.Y; + var w = regionScreen.X + regionScreen.Width >= Driver.Cols ? Driver.Cols - regionScreen.X : regionScreen.Width; + var h = regionScreen.Y + regionScreen.Height >= Driver.Rows ? Driver.Rows - regionScreen.Y : regionScreen.Height; return new Rect (x, y, w, h); } /// - /// Sets the Console driver's clip region to the current View's Bounds. + /// Sets the 's clip region to the current View's . /// - /// The existing driver's Clip region, which can be then set by setting the Driver.Clip property. + /// The existing driver's clip region, which can be then re-eapplied by setting .Clip (). + /// + /// is View-relative. + /// public Rect ClipToBounds () { return SetClip (Bounds); } /// - /// Sets the clipping region to the specified region, the region is view-relative + /// Sets the clip region to the specified view-relative region. /// - /// The previous clip region. - /// Rectangle region to clip into, the region is view-relative. - public Rect SetClip (Rect rect) + /// The previous screen-relative clip region. + /// View-relative clip region. + public Rect SetClip (Rect region) { - var bscreen = RectToScreen (rect); var previous = Driver.Clip; - Driver.Clip = ScreenClip (RectToScreen (Bounds)); + Driver.Clip = Rect.Intersect (previous, ViewToScreen (region)); return previous; } /// /// Draws a frame in the current view, clipped by the boundary of this view /// - /// Rectangular region for the frame to be drawn. - /// The padding to add to the drawn frame. + /// View-relative region for the frame to be drawn. + /// The padding to add around the outside of the drawn frame. /// If set to true it fill will the contents. - public void DrawFrame (Rect rect, int padding = 0, bool fill = false) + public void DrawFrame (Rect region, int padding = 0, bool fill = false) { - var scrRect = RectToScreen (rect); + var scrRect = ViewToScreen (region); var savedClip = ClipToBounds (); - Driver.DrawFrame (scrRect, padding, fill); + Driver.DrawWindowFrame (scrRect, padding + 1, padding + 1, padding + 1, padding + 1, border: true, fill: fill); Driver.Clip = savedClip; } /// - /// Utility function to draw strings that contain a hotkey + /// Utility function to draw strings that contain a hotkey. /// /// String to display, the underscoore before a letter flags the next letter as the hotkey. /// Hot color. /// Normal color. + /// + /// The hotkey is any character following an underscore ('_') character. public void DrawHotString (ustring text, Attribute hotColor, Attribute normalColor) { Driver.SetAttribute (normalColor); @@ -703,7 +740,7 @@ namespace Terminal.Gui { } /// - /// Utility function to draw strings that contains a hotkey using a colorscheme and the "focused" state. + /// Utility function to draw strings that contains a hotkey using a and the "focused" state. /// /// String to display, the underscoore before a letter flags the next letter as the hotkey. /// If set to true this uses the focused colors from the color scheme, otherwise the regular ones. @@ -720,8 +757,8 @@ namespace Terminal.Gui { /// This moves the cursor to the specified column and row in the view. /// /// The move. - /// Col. - /// Row. + /// Col (view-relative). + /// Row (view-relative). public void Move (int col, int row) { ViewToScreen (col, row, out var rcol, out var rrow); @@ -731,6 +768,11 @@ namespace Terminal.Gui { /// /// Positions the cursor in the right position based on the currently focused view in the chain. /// + /// Views that are focusable should override to ensure + /// the cursor is placed in a location that makes sense. Unix terminals do not have + /// a way of hiding the cursor, so it can be distracting to have the cursor left at + /// the last focused view. Views should make sure that they place the cursor + /// in a visually sensible place. public virtual void PositionCursor () { if (focused != null) @@ -763,7 +805,7 @@ namespace Terminal.Gui { } /// - /// Specifies the event arguments for + /// Defines the event arguments for /// public class FocusEventArgs : EventArgs { /// @@ -825,7 +867,7 @@ namespace Terminal.Gui { } /// - /// The color scheme for this view, if it is not defined, it returns the parent's + /// The color scheme for this view, if it is not defined, it returns the 's /// color scheme. /// public ColorScheme ColorScheme { @@ -842,10 +884,10 @@ namespace Terminal.Gui { ColorScheme colorScheme; /// - /// Displays the specified character in the specified column and row. + /// Displays the specified character in the specified column and row of the View. /// - /// Col. - /// Row. + /// Column (view-relative). + /// Row (view-relative). /// Ch. public void AddRune (int col, int row, Rune ch) { @@ -858,7 +900,7 @@ namespace Terminal.Gui { } /// - /// Removes the SetNeedsDisplay and the ChildNeedsDisplay setting on this view. + /// Removes the and the setting on this view. /// protected void ClearNeedsDisplay () { @@ -867,37 +909,40 @@ namespace Terminal.Gui { } /// - /// Performs a redraw of this view and its subviews, only redraws the views that have been flagged for a re-display. + /// Redraws this view and its subviews; only redraws the views that have been flagged for a re-display. /// - /// The region to redraw, this is relative to the view itself. + /// The bounds (view-relative region) to redraw. /// /// + /// Always use (view-relative) when calling , NOT (superview-relative). + /// + /// /// Views should set the color that they want to use on entry, as otherwise this will inherit /// the last color that was set globaly on the driver. /// + /// + /// Overrides of must ensure they do not set Driver.Clip to a clip region + /// larger than the region parameter. + /// /// - public virtual void Redraw (Rect region) + public virtual void Redraw (Rect bounds) { var clipRect = new Rect (Point.Empty, frame.Size); if (subviews != null) { foreach (var view in subviews) { if (view.NeedDisplay != null && (!view.NeedDisplay.IsEmpty || view.childNeedsDisplay)) { - if (view.Frame.IntersectsWith (clipRect) && view.Frame.IntersectsWith (region)) { + if (view.Frame.IntersectsWith (clipRect) && view.Frame.IntersectsWith (bounds)) { // FIXED: optimize this by computing the intersection of region and view.Bounds if (view.layoutNeeded) view.LayoutSubviews (); Application.CurrentView = view; - // Ensure we don't make the Driver's clip rect any bigger - if (Driver.Clip.IsEmpty || Driver.Clip.Contains(RectToScreen (view.Frame))) { - var savedClip = view.ClipToBounds (); - view.Redraw (view.Bounds); - Driver.Clip = savedClip; - } else { - view.Redraw (view.Bounds); - } + // Clip the sub-view + var savedClip = ClipToBounds (); + view.Redraw (view.Bounds); + Driver.Clip = savedClip; } view.NeedDisplay = Rect.Empty; view.childNeedsDisplay = false; @@ -908,7 +953,7 @@ namespace Terminal.Gui { } /// - /// Focuses the specified sub-view. + /// Causes the specified subview to have focus. /// /// View. public void SetFocus (View view) @@ -941,7 +986,7 @@ namespace Terminal.Gui { } /// - /// Specifies the event arguments for + /// Defines the event arguments for /// public class KeyEventEventArgs : EventArgs { /// @@ -1187,10 +1232,13 @@ namespace Terminal.Gui { } /// - /// Computes the RelativeLayout for the view, given the frame for its container. + /// Sets the View's to the relative coordinates if its container, given the for its container. /// - /// The Frame for the host. - internal void RelativeLayout (Rect hostFrame) + /// The screen-relative frame for the host. + /// + /// Reminder: is superview-relative; is view-relative. + /// + internal void SetRelativeLayout (Rect hostFrame) { int w, h, _x, _y; @@ -1228,7 +1276,6 @@ namespace Terminal.Gui { h = height.Anchor (hostFrame.Height - _y); } Frame = new Rect (_x, _y, w, h); - // layoutNeeded = false; } // https://en.wikipedia.org/wiki/Topological_sorting @@ -1274,15 +1321,45 @@ namespace Terminal.Gui { } /// - /// This virtual method is invoked when a view starts executing or - /// when the dimensions of the view have changed, for example in + /// Event arguments for the event. + /// + public class LayoutEventArgs : EventArgs { + /// + /// The view-relative bounds of the before it was laid out. + /// + public Rect OldBounds { get; set; } + } + + /// + /// Fired after the Views's method has completed. + /// + /// + /// Subscribe to this event to perform tasks when the has been resized or the layout has otherwise changed. + /// + public event EventHandler LayoutComplete; + + /// + /// Raises the event. Called from after all sub-views have been laid out. + /// + internal virtual void OnLayoutComplete (LayoutEventArgs args) + { + LayoutComplete?.Invoke (this, args); + } + + /// + /// Invoked when a view starts executing or when the dimensions of the view have changed, for example in /// response to the container view or terminal resizing. /// + /// + /// Calls (which raises the event) before it returns. + /// public virtual void LayoutSubviews () { if (!layoutNeeded) return; + Rect oldBounds = Bounds; + // Sort out the dependencies of the X, Y, Width, Height properties var nodes = new HashSet (); var edges = new HashSet<(View, View)> (); @@ -1307,7 +1384,7 @@ namespace Terminal.Gui { foreach (var v in ordered) { if (v.LayoutStyle == LayoutStyle.Computed) - v.RelativeLayout (Frame); + v.SetRelativeLayout (Frame); v.LayoutSubviews (); v.layoutNeeded = false; @@ -1315,10 +1392,12 @@ namespace Terminal.Gui { } if (SuperView == Application.Top && layoutNeeded && ordered.Count == 0 && LayoutStyle == LayoutStyle.Computed) { - RelativeLayout (Frame); + SetRelativeLayout (Frame); } layoutNeeded = false; + + OnLayoutComplete (new LayoutEventArgs () { OldBounds = oldBounds }); } /// diff --git a/Terminal.Gui/Core/Window.cs b/Terminal.Gui/Core/Window.cs index 3544fc2e5..37184cbf0 100644 --- a/Terminal.Gui/Core/Window.cs +++ b/Terminal.Gui/Core/Window.cs @@ -7,7 +7,7 @@ using NStack; namespace Terminal.Gui { /// - /// A that draws a frame around its region and has a "ContentView" subview where the contents are added. + /// A that draws a frame around its region and has a "Content" subview where the contents are added. /// public class Window : Toplevel, IEnumerable { View contentView; @@ -29,7 +29,7 @@ namespace Terminal.Gui { public ContentView (Rect frame) : base (frame) { } public ContentView () : base () { } #if false - public override void Redraw (Rect region) + public override void Redraw (Rect bounds) { Driver.SetAttribute (ColorScheme.Focus); @@ -50,6 +50,10 @@ namespace Terminal.Gui { /// /// Frame. /// Title. + /// + /// This constructor intitalizes a Window with a of . Use constructors + /// that do not take Rect parameters to initialize a Window with of + /// public Window (Rect frame, ustring title = null) : this (frame, title, padding: 0) { } @@ -58,19 +62,26 @@ namespace Terminal.Gui { /// Initializes a new instance of the class with an optional title. /// /// Title. + /// + /// This constructor intitalize a View with a of . + /// Use , , , and properties to dynamically control the size and location of the view. + /// public Window (ustring title = null) : this (title, padding: 0) { } int padding; /// - /// Initializes a new instance of the with - /// the specified frame for its location, with the specified border - /// an optional title. + /// Initializes a new instance of the with the specified frame for its location, with the specified border, + /// and an optional title. /// /// Frame. /// Number of characters to use for padding of the drawn frame. /// Title. + /// + /// This constructor intitalizes a Window with a of . Use constructors + /// that do not take Rect parameters to initialize a Window with of + /// public Window (Rect frame, ustring title = null, int padding = 0) : base (frame) { this.Title = title; @@ -82,12 +93,15 @@ namespace Terminal.Gui { } /// - /// Initializes a new instance of the with - /// the specified frame for its location, with the specified border - /// an optional title. + /// Initializes a new instance of the with the specified frame for its location, with the specified border, + /// and an optional title. /// /// Number of characters to use for padding of the drawn frame. /// Title. + /// + /// This constructor intitalize a View with a of . + /// Use , , , and properties to dynamically control the size and location of the view. + /// public Window (ustring title = null, int padding = 0) : base () { this.Title = title; @@ -111,10 +125,7 @@ namespace Terminal.Gui { return contentView.GetEnumerator (); } - /// - /// Add the specified view to the . - /// - /// View to add to the window. + /// public override void Add (View view) { contentView.Add (view); @@ -123,11 +134,7 @@ namespace Terminal.Gui { } - /// - /// Removes a widget from this container. - /// - /// - /// + /// public override void Remove (View view) { if (view == null) @@ -141,11 +148,7 @@ namespace Terminal.Gui { this.CanFocus = false; } - /// - /// Removes all widgets from this container. - /// - /// - /// + /// public override void RemoveAll () { contentView.RemoveAll (); @@ -156,24 +159,21 @@ namespace Terminal.Gui { { //var padding = 0; Application.CurrentView = this; - var scrRect = RectToScreen (new Rect(0, 0, Frame.Width, Frame.Height)); + var scrRect = ViewToScreen (new Rect (0, 0, Frame.Width, Frame.Height)); // BUGBUG: Why do we draw the frame twice? This call is here to clear the content area, I think. Why not just clear that area? if (NeedDisplay != null && !NeedDisplay.IsEmpty) { Driver.SetAttribute (ColorScheme.Normal); - Driver.DrawFrame (scrRect, padding, true); + Driver.DrawWindowFrame (scrRect, padding + 1, padding + 1, padding + 1, padding + 1, border: true, fill: true); } - if (Driver.Clip.IsEmpty || Driver.Clip.Contains (contentView.RectToScreen (contentView.Frame))) { - var savedClip = ClipToBounds (); - contentView.Redraw (contentView.Bounds); - Driver.Clip = savedClip; - } else { - contentView.Redraw (contentView.Bounds); - } + var savedClip = ClipToBounds (); + contentView.Redraw (contentView.Bounds); + Driver.Clip = savedClip; + ClearNeedsDisplay (); Driver.SetAttribute (ColorScheme.Normal); - Driver.DrawFrame (scrRect, padding, false); + Driver.DrawWindowFrame (scrRect, padding + 1, padding + 1, padding + 1, padding + 1, border: true, fill: false); if (HasFocus) Driver.SetAttribute (ColorScheme.HotNormal); @@ -187,6 +187,7 @@ namespace Terminal.Gui { // internal static Point? dragPosition; Point start; + /// public override bool MouseEvent (MouseEvent mouseEvent) { @@ -200,7 +201,7 @@ namespace Terminal.Gui { if (dragPosition.HasValue) { if (SuperView == null) { Application.Top.SetNeedsDisplay (Frame); - Application.Top.Redraw (Frame); + Application.Top.Redraw (Bounds); } else { SuperView.SetNeedsDisplay (Frame); } @@ -241,6 +242,5 @@ namespace Terminal.Gui { //Demo.ml.Text = me.ToString (); return false; } - } } diff --git a/Terminal.Gui/Terminal.Gui.csproj b/Terminal.Gui/Terminal.Gui.csproj index 01697a423..77c3a2342 100644 --- a/Terminal.Gui/Terminal.Gui.csproj +++ b/Terminal.Gui/Terminal.Gui.csproj @@ -5,11 +5,12 @@ Terminal.Gui bin\Release\Terminal.Gui.xml true + 0.82.0.0 true Terminal.Gui - 0.81 + 0.82 Miguel de Icaza MIT https://github.com/migueldeicaza/gui.cs/ @@ -18,80 +19,141 @@ Miguel de Icaza Application framework for creating modern console applications using .NET Gui.cs is a framework for creating console user interfaces - 0.81: Fix ncurses engine for macOS/Linux, it works again + + 0.82: Many fixes + * API documentation completely revamped and updated. Readme upated. Contributors guide added (Thanks @tig!) + * New sample/demo app - UI Catalog - Replaces demo.cs with an easy to use and extend set of demo scenarios. (Thanks @tig!) + * MenuBar can now have MenuItems directly (enables top-level menu items with no submenu). (Thanks @tig!) + * Apps can now get KeyUp/KeyDown events. (Thanks @tig!) + * Fixes #396 - Text alignnment issues. (Thanks @tig!) + * Fixes #423 - Fix putting results of ocgv on command line erases cursor. (Thanks @tig!) + * Example/Designer csproj files updated to latest Visual Studio model. (Thanks @tig!) + * Adjusted the default colors for Windows to make more readable. (Thanks @tig!) + * Toplevel.Ready event - Fired once the Toplevel's MainLoop has started (#445). (Thanks @tig!) + * Refactored several events to use event vs. Action. (BREAKING CHANGE) (Thanks @tig!) + * All compile warnings fixed. (Thanks @tig!) + * Fixed a crash in EnsureVisibleBounds. (Thanks @tig!) + * Application.Init/Shutdown are more robust. (Thanks @tig!) + * New "Draw Window Frame" code; consistent across Window, FrameView, and Menu. Fixes many drawing bugs. (Thanks @tig!) + * The project has been refactored an reorganized to reduce risk of bugs and make it easier to contribute #541. (Thanks @tig!) + * Fixes #522 - Last view of Frameview not drawn. (Thanks @tig!) + * Clipping has been fixed/restored - it now works properly. (#586) (Thanks @tig!) + * Added a View.LayoutComplete event (#569). (Thanks @tig!) + * Fixes #299 - MessageBox now auto sizes. (Thanks @tig!) + * Fixes #557 - MessageBoxes on small screens. (Thanks @tig!) + * Fixes #432 - MessageBox does not deal with long text; width/height params are goofy. (Thanks @tig!) + * Fixes #35 - Dialog should have 1 char padding. (Thanks @tig!) + * `MessageBox.Query` called with `width` and `height` == 0 get auto-size behavior. A new constructor is added making this easy to use. (Thanks @tig!) + * Multi-line `MessageBox`es are now supported. Just use `\n` to add lines. The height of the MessageBox will adjust automatically. (Thanks @tig!) + * The `MessageBoxes` Scenario in UI Catalog provides a full demo/test-case. (Thanks @tig!) + * `Dialog` called with `width` and `height` == 0 are sized to 85% container. A new constructor is added making this easy to use. (Thanks @tig!) + * Dialog (and MessageBox `Buttons` are now dynamically laid out using Computed layout. (Thanks @tig!) + * A `Dialogs` Scenario has been added to UI Catalog making it easy to test the API. (Thanks @tig!) + * `Button` now supports BOTH specifying a hotkey with '_' and the old behavior of using the first uppercase char (if '_' is not found). (Thanks @tig!) + * All UI Catalog scenarios that use `Dialog` or `MessageBox` now use the simplified API. (Thanks @tig!) + * `Terminal.Gui.dll` now has version metadata and UI Catalog's about box displays it as a test case. (Thanks @tig!) + * Button, Dialog, and MessageBox API documentation has been updated/revised. (Thanks @tig!) + * `View`, `Window`, `FrameView`, and `Dialog` have been upgraded to use the new `ConsoleDriver.DrawFrameWindow` API directly. (Thanks @tig!) + * New ComboBox control (Thanks @fergusonr!) + * ConsoleDriver now supports improved KeyModifers (shift keys) with an expanded Keys Sceanrio in UI Catalog. (Thanks @bdisp!) + * Tons of mouse handling improvements. (Thanks @bdisp!) + * Fsharp sample updated. (Thanks @bdisp!) + * Fixes #562 - Background drawing issue. (Thanks @bdisp!) + * Fixes #517 - Focus and mouse handlers enahced (BREAKING CHANGE). (Thanks @bdisp!) + * Fixed resizing update and correct Toplevel colors without colors. (Thanks @bdisp!) + * Fixed #515, #518, #536, #540. (Thanks @bdisp!) + * Added Threading Scenario to UI catalog. (Thanks @bdisp!) + * Added support for F11 and F12 keys. (Thanks @bdisp!) + * Multiple improvements to Date/TimeField. (Thanks @bdisp!) + * Fixes #409 - Invoke does not cause Wakeup #501. (Thanks @bdisp!) + * Fixed Label text alignemnt. (Thanks @bdisp!) + * Added mouse features in the Unix version. Supports xterm-1006. (Thanks @bdisp!) + * Several StatusBar fixes. (Thanks @bdisp!) + * Tons of mouse improvements including mouse wheel support (e.g. #404, #409). (Thanks @bdisp!) + * Added a CloseFile method to the TextView as stated in #452. (Thanks @bdisp) + * Added a OpenSelectedItem event to the ListView #429. (Thanks @bdisp!) + * Fixes the return value of the position cursor in the TextField. (Thanks @bdisp!) + * Updates screen on Unix window resizing. (Thanks @bdisp!) + * Fixes the functions of the Edit->Copy-Cut-Paste menu for the TextField that was not working well. (Thanks @bdisp!) + * More robust error handing in Pos/Dim. Fixes #355 stack overflow with Pos based on the size of windows at startup. Added a OnResized action to set the Pos after the terminal are resized. (Thanks @bdisp!) + * Fixes #389 Window layouting breaks when resizing. (Thanks @bdisp!) + * Fixes #557 MessageBox needs to take ustrings (BREAKING CHANGE). (Thanks @tig!) -* Fixes an issue with referencing views that have not been allocated yet causing a stack overflow -* New OnCloseMenu event on menus -* Button cursor position looks better -* Listview in single-selection mode uses a radio-button look -* Fixes a couple of crashes (356) -* Default the samples to work on Catalina + 0.81: + * Fix ncurses engine for macOS/Linux, it works again + * Fixes an issue with referencing views that have not been allocated yet causing a stack overflow + * New OnCloseMenu event on menus + * Button cursor position looks better + * Listview in single-selection mode uses a radio-button look + * Fixes a couple of crashes (356) + * Default the samples to work on Catalina -0.80: Jumbo update from BDisp: + 0.80: Jumbo update from BDisp: -* Fixed key events traversal for modal dialogs -* Fixes culture info of DataField from pr -* Fixes the rectangle drawing issue -* Redraw issue when setting coordinates of label -* Added sub menus into menu bar with mouse and key navigation -* Added Colors.Menu.Disabled to CursesDriver.cs -* Mouse text selection with cut, copy and paste on text fields -* Change sepChar from char to string in DateField -* Adding a disabled menu item in the demo file -* Fixes Button repainting issue when changing the text length to one smaller -* Fixes Redraw issue when setting coordinates of label -* Fixes ScrollView does not render some content -* Fixed bug in Button that caused a loop redraw calling TerminalResized -* Fixes a repaint issue (282) -* Mouse features added to FileDialog including wheel support. -* Switch netcoreapp target to netstandard2.0 -* Added TextView.TextChanged event -* Fixes issue #306 async/await hang (#312) -* Replaced static driver initialization with property getter for reference passing in Core.cs::View class, this allows the library to be reinitialized at any time. -* Made the Shutdown method on Core.cs::Application class public, since there is no reason to keep it private. Applications can shutdown the library and revert the console to the initial stage by calling it. -* Fixed a memory-leak on Drivers/WindowsDriver class by destroying the generated screen buffers at library shutdown by calling CloseHandle. -* Minor change to Core.cs::Application.Init(Func) for better initialization status tracking, via backend property instead of relying on the Top field. -* Moved `ListView.ListWrapper` out of `ListView` migueldeicaza/gui.cs#313` (#315) -* Resizing the MessageBox width to accommodate all message text (#299) -* Timefield format with bounds values (#303) -* Implemented lower and upper bounds to TimeField -* Passing old text to the Changed event handler -* Extract methods on ListView to make it controlable from other controls + * Fixed key events traversal for modal dialogs + * Fixes culture info of DataField from pr + * Fixes the rectangle drawing issue + * Redraw issue when setting coordinates of label + * Added sub menus into menu bar with mouse and key navigation + * Added Colors.Menu.Disabled to CursesDriver.cs + * Mouse text selection with cut, copy and paste on text fields + * Change sepChar from char to string in DateField + * Adding a disabled menu item in the demo file + * Fixes Button repainting issue when changing the text length to one smaller + * Fixes Redraw issue when setting coordinates of label + * Fixes ScrollView does not render some content + * Fixed bug in Button that caused a loop redraw calling TerminalResized + * Fixes a repaint issue (282) + * Mouse features added to FileDialog including wheel support. + * Switch netcoreapp target to netstandard2.0 + * Added TextView.TextChanged event + * Fixes issue #306 async/await hang (#312) + * Replaced static driver initialization with property getter for reference passing in Core.cs::View class, this allows the library to be reinitialized at any time. + * Made the Shutdown method on Core.cs::Application class public, since there is no reason to keep it private. Applications can shutdown the library and revert the console to the initial stage by calling it. + * Fixed a memory-leak on Drivers/WindowsDriver class by destroying the generated screen buffers at library shutdown by calling CloseHandle. + * Minor change to Core.cs::Application.Init(Func) for better initialization status tracking, via backend property instead of relying on the Top field. + * Moved `ListView.ListWrapper` out of `ListView` migueldeicaza/gui.cs#313` (#315) + * Resizing the MessageBox width to accommodate all message text (#299) + * Timefield format with bounds values (#303) + * Implemented lower and upper bounds to TimeField + * Passing old text to the Changed event handler + * Extract methods on ListView to make it controlable from other controls -0.70: Bug fixes (320, 321, 306, 304, 291, 299, 303); Surface ListView.ListWrapper, surface various internal methods for use in ListView; Allow list item selection; ; 0.65: Added new TimeField from Jörg Preiß; Fixes for Backtab by Martin Björkström; ListView now supports simple selection; Bug fixes by giladlevi, Daniel Cazzulino and Marius Ungureanu; New Application.Run of T entry point by Daniel Cazzulino; Added various View methods to bring forward, backwards and move views in the hierarchy; Switch to Portable PDBs by Daniel Cazzulino; Dims can now be compared by Daniel Cazzulino; OnMenuOpen handler by giladlevi; Various memory usage optimizations by giladlevi; FileDialog.FilePath is now a full path by Yanwei Wang; ISupportInitialize/ISupportInitializeNotification is now supported thanks to the work from Daniel Cazzulino; Support for non-modal TopLevels by Daniel Cazzulino and Adrian Alonso; 0.24: the Windows driver implements WakeUp, allowing some scenarios like bug #207 to be fixed; -0.23: Better support for disabled menu items; Raises text changed event after the internals have been updated; Fix Caps-NumLock; Alt-HotKey now work on menus -0.22: Correct vertical scrollview behavior, Small curses driver fix for terminals without mouse support, TextView support for scrolling, Surface Used property on TextField, Surface Cursor on RadioGroup. + 0.70: Bug fixes (320, 321, 306, 304, 291, 299, 303); Surface ListView.ListWrapper, surface various internal methods for use in ListView; Allow list item selection; ; 0.65: Added new TimeField from Jörg Preiß; Fixes for Backtab by Martin Björkström; ListView now supports simple selection; Bug fixes by giladlevi, Daniel Cazzulino and Marius Ungureanu; New Application.Run of T entry point by Daniel Cazzulino; Added various View methods to bring forward, backwards and move views in the hierarchy; Switch to Portable PDBs by Daniel Cazzulino; Dims can now be compared by Daniel Cazzulino; OnMenuOpen handler by giladlevi; Various memory usage optimizations by giladlevi; FileDialog.FilePath is now a full path by Yanwei Wang; ISupportInitialize/ISupportInitializeNotification is now supported thanks to the work from Daniel Cazzulino; Support for non-modal TopLevels by Daniel Cazzulino and Adrian Alonso; 0.24: the Windows driver implements WakeUp, allowing some scenarios like bug #207 to be fixed; + 0.23: Better support for disabled menu items; Raises text changed event after the internals have been updated; Fix Caps-NumLock; Alt-HotKey now work on menus + 0.22: Correct vertical scrollview behavior, Small curses driver fix for terminals without mouse support, TextView support for scrolling, Surface Used property on TextField, Surface Cursor on RadioGroup. -0.21: Introudce Attribute.Make to more easily create attributes, and fix a bug in the file panel. -0.20: Expose some of the CursesDriver APIs -0.19: PageUpDown updates (GaikwadPratik); Fixes in multi-line labels (hlfrye@gmail.com); Support Delete char in TextView (Greg Amidon); Prevent empty TextViews from crashing; Allow TextFields to be updated on the Changed event. -0.18: Fixes hotkeys for menus (Sang Kil); Fixes RemoveAll for all containers; Allows Toplevels with no views; Fixes FileDialog layout; Prevent crash in TextView -0.17: Unix, dynamically load ncurses library to support different configurations, and not require -dev on Linux, various bug fixes. + 0.21: Introudce Attribute.Make to more easily create attributes, and fix a bug in the file panel. + 0.20: Expose some of the CursesDriver APIs + 0.19: PageUpDown updates (GaikwadPratik); Fixes in multi-line labels (hlfrye@gmail.com); Support Delete char in TextView (Greg Amidon); Prevent empty TextViews from crashing; Allow TextFields to be updated on the Changed event. + 0.18: Fixes hotkeys for menus (Sang Kil); Fixes RemoveAll for all containers; Allows Toplevels with no views; Fixes FileDialog layout; Prevent crash in TextView + 0.17: Unix, dynamically load ncurses library to support different configurations, and not require -dev on Linux, various bug fixes. -0.16: Support for Shift-Tab on Windows (fix by @mholo65) + 0.16: Support for Shift-Tab on Windows (fix by @mholo65) -0.15: WindowsDriver fix for Legacy Console keyboard input (issue #105) + 0.15: WindowsDriver fix for Legacy Console keyboard input (issue #105) -0.14: WindowsDriver fix for EventType size. + 0.14: WindowsDriver fix for EventType size. -0.13: Fixes keyboard input for Alt-Gr and numbers. + 0.13: Fixes keyboard input for Alt-Gr and numbers. -0.12: Fixes the text editor merge line command. + 0.12: Fixes the text editor merge line command. -0.11: Simplify TextField implementation, fixes a couple of editing bugs. + 0.11: Simplify TextField implementation, fixes a couple of editing bugs. -0.10: Fix unicode rendering for TextField, and bring F# example + 0.10: Fix unicode rendering for TextField, and bring F# example -0.9: File Open/File Save dialogs, HexView, Windows Driver allows resizing, mouse events, faster (thanks to Nick Van Dyck, nickvdyck for the contribution!), smaller bug fixes, + 0.9: File Open/File Save dialogs, HexView, Windows Driver allows resizing, mouse events, faster (thanks to Nick Van Dyck, nickvdyck for the contribution!), smaller bug fixes, -0.8: Completes keyboard support on Windows; Fixes delete on Windows, some layout fixes. -0.7: terminal resizing on Linux propagates sizes with new layout system, and new features on the layout system (documented) -0.6: new layout system, multi-line textview editor, Linux bug fix for .NET Core -0.5: support Linux with .NET Core, Windows driver fixes. -0.4: hotkey handling fix for RadioButtons -0.3: Fix Windows key input to not echo characters on console, proper Fkey mapping -0.2: Auto-detect the best console + 0.8: Completes keyboard support on Windows; Fixes delete on Windows, some layout fixes. + 0.7: terminal resizing on Linux propagates sizes with new layout system, and new features on the layout system (documented) + 0.6: new layout system, multi-line textview editor, Linux bug fix for .NET Core + 0.5: support Linux with .NET Core, Windows driver fixes. + 0.4: hotkey handling fix for RadioButtons + 0.3: Fix Windows key input to not echo characters on console, proper Fkey mapping + 0.2: Auto-detect the best console + diff --git a/Terminal.Gui/Views/Button.cs b/Terminal.Gui/Views/Button.cs index 54298d093..eaf56b62f 100644 --- a/Terminal.Gui/Views/Button.cs +++ b/Terminal.Gui/Views/Button.cs @@ -55,29 +55,32 @@ namespace Terminal.Gui { public Action Clicked; /// - /// Initializes a new instance of based on the given text at position 0,0 + /// Initializes a new instance of using layout. /// /// - /// The size of the is computed based on the - /// text length. + /// The width of the is computed based on the + /// text length. The height will always be 1. /// /// The button's text - /// If set, this makes the button the default button in the current view. + /// + /// If true, a special decoration is used, and the user pressing the enter key + /// in a will implicitly activate this button. + /// public Button (ustring text, bool is_default = false) : base () { CanFocus = true; Text = text ?? string.Empty; this.IsDefault = is_default; int w = SetWidthHeight (text, is_default); - Frame = new Rect (0, 0, w, 1); + Frame = new Rect (Frame.Location, new Size (w, 1)); } /// - /// Initializes a new instance of at the given coordinates, based on the given text + /// Initializes a new instance of using layout, based on the given text /// /// - /// The size of the is computed based on the - /// text length. + /// The width of the is computed based on the + /// text length. The height will always be 1. /// /// X position where the button will be shown. /// Y position where the button will be shown. @@ -85,17 +88,19 @@ namespace Terminal.Gui { public Button (int x, int y, ustring text) : this (x, y, text, false) { } /// - /// Initializes a new instance of at the given coordinates, based on the given text, and with the specified value + /// Initializes a new instance of using layout, based on the given text. /// /// - /// If the value for is_default is true, a special - /// decoration is used, and the enter key on a - /// dialog would implicitly activate this button. + /// The width of the is computed based on the + /// text length. The height will always be 1. /// /// X position where the button will be shown. /// Y position where the button will be shown. /// The button's text - /// If set, this makes the button the default button in the current view, which means that if the user presses return on a view that does not handle return, it will be treated as if he had clicked on the button + /// + /// If true, a special decoration is used, and the user pressing the enter key + /// in a will implicitly activate this button. + /// public Button (int x, int y, ustring text, bool is_default) : base (new Rect (x, y, text.Length + 4 + (is_default ? 2 : 0), 1)) { @@ -110,6 +115,7 @@ namespace Terminal.Gui { int w = text.Length + 4 + (is_default ? 2 : 0); Width = w; Height = 1; + Frame = new Rect (Frame.Location, new Size (w, 1)); return w; } @@ -137,22 +143,32 @@ namespace Terminal.Gui { else shown_text = "[ " + text + " ]"; - hot_pos = -1; hot_key = (Rune)0; - int i = 0; - foreach (Rune c in shown_text) { - if (Rune.IsUpper (c)) { - hot_key = c; - hot_pos = i; - break; + hot_pos = shown_text.IndexOf ('_'); + + if (hot_pos == -1) { + // Use first upper-case char + int i = 0; + foreach (Rune c in shown_text) { + if (Rune.IsUpper (c)) { + hot_key = c; + hot_pos = i; + break; + } + i++; } - i++; + } else { + // Use char after '_' + var start = shown_text [0, hot_pos]; + shown_text = start + shown_text [hot_pos + 1, shown_text.Length]; + hot_key = Char.ToUpper((char)shown_text [hot_pos]); } + SetNeedsDisplay (); } /// - public override void Redraw (Rect region) + public override void Redraw (Rect bounds) { Driver.SetAttribute (HasFocus ? ColorScheme.Focus : ColorScheme.Normal); Move (0, 0); @@ -214,7 +230,7 @@ namespace Terminal.Gui { } /// - public override bool MouseEvent(MouseEvent me) + public override bool MouseEvent (MouseEvent me) { if (me.Flags == MouseFlags.Button1Clicked) { SuperView.SetFocus (this); diff --git a/Terminal.Gui/Views/Checkbox.cs b/Terminal.Gui/Views/Checkbox.cs index 056846b40..57421db73 100644 --- a/Terminal.Gui/Views/Checkbox.cs +++ b/Terminal.Gui/Views/Checkbox.cs @@ -98,7 +98,7 @@ namespace Terminal.Gui { } /// - public override void Redraw (Rect region) + public override void Redraw (Rect bounds) { Driver.SetAttribute (HasFocus ? ColorScheme.Focus : ColorScheme.Normal); Move (0, 0); diff --git a/Terminal.Gui/Views/ComboBox.cs b/Terminal.Gui/Views/ComboBox.cs index e5ff53dce..a89879f8d 100644 --- a/Terminal.Gui/Views/ComboBox.cs +++ b/Terminal.Gui/Views/ComboBox.cs @@ -58,7 +58,7 @@ namespace Terminal.Gui { SetValue (searchset [listview.SelectedItem]); }; - Application.Loaded += (object sender, Application.ResizedEventArgs e) => { + LayoutComplete += (sender, a) => { // Determine if this view is hosted inside a dialog for (View view = this.SuperView; view != null; view = view.SuperView) { if (view is Dialog) { diff --git a/Terminal.Gui/Views/FrameView.cs b/Terminal.Gui/Views/FrameView.cs index a08646ba0..b2d44bb57 100644 --- a/Terminal.Gui/Views/FrameView.cs +++ b/Terminal.Gui/Views/FrameView.cs @@ -136,23 +136,20 @@ namespace Terminal.Gui { { var padding = 0; Application.CurrentView = this; - var scrRect = RectToScreen (new Rect (0, 0, Frame.Width, Frame.Height)); + var scrRect = ViewToScreen (new Rect (0, 0, Frame.Width, Frame.Height)); if (NeedDisplay != null && !NeedDisplay.IsEmpty) { Driver.SetAttribute (ColorScheme.Normal); - Driver.DrawFrame (scrRect, padding, true); + Driver.DrawWindowFrame (scrRect, padding + 1, padding + 1, padding + 1, padding + 1, border: true, fill: true); } - if (Driver.Clip.IsEmpty || Driver.Clip.Contains (contentView.RectToScreen (contentView.Frame))) { - var savedClip = ClipToBounds (); - contentView.Redraw (contentView.Bounds); - Driver.Clip = savedClip; - } else { - contentView.Redraw (contentView.Bounds); - } + var savedClip = ClipToBounds (); + contentView.Redraw (contentView.Bounds); + Driver.Clip = savedClip; + ClearNeedsDisplay (); Driver.SetAttribute (ColorScheme.Normal); - Driver.DrawFrame (scrRect, padding, false); + Driver.DrawWindowFrame (scrRect, padding + 1, padding + 1, padding + 1, padding + 1, border: true, fill: false); if (HasFocus) Driver.SetAttribute (ColorScheme.HotNormal); diff --git a/Terminal.Gui/Views/HexView.cs b/Terminal.Gui/Views/HexView.cs index 08609731b..45ece2349 100644 --- a/Terminal.Gui/Views/HexView.cs +++ b/Terminal.Gui/Views/HexView.cs @@ -130,7 +130,7 @@ namespace Terminal.Gui { } /// - public override void Redraw (Rect region) + public override void Redraw (Rect bounds) { Attribute currentAttribute; var current = ColorScheme.Focus; @@ -149,7 +149,7 @@ namespace Terminal.Gui { for (int line = 0; line < frame.Height; line++) { var lineRect = new Rect (0, line, frame.Width, 1); - if (!region.Contains (lineRect)) + if (!bounds.Contains (lineRect)) continue; Move (0, line); diff --git a/Terminal.Gui/Views/Label.cs b/Terminal.Gui/Views/Label.cs index b1d2a575a..af56003c2 100644 --- a/Terminal.Gui/Views/Label.cs +++ b/Terminal.Gui/Views/Label.cs @@ -99,6 +99,8 @@ namespace Terminal.Gui { static ustring ClipAndJustify (ustring str, int width, TextAlignment talign) { + // Get rid of any '\r' added by Windows + str = str.Replace ("\r", ustring.Empty); int slen = str.RuneCount; if (slen > width){ var uints = str.ToRunes (width); @@ -161,7 +163,7 @@ namespace Terminal.Gui { } /// - public override void Redraw (Rect region) + public override void Redraw (Rect bounds) { if (recalcPending) Recalc (); @@ -173,7 +175,7 @@ namespace Terminal.Gui { Clear (); for (int line = 0; line < lines.Count; line++) { - if (line < region.Top || line > region.Bottom) + if (line < bounds.Top || line > bounds.Bottom) continue; var str = lines [line]; int x; diff --git a/Terminal.Gui/Views/ListView.cs b/Terminal.Gui/Views/ListView.cs index c325485cb..44ec32f20 100644 --- a/Terminal.Gui/Views/ListView.cs +++ b/Terminal.Gui/Views/ListView.cs @@ -272,7 +272,7 @@ namespace Terminal.Gui { } /// - public override void Redraw (Rect region) + public override void Redraw (Rect bounds) { var current = ColorScheme.Focus; Driver.SetAttribute (current); diff --git a/Terminal.Gui/Views/Menu.cs b/Terminal.Gui/Views/Menu.cs index 5f25cb797..5c5de6c8f 100644 --- a/Terminal.Gui/Views/Menu.cs +++ b/Terminal.Gui/Views/Menu.cs @@ -276,10 +276,10 @@ namespace Terminal.Gui { return ColorScheme.Normal; } - public override void Redraw (Rect region) + public override void Redraw (Rect bounds) { Driver.SetAttribute (ColorScheme.Normal); - DrawFrame (region, padding: 0, fill: true); + DrawFrame (bounds, padding: 0, fill: true); for (int i = 0; i < barItems.Children.Length; i++) { var item = barItems.Children [i]; @@ -624,7 +624,7 @@ namespace Terminal.Gui { } /// - public override void Redraw (Rect region) + public override void Redraw (Rect bounds) { Move (0, 0); Driver.SetAttribute (Colors.Menu.Normal); diff --git a/Terminal.Gui/Views/RadioGroup.cs b/Terminal.Gui/Views/RadioGroup.cs index c86ea2259..d3cf2e659 100644 --- a/Terminal.Gui/Views/RadioGroup.cs +++ b/Terminal.Gui/Views/RadioGroup.cs @@ -108,7 +108,7 @@ namespace Terminal.Gui { } /// - public override void Redraw (Rect region) + public override void Redraw (Rect bounds) { for (int i = 0; i < radioLabels.Length; i++) { Move (0, i); @@ -116,7 +116,7 @@ namespace Terminal.Gui { Driver.AddStr (i == selected ? "(o) " : "( ) "); DrawHotString (radioLabels [i], HasFocus && i == cursor, ColorScheme); } - base.Redraw (region); + base.Redraw (bounds); } /// diff --git a/Terminal.Gui/Views/ScrollView.cs b/Terminal.Gui/Views/ScrollView.cs index 0d1358784..2e9c8e74d 100644 --- a/Terminal.Gui/Views/ScrollView.cs +++ b/Terminal.Gui/Views/ScrollView.cs @@ -400,7 +400,6 @@ namespace Terminal.Gui { /// This event is raised when the contents have scrolled /// //public event Action Scrolled; - public override void Redraw(Rect region) { SetViewsNeedsDisplay (); @@ -409,6 +408,8 @@ namespace Terminal.Gui { var savedClip = ClipToBounds (); contentView.Redraw (contentView.Bounds); + Driver.Clip = savedClip; + vertical.Redraw (vertical.Bounds); horizontal.Redraw (horizontal.Bounds); Driver.Clip = savedClip; diff --git a/Terminal.Gui/Views/StatusBar.cs b/Terminal.Gui/Views/StatusBar.cs index 70618f228..1fd3448d6 100644 --- a/Terminal.Gui/Views/StatusBar.cs +++ b/Terminal.Gui/Views/StatusBar.cs @@ -120,7 +120,7 @@ namespace Terminal.Gui { Width = Dim.Fill (); Height = 1; - Application.Loaded += (sender, e) => { + LayoutComplete += (sender, e) => { X = 0; Height = 1; #if SNAP_TO_TOP @@ -132,7 +132,7 @@ namespace Terminal.Gui { case StatusBarStyle.SnapToBottom: #endif if (Parent == null) { - Y = e.Rows - 1; + Y = Driver.Rows - 1; } else { Y = Pos.Bottom (Parent); } @@ -151,7 +151,7 @@ namespace Terminal.Gui { } /// - public override void Redraw (Rect region) + public override void Redraw (Rect bounds) { //if (Frame.Y != Driver.Rows - 1) { // Frame = new Rect (Frame.X, Driver.Rows - 1, Frame.Width, Frame.Height); diff --git a/Terminal.Gui/Views/TextField.cs b/Terminal.Gui/Views/TextField.cs index 79e3b2400..afd94d408 100644 --- a/Terminal.Gui/Views/TextField.cs +++ b/Terminal.Gui/Views/TextField.cs @@ -184,7 +184,7 @@ namespace Terminal.Gui { } /// - public override void Redraw (Rect region) + public override void Redraw (Rect bounds) { ColorScheme color = Colors.Menu; SetSelectedStartSelectedLength (); diff --git a/Terminal.Gui/Views/TextView.cs b/Terminal.Gui/Views/TextView.cs index 6c5baedac..a6d782fe4 100644 --- a/Terminal.Gui/Views/TextView.cs +++ b/Terminal.Gui/Views/TextView.cs @@ -525,31 +525,31 @@ namespace Terminal.Gui { } /// - public override void Redraw (Rect region) + public override void Redraw (Rect bounds) { ColorNormal (); - int bottom = region.Bottom; - int right = region.Right; - for (int row = region.Top; row < bottom; row++) + int bottom = bounds.Bottom; + int right = bounds.Right; + for (int row = bounds.Top; row < bottom; row++) { int textLine = topRow + row; if (textLine >= model.Count) { ColorNormal (); - ClearRegion (region.Left, row, region.Right, row + 1); + ClearRegion (bounds.Left, row, bounds.Right, row + 1); continue; } var line = model.GetLine (textLine); int lineRuneCount = line.Count; - if (line.Count < region.Left) + if (line.Count < bounds.Left) { - ClearRegion (region.Left, row, region.Right, row + 1); + ClearRegion (bounds.Left, row, bounds.Right, row + 1); continue; } - Move (region.Left, row); - for (int col = region.Left; col < right; col++) + Move (bounds.Left, row); + for (int col = bounds.Left; col < right; col++) { var lineCol = leftColumn + col; var rune = lineCol >= lineRuneCount ? ' ' : line [lineCol]; diff --git a/Terminal.Gui/Windows/Dialog.cs b/Terminal.Gui/Windows/Dialog.cs index 82d696d73..1455ebacd 100644 --- a/Terminal.Gui/Windows/Dialog.cs +++ b/Terminal.Gui/Windows/Dialog.cs @@ -4,15 +4,15 @@ // Authors: // Miguel de Icaza (miguel@gnome.org) // - using System; using System.Collections.Generic; +using System.Linq; using NStack; namespace Terminal.Gui { /// /// The is a that by default is centered and contains one - /// or more . It defaults to the color scheme and has a 1 cell padding around the edges. + /// or more s. It defaults to the color scheme and has a 1 cell padding around the edges. /// /// /// To run the modally, create the , and pass it to . @@ -21,21 +21,37 @@ namespace Terminal.Gui { /// public class Dialog : Window { List