UltimateZoneBuilder/Source/Controls/ScriptEditorPanel.cs

658 lines
18 KiB
C#
Raw Normal View History

#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.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Windows;
using Microsoft.Win32;
using System.Diagnostics;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Types;
using CodeImp.DoomBuilder.IO;
2008-11-06 15:00:01 +00:00
using System.Globalization;
2008-11-11 06:43:33 +00:00
using System.IO;
2008-11-15 13:12:09 +00:00
using CodeImp.DoomBuilder.Compilers;
#endregion
namespace CodeImp.DoomBuilder.Controls
{
internal partial class ScriptEditorPanel : UserControl
{
#region ================== Constants
2008-11-06 15:00:01 +00:00
#endregion
2008-11-06 15:00:01 +00:00
#region ================== Variables
2008-11-06 15:00:01 +00:00
private List<ScriptConfiguration> scriptconfigs;
2008-11-15 13:12:09 +00:00
private List<CompilerError> compilererrors;
2008-11-06 15:00:01 +00:00
#endregion
2008-11-06 15:00:01 +00:00
#region ================== Properties
2008-11-06 15:00:01 +00:00
#endregion
2008-11-06 15:00:01 +00:00
#region ================== Constructor
2008-11-06 15:00:01 +00:00
// Constructor
public ScriptEditorPanel()
{
InitializeComponent();
2008-11-10 16:11:44 +00:00
}
// This initializes the control
public void Initialize()
{
ToolStripMenuItem item;
2008-11-06 15:00:01 +00:00
// Make list of script configs
scriptconfigs = new List<ScriptConfiguration>(General.ScriptConfigs.Values);
scriptconfigs.Add(new ScriptConfiguration());
scriptconfigs.Sort();
// Fill the list of new document types
foreach(ScriptConfiguration cfg in scriptconfigs)
{
2008-11-09 17:59:13 +00:00
// Button for new script menu
2008-11-06 15:00:01 +00:00
item = new ToolStripMenuItem(cfg.Description);
//item.Image = buttonnew.Image;
item.Tag = cfg;
item.Click += new EventHandler(buttonnew_Click);
buttonnew.DropDownItems.Add(item);
2008-11-09 17:59:13 +00:00
// Button for script type menu
item = new ToolStripMenuItem(cfg.Description);
//item.Image = buttonnew.Image;
item.Tag = cfg;
item.Click += new EventHandler(buttonscriptconfig_Click);
buttonscriptconfig.DropDownItems.Add(item);
2008-11-06 15:00:01 +00:00
}
// Setup supported extensions
string filterall = "";
string filterseperate = "";
foreach(ScriptConfiguration cfg in scriptconfigs)
{
if(cfg.Extensions.Length > 0)
{
string exts = "*." + string.Join(";*.", cfg.Extensions);
if(filterseperate.Length > 0) filterseperate += "|";
filterseperate += cfg.Description + "|" + exts;
if(filterall.Length > 0) filterall += ";";
filterall += exts;
}
}
2008-11-09 17:59:13 +00:00
openfile.Filter = "Script files|" + filterall + "|" + filterseperate + "|All files|*.*";
2008-11-10 16:11:44 +00:00
// Load the script lumps
foreach(MapLumpInfo maplumpinfo in General.Map.Config.MapLumps.Values)
{
// Is this a script lump?
if(maplumpinfo.script != null)
{
// Load this!
2008-11-15 13:12:09 +00:00
ScriptLumpDocumentTab t = new ScriptLumpDocumentTab(this, maplumpinfo.name, maplumpinfo.script);
2008-11-10 16:11:44 +00:00
tabs.TabPages.Add(t);
}
}
2008-11-11 06:43:33 +00:00
// Load the files that were previously opened for this map
foreach(String filename in General.Map.Options.ScriptFiles)
{
// Does this file exist?
if(File.Exists(filename))
{
// Load this!
OpenFile(filename);
}
}
// Select the first tab
if(tabs.TabPages.Count > 0) tabs.SelectedIndex = 0;
2008-11-10 16:11:44 +00:00
2008-11-15 13:12:09 +00:00
// If the map has remembered any compile errors, then show them
ShowErrors(General.Map.Errors);
2008-11-09 17:59:13 +00:00
// Done
UpdateToolbar(true);
}
2008-11-06 15:00:01 +00:00
// This applies user preferences
public void ApplySettings()
{
// Apply settings
//int panel2size = General.Settings.ReadSetting("scriptspanel.splitter", splitter.ClientRectangle.Height - splitter.SplitterDistance);
//splitter.SplitterDistance = splitter.ClientRectangle.Height - panel2size;
errorlist.Columns[0].Width = General.Settings.ReadSetting("scriptspanel.errorscolumn0width", errorlist.Columns[0].Width);
errorlist.Columns[1].Width = General.Settings.ReadSetting("scriptspanel.errorscolumn1width", errorlist.Columns[1].Width);
errorlist.Columns[2].Width = General.Settings.ReadSetting("scriptspanel.errorscolumn2width", errorlist.Columns[2].Width);
}
// This saves user preferences
public void SaveSettings()
{
//General.Settings.WriteSetting("scriptspanel.splitter", splitter.ClientRectangle.Height - splitter.SplitterDistance);
General.Settings.WriteSetting("scriptspanel.errorscolumn0width", errorlist.Columns[0].Width);
General.Settings.WriteSetting("scriptspanel.errorscolumn1width", errorlist.Columns[1].Width);
General.Settings.WriteSetting("scriptspanel.errorscolumn2width", errorlist.Columns[2].Width);
}
#endregion
#region ================== Methods
2008-11-10 16:11:44 +00:00
2008-11-17 23:32:13 +00:00
// This refreshes all settings
public void RefreshSettings()
{
foreach(ScriptDocumentTab t in tabs.TabPages)
{
t.RefreshSettings();
}
}
2008-11-15 13:12:09 +00:00
// This clears all error marks and hides the errors list
public void ClearErrors()
{
// Hide list
splitter.Panel2Collapsed = true;
errorlist.Items.Clear();
// Clear marks
foreach(ScriptDocumentTab t in tabs.TabPages)
{
t.ClearMarks();
}
}
// This shows the errors panel with the given errors
// Also updates the scripts with markers for the given errors
public void ShowErrors(IEnumerable<CompilerError> errors)
{
// Copy list
if(errors != null)
compilererrors = new List<CompilerError>(errors);
else
compilererrors = new List<CompilerError>();
// Fill list
errorlist.BeginUpdate();
errorlist.Items.Clear();
int listindex = 1;
foreach(CompilerError e in compilererrors)
{
ListViewItem ei = new ListViewItem(listindex.ToString());
ei.ImageIndex = 0;
ei.SubItems.Add(e.description);
if(e.filename.StartsWith("?"))
ei.SubItems.Add(e.filename.Replace("?", "") + " (line " + e.linenumber.ToString() + ")");
else
ei.SubItems.Add(Path.GetFileName(e.filename) + " (line " + e.linenumber.ToString() + ")");
ei.Tag = e;
errorlist.Items.Add(ei);
listindex++;
}
errorlist.EndUpdate();
// Show marks on scripts
foreach(ScriptDocumentTab t in tabs.TabPages)
{
t.MarkScriptErrors(compilererrors);
}
// Show/hide panel
splitter.Panel2Collapsed = (errorlist.Items.Count == 0);
}
2008-11-11 06:43:33 +00:00
// This writes all explicitly opened files to the configuration
public void WriteOpenFilesToConfiguration()
{
List<string> files = new List<string>();
foreach(ScriptDocumentTab t in tabs.TabPages)
{
if(t.ExplicitSave) files.Add(t.Filename);
}
General.Map.Options.ScriptFiles = files;
}
2008-11-10 16:11:44 +00:00
// This asks to save files and returns the result
public bool AskSaveAll()
{
foreach(ScriptDocumentTab t in tabs.TabPages)
{
if(t.ExplicitSave)
{
if(!CloseScript(t, true)) return false;
}
}
return true;
}
// This closes a script and returns true when closed
private bool CloseScript(ScriptDocumentTab t, bool saveonly)
{
if(t.IsChanged)
{
// Ask to save
DialogResult result = MessageBox.Show(this.ParentForm, "Do you want to save changes to " + t.Text + "?", "Close File", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if(result == DialogResult.Yes)
{
// Save file
if(!SaveScript(t)) return false;
}
else if(result == DialogResult.Cancel)
{
// Cancel
return false;
}
}
if(!saveonly)
{
// Close file
tabs.TabPages.Remove(t);
t.Dispose();
}
return true;
}
// This returns true when any of the implicit-save scripts are changed
public bool CheckImplicitChanges()
{
bool changes = false;
foreach(ScriptDocumentTab t in tabs.TabPages)
{
if(!t.ExplicitSave && t.IsChanged) changes = true;
}
return changes;
}
// This forces the focus to the script editor
public void ForceFocus()
{
ScriptDocumentTab t = (tabs.SelectedTab as ScriptDocumentTab);
tabs.Focus();
if(t != null) t.Focus();
}
// This does an implicit save on all documents that use implicit saving
// Call this to save the lumps before disposing the panel!
public void ImplicitSave()
{
// Save all scripts
foreach(ScriptDocumentTab t in tabs.TabPages)
{
if(!t.ExplicitSave) t.Save();
}
UpdateToolbar(false);
2008-11-10 16:11:44 +00:00
}
2008-11-09 17:59:13 +00:00
// This updates the toolbar for the current status
private void UpdateToolbar(bool focuseditor)
2008-11-09 17:59:13 +00:00
{
int numscriptsopen = tabs.TabPages.Count;
2008-11-10 16:11:44 +00:00
int explicitsavescripts = 0;
2008-11-09 17:59:13 +00:00
ScriptDocumentTab t = null;
2008-11-10 16:11:44 +00:00
// Any explicit save scripts?
foreach(ScriptDocumentTab dt in tabs.TabPages)
if(dt.ExplicitSave) explicitsavescripts++;
2008-11-09 17:59:13 +00:00
// Get current script, if any are open
if(numscriptsopen > 0)
t = (tabs.SelectedTab as ScriptDocumentTab);
// Enable/disable buttons
buttonsave.Enabled = (t != null) && t.ExplicitSave;
2008-11-10 16:11:44 +00:00
buttonsaveall.Enabled = (explicitsavescripts > 0);
2008-11-09 17:59:13 +00:00
buttoncompile.Enabled = (t != null) && (t.Config.Compiler != null);
buttonscriptconfig.Enabled = (t != null) && t.IsReconfigurable;
buttonundo.Enabled = (t != null);
buttonredo.Enabled = (t != null);
buttoncopy.Enabled = (t != null);
buttoncut.Enabled = (t != null);
buttonpaste.Enabled = (t != null);
buttonclose.Enabled = (t != null) && t.IsClosable;
if(t != null)
{
// Check the according script config in menu
foreach(ToolStripMenuItem item in buttonscriptconfig.DropDownItems)
{
ScriptConfiguration config = (item.Tag as ScriptConfiguration);
item.Checked = (config == t.Config);
}
2008-11-10 16:11:44 +00:00
// Focus to script editor
if(focuseditor) ForceFocus();
2008-11-09 17:59:13 +00:00
}
}
2008-11-11 06:43:33 +00:00
2008-11-15 13:12:09 +00:00
// This opens the given file, returns null when failed
public ScriptFileDocumentTab OpenFile(string filename)
2008-11-11 06:43:33 +00:00
{
ScriptConfiguration foundconfig = new ScriptConfiguration();
// Find the most suitable script configuration to use
foreach(ScriptConfiguration cfg in scriptconfigs)
{
foreach(string ext in cfg.Extensions)
{
// Use this configuration if the extension matches
if(filename.EndsWith("." + ext, true, CultureInfo.InvariantCulture))
{
foundconfig = cfg;
break;
}
}
}
// Create new document
2008-11-15 13:12:09 +00:00
ScriptFileDocumentTab t = new ScriptFileDocumentTab(this, foundconfig);
2008-11-11 06:43:33 +00:00
if(t.Open(filename))
{
2008-11-15 13:12:09 +00:00
// Mark any errors this script may have
if(compilererrors != null)
t.MarkScriptErrors(compilererrors);
2008-11-11 06:43:33 +00:00
// Add to tabs
tabs.TabPages.Add(t);
tabs.SelectedTab = t;
// Done
UpdateToolbar(true);
2008-11-15 13:12:09 +00:00
return t;
}
else
{
// Failed
return null;
2008-11-11 06:43:33 +00:00
}
}
// This saves the current open script
public void ExplicitSaveCurrentTab()
{
ScriptDocumentTab t = (tabs.SelectedTab as ScriptDocumentTab);
if((t != null) && t.ExplicitSave)
{
buttonsave_Click(this, EventArgs.Empty);
}
else
{
General.MessageBeep(MessageBeepType.Default);
}
}
// This opens a script
public void OpenBrowseScript()
{
buttonopen_Click(this, EventArgs.Empty);
}
2008-11-06 15:00:01 +00:00
#endregion
2008-11-06 15:00:01 +00:00
#region ================== Events
2008-11-10 16:11:44 +00:00
2008-11-09 17:59:13 +00:00
// When the user changes the script configuration
private void buttonscriptconfig_Click(object sender, EventArgs e)
{
// Get the tab and new script config
ScriptDocumentTab t = (tabs.SelectedTab as ScriptDocumentTab);
ScriptConfiguration scriptconfig = ((sender as ToolStripMenuItem).Tag as ScriptConfiguration);
// Change script config
t.ChangeScriptConfig(scriptconfig);
// Done
UpdateToolbar(true);
2008-11-09 17:59:13 +00:00
}
2008-11-06 15:00:01 +00:00
// When new script is clicked
private void buttonnew_Click(object sender, EventArgs e)
{
// Get the script config to use
ScriptConfiguration scriptconfig = ((sender as ToolStripMenuItem).Tag as ScriptConfiguration);
// Create new document
2008-11-15 13:12:09 +00:00
ScriptFileDocumentTab t = new ScriptFileDocumentTab(this, scriptconfig);
2008-11-06 15:00:01 +00:00
tabs.TabPages.Add(t);
tabs.SelectedTab = t;
2008-11-09 17:59:13 +00:00
// Done
UpdateToolbar(true);
2008-11-06 15:00:01 +00:00
}
// Open script clicked
private void buttonopen_Click(object sender, EventArgs e)
{
// Show open file dialog
if(openfile.ShowDialog(this.ParentForm) == DialogResult.OK)
{
2008-11-11 06:43:33 +00:00
// TODO: Make multi-select possible
OpenFile(openfile.FileName);
2008-11-06 15:00:01 +00:00
}
}
2008-11-09 17:59:13 +00:00
// Save script clicked
private void buttonsave_Click(object sender, EventArgs e)
{
// Save the current script
ScriptDocumentTab t = (tabs.SelectedTab as ScriptDocumentTab);
SaveScript(t);
UpdateToolbar(true);
2008-11-09 17:59:13 +00:00
}
// Save All clicked
private void buttonsaveall_Click(object sender, EventArgs e)
{
// Save all scripts
foreach(ScriptDocumentTab t in tabs.TabPages)
{
2008-11-10 16:11:44 +00:00
// Use explicit save for this script?
if(t.ExplicitSave)
{
if(!SaveScript(t)) break;
}
2008-11-09 17:59:13 +00:00
}
2008-11-10 16:11:44 +00:00
UpdateToolbar(true);
2008-11-09 17:59:13 +00:00
}
// This is called by Save and Save All to save a script
// Returns false when cancelled by the user
private bool SaveScript(ScriptDocumentTab t)
{
// Do we have to do a save as?
if(t.IsSaveAsRequired)
{
// Setup save dialog
string scriptfilter = t.Config.Description + "|*." + string.Join(";*.", t.Config.Extensions);
savefile.Filter = scriptfilter + "|All files|*.*";
if(savefile.ShowDialog(this.ParentForm) == DialogResult.OK)
{
// Save to new filename
t.SaveAs(savefile.FileName);
return true;
}
else
{
// Cancelled
return false;
}
}
else
{
// Save to same filename
t.Save();
return true;
}
}
2008-11-09 17:59:13 +00:00
// A tab is selected
private void tabs_Selecting(object sender, TabControlCancelEventArgs e)
{
UpdateToolbar(true);
2008-11-09 17:59:13 +00:00
}
2008-11-10 16:11:44 +00:00
2008-11-09 17:59:13 +00:00
// This closes the current file
private void buttonclose_Click(object sender, EventArgs e)
{
ScriptDocumentTab t = (tabs.SelectedTab as ScriptDocumentTab);
2008-11-10 16:11:44 +00:00
CloseScript(t, false);
UpdateToolbar(true);
2008-11-09 17:59:13 +00:00
}
// Compile Script clicked
private void buttoncompile_Click(object sender, EventArgs e)
{
// First save all implicit scripts to the temporary wad file
ImplicitSave();
2008-11-15 13:12:09 +00:00
// Get script
ScriptDocumentTab t = (tabs.SelectedTab as ScriptDocumentTab);
// Check if it must be saved as a new file
if(t.ExplicitSave && t.IsSaveAsRequired)
2008-11-15 13:12:09 +00:00
{
// Save the script first!
if(MessageBox.Show(this.ParentForm, "You must save your script before you can compile it. Do you want to save your script now?", "Compile Script", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
if(!SaveScript(t)) return;
}
else
{
return;
}
}
else
{
if(t.ExplicitSave && t.IsChanged)
{
// We can only compile when the script is saved
if(!SaveScript(t)) return;
}
2008-11-15 13:12:09 +00:00
}
// Compile now
General.MainWindow.DisplayStatus("Compiling script " + t.Text + "...");
Cursor.Current = Cursors.WaitCursor;
t.Compile();
2008-11-15 13:12:09 +00:00
// Show warning
if((compilererrors != null) && (compilererrors.Count > 0))
General.MainWindow.DisplayWarning(compilererrors.Count.ToString() + " errors while compiling " + t.Text + "!");
else
General.MainWindow.DisplayReady();
Cursor.Current = Cursors.Default;
UpdateToolbar(true);
}
2008-11-09 17:59:13 +00:00
// Undo clicked
private void buttonundo_Click(object sender, EventArgs e)
{
ScriptDocumentTab t = (tabs.SelectedTab as ScriptDocumentTab);
t.Undo();
UpdateToolbar(true);
2008-11-09 17:59:13 +00:00
}
2008-11-09 17:59:13 +00:00
// Redo clicked
private void buttonredo_Click(object sender, EventArgs e)
{
ScriptDocumentTab t = (tabs.SelectedTab as ScriptDocumentTab);
t.Redo();
UpdateToolbar(true);
2008-11-09 17:59:13 +00:00
}
2008-11-09 17:59:13 +00:00
// Cut clicked
private void buttoncut_Click(object sender, EventArgs e)
{
ScriptDocumentTab t = (tabs.SelectedTab as ScriptDocumentTab);
t.Cut();
UpdateToolbar(true);
2008-11-09 17:59:13 +00:00
}
2008-11-09 17:59:13 +00:00
// Copy clicked
private void buttoncopy_Click(object sender, EventArgs e)
{
ScriptDocumentTab t = (tabs.SelectedTab as ScriptDocumentTab);
t.Copy();
UpdateToolbar(true);
2008-11-09 17:59:13 +00:00
}
// Paste clicked
private void buttonpaste_Click(object sender, EventArgs e)
{
ScriptDocumentTab t = (tabs.SelectedTab as ScriptDocumentTab);
t.Paste();
UpdateToolbar(true);
2008-11-10 16:11:44 +00:00
}
// Mouse released on tabs
private void tabs_MouseUp(object sender, MouseEventArgs e)
{
ForceFocus();
2008-11-09 17:59:13 +00:00
}
2008-11-06 15:00:01 +00:00
2008-11-15 13:12:09 +00:00
// User double-clicks and error in the list
private void errorlist_ItemActivate(object sender, EventArgs e)
{
// Anything selection?
if(errorlist.SelectedItems.Count > 0)
{
// Get the compiler error
CompilerError err = (CompilerError)errorlist.SelectedItems[0].Tag;
// Show the tab with the script that matches
bool foundscript = false;
foreach(ScriptDocumentTab t in tabs.TabPages)
{
if(t.VerifyErrorForScript(err))
{
tabs.SelectedTab = t;
t.MoveToLine(err.linenumber);
foundscript = true;
break;
}
}
// If we don't have the script opened, see if we can find the file and open the script
if(!foundscript && File.Exists(err.filename))
{
ScriptDocumentTab t = OpenFile(err.filename);
if(t != null) t.MoveToLine(err.linenumber);
}
ForceFocus();
}
}
#endregion
}
}