mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-30 15:41:30 +00:00
6177c9cca9
Fixed, Map Analysis window: fixed an exception on copying warnings to clipboard when the clipboard was used by other application. Fixed, TEXTURES parser: added special handling for "TNT1A0" sprite name so a texture with this sprite as a single patch is no longer treated as failed loading. Fixed, Visual mode: in some cases (like line slopes used in several adjacent sectors) sector effect updates were triggered multiple times for the same sector, resulting in noticeable slowdowns and in some cases in infinite recursion. Updated ZDoom ACC.
770 lines
21 KiB
C#
770 lines
21 KiB
C#
|
|
#region ================== Copyright (c) 2007 Pascal vd Heiden
|
|
|
|
/*
|
|
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
|
|
* This program is released under GNU General Public License
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
*/
|
|
|
|
#endregion
|
|
|
|
#region ================== Namespaces
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Globalization;
|
|
using System.Windows.Forms;
|
|
using CodeImp.DoomBuilder.Data;
|
|
using CodeImp.DoomBuilder.Windows;
|
|
|
|
#endregion
|
|
|
|
namespace CodeImp.DoomBuilder.Controls
|
|
{
|
|
internal partial class ImageBrowserControl : UserControl
|
|
{
|
|
#region ================== Constants
|
|
|
|
#endregion
|
|
|
|
#region ================== Delegates / Events
|
|
|
|
public delegate void SelectedItemChangedDelegate();
|
|
public delegate void SelectedItemDoubleClickDelegate();
|
|
|
|
public event SelectedItemChangedDelegate SelectedItemChanged;
|
|
public event SelectedItemDoubleClickDelegate SelectedItemDoubleClicked;
|
|
|
|
#endregion
|
|
|
|
#region ================== Variables
|
|
|
|
// Properties
|
|
private bool preventselection;
|
|
|
|
// States
|
|
private bool updating;
|
|
private int keepselected;
|
|
private bool browseFlats; //mxd
|
|
private static bool uselongtexturenames; //mxd
|
|
private static bool showtexturesfromsubdirs; //mxd
|
|
private int currentlevel; //mxd
|
|
|
|
// All items
|
|
private readonly List<ImageBrowserItem> items;
|
|
|
|
// Items visible in the list
|
|
private List<ImageBrowserItem> visibleitems;
|
|
|
|
//mxd
|
|
private static int mixMode;
|
|
|
|
#endregion
|
|
|
|
#region ================== Properties
|
|
|
|
public bool PreventSelection { get { return preventselection; } set { preventselection = value; } }
|
|
public bool HideInputBox { get { return splitter.Panel2Collapsed; } set { splitter.Panel2Collapsed = value; } }
|
|
public bool BrowseFlats { get { return browseFlats; } set { browseFlats = value; } } //mxd
|
|
public static bool ShowTexturesFromSubDirectories { get { return showtexturesfromsubdirs; } internal set { showtexturesfromsubdirs = value; } } //mxd
|
|
public static bool UseLongTextureNames { get { return uselongtexturenames; } internal set { uselongtexturenames = value; } } //mxd
|
|
public ListViewItem SelectedItem { get { if(list.SelectedItems.Count > 0) return list.SelectedItems[0]; else return null; } }
|
|
|
|
#endregion
|
|
|
|
#region ================== Constructor / Disposer
|
|
|
|
// Constructor
|
|
public ImageBrowserControl()
|
|
{
|
|
// Initialize
|
|
InitializeComponent();
|
|
items = new List<ImageBrowserItem>();
|
|
|
|
//mxd
|
|
StepsList sizes = new StepsList { 4, 8, 16, 32, 48, 64, 96, 128, 196, 256, 512, 1024 };
|
|
filterWidth.StepValues = sizes;
|
|
filterHeight.StepValues = sizes;
|
|
|
|
//mxd. Looks like SplitterDistance is unaffected by DPI scaling. Let's fix that...
|
|
if(MainForm.DPIScaler.Height != 1.0f)
|
|
{
|
|
splitter.SplitterDistance = splitter.Height - splitter.Panel2.Height - (int)Math.Round(splitter.SplitterWidth * MainForm.DPIScaler.Height);
|
|
}
|
|
}
|
|
|
|
// This applies the application settings
|
|
public void ApplySettings()
|
|
{
|
|
// Force black background?
|
|
if(General.Settings.BlackBrowsers)
|
|
{
|
|
list.BackColor = Color.Black;
|
|
list.ForeColor = Color.White;
|
|
}
|
|
|
|
// Set the size of preview images
|
|
if(General.Map != null)
|
|
{
|
|
int itemwidth = General.Map.Data.Previews.MaxImageWidth + 26;
|
|
int itemheight = General.Map.Data.Previews.MaxImageHeight + 26;
|
|
list.TileSize = new Size(itemwidth, itemheight);
|
|
|
|
//mxd
|
|
if(General.Map.Config.MixTexturesFlats)
|
|
{
|
|
cbMixMode.SelectedIndex = mixMode;
|
|
}
|
|
else
|
|
{
|
|
labelMixMode.Visible = false;
|
|
cbMixMode.Visible = false;
|
|
|
|
int offset = label.Left - labelMixMode.Left;
|
|
label.Left -= offset;
|
|
objectname.Left -= offset;
|
|
filterWidth.Left -= offset;
|
|
filterwidthlabel.Left -= offset;
|
|
filterHeight.Left -= offset;
|
|
filterheightlabel.Left -= offset;
|
|
showsubdirtextures.Left -= offset;
|
|
longtexturenames.Left -= offset;
|
|
|
|
mixMode = 0;
|
|
}
|
|
|
|
//mxd. Use long texture names?
|
|
longtexturenames.Checked = (uselongtexturenames && General.Map.Config.UseLongTextureNames);
|
|
longtexturenames.Visible = General.Map.Config.UseLongTextureNames;
|
|
if(!General.Map.Config.UseLongTextureNames)
|
|
showsubdirtextures.Left = longtexturenames.Left; //mxd
|
|
}
|
|
else
|
|
{
|
|
longtexturenames.Visible = false; //mxd
|
|
uselongtexturenames = false; //mxd
|
|
showsubdirtextures.Left = longtexturenames.Left; //mxd
|
|
}
|
|
|
|
//mxd
|
|
if(!General.Settings.CapitalizeTextureNames)
|
|
objectname.CharacterCasing = CharacterCasing.Normal;
|
|
|
|
//mxd. Show textures in subfolders?
|
|
showsubdirtextures.Checked = showtexturesfromsubdirs;
|
|
}
|
|
|
|
// This cleans everything up
|
|
public virtual void CleanUp()
|
|
{
|
|
// Stop refresh timer
|
|
refreshtimer.Enabled = false;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Rendering
|
|
|
|
// Draw item
|
|
private void list_DrawItem(object sender, DrawListViewItemEventArgs e)
|
|
{
|
|
if(!updating) (e.Item as ImageBrowserItem).Draw(e.Graphics, e.Bounds);
|
|
}
|
|
|
|
// Refresher
|
|
private void refreshtimer_Tick(object sender, EventArgs e)
|
|
{
|
|
bool allpreviewsloaded = true;
|
|
|
|
// Go for all items
|
|
foreach(ImageBrowserItem i in list.Items)
|
|
{
|
|
// Check if there are still previews that are not loaded
|
|
allpreviewsloaded &= i.IsPreviewLoaded;
|
|
|
|
// Items needs to be redrawn?
|
|
if(i.CheckRedrawNeeded())
|
|
{
|
|
// Refresh item in list
|
|
//list.RedrawItems(i.Index, i.Index, false);
|
|
list.Invalidate();
|
|
}
|
|
}
|
|
|
|
// If all previews were loaded, stop this timer
|
|
if(allpreviewsloaded) refreshtimer.Stop();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Events
|
|
|
|
// Name typed
|
|
private void objectname_TextChanged(object sender, EventArgs e)
|
|
{
|
|
// Update list
|
|
RefillList(false);
|
|
|
|
// No item selected?
|
|
if(list.SelectedItems.Count == 0)
|
|
{
|
|
// Select first
|
|
SelectFirstItem();
|
|
}
|
|
}
|
|
|
|
// Key pressed in textbox
|
|
private void objectname_KeyDown(object sender, KeyEventArgs e)
|
|
{
|
|
// Check what key is pressed
|
|
switch(e.KeyData)
|
|
{
|
|
// Cursor keys
|
|
case Keys.Left: SelectNextItem(SearchDirectionHint.Left); e.SuppressKeyPress = true; break;
|
|
case Keys.Right: SelectNextItem(SearchDirectionHint.Right); e.SuppressKeyPress = true; break;
|
|
case Keys.Up: SelectNextItem(SearchDirectionHint.Up); e.SuppressKeyPress = true; break;
|
|
case Keys.Down: SelectNextItem(SearchDirectionHint.Down); e.SuppressKeyPress = true; break;
|
|
|
|
// Tab
|
|
case Keys.Tab: GoToNextSameTexture(); e.SuppressKeyPress = true; break;
|
|
}
|
|
}
|
|
|
|
//mxd. Handle keyboard navigation the same way regardless of list being focused...
|
|
private void list_KeyDown(object sender, KeyEventArgs e)
|
|
{
|
|
// Check what key is pressed
|
|
switch(e.KeyData)
|
|
{
|
|
// Cursor keys
|
|
case Keys.Left: SelectNextItem(SearchDirectionHint.Left); e.SuppressKeyPress = true; break;
|
|
case Keys.Right: SelectNextItem(SearchDirectionHint.Right); e.SuppressKeyPress = true; break;
|
|
case Keys.Up: SelectNextItem(SearchDirectionHint.Up); e.SuppressKeyPress = true; break;
|
|
case Keys.Down: SelectNextItem(SearchDirectionHint.Down); e.SuppressKeyPress = true; break;
|
|
}
|
|
}
|
|
|
|
//mxd
|
|
private void filterSize_WhenTextChanged(object sender, EventArgs e)
|
|
{
|
|
objectname_TextChanged(sender, e);
|
|
}
|
|
|
|
//mxd
|
|
protected override bool ProcessTabKey(bool forward)
|
|
{
|
|
GoToNextSameTexture();
|
|
return false;
|
|
}
|
|
|
|
// Selection changed
|
|
private void list_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
|
|
{
|
|
if(!e.IsSelected) return; //mxd. Don't want to trigger this twice
|
|
|
|
// Prevent selecting?
|
|
if(preventselection)
|
|
{
|
|
foreach(ListViewItem i in list.SelectedItems) i.Selected = false;
|
|
}
|
|
else
|
|
{
|
|
// Raise event
|
|
if(SelectedItemChanged != null) SelectedItemChanged();
|
|
}
|
|
}
|
|
|
|
// Doublelicking an item
|
|
private void list_DoubleClick(object sender, EventArgs e)
|
|
{
|
|
if(!preventselection && (list.SelectedItems.Count > 0))
|
|
if(SelectedItemDoubleClicked != null) SelectedItemDoubleClicked();
|
|
}
|
|
|
|
//mxd. Transfer focus to Filter textbox
|
|
private void list_KeyPress(object sender, KeyPressEventArgs e)
|
|
{
|
|
if(!General.Settings.KeepTextureFilterFocused) return;
|
|
|
|
objectname.Focus();
|
|
if(e.KeyChar == '\b') // Any better way to check for Backspace?..
|
|
{
|
|
if(!string.IsNullOrEmpty(objectname.Text) && objectname.SelectionStart > 0 && objectname.SelectionLength == 0)
|
|
{
|
|
int s = objectname.SelectionStart - 1;
|
|
objectname.Text = objectname.Text.Remove(s, 1);
|
|
objectname.SelectionStart = s;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
objectname.AppendText(e.KeyChar.ToString(CultureInfo.InvariantCulture));
|
|
}
|
|
}
|
|
|
|
//mxd
|
|
private void cbMixMode_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
mixMode = cbMixMode.SelectedIndex;
|
|
RefillList(false);
|
|
}
|
|
|
|
//mxd
|
|
private void longtexturenames_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
uselongtexturenames = longtexturenames.Checked;
|
|
RefillList(false);
|
|
}
|
|
|
|
//mxd
|
|
private void showsubdirtextures_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
showtexturesfromsubdirs = showsubdirtextures.Checked;
|
|
RefillList(false);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Methods
|
|
|
|
// This selects the next texture with the same name as the selected texture
|
|
public void GoToNextSameTexture()
|
|
{
|
|
if(list.SelectedItems.Count > 0)
|
|
{
|
|
list.Focus(); //mxd
|
|
ListViewItem selected = list.SelectedItems[0];
|
|
|
|
//mxd
|
|
foreach(ImageBrowserItem n in visibleitems)
|
|
{
|
|
if(n == selected) continue;
|
|
if(n.Text == selected.Text)
|
|
{
|
|
if(list.IsGroupCollapsed(n.Group)) list.SetGroupCollapsed(n.Group, false);
|
|
n.Selected = true;
|
|
n.Focused = true;
|
|
n.EnsureVisible();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// This selects an item by longname (mxd - changed from name to longname)
|
|
public void SelectItem(long longname, ListViewGroup preferredgroup)
|
|
{
|
|
ImageBrowserItem lvi = null; //mxd
|
|
|
|
// Not when selecting is prevented
|
|
if(preventselection) return;
|
|
|
|
// Search in preferred group first
|
|
if(preferredgroup != null)
|
|
{
|
|
foreach(ListViewItem item in list.Items)
|
|
{
|
|
ImageBrowserItem curitem = item as ImageBrowserItem;
|
|
if(curitem != null && longname == curitem.Icon.LongName) //mxd
|
|
{
|
|
lvi = curitem;
|
|
if(item.Group == preferredgroup) break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Select the item
|
|
if(lvi != null)
|
|
{
|
|
// Select this item
|
|
list.SelectedItems.Clear();
|
|
lvi.Selected = true;
|
|
lvi.EnsureVisible();
|
|
}
|
|
}
|
|
|
|
// This performs item sleection by keys
|
|
private void SelectNextItem(SearchDirectionHint dir)
|
|
{
|
|
// Not when selecting is prevented
|
|
if(preventselection) return;
|
|
|
|
// Nothing selected?
|
|
if(list.SelectedItems.Count == 0)
|
|
{
|
|
// Select first
|
|
SelectFirstItem();
|
|
}
|
|
else
|
|
{
|
|
//mxd
|
|
int index = list.SelectedItems[0].Index;
|
|
int targetindex = -1;
|
|
ListViewGroup startgroup = list.SelectedItems[0].Group;
|
|
Rectangle startrect = list.SelectedItems[0].GetBounds(ItemBoundsPortion.Entire);
|
|
|
|
switch(dir)
|
|
{
|
|
// Check previous items untill groups match...
|
|
case SearchDirectionHint.Left:
|
|
if(list.SelectedIndices[0] > 0)
|
|
{
|
|
while(--index > -1)
|
|
{
|
|
if(list.Items[index].Group == startgroup)
|
|
{
|
|
targetindex = index;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
// Same thing, other direction...
|
|
case SearchDirectionHint.Right:
|
|
if(list.SelectedIndices[0] < list.Items.Count - 1)
|
|
{
|
|
while(++index < list.Items.Count)
|
|
{
|
|
if(list.Items[index].Group == startgroup)
|
|
{
|
|
targetindex = index;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
// Check previous items untill X coordinate match and Y coordinate is less than the start ones...
|
|
case SearchDirectionHint.Up:
|
|
while(--index > -1)
|
|
{
|
|
ListViewItem item = list.Items[index];
|
|
if(item != null && item.Group == startgroup)
|
|
{
|
|
Rectangle rect = item.GetBounds(ItemBoundsPortion.Entire);
|
|
if(rect.X == startrect.X && rect.Y < startrect.Y)
|
|
{
|
|
targetindex = index;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
// Same thing, other direction...
|
|
case SearchDirectionHint.Down:
|
|
if(list.SelectedIndices[0] < list.Items.Count - 1)
|
|
{
|
|
while(++index < list.Items.Count)
|
|
{
|
|
ListViewItem item = list.Items[index];
|
|
if(item != null && item.Group == startgroup)
|
|
{
|
|
Rectangle rect = item.GetBounds(ItemBoundsPortion.Entire);
|
|
if(rect.X == startrect.X && rect.Y > startrect.Y)
|
|
{
|
|
targetindex = index;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
//mxd. Use the old method for Up/Down keys, becaue it can jump between Groups...
|
|
if(targetindex == -1 && (dir == SearchDirectionHint.Up || dir == SearchDirectionHint.Down))
|
|
{
|
|
Point spos = new Point(startrect.Location.X + startrect.Width / 2, startrect.Y + startrect.Height / 2);
|
|
|
|
// Try finding 5 times in the given direction
|
|
for(int i = 0; i < 5; i++)
|
|
{
|
|
// Move point in given direction
|
|
switch(dir)
|
|
{
|
|
case SearchDirectionHint.Up: spos.Y -= list.TileSize.Height / 2; break;
|
|
case SearchDirectionHint.Down: spos.Y += list.TileSize.Height / 2; break;
|
|
}
|
|
|
|
// Test position
|
|
ListViewItem lvi = list.GetItemAt(spos.X, spos.Y);
|
|
if(lvi != null)
|
|
{
|
|
targetindex = lvi.Index;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//mxd. Found something?..
|
|
if(targetindex != -1)
|
|
{
|
|
// Select item
|
|
list.SelectedItems.Clear();
|
|
list.Items[targetindex].Selected = true;
|
|
list.SelectedItems[0].EnsureVisible();
|
|
}
|
|
}
|
|
}
|
|
|
|
// This selectes the first item
|
|
private void SelectFirstItem()
|
|
{
|
|
// Not when selecting is prevented
|
|
if(preventselection) return;
|
|
|
|
// Select first
|
|
if(list.Items.Count > 0)
|
|
{
|
|
list.SelectedItems.Clear();
|
|
ListViewItem lvi = list.GetItemAt(list.TileSize.Width / 2, list.TileSize.Height / 2);
|
|
if(lvi != null)
|
|
{
|
|
lvi.Selected = true;
|
|
lvi.EnsureVisible();
|
|
}
|
|
}
|
|
}
|
|
|
|
// This adds a group
|
|
public ListViewGroup AddGroup(string name)
|
|
{
|
|
ListViewGroup grp = new ListViewGroup(name);
|
|
list.Groups.Add(grp);
|
|
return grp;
|
|
}
|
|
|
|
//mxd
|
|
public bool IsGroupCollapsed(ListViewGroup group)
|
|
{
|
|
if(!list.Groups.Contains(group)) return false;
|
|
return list.IsGroupCollapsed(group);
|
|
}
|
|
|
|
//mxd. This enables group collapsability and optionally collapses it
|
|
public void SetGroupCollapsed(ListViewGroup group, bool collapse)
|
|
{
|
|
if(!list.Groups.Contains(group)) return;
|
|
list.SetGroupCollapsed(group, collapse);
|
|
}
|
|
|
|
// This begins adding items
|
|
public void BeginAdding(bool keepselectedindex) { BeginAdding(0, keepselectedindex); } //mxd
|
|
public void BeginAdding(int selectedlevel, bool keepselectedindex)
|
|
{
|
|
if(keepselectedindex && (list.SelectedItems.Count > 0))
|
|
keepselected = list.SelectedIndices[0];
|
|
else
|
|
keepselected = -1;
|
|
|
|
currentlevel = selectedlevel;
|
|
|
|
// Clean list
|
|
items.Clear();
|
|
|
|
// Stop updating
|
|
refreshtimer.Enabled = false;
|
|
}
|
|
|
|
// This ends adding items
|
|
public void EndAdding()
|
|
{
|
|
// Fill list with items
|
|
RefillList(true);
|
|
|
|
// Start updating
|
|
refreshtimer.Enabled = true;
|
|
}
|
|
|
|
// This adds an item
|
|
public void Add(ImageData image, object tag, ListViewGroup group)
|
|
{
|
|
ImageBrowserItem i = new ImageBrowserItem(image, tag, uselongtexturenames); //mxd
|
|
i.ListGroup = group;
|
|
i.Group = group;
|
|
i.ToolTipText = image.Name; //mxd
|
|
items.Add(i);
|
|
}
|
|
|
|
// This adds an item
|
|
public void Add(ImageData image, object tag, ListViewGroup group, string tooltiptext)
|
|
{
|
|
ImageBrowserItem i = new ImageBrowserItem(image, tag, uselongtexturenames); //mxd
|
|
i.ListGroup = group;
|
|
i.Group = group;
|
|
i.ToolTipText = tooltiptext;
|
|
items.Add(i);
|
|
}
|
|
|
|
// This fills the list based on the objectname filter
|
|
private void RefillList(bool selectfirst)
|
|
{
|
|
visibleitems = new List<ImageBrowserItem>();
|
|
|
|
//mxd. Store info about currently selected item
|
|
string selectedname = string.Empty;
|
|
ListViewGroup selecteditemgroup = null;
|
|
if(!selectfirst && keepselected == -1 && list.SelectedIndices.Count > 0)
|
|
{
|
|
selectedname = list.Items[list.SelectedIndices[0]].Text;
|
|
selecteditemgroup = list.Items[list.SelectedIndices[0]].Group;
|
|
}
|
|
|
|
// Begin updating list
|
|
updating = true;
|
|
//list.SuspendLayout();
|
|
list.BeginUpdate();
|
|
|
|
// Clear list first
|
|
// Group property of items will be set to null, we will restore it later
|
|
list.Items.Clear();
|
|
|
|
//mxd. Filtering by texture size?
|
|
int w = filterWidth.GetResult(-1);
|
|
int h = filterHeight.GetResult(-1);
|
|
|
|
// Go for all items
|
|
ImageBrowserItem previtem = null; //mxd
|
|
for(int i = items.Count - 1; i > -1; i--)
|
|
{
|
|
// Add item if valid
|
|
items[i].ShowFullName = uselongtexturenames; //mxd
|
|
if(ValidateItem(items[i], previtem) && ValidateItemSize(items[i], w, h))
|
|
{
|
|
items[i].Group = items[i].ListGroup;
|
|
items[i].Selected = false;
|
|
visibleitems.Add(items[i]);
|
|
previtem = items[i];
|
|
}
|
|
}
|
|
|
|
// Fill list
|
|
visibleitems.Sort();
|
|
ListViewItem[] array = new ListViewItem[visibleitems.Count];
|
|
for(int i = 0; i < visibleitems.Count; i++) array[i] = visibleitems[i];
|
|
list.Items.AddRange(array);
|
|
|
|
// Done updating list
|
|
updating = false;
|
|
list.EndUpdate();
|
|
list.Invalidate();
|
|
//list.ResumeLayout();
|
|
|
|
// Make selection?
|
|
if(!preventselection && (list.Items.Count > 0))
|
|
{
|
|
// Select specific item?
|
|
if(keepselected > -1)
|
|
{
|
|
list.Items[keepselected].Selected = true;
|
|
list.Items[keepselected].EnsureVisible();
|
|
}
|
|
// Select first item?
|
|
else if(selectfirst)
|
|
{
|
|
SelectFirstItem();
|
|
}
|
|
//mxd. Try reselecting the same/next closest item
|
|
else if(selecteditemgroup != null && !string.IsNullOrEmpty(selectedname))
|
|
{
|
|
ListViewItem bestmatch = null;
|
|
int charsmatched = 1;
|
|
foreach(ListViewItem item in list.Items)
|
|
{
|
|
if(item.Group == selecteditemgroup && item.Text[0] == selectedname[0])
|
|
{
|
|
if(item.Text == selectedname)
|
|
{
|
|
bestmatch = item;
|
|
break;
|
|
}
|
|
|
|
for(int i = 1; i < Math.Min(item.Text.Length, selectedname.Length); i++)
|
|
{
|
|
if(item.Text[i] != selectedname[i])
|
|
{
|
|
if(i > charsmatched)
|
|
{
|
|
bestmatch = item;
|
|
charsmatched = i;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Select the first item from the same group...
|
|
if(bestmatch == null)
|
|
{
|
|
foreach(ListViewItem item in list.Items)
|
|
{
|
|
if(item.Group == selecteditemgroup)
|
|
{
|
|
bestmatch = item;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Select found item
|
|
if(bestmatch != null)
|
|
{
|
|
bestmatch.Selected = true;
|
|
bestmatch.EnsureVisible();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Raise event
|
|
if((SelectedItemChanged != null) && !preventselection) SelectedItemChanged();
|
|
}
|
|
|
|
// This validates an item
|
|
private bool ValidateItem(ImageBrowserItem item, ImageBrowserItem previtem)
|
|
{
|
|
//mxd. Don't show duplicate items
|
|
if(previtem != null && item.TextureName == previtem.TextureName && item.Group == previtem.Group) return false; //mxd
|
|
|
|
//mxd. mixMode: 0 = All, 1 = Textures, 2 = Flats, 3 = Based on BrowseFlats
|
|
if(!splitter.Panel2Collapsed)
|
|
{
|
|
if(mixMode == 1 && item.Icon.IsFlat) return false;
|
|
if(mixMode == 2 && !item.Icon.IsFlat) return false;
|
|
if(mixMode == 3 && (browseFlats != item.Icon.IsFlat)) return false;
|
|
if(!showtexturesfromsubdirs && item.Icon.Level > currentlevel) return false;
|
|
}
|
|
|
|
return item.Text.ToUpperInvariant().Contains(objectname.Text.ToUpperInvariant());
|
|
}
|
|
|
|
//mxd. This validates an item's texture size
|
|
private static bool ValidateItemSize(ImageBrowserItem i, int w, int h)
|
|
{
|
|
if(!i.Icon.IsPreviewLoaded) return true;
|
|
if(w > 0 && i.Icon.Width != w) return false;
|
|
if(h > 0 && i.Icon.Height != h) return false;
|
|
return true;
|
|
}
|
|
|
|
// This sends the focus to the textbox
|
|
public void FocusTextbox()
|
|
{
|
|
if(General.Settings.KeepTextureFilterFocused) //mxd
|
|
objectname.Focus();
|
|
else
|
|
list.Focus();
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|