UltimateZoneBuilder/Source/Plugins/BuilderModes/Interface/FindReplaceForm.cs
MaxED 7ab0a86a92 Added, Find & Replace mode, UDMF: added Linedef activation flags to the "Find Linedef flags" search mode flags list.
Changed, Sound Propagation mode: all sound zones are now shown when no sector is highlighted.
Changed, Sound Environments mode: the mode is now available only in UDMF map format.
Changed, Color Picker plugin: the plugin functionality is no longer available in Doom map format.
Restored the ability to create superimposed lines by dragging them with "Snap to Geometry" mode disabled.
Fixed, Sound Propagation mode: fixed a crash when a single-sided linedef had "Block Sound" flag.
Fixed, Find & Replace mode: in some cases "Find Sector/Sidedef/Linedef/Thing flags" search modes failed to find map elements with required flags.
Fixed, Edit Selection mode: in some cases incorrect geometry was created after applying multipart sector edit when "Replace with Dragged Geometry" mode was enabled.
Fixed a crash caused by eventual GDI font objects overflow.
2016-07-02 22:27:20 +00:00

438 lines
No EOL
12 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.Windows.Forms;
using CodeImp.DoomBuilder.Windows;
using System.Reflection;
using System.Globalization;
#endregion
namespace CodeImp.DoomBuilder.BuilderModes
{
public partial class FindReplaceForm : DelayedForm
{
#region ================== Constants
#endregion
#region ================== Variables
private FindReplaceMode mode; //mxd
private FindReplaceType newfinder;
private FindReplaceType finder;
private List<FindReplaceType> findtypeslist;
private bool controlpressed;
private bool shiftpressed;
private bool suppressevents;
private Font hintfont; //mxd
#endregion
#region ================== Properties
internal FindReplaceType Finder { get { return finder; } }
#endregion
#region ================== Constructor
// Constructor
public FindReplaceForm()
{
// Initialize
InitializeComponent();
//mxd. Create hint font
hintfont = new Font(this.Font, FontStyle.Underline);
// Find all find/replace types
Type[] findtypes = BuilderPlug.Me.FindClasses(typeof(FindReplaceType));
findtypeslist = new List<FindReplaceType>(findtypes.Length);
foreach(Type t in findtypes)
{
object[] attr = t.GetCustomAttributes(typeof(FindReplaceAttribute), true);
if(attr.Length > 0)
{
FindReplaceType finderinst;
try
{
// Create instance
finderinst = (FindReplaceType)Assembly.GetExecutingAssembly().CreateInstance(t.FullName, false, BindingFlags.Default, null, null, CultureInfo.CurrentCulture, new object[0]);
}
catch(TargetInvocationException ex)
{
// Error!
General.ErrorLogger.Add(ErrorType.Error, "Failed to create class instance \"" + t.Name + "\"");
General.WriteLogLine(ex.InnerException.GetType().Name + ": " + ex.InnerException.Message);
throw;
}
catch(Exception ex)
{
// Error!
General.ErrorLogger.Add(ErrorType.Error, "Failed to create class instance \"" + t.Name + "\"");
General.WriteLogLine(ex.GetType().Name + ": " + ex.Message);
throw;
}
// Add the finder to the list
findtypeslist.Add(finderinst);
}
}
}
#endregion
#region ================== Events
// Replace (un)checked
private void doreplace_CheckedChanged(object sender, EventArgs e)
{
findbutton.Text = (doreplace.Checked ? "Replace" : "Find");
replaceinput.Enabled = doreplace.Checked;
browsereplace.Enabled = doreplace.Checked && newfinder != null && newfinder.Attributes.BrowseButton;
}
// Search type selected
private void searchtypes_SelectedIndexChanged(object sender, EventArgs e)
{
// Create instance of the selected type
newfinder = (FindReplaceType)searchtypes.SelectedItem;
// Now setup the interface
browsefind.Enabled = newfinder.Attributes.BrowseButton;
browsefind.Image = newfinder.BrowseImage;
browsereplace.Enabled = newfinder.Attributes.BrowseButton;
browsereplace.Image = newfinder.BrowseImage;
if(!newfinder.CanReplace()) doreplace.Checked = false;
doreplace_CheckedChanged(this, EventArgs.Empty); //mxd. Update the rest of replace controls
doreplace.Enabled = newfinder.CanReplace();
//mxd. Update hint text
if(!string.IsNullOrEmpty(newfinder.UsageHint))
{
tooltip.SetToolTip(labelfind, newfinder.UsageHint);
labelfind.Font = hintfont;
labelfind.ForeColor = SystemColors.HotTrack;
labelfind.Cursor = Cursors.Hand;
}
else if(labelfind.ForeColor == SystemColors.HotTrack)
{
tooltip.SetToolTip(labelfind, string.Empty);
labelfind.Font = this.Font;
labelfind.ForeColor = SystemColors.ControlText;
labelfind.Cursor = Cursors.Default;
}
}
// Browse find button clicked
private void browsefind_Click(object sender, EventArgs e)
{
findinput.Text = newfinder.Browse(findinput.Text);
}
// Browse replacement clicked
private void browsereplace_Click(object sender, EventArgs e)
{
replaceinput.Text = newfinder.BrowseReplace(replaceinput.Text);
}
//mxd
private void findinput_TextChanged(object sender, EventArgs e)
{
findbutton.Enabled = !string.IsNullOrEmpty(findinput.Text);
}
// Find / Replace clicked
private void findbutton_Click(object sender, EventArgs e)
{
// Reset results
suppressevents = true;
resultslist.Items.Clear();
// Hide object information
General.Interface.HideInfo();
// Keep the finder we used for the search
finder = newfinder;
// Enable/disable buttons
editbutton.Enabled = false;
deletebutton.Visible = finder.AllowDelete;
deletebutton.Enabled = false;
resultslist.BeginUpdate();
// Perform the search / replace and show the results
if(doreplace.Checked)
{
General.Map.UndoRedo.CreateUndo("Replace " + searchtypes.SelectedItem);
resultslist.Items.AddRange(finder.Find(findinput.Text, withinselection.Checked, true, replaceinput.Text, false));
resultscount.Text = resultslist.Items.Count + " items found and replaced.";
// Withdraw the undo step if nothing was replaced
if(resultslist.Items.Count < 1)
{
mode.Volatile = false; //mxd. Otherwice UndoManager.PerformUndo will cancel the mode...
General.Map.UndoRedo.WithdrawUndo();
mode.Volatile = true; //mxd
}
}
else
{
resultslist.Items.AddRange(finder.Find(findinput.Text, withinselection.Checked, false, string.Empty, false));
resultscount.Text = resultslist.Items.Count + " items found.";
}
// Select all results
General.Map.Map.ClearAllSelected();
for(int i = 0; i < resultslist.Items.Count; i++)
resultslist.SelectedIndices.Add(i);
// Let the finder know about the selection
FindReplaceObject[] selection = GetSelection();
finder.ObjectSelected(selection);
// Open results part of window
this.Size = new Size(this.Width, this.Height - this.ClientSize.Height + resultspanel.Top + resultspanel.Height);
resultspanel.Visible = true;
resultslist.EndUpdate();
suppressevents = false;
// Enable/disable buttons
editbutton.Enabled = (resultslist.SelectedIndex > -1);
deletebutton.Enabled = (resultslist.SelectedIndex > -1);
// Set correct presentation mode
General.Map.Renderer2D.SetPresentation(finder.RenderPresentation);
// Redraw the screen, this will show the selection
General.Interface.RedrawDisplay();
}
// Found item selected
private void resultslist_SelectedIndexChanged(object sender, EventArgs e)
{
if(!suppressevents)
{
// Let the finder know about the selection
FindReplaceObject[] selection = GetSelection();
finder.ObjectSelected(selection);
// Enable/disable buttons
editbutton.Enabled = (resultslist.SelectedIndex > -1);
deletebutton.Enabled = (resultslist.SelectedIndex > -1);
// Redraw the screen, this will show the selection
General.Interface.RedrawDisplay();
}
}
// Mouse released
private void resultslist_MouseUp(object sender, MouseEventArgs e)
{
// Right-clicked?
if(e.Button == MouseButtons.Right)
{
int index = resultslist.IndexFromPoint(e.Location);
if(index != ListBox.NoMatches)
{
// Select the right-clicked item, if not selected
if(!resultslist.SelectedIndices.Contains(index))
{
if(!controlpressed && !shiftpressed) resultslist.SelectedItems.Clear();
resultslist.SelectedIndices.Add(index);
Update();
}
// Edit selected objects
editbutton_Click(this, EventArgs.Empty);
}
}
// Enable/disable buttons
editbutton.Enabled = (resultslist.SelectedIndex > -1);
deletebutton.Enabled = (resultslist.SelectedIndex > -1);
}
// Double clicked
private void resultslist_MouseDoubleClick(object sender, MouseEventArgs e)
{
resultslist_MouseUp(sender, new MouseEventArgs(MouseButtons.Right, 1, e.X, e.Y, e.Delta));
}
// Window closing
private void FindReplaceForm_FormClosing(object sender, FormClosingEventArgs e)
{
// If the user closes the form, then just cancel the mode
if(e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true;
General.Interface.Focus();
General.Editing.CancelMode();
}
//mxd
hintfont.Dispose();
}
// Close button clicked
private void closebutton_Click(object sender, EventArgs e)
{
General.Interface.Focus();
General.Editing.CancelMode();
}
// Key pressed
private void FindReplaceForm_KeyDown(object sender, KeyEventArgs e)
{
// Keep modifiers
controlpressed = e.Control;
shiftpressed = e.Shift;
// Enable/disable buttons
editbutton.Enabled = (resultslist.SelectedIndex > -1);
deletebutton.Enabled = (resultslist.SelectedIndex > -1);
}
// Key released
private void FindReplaceForm_KeyUp(object sender, KeyEventArgs e)
{
// Keep modifiers
controlpressed = e.Control;
shiftpressed = e.Shift;
// Enable/disable buttons
editbutton.Enabled = (resultslist.SelectedIndex > -1);
deletebutton.Enabled = (resultslist.SelectedIndex > -1);
}
// Edit Selection
private void editbutton_Click(object sender, EventArgs e)
{
FindReplaceObject[] items = GetSelection();
if(items.Length > 0)
{
// Edit selected objects
suppressevents = true;
finder.EditObjects(items);
suppressevents = false;
resultslist_SelectedIndexChanged(sender, e);
// Redraw the screen, this will show the selection
General.Interface.RedrawDisplay();
}
}
// Delete Selection
private void deletebutton_Click(object sender, EventArgs e)
{
// Delete selected objects
FindReplaceObject[] items = GetSelection();
if(items.Length > 0)
{
suppressevents = true;
finder.DeleteObjects(items);
foreach(FindReplaceObject obj in items)
{
resultslist.Items.Remove(obj);
}
suppressevents = false;
resultslist_SelectedIndexChanged(sender, e);
// Redraw the screen, this will show the selection
General.Interface.RedrawDisplay();
}
}
private void FindReplaceForm_HelpRequested(object sender, HelpEventArgs hlpevent)
{
General.ShowHelp("e_findreplace.html");
}
#endregion
#region ================== Methods
// This shows the window
public void Show(Form owner, FindReplaceMode mode)
{
//mxd
this.mode = mode;
// Position at left-top of owner
this.Location = new Point(owner.Location.X + 20, owner.Location.Y + 90);
// Re-fill the search types list
searchtypes.Items.Clear();
foreach(FindReplaceType t in findtypeslist)
{
// Check if it should be visible
if(t.DetermineVisiblity())
{
searchtypes.Items.Add(t);
}
}
// Select previously selected item
for(int i = 0; i < searchtypes.Items.Count; i++)
{
if(searchtypes.Items[i] == newfinder)
searchtypes.SelectedIndex = i;
}
// Select first if none was selected
if(searchtypes.SelectedIndex < 0) searchtypes.SelectedIndex = 0;
// Close results part
resultspanel.Visible = false;
this.Size = new Size(this.Width, this.Height - this.ClientSize.Height + resultspanel.Top);
// Show window
base.Show(owner);
}
// This hides the window
new public void Hide()
{
base.Hide();
// Clear search results
resultslist.Items.Clear();
}
// This returns the selected item(s)
internal FindReplaceObject[] GetSelection()
{
// Return selected objects
FindReplaceObject[] list = new FindReplaceObject[resultslist.SelectedItems.Count];
int index = 0;
foreach(object obj in resultslist.SelectedItems)
{
list[index++] = (FindReplaceObject)obj;
}
return list;
}
#endregion
}
}