Kaynağa Gözat

Fixes #2883. ProgressBar: 'Frame.DrawFrame(Rect, bool)' is obsolete: 'This method is obsolete in v2. Use use LineCanvas or Frame (#2979)

* Fixes #2883. ProgressBar: 'Frame.DrawFrame(Rect, bool)' is obsolete: 'This method is obsolete in v2. Use use LineCanvas or Frame

* Refactored ProgressBar to use Frames correctly

* Hacked other FramesEditor scenarios to work... needs to be done more cleanly

* Prevents for null state.

* re-added my changs

* Fixed unit tests

* Fixed unit tests2

* Commit to run CI test again.

---------

Co-authored-by: Tig <[email protected]>
Co-authored-by: Tig Kindel <[email protected]>
BDisp 1 yıl önce
ebeveyn
işleme
d2967c1ede

+ 218 - 326
Terminal.Gui/Views/ProgressBar.cs

@@ -1,381 +1,273 @@
 using System.Text;
 using System;
-namespace Terminal.Gui {
+
+namespace Terminal.Gui;
+/// <summary>
+/// Specifies the style that a <see cref="ProgressBar"/> uses to indicate the progress of an operation.
+/// </summary>
+public enum ProgressBarStyle {
 	/// <summary>
-	/// Specifies the style that a <see cref="ProgressBar"/> uses to indicate the progress of an operation.
+	/// Indicates progress by increasing the number of segmented blocks in a <see cref="ProgressBar"/>.
 	/// </summary>
-	public enum ProgressBarStyle {
-		/// <summary>
-		/// Indicates progress by increasing the number of segmented blocks in a <see cref="ProgressBar"/>.
-		/// </summary>
-		Blocks,
-		/// <summary>
-		/// Indicates progress by increasing the size of a smooth, continuous bar in a <see cref="ProgressBar"/>.
-		/// </summary>
-		Continuous,
-		/// <summary>
-		/// Indicates progress by continuously scrolling a block across a <see cref="ProgressBar"/> in a marquee fashion.
-		/// </summary>
-		MarqueeBlocks,
-		/// <summary>
-		/// Indicates progress by continuously scrolling a block across a <see cref="ProgressBar"/> in a marquee fashion.
-		/// </summary>
-		MarqueeContinuous
-
-	}
-
+	Blocks,
 	/// <summary>
-	///Specifies the format that a <see cref="ProgressBar"/> uses to indicate the visual presentation.
+	/// Indicates progress by increasing the size of a smooth, continuous bar in a <see cref="ProgressBar"/>.
 	/// </summary>
-	public enum ProgressBarFormat {
-		/// <summary>
-		/// A simple visual presentation showing only the progress bar.
-		/// </summary>
-		Simple,
-		/// <summary>
-		/// A simple visual presentation showing the progress bar and the percentage.
-		/// </summary>
-		SimplePlusPercentage,
-		/// <summary>
-		/// A framed visual presentation showing only the progress bar.
-		/// </summary>
-		Framed,
-		/// <summary>
-		/// A framed visual presentation showing the progress bar and the percentage.
-		/// </summary>
-		FramedPlusPercentage,
-		/// <summary>
-		/// A framed visual presentation showing all with the progress bar padded.
-		/// </summary>
-		FramedProgressPadded
-	}
-
+	Continuous,
 	/// <summary>
-	/// A Progress Bar view that can indicate progress of an activity visually.
+	/// Indicates progress by continuously scrolling a block across a <see cref="ProgressBar"/> in a marquee fashion.
 	/// </summary>
-	/// <remarks>
-	///   <para>
-	///     <see cref="ProgressBar"/> can operate in two modes, percentage mode, or
-	///     activity mode.  The progress bar starts in percentage mode and
-	///     setting the Fraction property will reflect on the UI the progress 
-	///     made so far.   Activity mode is used when the application has no 
-	///     way of knowing how much time is left, and is started when the <see cref="Pulse"/> method is called.  
-	///     Call <see cref="Pulse"/> repeatedly as progress is made.
-	///   </para>
-	/// </remarks>
-	public class ProgressBar : View {
-		bool isActivity;
-		int [] activityPos;
-		int delta, padding;
-
-		/// <summary>
-		/// Initializes a new instance of the <see cref="ProgressBar"/> class, starts in percentage mode with an absolute position and size.
-		/// </summary>
-		/// <param name="rect">Rect.</param>
-		public ProgressBar (Rect rect) : base (rect)
-		{
-			Initialize (rect);
-		}
-
-		/// <summary>
-		/// Initializes a new instance of the <see cref="ProgressBar"/> class, starts in percentage mode and uses relative layout.
-		/// </summary>
-		public ProgressBar () : base ()
-		{
-			Initialize (Rect.Empty);
-		}
-
-		void Initialize (Rect rect)
-		{
-			CanFocus = false;
-			fraction = 0;
-			ColorScheme = new ColorScheme () {
-				Normal = new Attribute (Color.BrightGreen, Color.Gray),
-				HotNormal = Colors.Base.Normal
-			};
-			if (rect.IsEmpty) {
-				Height = 1;
-			}
-		}
-
-		float fraction;
+	MarqueeBlocks,
+	/// <summary>
+	/// Indicates progress by continuously scrolling a block across a <see cref="ProgressBar"/> in a marquee fashion.
+	/// </summary>
+	MarqueeContinuous
+}
 
-		/// <summary>
-		/// Gets or sets the <see cref="ProgressBar"/> fraction to display, must be a value between 0 and 1.
-		/// </summary>
-		/// <value>The fraction representing the progress.</value>
-		public float Fraction {
-			get => fraction;
-			set {
-				fraction = Math.Min (value, 1);
-				isActivity = false;
-				SetNeedsDisplay ();
-			}
-		}
+/// <summary>
+///Specifies the format that a <see cref="ProgressBar"/> uses to indicate the visual presentation.
+/// </summary>
+public enum ProgressBarFormat {
+	/// <summary>
+	/// A simple visual presentation showing only the progress bar.
+	/// </summary>
+	Simple,
+	/// <summary>
+	/// A simple visual presentation showing the progress bar overlaid with the percentage.
+	/// </summary>
+	SimplePlusPercentage,
+}
 
-		ProgressBarStyle progressBarStyle;
+/// <summary>
+/// A Progress Bar view that can indicate progress of an activity visually.
+/// </summary>
+/// <remarks>
+///   <para>
+///     <see cref="ProgressBar"/> can operate in two modes, percentage mode, or
+///     activity mode. The progress bar starts in percentage mode and
+///     setting the Fraction property will reflect on the UI the progress 
+///     made so far. Activity mode is used when the application has no 
+///     way of knowing how much time is left, and is started when the <see cref="Pulse"/> method is called.  
+///     Call <see cref="Pulse"/> repeatedly as progress is made.
+///   </para>
+/// </remarks>
+public class ProgressBar : View {
+	bool _isActivity;
+	int [] _activityPos;
+	int _delta;
 
-		/// <summary>
-		/// Gets/Sets the progress bar style based on the <see cref="Terminal.Gui.ProgressBarStyle"/>
-		/// </summary>
-		public ProgressBarStyle ProgressBarStyle {
-			get => progressBarStyle;
-			set {
-				progressBarStyle = value;
-				switch (value) {
-				case ProgressBarStyle.Blocks:
-					SegmentCharacter = CM.Glyphs.BlocksMeterSegment;
-					break;
-				case ProgressBarStyle.Continuous:
-					SegmentCharacter = CM.Glyphs.ContinuousMeterSegment;
-					break;
-				case ProgressBarStyle.MarqueeBlocks:
-					SegmentCharacter = CM.Glyphs.BlocksMeterSegment;
-					break;
-				case ProgressBarStyle.MarqueeContinuous:
-					SegmentCharacter = CM.Glyphs.ContinuousMeterSegment;
-					break;
-				}
-				SetNeedsDisplay ();
-			}
-		}
+	/// <summary>
+	/// Initializes a new instance of the <see cref="ProgressBar"/> class, starts in percentage mode and uses relative layout.
+	/// </summary>
+	public ProgressBar ()
+	{
+		SetInitialProperties ();
+	}
 
-		private ProgressBarFormat progressBarFormat;
+	void SetInitialProperties ()
+	{
+		Height = 1; // This will be updated when Bounds is updated in ProgressBar_LayoutStarted
+		CanFocus = false;
+		_fraction = 0;
+		LayoutStarted += ProgressBar_LayoutStarted;
+		Initialized += ProgressBar_Initialized;
+	}
 
-		/// <summary>
-		/// Specifies the format that a <see cref="ProgressBar"/> uses to indicate the visual presentation.
-		/// </summary>
-		public ProgressBarFormat ProgressBarFormat {
-			get => progressBarFormat;
-			set {
-				progressBarFormat = value;
-				switch (progressBarFormat) {
-				case ProgressBarFormat.Simple:
-					Height = 1;
-					break;
-				case ProgressBarFormat.SimplePlusPercentage:
-					Height = 2;
-					break;
-				case ProgressBarFormat.Framed:
-					Height = 3;
-					break;
-				case ProgressBarFormat.FramedPlusPercentage:
-					Height = 4;
-					break;
-				case ProgressBarFormat.FramedProgressPadded:
-					Height = 6;
-					break;
-				}
-				SetNeedsDisplay ();
-			}
-		}
+	void ProgressBar_Initialized (object sender, EventArgs e)
+	{
+		ColorScheme = new ColorScheme (ColorScheme ?? SuperView?.ColorScheme ?? Colors.ColorSchemes ["Base"]) {
+			HotNormal = new Attribute (Color.BrightGreen, Color.Gray)
+		};
+	}
 
-		private Rune segmentCharacter = CM.Glyphs.BlocksMeterSegment;
+	void ProgressBar_LayoutStarted (object sender, EventArgs e)
+	{
+		Bounds = new Rect (Bounds.Location, new Size (Bounds.Width, 1));
+	}
 
-		/// <summary>
-		/// Segment indicator for meter views.
-		/// </summary>
-		public Rune SegmentCharacter {
-			get => segmentCharacter;
-			set {
-				segmentCharacter = value;
-				SetNeedsDisplay ();
-			}
-		}
+	float _fraction;
 
-		///<inheritdoc/>
-		public override string Text {
-			get => GetPercentageText ();
-			set {
-				base.Text = SetPercentageText (value);
-			}
+	/// <summary>
+	/// Gets or sets the <see cref="ProgressBar"/> fraction to display, must be a value between 0 and 1.
+	/// </summary>
+	/// <value>The fraction representing the progress.</value>
+	public float Fraction {
+		get => _fraction;
+		set {
+			_fraction = Math.Min (value, 1);
+			_isActivity = false;
+			SetNeedsDisplay ();
 		}
+	}
 
-		private bool bidirectionalMarquee = true;
+	ProgressBarStyle _progressBarStyle;
 
-		/// <summary>
-		/// Specifies if the <see cref="ProgressBarStyle.MarqueeBlocks"/> or the
-		///  <see cref="ProgressBarStyle.MarqueeContinuous"/> styles is unidirectional
-		///  or bidirectional.
-		/// </summary>
-		public bool BidirectionalMarquee {
-			get => bidirectionalMarquee;
-			set {
-				bidirectionalMarquee = value;
-				SetNeedsDisplay ();
-			}
-		}
-
-		string GetPercentageText ()
-		{
-			switch (progressBarStyle) {
+	/// <summary>
+	/// Gets/Sets the progress bar style based on the <see cref="Terminal.Gui.ProgressBarStyle"/>
+	/// </summary>
+	public ProgressBarStyle ProgressBarStyle {
+		get => _progressBarStyle;
+		set {
+			_progressBarStyle = value;
+			switch (value) {
 			case ProgressBarStyle.Blocks:
+				SegmentCharacter = CM.Glyphs.BlocksMeterSegment;
+				break;
 			case ProgressBarStyle.Continuous:
-				return $"{fraction * 100:F0}%";
+				SegmentCharacter = CM.Glyphs.ContinuousMeterSegment;
+				break;
 			case ProgressBarStyle.MarqueeBlocks:
+				SegmentCharacter = CM.Glyphs.BlocksMeterSegment;
+				break;
 			case ProgressBarStyle.MarqueeContinuous:
+				SegmentCharacter = CM.Glyphs.ContinuousMeterSegment;
 				break;
 			}
+			SetNeedsDisplay ();
+		}
+	}
 
-			return base.Text;
+	/// <summary>
+	/// Specifies the format that a <see cref="ProgressBar"/> uses to indicate the visual presentation.
+	/// </summary>
+	public ProgressBarFormat ProgressBarFormat { get; set; }
+	private Rune _segmentCharacter = CM.Glyphs.BlocksMeterSegment;
+
+	/// <summary>
+	/// Segment indicator for meter views.
+	/// </summary>
+	public Rune SegmentCharacter {
+		get => _segmentCharacter;
+		set {
+			_segmentCharacter = value;
+			SetNeedsDisplay ();
 		}
+	}
 
-		string SetPercentageText (string value)
-		{
-			switch (progressBarStyle) {
-			case ProgressBarStyle.Blocks:
-			case ProgressBarStyle.Continuous:
-				return $"{fraction * 100:F0}%";
-			case ProgressBarStyle.MarqueeBlocks:
-			case ProgressBarStyle.MarqueeContinuous:
-				break;
+	/// <summary>
+	/// Gets or sets the text displayed on the progress bar. If set to an empty string and <see cref="ProgressBarFormat"/> is
+	/// <see cref="ProgressBarFormat.SimplePlusPercentage"/> the percentage will be displayed.
+	/// If <see cref="ProgressBarStyle"/> is a marquee style, the text will be displayed.
+	/// </summary>
+	public override string Text {
+		get => string.IsNullOrEmpty (base.Text) ? $"{_fraction * 100:F0}%" : base.Text;
+		set {
+			if (ProgressBarStyle == ProgressBarStyle.MarqueeBlocks || ProgressBarStyle == ProgressBarStyle.MarqueeContinuous) {
+				base.Text = value;
 			}
+		}
+	}
+
+	bool _bidirectionalMarquee = true;
 
-			return value;
+	/// <summary>
+	/// Specifies if the <see cref="ProgressBarStyle.MarqueeBlocks"/> or the
+	///  <see cref="ProgressBarStyle.MarqueeContinuous"/> styles is unidirectional
+	///  or bidirectional.
+	/// </summary>
+	public bool BidirectionalMarquee {
+		get => _bidirectionalMarquee;
+		set {
+			_bidirectionalMarquee = value;
+			SetNeedsDisplay ();
 		}
+	}
 
-		/// <summary>
-		/// Notifies the <see cref="ProgressBar"/> that some progress has taken place.
-		/// </summary>
-		/// <remarks>
-		/// If the <see cref="ProgressBar"/> is percentage mode, it switches to activity
-		/// mode. If is in activity mode, the marker is moved.
-		/// </remarks>
-		public void Pulse ()
-		{
-			if (activityPos == null) {
-				PopulateActivityPos ();
+	/// <summary>
+	/// Notifies the <see cref="ProgressBar"/> that some progress has taken place.
+	/// </summary>
+	/// <remarks>
+	/// If the <see cref="ProgressBar"/> is percentage mode, it switches to activity
+	/// mode. If is in activity mode, the marker is moved.
+	/// </remarks>
+	public void Pulse ()
+	{
+		if (_activityPos == null) {
+			PopulateActivityPos ();
+		}
+		if (!_isActivity) {
+			_isActivity = true;
+			_delta = 1;
+		} else {
+			for (var i = 0; i < _activityPos.Length; i++) {
+				_activityPos [i] += _delta;
 			}
-			if (!isActivity) {
-				isActivity = true;
-				delta = 1;
-			} else {
-				for (int i = 0; i < activityPos.Length; i++) {
-					activityPos [i] += delta;
+			if (_activityPos [^1] < 0) {
+				for (var i = 0; i < _activityPos.Length; i++) {
+					_activityPos [i] = i - _activityPos.Length + 2;
 				}
-				int fWidth = GetFrameWidth ();
-				if (activityPos [activityPos.Length - 1] < 0) {
-					for (int i = 0; i < activityPos.Length; i++) {
-						activityPos [i] = i - activityPos.Length + 2;
-					}
-					delta = 1;
-				} else if (activityPos [0] >= fWidth) {
-					if (bidirectionalMarquee) {
-						for (int i = 0; i < activityPos.Length; i++) {
-							activityPos [i] = fWidth + i - 2;
-						}
-						delta = -1;
-					} else {
-						PopulateActivityPos ();
+				_delta = 1;
+			} else if (_activityPos [0] >= Bounds.Width) {
+				if (_bidirectionalMarquee) {
+					for (var i = 0; i < _activityPos.Length; i++) {
+						_activityPos [i] = Bounds.Width + i - 2;
 					}
+					_delta = -1;
+				} else {
+					PopulateActivityPos ();
 				}
 			}
-
-			SetNeedsDisplay ();
 		}
 
-		///<inheritdoc/>
-		public override void OnDrawContent (Rect contentArea)
-		{
-			DrawFrame ();
+		SetNeedsDisplay ();
+	}
 
-			Driver.SetAttribute (GetNormalColor ());
+	///<inheritdoc/>
+	public override void OnDrawContent (Rect contentArea)
+	{
+		Driver.SetAttribute (GetHotNormalColor ());
 
-			int fWidth = GetFrameWidth ();
-			if (isActivity) {
-				Move (padding, padding);
-				for (int i = 0; i < fWidth; i++)
-					if (Array.IndexOf (activityPos, i) != -1)
-						Driver.AddRune (SegmentCharacter);
-					else
-						Driver.AddRune ((Rune)' ');
-			} else {
-				Move (padding, padding);
-				int mid = (int)(fraction * fWidth);
-				int i;
-				for (i = 0; i < mid & i < fWidth; i++)
+		Move (0, 0);
+		if (_isActivity) {
+			for (int i = 0; i < Bounds.Width; i++)
+				if (Array.IndexOf (_activityPos, i) != -1) {
 					Driver.AddRune (SegmentCharacter);
-				for (; i < fWidth; i++)
+				} else {
 					Driver.AddRune ((Rune)' ');
+				}
+		} else {
+			int mid = (int)(_fraction * Bounds.Width);
+			int i;
+			for (i = 0; i < mid & i < Bounds.Width; i++) {
+				Driver.AddRune (SegmentCharacter);
 			}
-
-			DrawText (fWidth);
-		}
-
-		int GetFrameWidth ()
-		{
-			switch (progressBarFormat) {
-			case ProgressBarFormat.Simple:
-			case ProgressBarFormat.SimplePlusPercentage:
-				break;
-			case ProgressBarFormat.Framed:
-			case ProgressBarFormat.FramedPlusPercentage:
-				return Frame.Width - 2;
-			case ProgressBarFormat.FramedProgressPadded:
-				return Frame.Width - 2 - padding;
+			for (; i < Bounds.Width; i++) {
+				Driver.AddRune ((Rune)' ');
 			}
-
-			return Frame.Width;
 		}
 
-		void DrawText (int fWidth)
-		{
-			switch (progressBarFormat) {
-			case ProgressBarFormat.Simple:
-			case ProgressBarFormat.Framed:
-				break;
-			case ProgressBarFormat.SimplePlusPercentage:
-			case ProgressBarFormat.FramedPlusPercentage:
-			case ProgressBarFormat.FramedProgressPadded:
-				var tf = new TextFormatter () {
-					Alignment = TextAlignment.Centered,
-					Text = Text
-				};
-				var row = padding + (progressBarFormat == ProgressBarFormat.FramedProgressPadded
-					? 2 : 1);
-				Move (padding, row);
-				var rect = new Rect (padding, row, fWidth, Frame.Height);
-				tf?.Draw (ViewToScreen (rect), ColorScheme.HotNormal, ColorScheme.HotNormal,
-					SuperView == null ? default : SuperView.ViewToScreen (SuperView.Bounds));
-				break;
-			}
-		}
 
-		// TODO: Use v2 Frames
-		void DrawFrame ()
-		{
-			switch (progressBarFormat) {
-			case ProgressBarFormat.Simple:
-			case ProgressBarFormat.SimplePlusPercentage:
-				padding = 0;
-				break;
-			case ProgressBarFormat.Framed:
-			case ProgressBarFormat.FramedPlusPercentage:
-				padding = 1;
-				Border.DrawFrame (Bounds, false);
-				break;
-			case ProgressBarFormat.FramedProgressPadded:
-				padding = 2;
-				Border.DrawFrame (Bounds, false);
-				Border.DrawFrame (new Rect (Bounds.X + padding / 2, Bounds.Y + padding / 2, Bounds.Width - (padding), Bounds.Height - padding - 1), false);
-				break;
+		if (ProgressBarFormat != ProgressBarFormat.Simple && !_isActivity) {
+			var tf = new TextFormatter () {
+				Alignment = TextAlignment.Centered,
+				Text = Text
+			};
+			Attribute attr = new Attribute (ColorScheme.HotNormal.Foreground, ColorScheme.HotNormal.Background);
+			if (_fraction > .5) {
+				attr = new Attribute (ColorScheme.HotNormal.Background, ColorScheme.HotNormal.Foreground);
 			}
-		}
+			tf?.Draw (ViewToScreen (Bounds),
+				attr,
+				ColorScheme.Normal,
+				SuperView?.ViewToScreen (SuperView.Bounds) ?? default,
+				fillRemaining: false);
 
-		void PopulateActivityPos ()
-		{
-			activityPos = new int [Math.Min (Frame.Width / 3, 5)];
-			for (int i = 0; i < activityPos.Length; i++) {
-				activityPos [i] = i - activityPos.Length + 1;
-			}
-		}
 
-		///<inheritdoc/>
-		public override bool OnEnter (View view)
-		{
-			Application.Driver.SetCursorVisibility (CursorVisibility.Invisible);
+		}
+	}
 
-			return base.OnEnter (view);
+	void PopulateActivityPos ()
+	{
+		_activityPos = new int [Math.Min (Frame.Width / 3, 5)];
+		for (var i = 0; i < _activityPos.Length; i++) {
+			_activityPos [i] = i - _activityPos.Length + 1;
 		}
 	}
+
+	///<inheritdoc/>
+	public override bool OnEnter (View view)
+	{
+		Application.Driver.SetCursorVisibility (CursorVisibility.Invisible);
+		return base.OnEnter (view);
+	}
 }

+ 110 - 94
UICatalog/Scenarios/Frames.cs

@@ -180,7 +180,7 @@ namespace UICatalog.Scenarios {
 						break;
 					}
 				} catch {
-					if (!string.IsNullOrEmpty(e.NewText)) {
+					if (!string.IsNullOrEmpty (e.NewText)) {
 						e.Cancel = true;
 					}
 				}
@@ -192,99 +192,110 @@ namespace UICatalog.Scenarios {
 			private FrameEditor _marginEditor;
 			private FrameEditor _borderEditor;
 			private FrameEditor _paddingEditor;
+			private String _origTitle = string.Empty;
 
-			public FramesEditor (string title, View viewToEdit)
+			public FramesEditor ()
 			{
-				this._viewToEdit = viewToEdit;
-
-				viewToEdit.Margin.ColorScheme = new ColorScheme (Colors.ColorSchemes ["Toplevel"]);
-				_marginEditor = new FrameEditor () {
-					X = 0,
-					Y = 0,
-					Title = "Margin",
-					Thickness = viewToEdit.Margin.Thickness,
-					SuperViewRendersLineCanvas = true
-				};
-				_marginEditor.ThicknessChanged += Editor_ThicknessChanged;
-				_marginEditor.AttributeChanged += Editor_AttributeChanged; ;
-				Add (_marginEditor);
-
-				viewToEdit.Border.ColorScheme = new ColorScheme (Colors.ColorSchemes ["Base"]);
-				_borderEditor = new FrameEditor () {
-					X = Pos.Left (_marginEditor),
-					Y = Pos.Bottom (_marginEditor),
-					Title = "Border",
-					Thickness = viewToEdit.Border.Thickness,
-					SuperViewRendersLineCanvas = true
-				};
-				_borderEditor.ThicknessChanged += Editor_ThicknessChanged;
-				_borderEditor.AttributeChanged += Editor_AttributeChanged;
-				Add (_borderEditor);
-
-				viewToEdit.Padding.ColorScheme = new ColorScheme (Colors.ColorSchemes ["Error"]);
-
-				var borderStyleEnum = Enum.GetValues (typeof (LineStyle)).Cast<LineStyle> ().ToList ();
-				var rbBorderStyle = new RadioGroup (borderStyleEnum.Select (
-					e => e.ToString ()).ToArray ()) {
-
-					X = Pos.Right (_borderEditor) - 1,
-					Y = Pos.Top (_borderEditor),
-					SelectedItem = (int)viewToEdit.Border.BorderStyle,
-					BorderStyle = LineStyle.Double,
-					Title = "Border Style",
-					SuperViewRendersLineCanvas = true
-				};
-				Add (rbBorderStyle);
-
-				rbBorderStyle.SelectedItemChanged += (s, e) => {
-					var prevBorderStyle = viewToEdit.BorderStyle;
-					viewToEdit.Border.BorderStyle = (LineStyle)e.SelectedItem;
-					if (viewToEdit.Border.BorderStyle == LineStyle.None) {
-						viewToEdit.Border.Thickness = new Thickness (0);
-					} else if (prevBorderStyle == LineStyle.None && viewToEdit.Border.BorderStyle != LineStyle.None) {
-						viewToEdit.Border.Thickness = new Thickness (1);
-					}
-					_borderEditor.Thickness = new Thickness (viewToEdit.Border.Thickness.Left, viewToEdit.Border.Thickness.Top,
-						viewToEdit.Border.Thickness.Right, viewToEdit.Border.Thickness.Bottom);
-					viewToEdit.SetNeedsDisplay ();
-				};
-
-				var ckbTitle = new CheckBox ("Show Title") {
-					BorderStyle = LineStyle.Double,
-					X = Pos.Left (_borderEditor),
-					Y = Pos.Bottom (_borderEditor) - 1,
-					Width = Dim.Width (_borderEditor),
-					Checked = true,
-					SuperViewRendersLineCanvas = true
-				};
-				Add (ckbTitle);
-
-				_paddingEditor = new FrameEditor () {
-					X = Pos.Left (_borderEditor),
-					Y = Pos.Bottom (rbBorderStyle),
-					Title = "Padding",
-					Thickness = viewToEdit.Padding.Thickness,
-					SuperViewRendersLineCanvas = true
-				};
-				_paddingEditor.ThicknessChanged += Editor_ThicknessChanged;
-				_paddingEditor.AttributeChanged += Editor_AttributeChanged;
-				Add (_paddingEditor);
-
-				viewToEdit.X = Pos.Right (rbBorderStyle);
-				viewToEdit.Y = 0;
-				viewToEdit.Width = Dim.Fill ();
-				viewToEdit.Height = Dim.Fill ();
-				Add (viewToEdit);
-
-				viewToEdit.LayoutComplete += (s, e) => {
-					if (ckbTitle.Checked == true) {
-						viewToEdit.Title = viewToEdit.ToString ();
-					} else {
-						viewToEdit.Title = string.Empty;
-					}
-				};
+			}
 
-				Title = title;
+			public View ViewToEdit {
+				get {
+					return _viewToEdit;
+				}
+				set {
+					_origTitle = value.Title;
+					_viewToEdit = value;
+
+					_viewToEdit.Margin.ColorScheme = new ColorScheme (Colors.ColorSchemes ["Toplevel"]);
+					_marginEditor = new FrameEditor () {
+						X = 0,
+						Y = 0,
+						Title = "Margin",
+						Thickness = _viewToEdit.Margin.Thickness,
+						SuperViewRendersLineCanvas = true
+					};
+					_marginEditor.ThicknessChanged += Editor_ThicknessChanged;
+					_marginEditor.AttributeChanged += Editor_AttributeChanged;
+					Add (_marginEditor);
+
+					_viewToEdit.Border.ColorScheme = new ColorScheme (Colors.ColorSchemes ["Base"]);
+					_borderEditor = new FrameEditor () {
+						X = Pos.Left (_marginEditor),
+						Y = Pos.Bottom (_marginEditor),
+						Title = "Border",
+						Thickness = _viewToEdit.Border.Thickness,
+						SuperViewRendersLineCanvas = true
+					};
+					_borderEditor.ThicknessChanged += Editor_ThicknessChanged;
+					_borderEditor.AttributeChanged += Editor_AttributeChanged;
+					Add (_borderEditor);
+
+					_viewToEdit.Padding.ColorScheme = new ColorScheme (Colors.ColorSchemes ["Error"]);
+
+					var borderStyleEnum = Enum.GetValues (typeof (LineStyle)).Cast<LineStyle> ().ToList ();
+					var rbBorderStyle = new RadioGroup (borderStyleEnum.Select (
+						e => e.ToString ()).ToArray ()) {
+
+						X = Pos.Right (_borderEditor) - 1,
+						Y = Pos.Top (_borderEditor),
+						SelectedItem = (int)_viewToEdit.Border.BorderStyle,
+						BorderStyle = LineStyle.Double,
+						Title = "Border Style",
+						SuperViewRendersLineCanvas = true
+					};
+					Add (rbBorderStyle);
+
+					rbBorderStyle.SelectedItemChanged += (s, e) => {
+						var prevBorderStyle = _viewToEdit.BorderStyle;
+						_viewToEdit.Border.BorderStyle = (LineStyle)e.SelectedItem;
+						if (_viewToEdit.Border.BorderStyle == LineStyle.None) {
+							_viewToEdit.Border.Thickness = new Thickness (0);
+						} else if (prevBorderStyle == LineStyle.None && _viewToEdit.Border.BorderStyle != LineStyle.None) {
+							_viewToEdit.Border.Thickness = new Thickness (1);
+						}
+						_borderEditor.Thickness = new Thickness (_viewToEdit.Border.Thickness.Left, _viewToEdit.Border.Thickness.Top,
+							_viewToEdit.Border.Thickness.Right, _viewToEdit.Border.Thickness.Bottom);
+						_viewToEdit.SetNeedsDisplay ();
+						LayoutSubviews ();
+					};
+
+					var ckbTitle = new CheckBox ("Show Title") {
+						BorderStyle = LineStyle.Double,
+						X = Pos.Left (_borderEditor),
+						Y = Pos.Bottom (_borderEditor) - 1,
+						Width = Dim.Width (_borderEditor),
+						Checked = true,
+						SuperViewRendersLineCanvas = true
+					};
+					ckbTitle.Toggled += (sender, args) => {
+						if (ckbTitle.Checked == true) {
+							_viewToEdit.Title = _origTitle;
+						} else {
+							_viewToEdit.Title = string.Empty;
+						}
+					};
+					Add (ckbTitle);
+
+					_paddingEditor = new FrameEditor () {
+						X = Pos.Left (_borderEditor),
+						Y = Pos.Bottom (rbBorderStyle),
+						Title = "Padding",
+						Thickness = _viewToEdit.Padding.Thickness,
+						SuperViewRendersLineCanvas = true
+					};
+					_paddingEditor.ThicknessChanged += Editor_ThicknessChanged;
+					_paddingEditor.AttributeChanged += Editor_AttributeChanged;
+					Add (_paddingEditor);
+					Add (_viewToEdit);
+
+					_viewToEdit.LayoutComplete += (s, e) => {
+						if (ckbTitle.Checked == true) {
+							_viewToEdit.Title = _origTitle;
+						} else {
+							_viewToEdit.Title = string.Empty;
+						}
+					};
+				}
 			}
 
 			private void Editor_AttributeChanged (object sender, Terminal.Gui.Attribute attr)
@@ -368,9 +379,14 @@ namespace UICatalog.Scenarios {
 
 			view.Add (tf1, button, label, tf2, tv);
 
-			var editor = new FramesEditor (
-				$"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
-				view);
+			var editor = new FramesEditor () {
+				Title =$"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+				ViewToEdit = view
+			};
+			view.X = 36;
+			view.Y = 0;
+			view.Width = Dim.Fill ();
+			view.Height = Dim.Fill ();
 
 			Application.Run (editor);
 			Application.Shutdown ();

+ 71 - 49
UICatalog/Scenarios/ProgressBarStyles.cs

@@ -2,6 +2,7 @@
 using System.Linq;
 using System.Threading;
 using Terminal.Gui;
+using static UICatalog.Scenarios.Frames;
 
 namespace UICatalog.Scenarios {
 	[ScenarioMetadata (Name: "ProgressBar Styles", Description: "Shows the ProgressBar Styles.")]
@@ -9,64 +10,66 @@ namespace UICatalog.Scenarios {
 	[ScenarioCategory ("Progress")]
 	[ScenarioCategory ("Threading")]
 
+	// TODO: Add enable/disable to show that that is working
+	// TODO: Clean up how FramesEditor works 
+	// TODO: Better align rpPBFormat
+
 	public class ProgressBarStyles : Scenario {
 		private Timer _fractionTimer;
 		private Timer _pulseTimer;
-		private const uint _timerTick = 100;
+		private const uint _timerTick = 20;
 
-		public override void Setup ()
+		public override void Init ()
 		{
+			Application.Init ();
+			ConfigurationManager.Themes.Theme = Theme;
+			ConfigurationManager.Apply ();
+
+			var editor = new FramesEditor () {
+				Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+				BorderStyle = LineStyle.Single
+			};
+			editor.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme];
+
 			const float fractionStep = 0.01F;
-			const int pbWidth = 20;
+			const int pbWidth = 25;
 
 			var pbFormatEnum = Enum.GetValues (typeof (ProgressBarFormat)).Cast<ProgressBarFormat> ().ToList ();
 
 			var rbPBFormat = new RadioGroup (pbFormatEnum.Select (e => e.ToString ()).ToArray ()) {
 				X = Pos.Center (),
-				Y = 1
+				Y = 10
 			};
-			Win.Add (rbPBFormat);
+			editor.Add (rbPBFormat);
 
-			var ckbBidirectional = new CheckBox ("BidirectionalMarquee", true) {
+			var button = new Button ("Start timer") {
 				X = Pos.Center (),
 				Y = Pos.Bottom (rbPBFormat) + 1
 			};
-			Win.Add (ckbBidirectional);
-
-			var label = new Label ("Blocks") {
-				X = Pos.Center (),
-				Y = Pos.Bottom (ckbBidirectional) + 1
-			};
-			Win.Add (label);
 
+			editor.Add (button);
 			var blocksPB = new ProgressBar () {
+				Title = "Blocks",
 				X = Pos.Center (),
-				Y = Pos.Y (label) + 1,
-				Width = pbWidth
-			};
-			Win.Add (blocksPB);
-
-			label = new Label ("Continuous") {
-				X = Pos.Center (),
-				Y = Pos.Bottom (blocksPB) + 1
+				Y = Pos.Bottom (button) + 1,
+				Width = pbWidth,
+				BorderStyle = LineStyle.Single
 			};
-			Win.Add (label);
+			editor.Add (blocksPB);
 
 			var continuousPB = new ProgressBar () {
+				Title = "Continuous",
 				X = Pos.Center (),
-				Y = Pos.Y (label) + 1,
+				Y = Pos.Bottom (blocksPB) + 1,
 				Width = pbWidth,
-				ProgressBarStyle = ProgressBarStyle.Continuous
+				ProgressBarStyle = ProgressBarStyle.Continuous,
+				BorderStyle = LineStyle.Single
 			};
-			Win.Add (continuousPB);
+			editor.Add (continuousPB);
 
-			var button = new Button ("Start timer") {
-				X = Pos.Center (),
-				Y = Pos.Bottom (continuousPB) + 1
-			};
-			button.Clicked += (s,e) => {
+			button.Clicked += (s, e) => {
 				if (_fractionTimer == null) {
-					button.Enabled = false;
+					//blocksPB.Enabled = false;
 					blocksPB.Fraction = 0;
 					continuousPB.Fraction = 0;
 					float fractionSum = 0;
@@ -83,44 +86,41 @@ namespace UICatalog.Scenarios {
 					}, null, 0, _timerTick);
 				}
 			};
-			Win.Add (button);
 
-			label = new Label ("Marquee Blocks") {
+			var ckbBidirectional = new CheckBox ("BidirectionalMarquee", true) {
 				X = Pos.Center (),
-				Y = Pos.Y (button) + 3
+				Y = Pos.Bottom (continuousPB) + 1
 			};
-			Win.Add (label);
+			editor.Add (ckbBidirectional);
 
 			var marqueesBlocksPB = new ProgressBar () {
+				Title = "Marquee Blocks",
 				X = Pos.Center (),
-				Y = Pos.Y (label) + 1,
+				Y = Pos.Bottom (ckbBidirectional) + 1,
 				Width = pbWidth,
-				ProgressBarStyle = ProgressBarStyle.MarqueeBlocks
-			};
-			Win.Add (marqueesBlocksPB);
-
-			label = new Label ("Marquee Continuous") {
-				X = Pos.Center (),
-				Y = Pos.Bottom (marqueesBlocksPB) + 1
+				ProgressBarStyle = ProgressBarStyle.MarqueeBlocks,
+				BorderStyle = LineStyle.Single
 			};
-			Win.Add (label);
+			editor.Add (marqueesBlocksPB);
 
 			var marqueesContinuousPB = new ProgressBar () {
+				Title = "Marquee Continuous",
 				X = Pos.Center (),
-				Y = Pos.Y (label) + 1,
+				Y = Pos.Bottom (marqueesBlocksPB) + 1,
 				Width = pbWidth,
-				ProgressBarStyle = ProgressBarStyle.MarqueeContinuous
+				ProgressBarStyle = ProgressBarStyle.MarqueeContinuous,
+				BorderStyle = LineStyle.Single
 			};
-			Win.Add (marqueesContinuousPB);
+			editor.Add (marqueesContinuousPB);
 
-			rbPBFormat.SelectedItemChanged += (s,e) => {
+			rbPBFormat.SelectedItemChanged += (s, e) => {
 				blocksPB.ProgressBarFormat = (ProgressBarFormat)e.SelectedItem;
 				continuousPB.ProgressBarFormat = (ProgressBarFormat)e.SelectedItem;
 				marqueesBlocksPB.ProgressBarFormat = (ProgressBarFormat)e.SelectedItem;
 				marqueesContinuousPB.ProgressBarFormat = (ProgressBarFormat)e.SelectedItem;
 			};
 
-			ckbBidirectional.Toggled += (s,e) => {
+			ckbBidirectional.Toggled += (s, e) => {
 				ckbBidirectional.Checked = marqueesBlocksPB.BidirectionalMarquee = marqueesContinuousPB.BidirectionalMarquee = (bool)!e.OldValue;
 			};
 
@@ -145,6 +145,28 @@ namespace UICatalog.Scenarios {
 				}
 				Application.Top.Unloaded -= Top_Unloaded;
 			}
+
+			var pbs = editor.Subviews.Where (v => v.GetType () == typeof (ProgressBar)).Select(v => v.Title).ToList ();
+			var pbList = new ListView (pbs) {
+				Title = "Focused ProgressBar",
+				Y = 0,
+				X = Pos.Center(),
+				Width = 30,
+				Height = 7,
+				BorderStyle = LineStyle.Single
+			};
+			pbList.SelectedItemChanged += (sender, e) => {
+				editor.ViewToEdit = (View)editor.Subviews.First(v => v.GetType () == typeof (ProgressBar) && v.Title == (string)e.Value);
+			};
+			editor.Add (pbList);
+			pbList.SelectedItem = 0;
+
+			Application.Run (editor);
+			Application.Shutdown ();
+		}
+
+		public override void Run ()
+		{
 		}
 	}
 }

+ 8 - 1
UICatalog/Scenarios/ViewExperiments.cs

@@ -220,13 +220,20 @@ namespace UICatalog.Scenarios {
 
 			view.X = Pos.Center ();
 
-			var editor = new Frames.FramesEditor ($"Frames Editor", view) {
+			var editor = new Frames.FramesEditor () {
+				Title = $"Frames Editor",
 				X = 0,
 				Y = Pos.Bottom (containerLabel),
 				Width = Dim.Fill (),
+				ViewToEdit = view,
 			};
 
 			Application.Top.Add (editor);
+			view.X = 36;
+			view.Y = 4;
+			view.Width = Dim.Fill ();
+			view.Height = Dim.Fill ();
+			Application.Top.Add (view);
 		}
 	}
 }

+ 12 - 57
UnitTests/Views/ProgressBarTests.cs

@@ -1,23 +1,21 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Text;
 using Xunit;
 
 namespace Terminal.Gui.ViewsTests {
 	public class ProgressBarTests {
 		[Fact]
 		[AutoInitShutdown]
-		public void Default_Contructor ()
+		public void Default_Constructor ()
 		{
 			var pb = new ProgressBar ();
+			pb.BeginInit();
+			pb.EndInit();
 
 			Assert.False (pb.CanFocus);
 			Assert.Equal (0, pb.Fraction);
 			Assert.Equal (new Attribute (Color.BrightGreen, Color.Gray),
-				new Attribute (pb.ColorScheme.Normal.Foreground, pb.ColorScheme.Normal.Background));
-			Assert.Equal (Colors.Base.Normal, pb.ColorScheme.HotNormal);
+				new Attribute (pb.ColorScheme.HotNormal.Foreground, pb.ColorScheme.HotNormal.Background));
+			Assert.Equal (Colors.Base.Normal, pb.ColorScheme.Normal);
 			Assert.Equal (1, pb.Height);
 			Assert.Equal (ProgressBarStyle.Blocks, pb.ProgressBarStyle);
 			Assert.Equal (ProgressBarFormat.Simple, pb.ProgressBarFormat);
@@ -55,16 +53,7 @@ namespace Terminal.Gui.ViewsTests {
 			Assert.Equal (1, pb.Height);
 
 			pb.ProgressBarFormat = ProgressBarFormat.SimplePlusPercentage;
-			Assert.Equal (2, pb.Height);
-
-			pb.ProgressBarFormat = ProgressBarFormat.Framed;
-			Assert.Equal (3, pb.Height);
-
-			pb.ProgressBarFormat = ProgressBarFormat.FramedPlusPercentage;
-			Assert.Equal (4, pb.Height);
-
-			pb.ProgressBarFormat = ProgressBarFormat.FramedProgressPadded;
-			Assert.Equal (6, pb.Height);
+			Assert.Equal (1, pb.Height);
 		}
 
 		[Fact]
@@ -85,31 +74,11 @@ namespace Terminal.Gui.ViewsTests {
 
 			pb1.ProgressBarFormat = ProgressBarFormat.SimplePlusPercentage;
 			Assert.Equal (ProgressBarFormat.SimplePlusPercentage, pb1.ProgressBarFormat);
-			Assert.Equal (2, pb1.Height);
+			Assert.Equal (1, pb1.Height);
 			pb2.ProgressBarFormat = ProgressBarFormat.SimplePlusPercentage;
 			Assert.Equal (ProgressBarFormat.SimplePlusPercentage, pb2.ProgressBarFormat);
-			Assert.Equal (2, pb2.Height);
-
-			pb1.ProgressBarFormat = ProgressBarFormat.Framed;
-			Assert.Equal (ProgressBarFormat.Framed, pb1.ProgressBarFormat);
-			Assert.Equal (3, pb1.Height);
-			pb2.ProgressBarFormat = ProgressBarFormat.Framed;
-			Assert.Equal (ProgressBarFormat.Framed, pb2.ProgressBarFormat);
-			Assert.Equal (3, pb2.Height);
-
-			pb1.ProgressBarFormat = ProgressBarFormat.FramedPlusPercentage;
-			Assert.Equal (ProgressBarFormat.FramedPlusPercentage, pb1.ProgressBarFormat);
-			Assert.Equal (4, pb1.Height);
-			pb2.ProgressBarFormat = ProgressBarFormat.FramedPlusPercentage;
-			Assert.Equal (ProgressBarFormat.FramedPlusPercentage, pb2.ProgressBarFormat);
-			Assert.Equal (4, pb2.Height);
+			Assert.Equal (1, pb2.Height);
 
-			pb1.ProgressBarFormat = ProgressBarFormat.FramedProgressPadded;
-			Assert.Equal (ProgressBarFormat.FramedProgressPadded, pb1.ProgressBarFormat);
-			Assert.Equal (6, pb1.Height);
-			pb2.ProgressBarFormat = ProgressBarFormat.FramedProgressPadded;
-			Assert.Equal (ProgressBarFormat.FramedProgressPadded, pb2.ProgressBarFormat);
-			Assert.Equal (6, pb2.Height);
 		}
 
 		[Fact]
@@ -126,14 +95,6 @@ namespace Terminal.Gui.ViewsTests {
 			pb.Text = "bleble";
 			Assert.Equal ("25%", pb.Text);
 
-			pb.ProgressBarFormat = ProgressBarFormat.Framed;
-			Assert.Equal ("25%", pb.Text);
-
-			pb.ProgressBarFormat = ProgressBarFormat.FramedPlusPercentage;
-			Assert.Equal ("25%", pb.Text);
-
-			pb.ProgressBarFormat = ProgressBarFormat.FramedProgressPadded;
-			Assert.Equal ("25%", pb.Text);
 		}
 
 		[Fact]
@@ -149,15 +110,6 @@ namespace Terminal.Gui.ViewsTests {
 			pb.ProgressBarFormat = ProgressBarFormat.SimplePlusPercentage;
 			pb.Text = "bleble";
 			Assert.Equal ("bleble", pb.Text);
-
-			pb.ProgressBarFormat = ProgressBarFormat.Framed;
-			Assert.Equal ("bleble", pb.Text);
-
-			pb.ProgressBarFormat = ProgressBarFormat.FramedPlusPercentage;
-			Assert.Equal ("bleble", pb.Text);
-
-			pb.ProgressBarFormat = ProgressBarFormat.FramedProgressPadded;
-			Assert.Equal ("bleble", pb.Text);
 		}
 
 		[Fact]
@@ -173,6 +125,7 @@ namespace Terminal.Gui.ViewsTests {
 
 			pb.BeginInit ();
 			pb.EndInit ();
+			pb.LayoutSubviews ();
 
 			for (int i = 0; i < 38; i++) {
 				pb.Pulse ();
@@ -803,6 +756,7 @@ namespace Terminal.Gui.ViewsTests {
 
 			pb.BeginInit ();
 			pb.EndInit ();
+			pb.LayoutSubviews ();
 
 			for (int i = 0; i < 38; i++) {
 				pb.Pulse ();
@@ -1431,6 +1385,7 @@ namespace Terminal.Gui.ViewsTests {
 
 			pb.BeginInit ();
 			pb.EndInit ();
+			pb.LayoutSubviews ();
 
 			for (int i = 0; i <= pb.Frame.Width; i++) {
 				pb.Fraction += 0.2F;

+ 0 - 1
UnitTests/Views/TreeViewTests.cs

@@ -856,7 +856,6 @@ namespace Terminal.Gui.ViewsTests {
 			var pink = new Attribute (Color.Magenta, Color.Black);
 			var hotpink = new Attribute (Color.BrightMagenta, Color.Black);
 
-
 			// Normal drawing of the tree view
 			TestHelpers.AssertDriverContentsAre (@"
 ├-normal