2009-04-19 18:07:22 +00:00
#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.Windows.Forms ;
using CodeImp.DoomBuilder.Windows ;
using CodeImp.DoomBuilder.Actions ;
using CodeImp.DoomBuilder.Plugins ;
using CodeImp.DoomBuilder.VisualModes ;
#endregion
namespace CodeImp.DoomBuilder.Editing
{
public sealed class EditingManager
{
#region = = = = = = = = = = = = = = = = = = Constants
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
// All editing mode groups, sorted alphabetically
private List < string > groups ;
// All editing modes available
private List < EditModeInfo > allmodes ;
// Editing modes selected through configuration
private List < EditModeInfo > usedmodes ;
// Status
private EditMode mode ;
private EditMode newmode ;
private Type prevmode ;
private Type prevstablemode ;
private Type prevclassicmode ;
2009-07-10 13:56:22 +00:00
private bool disengaging ;
2009-04-19 18:07:22 +00:00
// Disposing
2014-02-21 14:42:12 +00:00
private bool isdisposed ;
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
internal List < EditModeInfo > ModesInfo { get { return allmodes ; } }
public EditMode Mode { get { return mode ; } }
public EditMode NewMode { get { return newmode ; } }
public Type PreviousMode { get { return prevmode ; } }
public Type PreviousStableMode { get { return prevstablemode ; } }
public Type PreviousClassicMode { get { return prevclassicmode ; } }
public bool IsDisposed { get { return isdisposed ; } }
#endregion
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
// Constructor
internal EditingManager ( )
{
// Initialize
allmodes = new List < EditModeInfo > ( ) ;
usedmodes = new List < EditModeInfo > ( ) ;
groups = new List < string > ( ) ;
// Bind any methods
General . Actions . BindMethods ( this ) ;
// Make list of all editing modes we can find
foreach ( Plugin p in General . Plugins . Plugins )
{
// For all classes that inherit from EditMode
Type [ ] editclasses = p . FindClasses ( typeof ( EditMode ) ) ;
foreach ( Type t in editclasses )
{
// For all defined EditMode attributes
EditModeAttribute [ ] emattrs = ( EditModeAttribute [ ] ) t . GetCustomAttributes ( typeof ( EditModeAttribute ) , false ) ;
foreach ( EditModeAttribute a in emattrs )
{
// Make edit mode information
EditModeInfo modeinfo = new EditModeInfo ( p , t , a ) ;
allmodes . Add ( modeinfo ) ;
// Add group if not added yet
if ( ! groups . Contains ( modeinfo . Attributes . ButtonGroup ) )
groups . Add ( modeinfo . Attributes . ButtonGroup ) ;
}
}
}
// Sort the lists
allmodes . Sort ( ) ;
groups . Sort ( ) ;
// Update modes
UpdateCurrentEditModes ( ) ;
// We have no destructor
GC . SuppressFinalize ( this ) ;
}
// Disposer
internal void Dispose ( )
{
// Not already disposed?
if ( ! isdisposed )
{
// Unbind any methods
General . Actions . UnbindMethods ( this ) ;
// Clean up
2015-09-16 12:10:43 +00:00
foreach ( EditModeInfo i in allmodes ) i . Dispose ( ) ; //mxd
2009-04-19 18:07:22 +00:00
// Done
isdisposed = true ;
}
}
#endregion
#region = = = = = = = = = = = = = = = = = = Switch Actions
// This unbinds all editing mode switch actions
private void UnbindSwitchActions ( )
{
foreach ( EditModeInfo emi in allmodes )
{
emi . UnbindSwitchAction ( ) ;
}
}
// This binds all editing mode switch actions for the available modes only
private void BindAvailableSwitchActions ( )
{
// In case of VisualMode, we only bind the switch action
// of the VisualMode to switch back to the previous mode
if ( mode is VisualMode )
{
// Bind only the switch action for this mode
EditModeInfo info = GetEditModeInfo ( mode . GetType ( ) ) ;
info . BindSwitchAction ( ) ;
}
else
{
// Bind all available mode swtich actions
foreach ( EditModeInfo emi in usedmodes )
{
emi . BindSwitchAction ( ) ;
}
}
}
#endregion
#region = = = = = = = = = = = = = = = = = = Methods
2009-07-10 13:56:22 +00:00
// This cancels a volatile mode, as if the user presses cancel
public bool CancelVolatileMode ( )
{
// Volatile mode?
if ( ( General . Map ! = null ) & ( mode ! = null ) & & mode . Attributes . Volatile & & ! disengaging )
{
// Cancel
disengaging = true ;
2010-08-22 11:36:09 +00:00
General . Plugins . OnEditCancel ( ) ;
2009-07-10 13:56:22 +00:00
mode . OnCancel ( ) ;
return true ;
}
else
{
// Mode is not volatile
return false ;
}
}
// This disengages a volatile mode, leaving the choice to cancel or accept to the editing mode
public bool DisengageVolatileMode ( )
{
// Volatile mode?
if ( ( General . Map ! = null ) & & ( mode ! = null ) & & mode . Attributes . Volatile & & ! disengaging )
{
// Change back to normal mode
disengaging = true ;
ChangeMode ( prevstablemode . Name ) ;
return true ;
}
else
{
// Mode is not volatile
return false ;
}
}
2009-04-19 18:07:22 +00:00
// This returns specific editing mode info by name
internal EditModeInfo GetEditModeInfo ( string editmodename )
{
// Find the edit mode
foreach ( EditModeInfo emi in usedmodes )
{
// Mode matches class name?
2009-07-09 15:15:49 +00:00
if ( emi . Type . Name = = editmodename ) return emi ;
2009-04-19 18:07:22 +00:00
}
// No such mode found
return null ;
}
// This returns specific editing mode info by name
internal EditModeInfo GetEditModeInfo ( Type modetype )
{
// Find the edit mode
foreach ( EditModeInfo emi in usedmodes )
{
// Mode matches class name?
if ( emi . Type = = modetype ) return emi ;
}
// No such mode found
return null ;
}
// This is called when the editing modes must update
internal void UpdateCurrentEditModes ( )
{
// Unbind editing mode switch actions
UnbindSwitchActions ( ) ;
// Rebuild list of used modes
usedmodes . Clear ( ) ;
if ( General . Map ! = null )
{
foreach ( EditModeInfo emi in allmodes )
{
2021-03-21 21:58:06 +00:00
// Include the mode if it supports current map format (mxd) and map features
2014-09-08 13:09:14 +00:00
// Also include the mode when it is listed and enabled or when it's not optional
if ( ( emi . Attributes . SupportedMapFormats = = null | | Array . IndexOf ( emi . Attributes . SupportedMapFormats , General . Map . Config . FormatInterface ) ! = - 1 ) & &
2021-03-21 21:58:06 +00:00
( emi . Attributes . RequiredMapFeatures = = null | | General . Map . Config . SupportsMapFeatures ( emi . Attributes . RequiredMapFeatures ) ) & &
2014-09-08 13:09:14 +00:00
( ( General . Map . ConfigSettings . EditModes . ContainsKey ( emi . Type . FullName ) & &
General . Map . ConfigSettings . EditModes [ emi . Type . FullName ] )
| | ! emi . IsOptional ) )
2009-04-19 18:07:22 +00:00
{
// Add the mode to be used and bind switch action
usedmodes . Add ( emi ) ;
}
}
}
// Bind switch action for used modes
BindAvailableSwitchActions ( ) ;
// Remove editing mode buttons from interface
General . MainWindow . RemoveEditModeButtons ( ) ;
// Go for all the editing mode groups
foreach ( string grp in groups )
{
2014-02-26 14:11:06 +00:00
General . MainWindow . AddEditModeSeperator ( grp ) ;
2009-04-19 18:07:22 +00:00
// Go for all used edit modes to add buttons
foreach ( EditModeInfo emi in usedmodes )
{
if ( ( emi . ButtonImage ! = null ) & & ( emi . ButtonDesc ! = null ) & &
( emi . Attributes . ButtonGroup = = grp ) )
General . MainWindow . AddEditModeButton ( emi ) ;
}
}
}
//
// This changes the editing mode.
// Order in which events occur for the old and new modes:
//
// - Constructor of new mode is called
// - Disengage of old mode is called
// ----- Mode switches -----
// - Engage of new mode is called
// - Dispose of old mode is called
//
// Returns false when cancelled
public bool ChangeMode ( EditMode nextmode )
{
EditMode oldmode = mode ;
if ( nextmode ! = null )
{
// Verify that this mode is usable
bool allowuse = false ;
foreach ( EditModeInfo emi in usedmodes )
{
if ( emi . Type . FullName = = nextmode . GetType ( ) . FullName )
{
allowuse = true ;
break ;
}
}
if ( ! allowuse )
{
General . Interface . MessageBeep ( MessageBeepType . Error ) ;
General . WriteLogLine ( "Attempt to switch to an invalid edit mode " + nextmode . GetType ( ) . Name + "!" ) ;
return false ;
}
else
{
General . WriteLogLine ( "Preparing to change editing mode to " + nextmode . GetType ( ) . Name + "..." ) ;
}
}
else
{
General . WriteLogLine ( "Stopping editing mode..." ) ;
}
// Remember previous mode
newmode = nextmode ;
if ( mode ! = null )
{
prevmode = mode . GetType ( ) ;
if ( ! mode . Attributes . Volatile )
{
prevstablemode = prevmode ;
if ( mode is ClassicMode ) prevclassicmode = prevmode ;
}
}
else
{
prevmode = null ;
prevstablemode = null ;
prevclassicmode = null ;
}
// Let the plugins know beforehand and check if not cancelled
if ( General . Plugins . ModeChanges ( oldmode , newmode ) )
{
// Disenagage old mode
2009-07-10 13:56:22 +00:00
disengaging = true ;
2010-08-22 11:36:09 +00:00
if ( oldmode ! = null )
{
General . Plugins . OnEditDisengage ( oldmode , newmode ) ;
oldmode . OnDisengage ( ) ;
}
2009-04-19 18:07:22 +00:00
// Reset cursor
General . Interface . SetCursor ( Cursors . Default ) ;
// Apply new mode
General . WriteLogLine ( "Editing mode changes from " + TypeNameOrNull ( oldmode ) + " to " + TypeNameOrNull ( nextmode ) ) ;
General . WriteLogLine ( "Previous stable mode is " + TypeNameOrNull ( prevstablemode ) + ", previous classic mode is " + TypeNameOrNull ( prevclassicmode ) ) ;
mode = newmode ;
2009-07-10 13:56:22 +00:00
disengaging = false ;
2009-04-19 18:07:22 +00:00
// Engage new mode
2010-08-22 11:36:09 +00:00
if ( newmode ! = null )
{
2021-03-21 20:19:14 +00:00
if ( newmode . Attributes . IsDeprecated )
General . ErrorLogger . Add ( ErrorType . Warning , "The editing mode \"" + newmode . Attributes . DisplayName + "\" is deprecated and will be removed in the future. " + newmode . Attributes . DeprecationMessage ) ;
2010-08-22 11:36:09 +00:00
newmode . OnEngage ( ) ;
General . Plugins . OnEditEngage ( oldmode , newmode ) ;
}
2009-04-19 18:07:22 +00:00
// Bind new switch actions
UnbindSwitchActions ( ) ;
BindAvailableSwitchActions ( ) ;
// Update the interface
General . MainWindow . EditModeChanged ( ) ;
// Dispose old mode
if ( oldmode ! = null ) oldmode . Dispose ( ) ;
// Done switching
General . WriteLogLine ( "Editing mode change complete." ) ;
newmode = null ;
// Redraw the display
General . MainWindow . RedrawDisplay ( ) ;
return true ;
}
else
{
// Cancelled
General . WriteLogLine ( "Editing mode change cancelled." ) ;
return false ;
}
}
// This changes mode by class name and optionally with arguments
public void ChangeMode ( string classname , params object [ ] args )
{
EditModeInfo emi = GetEditModeInfo ( classname ) ;
if ( emi ! = null ) emi . SwitchToMode ( args ) ;
}
// This returns the type name as string
2014-05-20 09:09:28 +00:00
private static string TypeNameOrNull ( Type type )
2009-04-19 18:07:22 +00:00
{
return ( type ! = null ) ? type . Name : "NULL" ;
}
// This returns the type name as string
2014-05-20 09:09:28 +00:00
private static string TypeNameOrNull ( object obj )
2009-04-19 18:07:22 +00:00
{
return ( obj ! = null ) ? obj . GetType ( ) . Name : "NULL" ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Actions
/// <summary>
/// This cancels the current mode.
/// </summary>
[BeginAction("cancelmode")]
public void CancelMode ( )
{
// Let the mode know
if ( mode ! = null )
2010-08-22 11:36:09 +00:00
{
General . Plugins . OnEditCancel ( ) ;
2009-04-19 18:07:22 +00:00
mode . OnCancel ( ) ;
2010-08-22 11:36:09 +00:00
}
2009-04-19 18:07:22 +00:00
}
/// <summary>
/// This accepts the changes in the current mode.
/// </summary>
[BeginAction("acceptmode")]
public void AcceptMode ( )
{
// Let the mode know
if ( mode ! = null )
2010-08-22 11:36:09 +00:00
{
General . Plugins . OnEditAccept ( ) ;
2009-04-19 18:07:22 +00:00
mode . OnAccept ( ) ;
2010-08-22 11:36:09 +00:00
}
2009-04-19 18:07:22 +00:00
}
#endregion
}
}