Skip to content

Commit

Permalink
Work around OpenFileDialog always showing all shortcuts despite filters
Browse files Browse the repository at this point in the history
  • Loading branch information
HebaruSan committed Aug 21, 2024
1 parent 9fc1313 commit 82e5c35
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 46 deletions.
115 changes: 71 additions & 44 deletions GUI/Dialogs/ManageGameInstancesDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,42 +18,24 @@ namespace CKAN.GUI
#endif
public partial class ManageGameInstancesDialog : Form
{
private static GameInstanceManager manager => Main.Instance.Manager;
private readonly IUser _user;
private RenameInstanceDialog _renameInstanceDialog;
private readonly OpenFileDialog _instanceDialog = new OpenFileDialog()
{
AddExtension = false,
CheckFileExists = false,
CheckPathExists = false,
InitialDirectory = Environment.CurrentDirectory,
Filter = GameFolderFilter(manager),
Multiselect = false
};

/// <summary>
/// Generate filter string for OpenFileDialog
/// </summary>
/// <param name="mgr">Game instance manager that can tell us about the build ID files</param>
/// <returns>
/// "Build metadata files (buildID.txt;buildID64.txt)|buildID.txt;buildID64.txt"
/// </returns>
public static string GameFolderFilter(GameInstanceManager mgr)
=> Properties.Resources.GameProgramFileDescription
+ "|" + string.Join(";", mgr.AllInstanceAnchorFiles);

public bool HasSelections => GameInstancesListView.SelectedItems.Count > 0;

/// <summary>
/// Initialize the game instance selection window
/// </summary>
/// <param name="mgr">Game instance manager object to provide our game instances</param>
/// <param name="centerScreen">true to center the window on the screen, false to center it on the parent</param>
public ManageGameInstancesDialog(bool centerScreen, IUser user)
/// <param name="user">IUser object reference for raising dialogs</param>
public ManageGameInstancesDialog(GameInstanceManager mgr,
bool centerScreen,
IUser user)
{
_user = user;
manager = mgr;
this.user = user;
InitializeComponent();
DialogResult = DialogResult.Cancel;

instanceDialog.Filter = GameFolderFilter(manager);
instanceDialog.FileOk += InstanceFileOK;

if (centerScreen)
{
StartPosition = FormStartPosition.CenterScreen;
Expand Down Expand Up @@ -101,6 +83,19 @@ public void UpdateInstancesList()
GameInstancesListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
}

/// <summary>
/// Generate filter string for OpenFileDialog
/// </summary>
/// <param name="mgr">Game instance manager that can tell us about the build ID files</param>
/// <returns>
/// "Build metadata files (buildID.txt;buildID64.txt)|buildID.txt;buildID64.txt"
/// </returns>
public static string GameFolderFilter(GameInstanceManager mgr)
=> Properties.Resources.GameProgramFileDescription
+ "|" + string.Join(";", mgr.AllInstanceAnchorFiles);

public bool HasSelections => GameInstancesListView.SelectedItems.Count > 0;

private void AddOrRemoveColumn(ListView listView, ColumnHeader column, bool condition, int index)
{
if (condition && !listView.Columns.Contains(column))
Expand Down Expand Up @@ -157,22 +152,20 @@ protected override void OnHelpButtonClicked(CancelEventArgs evt)
}

private static string FormatVersion(GameVersion v)
{
return v == null
=> v == null
? Properties.Resources.CompatibleGameVersionsDialogNone
// The BUILD component is not useful visually
: new GameVersion(v.Major, v.Minor, v.Patch).ToString();
}

private void AddToCKANMenuItem_Click(object sender, EventArgs e)
{
if (_instanceDialog.ShowDialog(this) != DialogResult.OK
|| !File.Exists(_instanceDialog.FileName))
if (instanceDialog.ShowDialog(this) != DialogResult.OK
|| !File.Exists(instanceDialog.FileName))
{
return;
}

var path = Path.GetDirectoryName(_instanceDialog.FileName);
var path = Path.GetDirectoryName(instanceDialog.FileName);
try
{
var instanceName = Path.GetFileName(path);
Expand All @@ -181,17 +174,17 @@ private void AddToCKANMenuItem_Click(object sender, EventArgs e)
instanceName = path;
}
instanceName = manager.GetNextValidInstanceName(instanceName);
manager.AddInstance(path, instanceName, _user);
manager.AddInstance(path, instanceName, user);
UpdateInstancesList();
}
catch (NotKSPDirKraken k)
{
_user.RaiseError(Properties.Resources.ManageGameInstancesNotValid,
user.RaiseError(Properties.Resources.ManageGameInstancesNotValid,
new object[] { k.path });
}
catch (Exception exc)
{
_user.RaiseError(exc.Message);
user.RaiseError(exc.Message);
}
}

Expand All @@ -213,7 +206,7 @@ private void CloneGameInstanceMenuItem_Click(object sender, EventArgs e)
{
var old_instance = manager.CurrentInstance;

var result = new CloneGameInstanceDialog(manager, _user, (string)GameInstancesListView.SelectedItems[0].Tag).ShowDialog(this);
var result = new CloneGameInstanceDialog(manager, user, (string)GameInstancesListView.SelectedItems[0].Tag).ShowDialog(this);
if (result == DialogResult.OK && !Equals(old_instance, manager.CurrentInstance))
{
DialogResult = DialogResult.OK;
Expand Down Expand Up @@ -246,7 +239,7 @@ private void UseSelectedInstance()
}
catch (NotKSPDirKraken k)
{
_user.RaiseError(Properties.Resources.ManageGameInstancesNotValid, k.path);
user.RaiseError(Properties.Resources.ManageGameInstancesNotValid, k.path);
}
}
}
Expand All @@ -270,7 +263,7 @@ private void SetAsDefaultCheckbox_Click(object sender, EventArgs e)
}
catch (NotKSPDirKraken k)
{
_user.RaiseError(Properties.Resources.ManageGameInstancesNotValid, k.path);
user.RaiseError(Properties.Resources.ManageGameInstancesNotValid, k.path);
}
}
}
Expand Down Expand Up @@ -321,7 +314,7 @@ private void OpenDirectoryMenuItem_Click(object sender, EventArgs e)

if (!Directory.Exists(path))
{
_user.RaiseError(Properties.Resources.ManageGameInstancesDirectoryDeleted, path);
user.RaiseError(Properties.Resources.ManageGameInstancesDirectoryDeleted, path);
return;
}

Expand All @@ -333,14 +326,14 @@ private void RenameButton_Click(object sender, EventArgs e)
var instance = (string)GameInstancesListView.SelectedItems[0].Tag;

// show the dialog, and only continue if the user selected "OK"
_renameInstanceDialog = new RenameInstanceDialog();
if (_renameInstanceDialog.ShowRenameInstanceDialog(instance) != DialogResult.OK)
var renameInstanceDialog = new RenameInstanceDialog();
if (renameInstanceDialog.ShowRenameInstanceDialog(instance) != DialogResult.OK)
{
return;
}

// proceed with instance rename
manager.RenameInstance(instance, _renameInstanceDialog.GetResult());
manager.RenameInstance(instance, renameInstanceDialog.GetResult());
UpdateInstancesList();
}

Expand All @@ -359,5 +352,39 @@ private void UpdateButtonState()
ForgetButton.Enabled = HasSelections && (string)GameInstancesListView.SelectedItems[0].Tag != manager.CurrentInstance?.Name;
ImportFromSteamMenuItem.Enabled = manager.SteamLibrary.Games.Length > 0;
}

private readonly GameInstanceManager manager;

private readonly IUser user;

private readonly OpenFileDialog instanceDialog = new OpenFileDialog()
{
AddExtension = false,
CheckFileExists = false,
CheckPathExists = false,
DereferenceLinks = false,
InitialDirectory = Environment.CurrentDirectory,
Multiselect = false,
};

private void InstanceFileOK(object sender, CancelEventArgs e)
{
if (sender is OpenFileDialog dlg)
{
// OpenFileDialog always shows shortcuts (!!!!!),
// so we have to re-enforce the filter ourselves
var chosen = Path.GetFileName(dlg.FileName);
var allowed = manager.AllInstanceAnchorFiles;
if (!allowed.Contains(chosen))
{
e.Cancel = true;
user.RaiseError(Properties.Resources.ManageGameInstancesInvalidFileSelected,
chosen,
string.Join(Environment.NewLine,
allowed.OrderBy(f => f)
.Select(f => $" - {f}")));
}
}
}
}
}
4 changes: 2 additions & 2 deletions GUI/Main/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ private bool InstancePromptAtStart()
bool gotInstance = false;
Util.Invoke(this, () =>
{
var result = new ManageGameInstancesDialog(!actuallyVisible, currentUser).ShowDialog(this);
var result = new ManageGameInstancesDialog(Manager, !actuallyVisible, currentUser).ShowDialog(this);
gotInstance = result == DialogResult.OK;
});
return gotInstance;
Expand All @@ -335,7 +335,7 @@ private bool InstancePromptAtStart()
private void manageGameInstancesMenuItem_Click(object sender, EventArgs e)
{
var old_instance = CurrentInstance;
var result = new ManageGameInstancesDialog(!actuallyVisible, currentUser).ShowDialog(this);
var result = new ManageGameInstancesDialog(Manager, !actuallyVisible, currentUser).ShowDialog(this);
if (result == DialogResult.OK && !Equals(old_instance, CurrentInstance))
{
for (bool done = false; !done;)
Expand Down
7 changes: 7 additions & 0 deletions GUI/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,13 @@ You can refresh the mod list manually with the Refresh button at the top, and yo
<data name="ManageGameInstancesDirectoryDeleted" xml:space="preserve"><value>Directory "{0}" doesn't exist.</value></data>
<data name="ManageGameInstancesNameColumnInvalid" xml:space="preserve"><value>{0} (INVALID)</value></data>
<data name="ManageGameInstancesNameColumnLocked" xml:space="preserve"><value>{0} (LOCKED)</value></data>
<data name="ManageGameInstancesInvalidFileSelected" xml:space="preserve"><value>Not a valid game instance file: "{0}"

If you selected a shortcut, don't do that; Windows won't let us hide them from this dialog even though they're invalid.

Find the folder where your game is installed and choose one of these files:

{1}</value></data>
<data name="NewRepoDialogFailed" xml:space="preserve"><value>Failed to fetch master list.</value></data>
<data name="PluginsDialogFilter" xml:space="preserve"><value>CKAN Plugins (*.dll)|*.dll</value></data>
<data name="SettingsDialogSummmary" xml:space="preserve"><value>{0} files, {1}, {2} free</value></data>
Expand Down

0 comments on commit 82e5c35

Please sign in to comment.