Texture browser: using the tab key to jump between the currently selected used texture and the position of the texture in the list of all textures works again (this time without toggling the "used textures on top" checkbox). Also added option to vertically center the view on the selected texture (enabled by default)

This commit is contained in:
biwa 2020-11-01 18:21:22 +01:00
parent eab7de4f9e
commit 15772da839
4 changed files with 469 additions and 337 deletions

View file

@ -34,6 +34,7 @@ namespace CodeImp.DoomBuilder.Controls
this.label = new System.Windows.Forms.Label();
this.splitter = new System.Windows.Forms.SplitContainer();
this.list = new CodeImp.DoomBuilder.Controls.ImageSelectorPanel();
this.centeritem = new System.Windows.Forms.CheckBox();
this.classicview = new System.Windows.Forms.CheckBox();
this.objectclear = new System.Windows.Forms.Button();
this.sizecombo = new System.Windows.Forms.ComboBox();
@ -47,6 +48,7 @@ namespace CodeImp.DoomBuilder.Controls
this.texturetypecombo = new System.Windows.Forms.ComboBox();
this.objectname = new System.Windows.Forms.TextBox();
this.refreshtimer = new System.Windows.Forms.Timer(this.components);
((System.ComponentModel.ISupportInitialize)(this.splitter)).BeginInit();
this.splitter.Panel1.SuspendLayout();
this.splitter.Panel2.SuspendLayout();
this.splitter.SuspendLayout();
@ -85,6 +87,7 @@ namespace CodeImp.DoomBuilder.Controls
//
// splitter.Panel2
//
this.splitter.Panel2.Controls.Add(this.centeritem);
this.splitter.Panel2.Controls.Add(this.classicview);
this.splitter.Panel2.Controls.Add(this.objectclear);
this.splitter.Panel2.Controls.Add(this.sizecombo);
@ -120,9 +123,22 @@ namespace CodeImp.DoomBuilder.Controls
this.list.Size = new System.Drawing.Size(840, 284);
this.list.TabIndex = 1;
this.list.Title = "Default group";
this.list.UsedTexturesFirst = false;
this.list.ItemDoubleClicked += new CodeImp.DoomBuilder.Controls.ImageSelectorPanel.ItemSelectedEventHandler(this.list_ItemDoubleClicked);
this.list.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.list_KeyPress);
//
// centeritem
//
this.centeritem.AutoSize = true;
this.centeritem.Location = new System.Drawing.Point(510, 34);
this.centeritem.Name = "centeritem";
this.centeritem.Size = new System.Drawing.Size(146, 17);
this.centeritem.TabIndex = 5;
this.centeritem.TabStop = false;
this.centeritem.Text = "Vertically center selection";
this.centeritem.UseVisualStyleBackColor = true;
this.centeritem.CheckedChanged += new System.EventHandler(this.centeritem_CheckedChanged);
//
// classicview
//
this.classicview.AutoSize = true;
@ -302,6 +318,7 @@ namespace CodeImp.DoomBuilder.Controls
this.splitter.Panel1.ResumeLayout(false);
this.splitter.Panel2.ResumeLayout(false);
this.splitter.Panel2.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.splitter)).EndInit();
this.splitter.ResumeLayout(false);
this.ResumeLayout(false);
@ -326,5 +343,6 @@ namespace CodeImp.DoomBuilder.Controls
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button objectclear;
private System.Windows.Forms.CheckBox classicview;
private System.Windows.Forms.CheckBox centeritem;
}
}

View file

@ -28,6 +28,21 @@ using CodeImp.DoomBuilder.Windows;
namespace CodeImp.DoomBuilder.Controls
{
/// <summary>
/// Holds a title of an item group and its items
/// </summary>
internal struct ImageBrowserItemGroup
{
public string Title;
public List<ImageBrowserItem> Items;
public ImageBrowserItemGroup(string title)
{
Title = title;
Items = new List<ImageBrowserItem>();
}
}
internal partial class ImageBrowserControl : UserControl
{
#region ================== Constants
@ -63,9 +78,6 @@ namespace CodeImp.DoomBuilder.Controls
private string usedfirstgroup;
private string availgroup;
// Filtered items
private List<ImageBrowserItem> visibleitems;
//mxd
private int texturetype;
@ -130,6 +142,7 @@ namespace CodeImp.DoomBuilder.Controls
ElementName = (texturetype == 2 || (texturetype == 3 && browseflats)) ? "flats" : "textures";
list.UsedTexturesFirst = usedtexturesfirst.Checked = General.Settings.ReadSetting(settingpath + ".showusedtexturesfirst", false);
list.ClassicView = classicview.Checked = General.Settings.ReadSetting(settingpath + ".classicview", false);
list.CenterItem = centeritem.Checked = General.Settings.ReadSetting(settingpath + ".verticallycenteritem", true);
int _imagesize = General.Settings.ReadSetting(settingpath + ".imagesize", 128);
sizecombo.Text = (_imagesize == 0 ? sizecombo.Items[0].ToString() : _imagesize.ToString());
@ -187,7 +200,9 @@ namespace CodeImp.DoomBuilder.Controls
{
General.Settings.WriteSetting(settingpath + ".showusedtexturesfirst", usedtexturesfirst.Checked);
General.Settings.WriteSetting(settingpath + ".classicview", classicview.Checked);
General.Settings.WriteSetting(settingpath + ".verticallycenteritem", list.CenterItem);
General.Settings.WriteSetting(settingpath + ".imagesize", list.ImageSize);
if (General.Map.Config.UseLongTextureNames) General.Map.Options.UseLongTextureNames = uselongtexturenames;
CleanUp();
@ -278,7 +293,11 @@ namespace CodeImp.DoomBuilder.Controls
//mxd
protected override bool ProcessTabKey(bool forward)
{
usedtexturesfirst.Checked = !usedtexturesfirst.Checked;
if (list.SelectedItems.Count == 0)
return false;
list.JumpBetweenItems(list.SelectedItems[0]);
return false;
}
@ -380,6 +399,7 @@ namespace CodeImp.DoomBuilder.Controls
{
list.UsedTexturesFirst = usedtexturesfirst.Checked;
RefillList(false);
list.UpdateRectangles();
list.Focus();
}
}
@ -499,7 +519,9 @@ namespace CodeImp.DoomBuilder.Controls
// This fills the list based on the objectname filter
private void RefillList(bool selectfirst)
{
visibleitems = new List<ImageBrowserItem>();
ImageBrowserItemGroup directoryitems = new ImageBrowserItemGroup("Directories");
ImageBrowserItemGroup useditems = new ImageBrowserItemGroup("Used textures");
ImageBrowserItemGroup visibleitems = new ImageBrowserItemGroup("All textures");
// Clear list first
list.Clear();
@ -523,18 +545,22 @@ namespace CodeImp.DoomBuilder.Controls
case ImageBrowserItemType.IMAGE:
if(ValidateItem(items[i], previtem) && ValidateItemSize(items[i], w, h))
{
visibleitems.Add(items[i]);
visibleitems.Items.Add(items[i]);
if (items[i].Icon.UsedInMap)
useditems.Items.Add(items[i]);
previtem = items[i];
}
break;
case ImageBrowserItemType.FOLDER_UP: //mxd. "Browse Up" items are always valid
visibleitems.Add(items[i]);
directoryitems.Items.Add(items[i]);
break;
case ImageBrowserItemType.FOLDER: //mxd. Only apply name filtering to "Folder" items
if(items[i].TextureName.ToUpperInvariant().Contains(objectname.Text.ToUpperInvariant()))
visibleitems.Add(items[i]);
directoryitems.Items.Add(items[i]);
break;
default: throw new NotImplementedException("Unknown ImageBrowserItemType");
@ -542,8 +568,24 @@ namespace CodeImp.DoomBuilder.Controls
}
// Fill list
visibleitems.Sort(SortItems);
list.SetItems(visibleitems);
directoryitems.Items.Sort();
useditems.Items.Sort();
visibleitems.Items.Sort();
List<ImageBrowserItemGroup> itemgroups = new List<ImageBrowserItemGroup>();
// Always add the directories
itemgroups.Add(directoryitems);
// Add used textures if the user wants to and there are any
if (usedtexturesfirst.Checked && useditems.Items.Count > 0)
itemgroups.Add(useditems);
// Finally add all items
if (visibleitems.Items.Count > 0)
itemgroups.Add(visibleitems);
list.SetItems(itemgroups);
// Make selection?
if (!preventselection && list.Items.Count > 0)
@ -658,6 +700,11 @@ namespace CodeImp.DoomBuilder.Controls
list.Focus();
}
private void centeritem_CheckedChanged(object sender, EventArgs e)
{
list.CenterItem = centeritem.Checked;
}
#endregion
}
}

View file

@ -112,15 +112,15 @@
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="splitter.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="splitter.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="refreshtimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<metadata name="refreshtimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>103, 17</value>
</metadata>
</root>

View file

@ -51,6 +51,9 @@ namespace CodeImp.DoomBuilder.Controls
// Selection
private bool allowselection;
private bool allowmultipleselection;
private bool centeritem;
private List<ImageBrowserItemGroup> itemgroups = new List<ImageBrowserItemGroup>();
#endregion
@ -144,6 +147,8 @@ namespace CodeImp.DoomBuilder.Controls
}
}
public bool CenterItem { get { return centeritem; } set { centeritem = value; } }
public List<ImageBrowserItem> Items { get { return items; } }
public List<ImageBrowserItem> SelectedItems { get { return selection; } }
public string Title { get { return title; } set { title = value; } }
@ -200,6 +205,24 @@ namespace CodeImp.DoomBuilder.Controls
Refresh();
}
public void SetItems(IEnumerable<ImageBrowserItemGroup> itemgroups)
{
this.items.Clear();
lastselecteditem = null;
selection.Clear();
this.itemgroups.Clear();
foreach (ImageBrowserItemGroup ibig in itemgroups)
{
this.items.AddRange(ibig.Items);
this.itemgroups.Add(ibig);
}
OnSelectionChanged(selection);
UpdateRectangles();
}
public void SetItems(IEnumerable<ImageBrowserItem> items)
{
this.items.Clear();
@ -229,6 +252,11 @@ namespace CodeImp.DoomBuilder.Controls
}
public void ScrollToItem(ImageBrowserItem item)
{
ScrollToItem(item, centeritem);
}
public void ScrollToItem(ImageBrowserItem item, bool centeritem)
{
int index = items.IndexOf(item);
if(index < 0) return;
@ -240,8 +268,49 @@ namespace CodeImp.DoomBuilder.Controls
int ymax = ymin + this.ClientRectangle.Height + titleheight;
if(rec.Top - 3 >= ymin && rec.Bottom + 3 <= ymax) return;
int yscroll = Math.Max(0, Math.Min(rec.Top - titleheight - 3, scrollbar.Maximum - ClientRectangle.Height));
scrollbar.Value = yscroll;
int yscroll;
if (centeritem)
yscroll = rec.Top + rec.Height / 2 - ClientRectangle.Height / 2;
else
yscroll = rec.Top - titleheight - 3;
scrollbar.Value = Math.Max(0, Math.Min(yscroll, scrollbar.Maximum - ClientRectangle.Height)); ;
Refresh();
}
/// <summary>
/// Jumps back and forth between the currently selected texture at the top and in the pile of all textures
/// </summary>
/// <param name="item">The item to jump back and forth between</param>
public void JumpBetweenItems(ImageBrowserItem item)
{
// The item has to exist twice, once in the used textures at the top and in the pile, so get the indexes
int index1 = items.IndexOf(item);
int index2 = items.LastIndexOf(item);
// Item only exists once, so stop here
if (index1 == index2)
return;
Rectangle rect1 = rectangles[index1];
Rectangle rect2 = rectangles[index2];
// Get the distance to the two images. Count from the center of the currently scrolled to position and take the bottom
// of the first image and the top of the second image
int distance1 = Math.Abs(rect1.Bottom - (scrollbar.Value + ClientRectangle.Height / 2));
int distance2 = Math.Abs(rect2.Top - (scrollbar.Value + ClientRectangle.Height / 2));
int yscroll;
// Get the y position we want to scroll to
if(centeritem)
yscroll = (distance1 > distance2 ? (rect1.Top + rect1.Height / 2) : (rect2.Top + rect2.Height / 2)) - ClientRectangle.Height / 2;
else
yscroll = distance1 > distance2 ? rect1.Top : rect2.Top;
// The desired y position might be outside of the range we can scroll to, so clamp the value
scrollbar.Value = Math.Max(0, Math.Min(yscroll, scrollbar.Maximum - ClientRectangle.Height));
Refresh();
}
@ -503,24 +572,22 @@ namespace CodeImp.DoomBuilder.Controls
int my = 0;
rectangles.Clear();
//
ImageBrowserItemType currentType = ImageBrowserItemType.IMAGE; // initialized to random value
bool currentUsedInMap = false;
var firstItem = (items.Count > 0) ? items[0] : null;
foreach (var ti in items)
foreach (ImageBrowserItemGroup ibig in itemgroups)
{
Image preview = GetPreview(ti, imagesize);
if (classicview && (ti == firstItem || ((currentType == ImageBrowserItemType.IMAGE) != (ti.ItemType == ImageBrowserItemType.IMAGE)) || (usedtexturesfirst && currentUsedInMap != ti.Icon.UsedInMap)))
if (classicview)
{
// new row, also provide space for category name.
cx = 0;
cy += SystemFonts.MessageBoxFont.Height + 6 + my + ((ti != firstItem) ? 16 : 0);
cy += SystemFonts.MessageBoxFont.Height + 6 + my + 16 /* ((ti != firstItem) ? 16 : 0) */;
my = 0;
currentType = ti.ItemType;
currentUsedInMap = ti.Icon.UsedInMap;
}
foreach (var ti in ibig.Items)
{
Image preview = GetPreview(ti, imagesize);
int rw = w - cx;
int wid = Math.Max((imagesize > 0 ? imagesize : preview.Width), ti.TextureNameWidth) + padhorz + padhorz;
int hei = (imagesize > 0 ? imagesize : preview.Height) + padvert + padvert + font;
@ -541,6 +608,7 @@ namespace CodeImp.DoomBuilder.Controls
rectangles.Add(rect);
cx += wid;
}
}
if(rectangles.Count > 0)
{
@ -607,28 +675,26 @@ namespace CodeImp.DoomBuilder.Controls
{
int y = scrollbar.Value;
int height = ClientRectangle.Height;
int i = 0;
ImageBrowserItemType currentType = ImageBrowserItemType.IMAGE; // initialized to random value
bool currentUsedInMap = false;
ImageBrowserItem.SetBrushes(classicview, rectangles[0].X, rectangles[0].Y - y, rectangles[0].Width, rectangles[0].Height);
for (var i = 0; i < items.Count; i++)
foreach (ImageBrowserItemGroup ibig in itemgroups)
{
if (classicview && (i == 0 || ((currentType == ImageBrowserItemType.IMAGE) != (items[i].ItemType == ImageBrowserItemType.IMAGE)) || (usedtexturesfirst && currentUsedInMap != items[i].Icon.UsedInMap)))
if (classicview)
{
// draw corresponding title right above this item.
string hdrname;
if (items[i].ItemType == ImageBrowserItemType.IMAGE)
{
if (usedtexturesfirst && items[i].Icon.UsedInMap) hdrname = "Used " + contenttype + ":";
else hdrname = "All " + contenttype + ":";
}
else hdrname = "Directories:";
string hdrname = ibig.Title + ":";
DrawTextureHeader(g, hdrname, new Rectangle(2, rectangles[i].Y - (SystemFonts.MessageBoxFont.Height + 6) - y, ClientRectangle.Width - scrollwidth - 4, SystemFonts.MessageBoxFont.Height), false);
currentType = items[i].ItemType;
currentUsedInMap = items[i].Icon.UsedInMap;
}
for(int j=0; j < ibig.Items.Count; j++, i++)
{
Rectangle rec = rectangles[i];
if (rec.Bottom < y) continue;
if (rec.Top > y + height) break;
@ -637,6 +703,7 @@ namespace CodeImp.DoomBuilder.Controls
items[i].Draw(g, bmp, rec.X, rec.Y - y, rec.Width, rec.Height, selection.Contains(items[i]), items[i].Icon.UsedInMap, classicview);
}
}
}
// Draw title on top of items
if(!string.IsNullOrEmpty(title) && !classicview)