浏览代码

Merge pull request #2863 from tznind/2859-customize-v2-file-dialog

Fixes 2859 - Add more file dialog customization options
Tig 1 年之前
父节点
当前提交
5e7933564c

+ 28 - 16
Terminal.Gui/FileServices/FileDialogStyle.cs

@@ -21,7 +21,7 @@ namespace Terminal.Gui {
 		/// Gets or sets the default value to use for <see cref="UseColors"/>.
 		/// Gets or sets the default value to use for <see cref="UseColors"/>.
 		/// This can be populated from .tui config files via <see cref="ConfigurationManager"/>
 		/// This can be populated from .tui config files via <see cref="ConfigurationManager"/>
 		/// </summary>
 		/// </summary>
-		[SerializableConfigurationProperty(Scope = typeof (SettingsScope))]
+		[SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
 		public static bool DefaultUseColors { get; set; }
 		public static bool DefaultUseColors { get; set; }
 
 
 		/// <summary>
 		/// <summary>
@@ -42,20 +42,20 @@ namespace Terminal.Gui {
 		/// Gets or sets the class responsible for determining which symbol
 		/// Gets or sets the class responsible for determining which symbol
 		/// to use to represent files and directories.
 		/// to use to represent files and directories.
 		/// </summary>
 		/// </summary>
-		public FileSystemIconProvider IconProvider { get; set;} = new FileSystemIconProvider();
+		public FileSystemIconProvider IconProvider { get; set; } = new FileSystemIconProvider ();
 
 
 		/// <summary>
 		/// <summary>
 		///	Gets or sets the class thatis responsible for determining which color
 		///	Gets or sets the class thatis responsible for determining which color
 		/// to use to represent files and directories when <see cref="UseColors"/> is
 		/// to use to represent files and directories when <see cref="UseColors"/> is
 		/// <see langword="true"/>.
 		/// <see langword="true"/>.
 		/// </summary>
 		/// </summary>
-		public FileSystemColorProvider ColorProvider { get;set;} = new FileSystemColorProvider();
+		public FileSystemColorProvider ColorProvider { get; set; } = new FileSystemColorProvider ();
 
 
 		/// <summary>
 		/// <summary>
 		/// Gets or sets the culture to use (e.g. for number formatting).
 		/// Gets or sets the culture to use (e.g. for number formatting).
 		/// Defaults to <see cref="CultureInfo.CurrentUICulture"/>.
 		/// Defaults to <see cref="CultureInfo.CurrentUICulture"/>.
 		/// </summary>
 		/// </summary>
-		public CultureInfo Culture {get;set;} = CultureInfo.CurrentUICulture;
+		public CultureInfo Culture { get; set; } = CultureInfo.CurrentUICulture;
 
 
 		/// <summary>
 		/// <summary>
 		/// Gets or sets the header text displayed in the Filename column of the files table.
 		/// Gets or sets the header text displayed in the Filename column of the files table.
@@ -80,12 +80,12 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// <summary>
 		/// Gets or sets the text displayed in the 'Search' text box when user has not supplied any input yet.
 		/// Gets or sets the text displayed in the 'Search' text box when user has not supplied any input yet.
 		/// </summary>
 		/// </summary>
-		public string SearchCaption { get; internal set; } = Strings.fdSearchCaption;
+		public string SearchCaption { get; set; } = Strings.fdSearchCaption;
 
 
 		/// <summary>
 		/// <summary>
 		/// Gets or sets the text displayed in the 'Path' text box when user has not supplied any input yet.
 		/// Gets or sets the text displayed in the 'Path' text box when user has not supplied any input yet.
 		/// </summary>
 		/// </summary>
-		public string PathCaption { get; internal set; } = Strings.fdPathCaption;
+		public string PathCaption { get; set; } = Strings.fdPathCaption;
 
 
 		/// <summary>
 		/// <summary>
 		/// Gets or sets the text on the 'Ok' button.  Typically you may want to change this to
 		/// Gets or sets the text on the 'Ok' button.  Typically you may want to change this to
@@ -93,40 +93,52 @@ namespace Terminal.Gui {
 		/// </summary>
 		/// </summary>
 		public string OkButtonText { get; set; } = "Ok";
 		public string OkButtonText { get; set; } = "Ok";
 
 
+		/// <summary>
+		/// Gets or sets the text on the 'Cancel' button.
+		/// </summary>
+		public string CancelButtonText { get; set; } = "Cancel";
+
+		/// <summary>
+		/// Gets or sets whether to flip the order of the Ok and Cancel buttons. Defaults
+		/// to false (Ok button then Cancel button). Set to true to show Cancel button on
+		/// left then Ok button instead.
+		/// </summary>
+		public bool FlipOkCancelButtonLayoutOrder { get; set; }
+
 		/// <summary>
 		/// <summary>
 		/// Gets or sets error message when user attempts to select a file type that is not one of <see cref="FileDialog.AllowedTypes"/>
 		/// Gets or sets error message when user attempts to select a file type that is not one of <see cref="FileDialog.AllowedTypes"/>
 		/// </summary>
 		/// </summary>
-		public string WrongFileTypeFeedback { get; internal set; } = Strings.fdWrongFileTypeFeedback;
+		public string WrongFileTypeFeedback { get; set; } = Strings.fdWrongFileTypeFeedback;
 
 
 		/// <summary>
 		/// <summary>
 		/// Gets or sets error message when user selects a directory that does not exist and
 		/// Gets or sets error message when user selects a directory that does not exist and
 		/// <see cref="OpenMode"/> is <see cref="OpenMode.Directory"/> and <see cref="FileDialog.MustExist"/> is <see langword="true"/>.
 		/// <see cref="OpenMode"/> is <see cref="OpenMode.Directory"/> and <see cref="FileDialog.MustExist"/> is <see langword="true"/>.
 		/// </summary>
 		/// </summary>
-		public string DirectoryMustExistFeedback { get; internal set; } = Strings.fdDirectoryMustExistFeedback;
+		public string DirectoryMustExistFeedback { get; set; } = Strings.fdDirectoryMustExistFeedback;
 
 
 		/// <summary>
 		/// <summary>
 		/// Gets or sets error message when user <see cref="OpenMode"/> is <see cref="OpenMode.Directory"/>
 		/// Gets or sets error message when user <see cref="OpenMode"/> is <see cref="OpenMode.Directory"/>
 		/// and user enters the name of an existing file (File system cannot have a folder with the same name as a file).
 		/// and user enters the name of an existing file (File system cannot have a folder with the same name as a file).
 		/// </summary>
 		/// </summary>
-		public string FileAlreadyExistsFeedback { get; internal set; } = Strings.fdFileAlreadyExistsFeedback;
+		public string FileAlreadyExistsFeedback { get; set; } = Strings.fdFileAlreadyExistsFeedback;
 
 
 		/// <summary>
 		/// <summary>
 		/// Gets or sets error message when user selects a file that does not exist and
 		/// Gets or sets error message when user selects a file that does not exist and
 		/// <see cref="OpenMode"/> is <see cref="OpenMode.File"/> and <see cref="FileDialog.MustExist"/> is <see langword="true"/>.
 		/// <see cref="OpenMode"/> is <see cref="OpenMode.File"/> and <see cref="FileDialog.MustExist"/> is <see langword="true"/>.
 		/// </summary>
 		/// </summary>
-		public string FileMustExistFeedback { get; internal set; } = Strings.fdFileMustExistFeedback;
+		public string FileMustExistFeedback { get; set; } = Strings.fdFileMustExistFeedback;
 
 
 		/// <summary>
 		/// <summary>
 		/// Gets or sets error message when user <see cref="OpenMode"/> is <see cref="OpenMode.File"/>
 		/// Gets or sets error message when user <see cref="OpenMode"/> is <see cref="OpenMode.File"/>
 		/// and user enters the name of an existing directory (File system cannot have a folder with the same name as a file).
 		/// and user enters the name of an existing directory (File system cannot have a folder with the same name as a file).
 		/// </summary>
 		/// </summary>
-		public string DirectoryAlreadyExistsFeedback { get; internal set; } = Strings.fdDirectoryAlreadyExistsFeedback;
+		public string DirectoryAlreadyExistsFeedback { get; set; } = Strings.fdDirectoryAlreadyExistsFeedback;
 
 
 		/// <summary>
 		/// <summary>
 		/// Gets or sets error message when user selects a file/dir that does not exist and
 		/// Gets or sets error message when user selects a file/dir that does not exist and
 		/// <see cref="OpenMode"/> is <see cref="OpenMode.Mixed"/> and <see cref="FileDialog.MustExist"/> is <see langword="true"/>.
 		/// <see cref="OpenMode"/> is <see cref="OpenMode.Mixed"/> and <see cref="FileDialog.MustExist"/> is <see langword="true"/>.
 		/// </summary>
 		/// </summary>
-		public string FileOrDirectoryMustExistFeedback { get; internal set; } = Strings.fdFileOrDirectoryMustExistFeedback;
+		public string FileOrDirectoryMustExistFeedback { get; set; } = Strings.fdFileOrDirectoryMustExistFeedback;
 
 
 		/// <summary>
 		/// <summary>
 		/// Gets the style settings for the table of files (in currently selected directory).
 		/// Gets the style settings for the table of files (in currently selected directory).
@@ -172,7 +184,7 @@ namespace Terminal.Gui {
 		}
 		}
 
 
 
 
-		private Dictionary<IDirectoryInfo,string> DefaultTreeRootGetter ()
+		private Dictionary<IDirectoryInfo, string> DefaultTreeRootGetter ()
 		{
 		{
 			var roots = new Dictionary<IDirectoryInfo, string> ();
 			var roots = new Dictionary<IDirectoryInfo, string> ();
 			try {
 			try {
@@ -180,7 +192,7 @@ namespace Terminal.Gui {
 
 
 					var dir = _fileSystem.DirectoryInfo.New (d);
 					var dir = _fileSystem.DirectoryInfo.New (d);
 
 
-					if (!roots.ContainsKey(dir)) {
+					if (!roots.ContainsKey (dir)) {
 						roots.Add (dir, d);
 						roots.Add (dir, d);
 					}
 					}
 				}
 				}
@@ -194,14 +206,14 @@ namespace Terminal.Gui {
 					try {
 					try {
 						var path = Environment.GetFolderPath (special);
 						var path = Environment.GetFolderPath (special);
 
 
-						if(string.IsNullOrWhiteSpace (path)) {
+						if (string.IsNullOrWhiteSpace (path)) {
 							continue;
 							continue;
 						}
 						}
 
 
 						var dir = _fileSystem.DirectoryInfo.New (path);
 						var dir = _fileSystem.DirectoryInfo.New (path);
 
 
 						if (!roots.ContainsKey (dir) && dir.Exists) {
 						if (!roots.ContainsKey (dir) && dir.Exists) {
-							roots.Add (dir, special.ToString());
+							roots.Add (dir, special.ToString ());
 						}
 						}
 					} catch (Exception) {
 					} catch (Exception) {
 						// Special file exists but contents are unreadable (permissions?)
 						// Special file exists but contents are unreadable (permissions?)

+ 44 - 32
Terminal.Gui/Views/FileDialog.cs

@@ -105,7 +105,7 @@ namespace Terminal.Gui {
 		private int currentSortColumn;
 		private int currentSortColumn;
 
 
 		private bool currentSortIsAsc = true;
 		private bool currentSortIsAsc = true;
-		private Dictionary<IDirectoryInfo,string> _treeRoots = new Dictionary<IDirectoryInfo, string>();
+		private Dictionary<IDirectoryInfo, string> _treeRoots = new Dictionary<IDirectoryInfo, string> ();
 
 
 		/// <summary>
 		/// <summary>
 		/// Event fired when user attempts to confirm a selection (or multi selection).
 		/// Event fired when user attempts to confirm a selection (or multi selection).
@@ -142,11 +142,7 @@ namespace Terminal.Gui {
 
 
 			this.btnOk = new Button (Style.OkButtonText) {
 			this.btnOk = new Button (Style.OkButtonText) {
 				Y = Pos.AnchorEnd (1),
 				Y = Pos.AnchorEnd (1),
-				X = Pos.Function (() =>
-					this.Bounds.Width
-					- btnOk.Bounds.Width
-					// TODO: Fiddle factor, seems the Bounds are wrong for someone
-					- 2)
+				X = Pos.Function (CalculateOkButtonPosX)
 			};
 			};
 			this.btnOk.Clicked += (s, e) => this.Accept (true);
 			this.btnOk.Clicked += (s, e) => this.Accept (true);
 			this.btnOk.KeyPress += (s, k) => {
 			this.btnOk.KeyPress += (s, k) => {
@@ -156,14 +152,7 @@ namespace Terminal.Gui {
 
 
 			this.btnCancel = new Button (Strings.btnCancel) {
 			this.btnCancel = new Button (Strings.btnCancel) {
 				Y = Pos.AnchorEnd (1),
 				Y = Pos.AnchorEnd (1),
-				X = Pos.Function (() =>
-					this.Bounds.Width
-					- btnOk.Bounds.Width
-					- btnCancel.Bounds.Width
-					- 1
-					// TODO: Fiddle factor, seems the Bounds are wrong for someone
-					- 2
-					)
+				X = Pos.Right (btnOk) + 1
 			};
 			};
 			this.btnCancel.KeyPress += (s, k) => {
 			this.btnCancel.KeyPress += (s, k) => {
 				this.NavigateIf (k, Key.CursorLeft, this.btnToggleSplitterCollapse);
 				this.NavigateIf (k, Key.CursorLeft, this.btnToggleSplitterCollapse);
@@ -188,7 +177,6 @@ namespace Terminal.Gui {
 
 
 			this.tbPath = new TextField {
 			this.tbPath = new TextField {
 				Width = Dim.Fill (0),
 				Width = Dim.Fill (0),
-				Caption = Style.PathCaption,
 				CaptionColor = Color.Black
 				CaptionColor = Color.Black
 			};
 			};
 			this.tbPath.KeyPress += (s, k) => {
 			this.tbPath.KeyPress += (s, k) => {
@@ -285,7 +273,6 @@ namespace Terminal.Gui {
 
 
 			tbFind = new TextField {
 			tbFind = new TextField {
 				X = Pos.Right (this.btnToggleSplitterCollapse) + 1,
 				X = Pos.Right (this.btnToggleSplitterCollapse) + 1,
-				Caption = Style.SearchCaption,
 				CaptionColor = Color.Black,
 				CaptionColor = Color.Black,
 				Width = 30,
 				Width = 30,
 				Y = Pos.AnchorEnd (1),
 				Y = Pos.AnchorEnd (1),
@@ -373,17 +360,27 @@ namespace Terminal.Gui {
 			this.Add (this.splitContainer);
 			this.Add (this.splitContainer);
 		}
 		}
 
 
+		private int CalculateOkButtonPosX ()
+		{
+			return this.Bounds.Width
+				- btnOk.Bounds.Width
+				- btnCancel.Bounds.Width
+				- 1
+				// TODO: Fiddle factor, seems the Bounds are wrong for someone
+				- 2;
+		}
+
 		private string AspectGetter (object o)
 		private string AspectGetter (object o)
 		{
 		{
 			var fsi = (IFileSystemInfo)o;
 			var fsi = (IFileSystemInfo)o;
 
 
-			if(o is IDirectoryInfo dir && _treeRoots.ContainsKey(dir)) {
+			if (o is IDirectoryInfo dir && _treeRoots.ContainsKey (dir)) {
 
 
 				// Directory has a special name e.g. 'Pictures'
 				// Directory has a special name e.g. 'Pictures'
 				return _treeRoots [dir];
 				return _treeRoots [dir];
 			}
 			}
 
 
-			return (Style.IconProvider.GetIconWithOptionalSpace(fsi) + fsi.Name).Trim();
+			return (Style.IconProvider.GetIconWithOptionalSpace (fsi) + fsi.Name).Trim ();
 		}
 		}
 
 
 		private void OnTableViewMouseClick (object sender, MouseEventEventArgs e)
 		private void OnTableViewMouseClick (object sender, MouseEventEventArgs e)
@@ -644,11 +641,28 @@ namespace Terminal.Gui {
 
 
 			// May have been updated after instance was constructed
 			// May have been updated after instance was constructed
 			this.btnOk.Text = Style.OkButtonText;
 			this.btnOk.Text = Style.OkButtonText;
+			this.btnCancel.Text = Style.CancelButtonText;
 			this.btnUp.Text = this.GetUpButtonText ();
 			this.btnUp.Text = this.GetUpButtonText ();
 			this.btnBack.Text = this.GetBackButtonText ();
 			this.btnBack.Text = this.GetBackButtonText ();
 			this.btnForward.Text = this.GetForwardButtonText ();
 			this.btnForward.Text = this.GetForwardButtonText ();
 			this.btnToggleSplitterCollapse.Text = this.GetToggleSplitterText (false);
 			this.btnToggleSplitterCollapse.Text = this.GetToggleSplitterText (false);
 
 
+			if (Style.FlipOkCancelButtonLayoutOrder) {
+				btnCancel.X = Pos.Function (this.CalculateOkButtonPosX);
+				btnOk.X = Pos.Right (btnCancel) + 1;
+
+
+				// Flip tab order too for consistency
+				var p1 = this.btnOk.TabIndex;
+				var p2 = this.btnCancel.TabIndex;
+
+				this.btnOk.TabIndex = p2;
+				this.btnCancel.TabIndex = p1;
+			}
+
+			tbPath.Caption = Style.PathCaption;
+			tbFind.Caption = Style.SearchCaption;
+
 			tbPath.Autocomplete.ColorScheme.Normal = Attribute.Make (Color.Black, tbPath.ColorScheme.Normal.Background);
 			tbPath.Autocomplete.ColorScheme.Normal = Attribute.Make (Color.Black, tbPath.ColorScheme.Normal.Background);
 
 
 			_treeRoots = Style.TreeRootGetter ();
 			_treeRoots = Style.TreeRootGetter ();
@@ -700,7 +714,7 @@ namespace Terminal.Gui {
 
 
 			// if no path has been provided
 			// if no path has been provided
 			if (this.tbPath.Text.Length <= 0) {
 			if (this.tbPath.Text.Length <= 0) {
-				this.tbPath.Text = Environment.CurrentDirectory;
+				this.Path = Environment.CurrentDirectory;
 			}
 			}
 
 
 			// to streamline user experience and allow direct typing of paths
 			// to streamline user experience and allow direct typing of paths
@@ -803,7 +817,7 @@ namespace Terminal.Gui {
 				.Select (s => s.FileSystemInfo.FullName)
 				.Select (s => s.FileSystemInfo.FullName)
 				.ToList ().AsReadOnly ();
 				.ToList ().AsReadOnly ();
 
 
-			this.tbPath.Text = this.MultiSelected.Count == 1 ? this.MultiSelected [0] : string.Empty;
+			this.Path = this.MultiSelected.Count == 1 ? this.MultiSelected [0] : string.Empty;
 
 
 			FinishAccept ();
 			FinishAccept ();
 		}
 		}
@@ -816,7 +830,7 @@ namespace Terminal.Gui {
 				return;
 				return;
 			}
 			}
 
 
-			this.tbPath.Text = f.FullName;
+			this.Path = f.FullName;
 
 
 			if (AllowsMultipleSelection) {
 			if (AllowsMultipleSelection) {
 				this.MultiSelected = new List<string> { f.FullName }.AsReadOnly ();
 				this.MultiSelected = new List<string> { f.FullName }.AsReadOnly ();
@@ -895,7 +909,7 @@ namespace Terminal.Gui {
 				return;
 				return;
 			}
 			}
 
 
-			this.tbPath.Text = e.NewValue.FullName;
+			this.Path = e.NewValue.FullName;
 		}
 		}
 
 
 		private void UpdateNavigationVisibility ()
 		private void UpdateNavigationVisibility ()
@@ -931,7 +945,7 @@ namespace Terminal.Gui {
 			try {
 			try {
 				this.pushingState = true;
 				this.pushingState = true;
 
 
-				this.tbPath.Text = dest.FullName;
+				this.Path = dest.FullName;
 				this.State.Selected = stats;
 				this.State.Selected = stats;
 				this.tbPath.Autocomplete.ClearSuggestions ();
 				this.tbPath.Autocomplete.ClearSuggestions ();
 
 
@@ -1134,12 +1148,10 @@ namespace Terminal.Gui {
 				this.tbPath.Autocomplete.ClearSuggestions ();
 				this.tbPath.Autocomplete.ClearSuggestions ();
 
 
 				if (pathText != null) {
 				if (pathText != null) {
-					this.tbPath.Text = pathText;
-					this.tbPath.MoveEnd ();
+					this.Path = pathText;
 				} else
 				} else
 				if (setPathText) {
 				if (setPathText) {
-					this.tbPath.Text = newState.Directory.FullName;
-					this.tbPath.MoveEnd ();
+					this.Path = newState.Directory.FullName;
 				}
 				}
 
 
 				this.State = newState;
 				this.State = newState;
@@ -1185,13 +1197,13 @@ namespace Terminal.Gui {
 			}
 			}
 
 
 
 
-			var color = Style.ColorProvider.GetTrueColor(stats.FileSystemInfo)
-			??	TrueColor.FromConsoleColor(Color.White);
-			var black = TrueColor.FromConsoleColor(Color.Black);
+			var color = Style.ColorProvider.GetTrueColor (stats.FileSystemInfo)
+			?? TrueColor.FromConsoleColor (Color.White);
+			var black = TrueColor.FromConsoleColor (Color.Black);
 
 
 			// TODO: Add some kind of cache for this
 			// TODO: Add some kind of cache for this
-			return new ColorScheme{
-				Normal = new Attribute (color,black),
+			return new ColorScheme {
+				Normal = new Attribute (color, black),
 				HotNormal = new Attribute (color, black),
 				HotNormal = new Attribute (color, black),
 				Focus = new Attribute (black, color),
 				Focus = new Attribute (black, color),
 				HotFocus = new Attribute (black, color),
 				HotFocus = new Attribute (black, color),

+ 33 - 1
UICatalog/Scenarios/FileDialogExamples.cs

@@ -25,6 +25,9 @@ namespace UICatalog.Scenarios {
 		private RadioGroup rgIcons;
 		private RadioGroup rgIcons;
 		private RadioGroup rgAllowedTypes;
 		private RadioGroup rgAllowedTypes;
 
 
+		private TextField tbOkButton;
+		private TextField tbCancelButton;
+		private CheckBox cbFlipButtonOrder;
 		public override void Setup ()
 		public override void Setup ()
 		{
 		{
 			var y = 0;
 			var y = 0;
@@ -110,6 +113,25 @@ namespace UICatalog.Scenarios {
 			rgAllowedTypes.RadioLabels = new string [] { "Any", "Csv (Recommended)", "Csv (Strict)" };
 			rgAllowedTypes.RadioLabels = new string [] { "Any", "Csv (Recommended)", "Csv (Strict)" };
 			Win.Add (rgAllowedTypes);
 			Win.Add (rgAllowedTypes);
 
 
+			y = 5;
+			x = 45;
+
+			Win.Add (new LineView (Orientation.Vertical) {
+				X = x++,
+				Y = y + 1,
+				Height = 4
+			});
+			Win.Add (new Label ("Buttons") { X = x++, Y = y++ });
+
+			Win.Add (new Label ("Ok Text:") { X = x, Y = y++ });
+			tbOkButton = new TextField () { X = x, Y = y++, Width = 12 };
+			Win.Add (tbOkButton);
+			Win.Add (new Label ("Cancel Text:") { X = x, Y = y++ });
+			tbCancelButton = new TextField () { X = x, Y = y++, Width = 12 };
+			Win.Add (tbCancelButton);
+			cbFlipButtonOrder = new CheckBox ("Flip Order") { X = x, Y = y++ };
+			Win.Add (cbFlipButtonOrder);
+
 			var btn = new Button ($"Run Dialog") {
 			var btn = new Button ($"Run Dialog") {
 				X = 1,
 				X = 1,
 				Y = 9
 				Y = 9
@@ -165,7 +187,7 @@ namespace UICatalog.Scenarios {
 
 
 			if (cbDrivesOnlyInTree.Checked ?? false) {
 			if (cbDrivesOnlyInTree.Checked ?? false) {
 				fd.Style.TreeRootGetter = () => {
 				fd.Style.TreeRootGetter = () => {
-					return System.Environment.GetLogicalDrives ().ToDictionary(dirInfoFactory.New,k=>k);
+					return System.Environment.GetLogicalDrives ().ToDictionary (dirInfoFactory.New, k => k);
 				};
 				};
 			}
 			}
 
 
@@ -178,6 +200,16 @@ namespace UICatalog.Scenarios {
 
 
 			}
 			}
 
 
+			if (!string.IsNullOrWhiteSpace (tbOkButton.Text)) {
+				fd.Style.OkButtonText = tbOkButton.Text;
+			}
+			if (!string.IsNullOrWhiteSpace (tbCancelButton.Text)) {
+				fd.Style.CancelButtonText = tbCancelButton.Text;
+			}
+			if (cbFlipButtonOrder.Checked ?? false) {
+				fd.Style.FlipOkCancelButtonLayoutOrder = true;
+			}
+
 			Application.Run (fd);
 			Application.Run (fd);
 
 
 			if (fd.Canceled) {
 			if (fd.Canceled) {

+ 2 - 2
UnitTests/FileServices/FileDialogTests.cs

@@ -398,7 +398,7 @@ namespace Terminal.Gui.FileServicesTests {
  │                                                                  │
  │                                                                  │
  │                                                                  │
  │                                                                  │
  │                                                                  │
  │                                                                  │
-│{CM.Glyphs.LeftBracket} ►► {CM.Glyphs.RightBracket} Enter Search                            {CM.Glyphs.LeftBracket} Cancel {CM.Glyphs.RightBracket} {CM.Glyphs.LeftBracket} Ok {CM.Glyphs.RightBracket}  │
+│{CM.Glyphs.LeftBracket} ►► {CM.Glyphs.RightBracket} Enter Search                            {CM.Glyphs.LeftBracket} Ok {CM.Glyphs.RightBracket} {CM.Glyphs.LeftBracket} Cancel {CM.Glyphs.RightBracket}  │
  └──────────────────────────────────────────────────────────────────┘
  └──────────────────────────────────────────────────────────────────┘
 ";
 ";
 			TestHelpers.AssertDriverContentsAre (expected, output, true);
 			TestHelpers.AssertDriverContentsAre (expected, output, true);
@@ -434,7 +434,7 @@ namespace Terminal.Gui.FileServicesTests {
 ││mybinary.exe│7.00 bytes│2001-01-01T11:44:42           │.exe     ││
 ││mybinary.exe│7.00 bytes│2001-01-01T11:44:42           │.exe     ││
 │                                                                  │
 │                                                                  │
 │                                                                  │
 │                                                                  │
-│{CM.Glyphs.LeftBracket} ►► {CM.Glyphs.RightBracket} Enter Search                            {CM.Glyphs.LeftBracket} Cancel {CM.Glyphs.RightBracket} {CM.Glyphs.LeftBracket} Ok {CM.Glyphs.RightBracket}  │
+│{CM.Glyphs.LeftBracket} ►► {CM.Glyphs.RightBracket} Enter Search                            {CM.Glyphs.LeftBracket} Ok {CM.Glyphs.RightBracket} {CM.Glyphs.LeftBracket} Cancel {CM.Glyphs.RightBracket}  │
 └──────────────────────────────────────────────────────────────────┘
 └──────────────────────────────────────────────────────────────────┘
 ";
 ";
 			TestHelpers.AssertDriverContentsAre (expected, output, true);
 			TestHelpers.AssertDriverContentsAre (expected, output, true);