mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2026-01-02 01:03:29 +01:00
Merge branch 'filedialog-features' into all-pull-request-at-once
This commit is contained in:
@@ -52,4 +52,4 @@
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -222,10 +222,13 @@ static class Demo {
|
||||
|
||||
public static void Open ()
|
||||
{
|
||||
var d = new OpenDialog ("Open", "Open a file");
|
||||
var d = new OpenDialog ("Open", "Open a file") {
|
||||
AllowsMultipleSelection = true
|
||||
};
|
||||
Application.Run (d);
|
||||
|
||||
MessageBox.Query (50, 7, "Selected File", string.Join (", ", d.FilePaths), "Ok");
|
||||
if (!d.Canceled)
|
||||
MessageBox.Query(50, 7, "Selected File", string.Join(", ", d.FilePaths), "Ok");
|
||||
}
|
||||
|
||||
public static void ShowHex (Toplevel top)
|
||||
|
||||
@@ -23,11 +23,13 @@ namespace Terminal.Gui {
|
||||
internal bool canChooseFiles = true;
|
||||
internal bool canChooseDirectories = false;
|
||||
internal bool allowsMultipleSelection = false;
|
||||
FileDialog host;
|
||||
|
||||
public DirListView ()
|
||||
public DirListView (FileDialog host)
|
||||
{
|
||||
infos = new List<(string,bool,bool)> ();
|
||||
CanFocus = true;
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
bool IsAllowed (FileSystemInfo fsi)
|
||||
@@ -71,6 +73,70 @@ namespace Terminal.Gui {
|
||||
Move (0, selected - top);
|
||||
}
|
||||
|
||||
int lastSelected;
|
||||
bool shiftOnWheel;
|
||||
public override bool MouseEvent (MouseEvent me)
|
||||
{
|
||||
if ((me.Flags & (MouseFlags.Button1Clicked | MouseFlags.Button1DoubleClicked |
|
||||
MouseFlags.WheeledUp | MouseFlags.WheeledDown)) == 0)
|
||||
return false;
|
||||
|
||||
if (!HasFocus)
|
||||
SuperView.SetFocus (this);
|
||||
|
||||
if (infos == null)
|
||||
return false;
|
||||
|
||||
if (me.Y + top >= infos.Count)
|
||||
return true;
|
||||
|
||||
int lastSelectedCopy = shiftOnWheel ? lastSelected : selected;
|
||||
lastSelected = selected;
|
||||
selected = top + me.Y;
|
||||
|
||||
switch (me.Flags) {
|
||||
case MouseFlags.Button1DoubleClicked:
|
||||
if (ExecuteSelection ()) {
|
||||
host.canceled = false;
|
||||
Application.RequestStop ();
|
||||
}
|
||||
return true;
|
||||
case MouseFlags.Button1Clicked | MouseFlags.ButtonShift:
|
||||
if (shiftOnWheel)
|
||||
lastSelected = lastSelectedCopy;
|
||||
shiftOnWheel = false;
|
||||
PerformMultipleSelection (lastSelected);
|
||||
return true;
|
||||
case MouseFlags.Button1Clicked | MouseFlags.ButtonCtrl:
|
||||
PerformMultipleSelection ();
|
||||
return true;
|
||||
case MouseFlags.WheeledUp:
|
||||
selected = lastSelected;
|
||||
MoveUp ();
|
||||
return true;
|
||||
case MouseFlags.WheeledDown:
|
||||
selected = lastSelected;
|
||||
MoveDown ();
|
||||
return true;
|
||||
case MouseFlags.WheeledUp | MouseFlags.ButtonShift:
|
||||
selected = lastSelected;
|
||||
lastSelected = lastSelectedCopy;
|
||||
shiftOnWheel = true;
|
||||
MoveUp ();
|
||||
return true;
|
||||
case MouseFlags.WheeledDown | MouseFlags.ButtonShift:
|
||||
selected = lastSelected;
|
||||
lastSelected = lastSelectedCopy;
|
||||
shiftOnWheel = true;
|
||||
MoveDown ();
|
||||
return true;
|
||||
}
|
||||
|
||||
SelectionChanged ();
|
||||
SetNeedsDisplay ();
|
||||
return true;
|
||||
}
|
||||
|
||||
void DrawString (int line, string str)
|
||||
{
|
||||
var f = Frame;
|
||||
@@ -91,7 +157,7 @@ namespace Terminal.Gui {
|
||||
}
|
||||
for (; used < width; used++) {
|
||||
Driver.AddRune (' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Redraw (Rect region)
|
||||
@@ -123,7 +189,7 @@ namespace Terminal.Gui {
|
||||
|
||||
if (allowsMultipleSelection)
|
||||
Driver.AddRune (fi.Item3 ? '*' : ' ');
|
||||
|
||||
|
||||
if (fi.Item2)
|
||||
Driver.AddRune ('/');
|
||||
else
|
||||
@@ -138,35 +204,38 @@ namespace Terminal.Gui {
|
||||
|
||||
void SelectionChanged ()
|
||||
{
|
||||
if (FilePaths.Count > 0)
|
||||
FileChanged?.Invoke (string.Join (", ", GetFilesName (FilePaths)));
|
||||
else
|
||||
FileChanged?.Invoke (infos [selected].Item2 ? "" : Path.GetFileName (infos [selected].Item1));
|
||||
if (SelectedChanged != null) {
|
||||
var sel = infos [selected];
|
||||
SelectedChanged ((sel.Item1, sel.Item2));
|
||||
}
|
||||
}
|
||||
|
||||
List<string> GetFilesName (IReadOnlyList<string> files)
|
||||
{
|
||||
List<string> filesName = new List<string> ();
|
||||
|
||||
foreach (var file in files) {
|
||||
filesName.Add (Path.GetFileName (file));
|
||||
}
|
||||
|
||||
return filesName;
|
||||
}
|
||||
|
||||
public override bool ProcessKey (KeyEvent keyEvent)
|
||||
{
|
||||
switch (keyEvent.Key) {
|
||||
case Key.CursorUp:
|
||||
case Key.ControlP:
|
||||
if (selected > 0) {
|
||||
selected--;
|
||||
if (selected < top)
|
||||
top = selected;
|
||||
SelectionChanged ();
|
||||
SetNeedsDisplay ();
|
||||
}
|
||||
MoveUp ();
|
||||
return true;
|
||||
|
||||
case Key.CursorDown:
|
||||
case Key.ControlN:
|
||||
if (selected + 1 < infos.Count) {
|
||||
selected++;
|
||||
if (selected >= top + Frame.Height)
|
||||
top++;
|
||||
SelectionChanged ();
|
||||
SetNeedsDisplay ();
|
||||
}
|
||||
MoveDown ();
|
||||
return true;
|
||||
|
||||
case Key.ControlV:
|
||||
@@ -187,22 +256,10 @@ namespace Terminal.Gui {
|
||||
return true;
|
||||
|
||||
case Key.Enter:
|
||||
var isDir = infos [selected].Item2;
|
||||
|
||||
if (isDir) {
|
||||
Directory = Path.GetFullPath (Path.Combine (Path.GetFullPath (Directory.ToString ()), infos [selected].Item1));
|
||||
if (DirectoryChanged != null)
|
||||
DirectoryChanged (Directory);
|
||||
} else {
|
||||
if (FileChanged != null)
|
||||
FileChanged (infos [selected].Item1);
|
||||
if (canChooseFiles) {
|
||||
// Let the OK handler take it over
|
||||
return false;
|
||||
}
|
||||
// No files allowed, do not let the default handler take it.
|
||||
}
|
||||
return true;
|
||||
if (ExecuteSelection ())
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
|
||||
case Key.PageUp:
|
||||
n = (selected - Frame.Height);
|
||||
@@ -217,21 +274,97 @@ namespace Terminal.Gui {
|
||||
return true;
|
||||
|
||||
case Key.Space:
|
||||
case Key.ControlT:
|
||||
if (allowsMultipleSelection) {
|
||||
if ((canChooseFiles && infos [selected].Item2 == false) ||
|
||||
(canChooseDirectories && infos [selected].Item2 &&
|
||||
infos [selected].Item1 != "..")){
|
||||
infos [selected] = (infos [selected].Item1, infos [selected].Item2, !infos [selected].Item3);
|
||||
SelectionChanged ();
|
||||
SetNeedsDisplay ();
|
||||
}
|
||||
}
|
||||
case Key.ControlT:
|
||||
PerformMultipleSelection ();
|
||||
return true;
|
||||
|
||||
case Key.Home:
|
||||
MoveFirst ();
|
||||
return true;
|
||||
|
||||
case Key.End:
|
||||
MoveLast ();
|
||||
return true;
|
||||
}
|
||||
return base.ProcessKey (keyEvent);
|
||||
}
|
||||
|
||||
private void MoveLast ()
|
||||
{
|
||||
selected = infos.Count - 1;
|
||||
top = infos.Count () - 1;
|
||||
SelectionChanged ();
|
||||
SetNeedsDisplay ();
|
||||
}
|
||||
|
||||
private void MoveFirst ()
|
||||
{
|
||||
selected = 0;
|
||||
top = 0;
|
||||
SelectionChanged ();
|
||||
SetNeedsDisplay ();
|
||||
}
|
||||
|
||||
private void MoveDown ()
|
||||
{
|
||||
if (selected + 1 < infos.Count) {
|
||||
selected++;
|
||||
if (selected >= top + Frame.Height)
|
||||
top++;
|
||||
SelectionChanged ();
|
||||
SetNeedsDisplay ();
|
||||
}
|
||||
}
|
||||
|
||||
private void MoveUp ()
|
||||
{
|
||||
if (selected > 0) {
|
||||
selected--;
|
||||
if (selected < top)
|
||||
top = selected;
|
||||
SelectionChanged ();
|
||||
SetNeedsDisplay ();
|
||||
}
|
||||
}
|
||||
|
||||
internal bool ExecuteSelection ()
|
||||
{
|
||||
var isDir = infos [selected].Item2;
|
||||
|
||||
if (isDir) {
|
||||
Directory = Path.GetFullPath (Path.Combine (Path.GetFullPath (Directory.ToString ()), infos [selected].Item1));
|
||||
DirectoryChanged?.Invoke (Directory);
|
||||
} else {
|
||||
FileChanged?.Invoke (infos [selected].Item1);
|
||||
if (canChooseFiles) {
|
||||
// Ensures that at least one file is selected.
|
||||
if (FilePaths.Count == 0)
|
||||
PerformMultipleSelection ();
|
||||
// Let the OK handler take it over
|
||||
return true;
|
||||
}
|
||||
// No files allowed, do not let the default handler take it.
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void PerformMultipleSelection (int? firstSelected = null)
|
||||
{
|
||||
if (allowsMultipleSelection) {
|
||||
int first = Math.Min (firstSelected ?? selected, selected);
|
||||
int last = Math.Max (selected, firstSelected ?? selected);
|
||||
for (int i = first; i <= last; i++) {
|
||||
if ((canChooseFiles && infos [i].Item2 == false) ||
|
||||
(canChooseDirectories && infos [i].Item2 &&
|
||||
infos [i].Item1 != "..")) {
|
||||
infos [i] = (infos [i].Item1, infos [i].Item2, !infos [i].Item3);
|
||||
}
|
||||
}
|
||||
SelectionChanged ();
|
||||
SetNeedsDisplay ();
|
||||
}
|
||||
}
|
||||
|
||||
string [] allowedFileTypes;
|
||||
public string [] AllowedFileTypes {
|
||||
get => allowedFileTypes;
|
||||
@@ -306,18 +439,16 @@ namespace Terminal.Gui {
|
||||
};
|
||||
Add (this.nameFieldLabel, nameEntry);
|
||||
|
||||
dirListView = new DirListView () {
|
||||
dirListView = new DirListView (this) {
|
||||
X = 1,
|
||||
Y = 3 + msgLines + 2,
|
||||
Width = Dim.Fill () - 2,
|
||||
Width = Dim.Fill () - 3,
|
||||
Height = Dim.Fill () - 2,
|
||||
};
|
||||
DirectoryPath = Path.GetFullPath (Environment.CurrentDirectory);
|
||||
Add (dirListView);
|
||||
dirListView.DirectoryChanged = (dir) => dirEntry.Text = dir;
|
||||
dirListView.FileChanged = (file) => {
|
||||
nameEntry.Text = file;
|
||||
};
|
||||
dirListView.FileChanged = (file) => nameEntry.Text = file;
|
||||
|
||||
this.cancel = new Button ("Cancel");
|
||||
this.cancel.Clicked += () => {
|
||||
@@ -330,6 +461,7 @@ namespace Terminal.Gui {
|
||||
IsDefault = true,
|
||||
};
|
||||
this.prompt.Clicked += () => {
|
||||
dirListView.ExecuteSelection ();
|
||||
canceled = false;
|
||||
Application.RequestStop ();
|
||||
};
|
||||
@@ -430,6 +562,8 @@ namespace Terminal.Gui {
|
||||
nameEntry.Text = Path.GetFileName(value.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public bool Canceled { get => canceled; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -151,7 +151,8 @@ namespace Terminal.Gui {
|
||||
Button3Pressed = 8,
|
||||
Button4Pressed = 16,
|
||||
RightmostButtonPressed = 2,
|
||||
|
||||
WheeledUp = unchecked((int)0x780000),
|
||||
WheeledDown = unchecked((int)0xFF880000),
|
||||
}
|
||||
|
||||
[Flags]
|
||||
@@ -595,7 +596,7 @@ namespace Terminal.Gui {
|
||||
mouseFlag = MouseFlags.Button2Pressed;
|
||||
break;
|
||||
|
||||
case WindowsConsole.ButtonState.Button3Pressed:
|
||||
case WindowsConsole.ButtonState.RightmostButtonPressed:
|
||||
mouseFlag = MouseFlags.Button3Pressed;
|
||||
break;
|
||||
}
|
||||
@@ -610,11 +611,57 @@ namespace Terminal.Gui {
|
||||
mouseFlag = MouseFlags.Button2Clicked;
|
||||
break;
|
||||
|
||||
case WindowsConsole.ButtonState.Button3Pressed:
|
||||
case WindowsConsole.ButtonState.RightmostButtonPressed:
|
||||
mouseFlag = MouseFlags.Button3Clicked;
|
||||
break;
|
||||
}
|
||||
LastMouseButtonPressed = null;
|
||||
|
||||
switch (mouseEvent.ControlKeyState) {
|
||||
case WindowsConsole.ControlKeyState.RightControlPressed:
|
||||
case WindowsConsole.ControlKeyState.LeftControlPressed:
|
||||
mouseFlag |= MouseFlags.ButtonCtrl;
|
||||
break;
|
||||
|
||||
case WindowsConsole.ControlKeyState.ShiftPressed:
|
||||
mouseFlag |= MouseFlags.ButtonShift;
|
||||
break;
|
||||
}
|
||||
} else if (mouseEvent.EventFlags == WindowsConsole.EventFlags.DoubleClick) {
|
||||
switch (mouseEvent.ButtonState) {
|
||||
case WindowsConsole.ButtonState.Button1Pressed:
|
||||
mouseFlag = MouseFlags.Button1DoubleClicked;
|
||||
break;
|
||||
|
||||
case WindowsConsole.ButtonState.Button2Pressed:
|
||||
mouseFlag = MouseFlags.Button2DoubleClicked;
|
||||
break;
|
||||
|
||||
case WindowsConsole.ButtonState.RightmostButtonPressed:
|
||||
mouseFlag = MouseFlags.Button3DoubleClicked;
|
||||
break;
|
||||
}
|
||||
} else if (mouseEvent.EventFlags == WindowsConsole.EventFlags.MouseWheeled) {
|
||||
switch (mouseEvent.ButtonState) {
|
||||
case WindowsConsole.ButtonState.WheeledUp:
|
||||
mouseFlag = MouseFlags.WheeledUp;
|
||||
break;
|
||||
|
||||
case WindowsConsole.ButtonState.WheeledDown:
|
||||
mouseFlag = MouseFlags.WheeledDown;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (mouseEvent.ControlKeyState) {
|
||||
case WindowsConsole.ControlKeyState.RightControlPressed:
|
||||
case WindowsConsole.ControlKeyState.LeftControlPressed:
|
||||
mouseFlag |= MouseFlags.ButtonCtrl;
|
||||
break;
|
||||
|
||||
case WindowsConsole.ControlKeyState.ShiftPressed:
|
||||
mouseFlag |= MouseFlags.ButtonShift;
|
||||
break;
|
||||
}
|
||||
} else if (mouseEvent.EventFlags == WindowsConsole.EventFlags.MouseMoved) {
|
||||
mouseFlag = MouseFlags.ReportMousePosition;
|
||||
}
|
||||
|
||||
@@ -336,7 +336,7 @@ namespace Terminal.Gui {
|
||||
/// </summary>
|
||||
Button1DoubleClicked = unchecked((int)0x8),
|
||||
/// <summary>
|
||||
/// The first mouse button was tripple-clicked.
|
||||
/// The first mouse button was triple-clicked.
|
||||
/// </summary>
|
||||
Button1TripleClicked = unchecked((int)0x10),
|
||||
/// <summary>
|
||||
@@ -356,7 +356,7 @@ namespace Terminal.Gui {
|
||||
/// </summary>
|
||||
Button2DoubleClicked = unchecked((int)0x200),
|
||||
/// <summary>
|
||||
/// The second mouse button was tripple-clicked.
|
||||
/// The second mouse button was triple-clicked.
|
||||
/// </summary>
|
||||
Button2TrippleClicked = unchecked((int)0x400),
|
||||
/// <summary>
|
||||
@@ -376,7 +376,7 @@ namespace Terminal.Gui {
|
||||
/// </summary>
|
||||
Button3DoubleClicked = unchecked((int)0x8000),
|
||||
/// <summary>
|
||||
/// The third mouse button was tripple-clicked.
|
||||
/// The third mouse button was triple-clicked.
|
||||
/// </summary>
|
||||
Button3TripleClicked = unchecked((int)0x10000),
|
||||
/// <summary>
|
||||
@@ -396,15 +396,15 @@ namespace Terminal.Gui {
|
||||
/// </summary>
|
||||
Button4DoubleClicked = unchecked((int)0x200000),
|
||||
/// <summary>
|
||||
/// The fourth button was tripple-clicked.
|
||||
/// The fourth button was triple-clicked.
|
||||
/// </summary>
|
||||
Button4TripleClicked = unchecked((int)0x400000),
|
||||
/// <summary>
|
||||
/// The fourth button was pressed.
|
||||
/// Flag: the shift key was pressed when the mouse button took place.
|
||||
/// </summary>
|
||||
ButtonShift = unchecked((int)0x2000000),
|
||||
/// <summary>
|
||||
/// Flag: the shift key was pressed when the mouse button took place.
|
||||
/// Flag: the ctrl key was pressed when the mouse button took place.
|
||||
/// </summary>
|
||||
ButtonCtrl = unchecked((int)0x1000000),
|
||||
/// <summary>
|
||||
@@ -416,6 +416,14 @@ namespace Terminal.Gui {
|
||||
/// </summary>
|
||||
ReportMousePosition = unchecked((int)0x8000000),
|
||||
/// <summary>
|
||||
/// Vertical button wheeled up.
|
||||
/// </summary>
|
||||
WheeledUp = unchecked((int)0x10000000),
|
||||
/// <summary>
|
||||
/// Vertical button wheeled up.
|
||||
/// </summary>
|
||||
WheeledDown = unchecked((int)0x20000000),
|
||||
/// <summary>
|
||||
/// Mask that captures all the events.
|
||||
/// </summary>
|
||||
AllEvents = unchecked((int)0x7ffffff),
|
||||
|
||||
Reference in New Issue
Block a user