123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- using NStack;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Xml.Linq;
- using Terminal.Gui.Graphs;
- namespace Terminal.Gui {
- public class Frame : View {
- /// <summary>
- /// Frames are a special form of <see cref="View"/> that act as adornments; they appear outside of the <see cref="View>Bounds"/>
- /// eanbling borders, menus, etc...
- /// </summary>
- public Frame ()
- {
- IgnoreBorderPropertyOnRedraw = true;
- }
- /// <summary>
- /// The Parent of this Frame (Adornment).
- /// </summary>
- public View Parent { get; set; }
- /// <summary>
- /// Frames cannot be used as sub-views, so this method always throws an <see cref="InvalidOperationException"/>.
- /// TODO: Are we sure?
- /// </summary>
- public override View SuperView {
- get {
- return null;
- }
- set {
- throw new NotImplementedException ();
- }
- }
- /// <inheritdoc/>
- public override void ViewToScreen (int col, int row, out int rcol, out int rrow, bool clipped = true)
- {
- // Frames are children of a View, not SubViews. Thus ViewToScreen will not work.
- // To get the screen-relative coordinates of a Frame, we need to know who
- // the Parent is
- // Computes the real row, col relative to the screen.
- var inner = Parent?.Bounds ?? Bounds;
- rrow = row - inner.Y;
- rcol = col - inner.X;
- Parent?.ViewToScreen (rcol, rrow, out rcol, out rrow, clipped);
- }
- public virtual void OnDrawSubViews (Rect clipRect)
- {
- // if (Subviews == null) {
- // return;
- // }
- // foreach (var view in Subviews) {
- // // BUGBUG: v2 - shouldn't this be !view.LayoutNeeded? Why draw if layout is going to happen and we'll just draw again?
- // if (view.LayoutNeeded) {
- // view.LayoutSubviews ();
- // }
- // if ((view.Visible && !view.NeedDisplay.IsEmpty && view.Frame.Width > 0 && view.Frame.Height > 0) || view.ChildNeedsDisplay) {
- // view.Redraw (view.Bounds);
- // view.NeedDisplay = Rect.Empty;
- // // BUGBUG - v2 why does this need to be set to false?
- // // Shouldn't it be set when the subviews draw?
- // view.ChildNeedsDisplay = false;
- // }
- // }
- }
- public override void OnDrawContent (Rect viewport)
- {
- if (!ustring.IsNullOrEmpty (TextFormatter.Text)) {
- Clear (viewport);
- SetChildNeedsDisplay ();
- // Draw any Text
- if (TextFormatter != null) {
- TextFormatter.NeedsFormat = true;
- Rect containerBounds = GetContainerBounds ();
- TextFormatter?.Draw (ViewToScreen (viewport), HasFocus ? ColorScheme.Focus : GetNormalColor (),
- HasFocus ? ColorScheme.HotFocus : Enabled ? ColorScheme.HotNormal : ColorScheme.Disabled,
- containerBounds);
- }
- }
- }
- /// <summary>
- /// Redraws the Frames that comprise the <see cref="Frame"/>.
- /// </summary>
- /// <param name="clipRect"></param>
- public override void Redraw (Rect clipRect)
- {
- //OnDrawContent (bounds);
- //OnDrawSubViews (bounds);
- //OnDrawContentComplete (bounds);
- if (ColorScheme != null) {
- Driver.SetAttribute (ColorScheme.Normal);
- }
- var screenBounds = ViewToScreen (Frame);
- Thickness.Draw (screenBounds, (string)Data);
- //OnDrawContent (bounds);
- if (BorderStyle != BorderStyle.None) {
- var lc = new LineCanvas ();
- lc.AddLine (screenBounds.Location, Frame.Width - 1, Orientation.Horizontal, BorderStyle);
- lc.AddLine (screenBounds.Location, Frame.Height - 1, Orientation.Vertical, BorderStyle);
- lc.AddLine (new Point (screenBounds.X, screenBounds.Y + screenBounds.Height - 1), screenBounds.Width - 1, Orientation.Horizontal, BorderStyle);
- lc.AddLine (new Point (screenBounds.X + screenBounds.Width - 1, screenBounds.Y), screenBounds.Height - 1, Orientation.Vertical, BorderStyle);
- foreach (var p in lc.GenerateImage (screenBounds)) {
- Driver.Move (p.Key.X, p.Key.Y);
- Driver.AddRune (p.Value);
- }
- if (!ustring.IsNullOrEmpty (Title)) {
- Driver.DrawWindowTitle (screenBounds, Title, 0, 0, 0, 0);
- }
- }
- }
- //public Label DiagnosticsLabel { get; set; }
- // TODO: v2 = This is teporary; need to also enable (or not) simple way of setting
- // other border properties
- // TOOD: v2 - Missing 3D effect
- public BorderStyle BorderStyle { get; set; } = BorderStyle.None;
- public Thickness Thickness { get; set; }
- // TODO: v2 - This is confusing. It is a read-only property and actually only returns a size, so
- // should not be a Rect. However, it may make sense to keep it a Rect and support negative Location
- // for scrolling. Still noodling this.
- /// <summary>
- /// Gets the rectangle that describes the inner area of the frame. The Location is always 0, 0.
- /// </summary>
- public Rect Bounds {
- get {
- if (Thickness != null) {
- new Rect (Point.Empty, Frame.Size);
- }
- // Return the frame-relative bounds
- return Thickness.GetInnerRect (new Rect (Point.Empty, Frame.Size));
- }
- set {
- throw new InvalidOperationException ("It makes no sense to explicitly set Bounds.");
- }
- }
- //public override void OnDrawContent (Rect viewport)
- //{
- // // do nothing
- //}
- //public override void Redraw (Rect bounds)
- //{
- // if (ColorScheme != null) {
- // Driver.SetAttribute (HasFocus ? ColorScheme.Focus : ColorScheme.Normal);
- // }
- // //if (Text != null) {
- // // Thickness?.Draw (Frame, $"{Text} {DiagnosticsLabel?.Text}");
- // //}
- // if (BorderStyle != BorderStyle.None) {
- // var lc = new LineCanvas ();
- // lc.AddLine (Frame.Location, Frame.Width - 1, Orientation.Horizontal, BorderStyle);
- // lc.AddLine (Frame.Location, Frame.Height - 1, Orientation.Vertical, BorderStyle);
- // lc.AddLine (new Point (Frame.X, Frame.Y + Frame.Height - 1), Frame.Width - 1, Orientation.Horizontal, BorderStyle);
- // lc.AddLine (new Point (Frame.X + Frame.Width - 1, Frame.Y), Frame.Height - 1, Orientation.Vertical, BorderStyle);
- // foreach (var p in lc.GenerateImage (Frame)) {
- // Driver.Move (p.Key.X, p.Key.Y);
- // Driver.AddRune (p.Value);
- // }
- // if (!ustring.IsNullOrEmpty (Title)) {
- // Driver.DrawWindowTitle (Frame, Title, 0, 0, 0, 0);
- // }
- // }
- // base.Redraw (bounds);
- //}
- }
- }
|