mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-27 14:12:16 +00:00
7ab0a86a92
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.
438 lines
No EOL
12 KiB
C#
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
|
|
|
|
}
|
|
} |