Skip to content

Commit

Permalink
Master search bar and misc GUI clean-up
Browse files Browse the repository at this point in the history
  • Loading branch information
HebaruSan committed May 5, 2020
1 parent 51d8f85 commit 6d897c7
Show file tree
Hide file tree
Showing 35 changed files with 4,878 additions and 3,063 deletions.
35 changes: 32 additions & 3 deletions GUI/CKAN-GUI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,18 @@
<Compile Include="Controls\ModInfo.Designer.cs">
<DependentUpon>ModInfo.cs</DependentUpon>
</Compile>
<Compile Include="Controls\EditModSearch.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Controls\EditModSearch.Designer.cs">
<DependentUpon>EditModSearch.cs</DependentUpon>
</Compile>
<Compile Include="Controls\ManageMods.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Controls\ManageMods.Designer.cs">
<DependentUpon>ManageMods.cs</DependentUpon>
</Compile>
<Compile Include="Controls\ThemedTabControl.cs" />
<Compile Include="Controls\ThemedListView.cs" />
<Compile Include="Controls\TransparentTextBox.cs">
Expand All @@ -235,6 +247,8 @@
<Compile Include="Model\ExportOption.cs" />
<Compile Include="Model\GUIMod.cs" />
<Compile Include="Model\ModChange.cs" />
<Compile Include="Model\ModList.cs" />
<Compile Include="Model\ModSearch.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="Main\Main.cs">
Expand Down Expand Up @@ -265,9 +279,6 @@
<SubType>Form</SubType>
</Compile>
<Compile Include="Main\MainLabels.cs" />
<Compile Include="Main\MainModList.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Main\MainRecommendations.cs">
<SubType>Form</SubType>
</Compile>
Expand Down Expand Up @@ -472,6 +483,24 @@
<EmbeddedResource Include="Controls\ModInfo.resx">
<DependentUpon>ModInfo.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Controls\ManageMods.resx">
<DependentUpon>ManageMods.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Localization\de-DE\ManageMods.de-DE.resx">
<DependentUpon>..\..\Controls\ManageMods.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Localization\zh-CN\ManageMods.zh-CN.resx">
<DependentUpon>..\..\Controls\ManageMods.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Controls\EditModSearch.resx">
<DependentUpon>EditModSearch.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Localization\de-DE\EditModSearch.de-DE.resx">
<DependentUpon>..\..\Controls\EditModSearch.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Localization\zh-CN\EditModSearch.zh-CN.resx">
<DependentUpon>..\..\Controls\EditModSearch.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Localization\de-DE\ModInfo.de-DE.resx">
<DependentUpon>..\..\Controls\ModInfo.cs</DependentUpon>
</EmbeddedResource>
Expand Down
342 changes: 342 additions & 0 deletions GUI/Controls/EditModSearch.Designer.cs

Large diffs are not rendered by default.

258 changes: 258 additions & 0 deletions GUI/Controls/EditModSearch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
using System;
using System.Linq;
using System.Drawing;
using System.Windows.Forms;
using Timer = System.Windows.Forms.Timer;
using log4net;

namespace CKAN
{
/// <summary>
/// A control for displaying and editing a search of mods.
/// Contains several separate fields for searching different properties,
/// plus a combined field that represents them all in a special syntax.
/// </summary>
public partial class EditModSearch : UserControl
{
/// <summary>
/// Initialize a mod search editing control
/// </summary>
public EditModSearch()
{
InitializeComponent();

this.ToolTip.SetToolTip(ExpandButton, Properties.Resources.EditModSearchTooltipExpandButton);

labels = new Label[]
{
FilterByNameLabel,
FilterByAuthorLabel,
FilterByDescriptionLabel,
FilterByLanguageLabel,
FilterByDependsLabel,
FilterByRecommendsLabel,
FilterBySuggestsLabel,
FilterByConflictsLabel,
FilterCombinedLabel,
};
textboxes = new TextBox[]
{
FilterByNameTextBox,
FilterByAuthorTextBox,
FilterByDescriptionTextBox,
FilterByLanguageTextBox,
FilterByDependsTextBox,
FilterByRecommendsTextBox,
FilterBySuggestsTextBox,
FilterByConflictsTextBox,
FilterCombinedTextBox,
};
rowCount = labels.Length;
maxLabelWidth = labels.Select(l => l.Width).Max();
DoLayout(ExpandButton.Checked);
}

/// <summary>
/// Clear the input fields
/// </summary>
public void Clear()
{
FilterCombinedTextBox.Text = "";
}

/// <summary>
/// Toggle whether the detailed controls are shown or hidden.
/// </summary>
public void ExpandCollapse()
{
ExpandButton.Checked = !ExpandButton.Checked;
}

/// <summary>
/// Event fired when a search needs to be executed.
/// </summary>
public event Action<ModSearch> ApplySearch;

/// <summary>
/// Event fired when user wants to switch focus away from this control.
/// </summary>
public event Action SurrenderFocus;

private static readonly ILog log = LogManager.GetLogger(typeof(EditModSearch));
private Label[] labels;
private TextBox[] textboxes;
private readonly int rowCount;
private const int rowHeight = 26;
private const int padding = 4;
private readonly int maxLabelWidth;
private Timer filterTimer;
private bool suppressSearch = false;
private ModSearch currentSearch = null;

private void ExpandButton_CheckedChanged(object sender, EventArgs e)
{
ExpandButton.Text = ExpandButton.Checked ? "▾" : "▴";
DoLayout(ExpandButton.Checked);
}

private void DoLayout(bool expanded)
{
if (expanded)
{
for (int row = 0; row < rowCount; ++row)
{
labels[row].Visible = true;
labels[row].Left = padding;
labels[row].Top = padding + row * (rowHeight + padding);
textboxes[row].Visible = true;
textboxes[row].Left = maxLabelWidth + 2 * padding;
textboxes[row].Top = padding + row * (rowHeight + padding);
}
Height = rowCount * (rowHeight + padding);
}
else
{
Height = rowHeight + padding;
for (int row = 0; row < labels.Length; ++row)
{
if (row < labels.Length - 1)
{
labels[row].Visible = false;
textboxes[row].Visible = false;
}
else
{
labels[row].Top = padding;
labels[row].Left = padding;
textboxes[row].Top = padding;
textboxes[row].Left = maxLabelWidth + 2 * padding;
}
}
}
var botTB = textboxes[rowCount - 1];
ExpandButton.Left = botTB.Left + botTB.Width;
ExpandButton.Top = botTB.Top;
ExpandButton.Height = botTB.Height;
ExpandButton.Width = botTB.Height;
}

private void FilterCombinedTextBox_TextChanged(object sender, EventArgs e)
{
if (suppressSearch)
return;

try
{
currentSearch = ModSearch.Parse(FilterCombinedTextBox.Text);
suppressSearch = true;
FilterByNameTextBox.Text = currentSearch?.Name ?? "";
FilterByAuthorTextBox.Text = currentSearch?.Author ?? "";
FilterByDescriptionTextBox.Text = currentSearch?.Description ?? "";
FilterByLanguageTextBox.Text = currentSearch?.Localization ?? "";
FilterByDependsTextBox.Text = currentSearch?.DependsOn ?? "";
FilterByRecommendsTextBox.Text = currentSearch?.Recommends ?? "";
FilterBySuggestsTextBox.Text = currentSearch?.Suggests ?? "";
FilterByConflictsTextBox.Text = currentSearch?.ConflictsWith ?? "";
suppressSearch = false;
TriggerSearchOrTimer();
}
catch (Kraken k)
{
Main.Instance.AddStatusMessage(k.Message);
}
}

private void FilterTextBox_TextChanged(object sender, EventArgs e)
{
if (suppressSearch)
return;

currentSearch = new ModSearch(
FilterByNameTextBox.Text,
FilterByAuthorTextBox.Text,
FilterByDescriptionTextBox.Text,
FilterByLanguageTextBox.Text,
FilterByDependsTextBox.Text,
FilterByRecommendsTextBox.Text,
FilterBySuggestsTextBox.Text,
FilterByConflictsTextBox.Text
);
suppressSearch = true;
FilterCombinedTextBox.Text = currentSearch?.Combined ?? "";
suppressSearch = false;
TriggerSearchOrTimer();
}

private void FilterTextBox_KeyDown(object sender, KeyEventArgs e)
{
// Switch focus from filters to mod list on enter, down, or pgdn
switch (e.KeyCode)
{
case Keys.Enter:
case Keys.Up:
case Keys.Down:
case Keys.PageUp:
case Keys.PageDown:
if (SurrenderFocus != null)
{
SurrenderFocus();
}
e.Handled = true;
break;
}
}

private void TriggerSearchOrTimer()
{
if (Platform.IsMac)
{
// Delay updating to improve typing performance on OS X.
RunFilterUpdateTimer();
}
else
{
TriggerSearch();
}
}

/// <summary>
/// Start or restart a timer to update the filter after an interval since the last keypress.
/// On Mac OS X, this prevents the search field from locking up due to DataGridViews being
/// slow and key strokes being interpreted incorrectly when slowed down:
/// http://mono.1490590.n4.nabble.com/Incorrect-missing-and-duplicate-keypress-events-td4658863.html
/// </summary>
private void RunFilterUpdateTimer()
{
if (filterTimer == null)
{
filterTimer = new Timer();
filterTimer.Tick += OnFilterUpdateTimer;
filterTimer.Interval = 700;
filterTimer.Start();
}
else
{
filterTimer.Stop();
filterTimer.Start();
}
}

/// <summary>
/// Updates the filter after an interval of time has passed since the last keypress.
/// </summary>
private void OnFilterUpdateTimer(object source, EventArgs e)
{
TriggerSearch();
filterTimer.Stop();
}

private void TriggerSearch()
{
if (ApplySearch != null)
{
ApplySearch(currentSearch);
}
}

}
}
Loading

0 comments on commit 6d897c7

Please sign in to comment.