// $Id: layergal.cpp 1282 2006-06-09 09:46:49Z alex $
/* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
================================XARAHEADERSTART===========================
 
               Xara LX, a vector drawing and manipulation program.
                    Copyright (C) 1993-2006 Xara Group Ltd.
       Copyright on certain contributions may be held in joint with their
              respective authors. See AUTHORS file for details.

LICENSE TO USE AND MODIFY SOFTWARE
----------------------------------

This file is part of Xara LX.

Xara LX is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as published
by the Free Software Foundation.

Xara LX and its component source files are 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.

You should have received a copy of the GNU General Public License along
with Xara LX (see the file GPL in the root directory of the
distribution); if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA  02110-1301 USA


ADDITIONAL RIGHTS
-----------------

Conditional upon your continuing compliance with the GNU General Public
License described above, Xara Group Ltd grants to you certain additional
rights. 

The additional rights are to use, modify, and distribute the software
together with the wxWidgets library, the wxXtra library, and the "CDraw"
library and any other such library that any version of Xara LX relased
by Xara Group Ltd requires in order to compile and execute, including
the static linking of that library to XaraLX. In the case of the
"CDraw" library, you may satisfy obligation under the GNU General Public
License to provide source code by providing a binary copy of the library
concerned and a copy of the license accompanying it.

Nothing in this section restricts any of the rights you have under
the GNU General Public License.


SCOPE OF LICENSE
----------------

This license applies to this program (XaraLX) and its constituent source
files only, and does not necessarily apply to other Xara products which may
in part share the same code base, and are subject to their own licensing
terms.

This license does not apply to files in the wxXtra directory, which
are built into a separate library, and are subject to the wxWindows
license contained within that directory in the file "WXXTRA-LICENSE".

This license does not apply to the binary libraries (if any) within
the "libs" directory, which are subject to a separate license contained
within that directory in the file "LIBS-LICENSE".


ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
----------------------------------------------

Subject to the terms of the GNU Public License (see above), you are
free to do whatever you like with your modifications. However, you may
(at your option) wish contribute them to Xara's source tree. You can
find details of how to do this at:
  http://www.xaraxtreme.org/developers/

Prior to contributing your modifications, you will need to complete our
contributor agreement. This can be found at:
  http://www.xaraxtreme.org/developers/contribute/

Please note that Xara will not accept modifications which modify any of
the text between the start and end of this header (marked
XARAHEADERSTART and XARAHEADEREND).


MARKS
-----

Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
designs are registered or unregistered trademarks, design-marks, and/or
service marks of Xara Group Ltd. All rights in these marks are reserved.


      Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
                        http://www.xara.com/

=================================XARAHEADEREND============================
 */
// The Layers gallery

/*
*/

#include "camtypes.h"
#include "layergal.h"

DECLARE_SOURCE("$Revision: 1282 $");

//#include "ensure.h"
#include "sprdmsg.h"
//#include "markn.h"
//#include "simon.h"
//#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED]
//#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
#include "layermgr.h"
//#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
#include "insertnd.h"
//#include "ink.h" - in camtypes.h [AUTOMATICALLY REMOVED]
//#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
//#include "resource.h"
//#include "barsdlgs.h" 
#include "guides.h" 
#include "nodetxts.h"
#include "textops.h"
#include "bubbleid.h"
#include "ophist.h"
#include "sglayer.h"		// The LayerSGallery class
#include "sginit.h"

//#include "will2.h"
//#include "galstr.h"			// _R(IDS_DELETEPAGEBACKGROUND)
//#include "prevwres.h"		// _R(IDS_DISPLAY_FRAME_GALLERY) _R(IDD_ANIMATIONBAR) ...
//#include "sgframe.h"		// FrameSGallery

//#include "frameops.h"		// Frame related ops
//#include "aprps.h"

#include "nodetxts.h"		//TextStory::SetFocusStory

#include "layermsg.h"		// LayerMsg::LayerReason::REDRAW_LAYER
//#include "xshelpid.h"		//For the help id

#define Swap(a,b)       { (a)^=(b), (b)^=(a), (a)^=(b); }

//-----------------------------------------------------------------------
//-----------------------------------------------------------------------

CC_IMPLEMENT_DYNCREATE(OpDeletePageBackground,OpLayerGalChange);
CC_IMPLEMENT_DYNCREATE(OpLayerGalChange,UndoableOperation);
CC_IMPLEMENT_DYNCREATE(OpDisplayLayerGallery,Operation);
PORTNOTE("galleries", "disabled frame gallery")
#ifndef EXCLUDE_FROM_XARALX
CC_IMPLEMENT_DYNCREATE(OpDisplayFrameGallery,Operation);
#endif
CC_IMPLEMENT_DYNCREATE(LayerNameDlg, DialogOp)   
CC_IMPLEMENT_DYNCREATE(LayerStateAction,Action)
			  
const CDlgMode 	LayerNameDlg::Mode 	 		= MODAL;   // The dialog is modal
const INT32		LayerNameDlg::IDD			= _R(IDD_LAYER_NAME);
BOOL 			LayerNameDlg::IsOpen 		= FALSE;  // It's not open yet
LayerNameDlg*	LayerNameDlg::pLayerNameDlg = NULL;  // The layer name dlg that is open

// This will get Camelot to display the filename and linenumber of any memory allocations
// that are not released at program exit
#define new CAM_DEBUG_NEW


//------------------------------------------------------------------------------------------
// Methods for the OpDeletePageBackground

/********************************************************************************************

>	OpDeletePageBackground::OpDeletePageBackground() 

	Author:		Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
	Created:	10/4/97
	Purpose:	OpDeletePageBackground constructor (Creates an undoable operation)
	Errors:		-
	SeeAlso:	-

********************************************************************************************/

OpDeletePageBackground::OpDeletePageBackground()								
{                              
	// nothing to do yet
}

/********************************************************************************************

>	OpState	OpDeletePageBackground::GetState(String_256*, OpDescriptor*)

	Author:		Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
	Created:	10/4/97
	Inputs:		Name of the OpDescriptor being queried
	Outputs:	The string to show to the user
	Returns:	The state of the OpDeletePageBackground operation
	Purpose:	For finding the OpDeletePageBackground's state. 
	Errors:		-
	SeeAlso:	-

********************************************************************************************/

OpState	OpDeletePageBackground::GetState(String_256* pUIDescription, OpDescriptor* pOpDesc)
{
	OpState OpSt;  

	// Is there a selected spread?
	Spread * pSpread = Document::GetSelectedSpread();
	if (pSpread)
	{
		// yes, so check if there is a background layer
		Layer* pLayer = pSpread->FindFirstPageBackgroundLayer();
		if (pLayer)
		{
			// Yes, so we are allowed to delete it
			OpSt.Greyed = FALSE;
		}
		else
		{
			// No, so we are greyed
			OpSt.Greyed = TRUE;
		}
	}
	else
	{
		// No selected spread, so we are greyed
		OpSt.Greyed = TRUE;
	}

 	return OpSt;   
}

/********************************************************************************************

>	void OpDeletePageBackground::Do(OpDescriptor* pOpDesc)

	Author:		Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
	Created:	10/4/97
	Inputs:		OpDescriptor (unused)
	Outputs:	-
	Returns:	-
	Purpose:	Finds and deletes the page background layer from the selected spread.
	Errors:		-
	SeeAlso:	-

********************************************************************************************/

void OpDeletePageBackground::Do(OpDescriptor* pOpDesc)
{
	// Just find the background layer and then ask our baseclass to delete it for us
	// Is there a selected spread?
	Spread * pSpread = Document::GetSelectedSpread();
	if (pSpread)
	{
		// yes, so check if there is a background layer
		Layer* pLayer = pSpread->FindFirstPageBackgroundLayer();
		if (pLayer)
		{
			OpLayerGalParam Param(PAGEBACKGROUND_DEFAULT, pSpread);
			Param.pLayer = pLayer;
			DoWithParam(pOpDesc, (OpParam*)&Param);
		}
	}

	return;
}

//------------------------------------------------------------------------------------------
// Methods for the OpLayerGalChange

/********************************************************************************************

>	OpLayerGalChange::OpLayerGalChange() 

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	4/8/94
	Inputs:		-
	Outputs:	-
	Returns:	-
	Purpose:	OpLayerGalChange constructor (Creates an undoable operation)
	Errors:		-
	SeeAlso:	-

********************************************************************************************/
            
            
OpLayerGalChange::OpLayerGalChange(): UndoableOperation()								
{                              
	pSpread 				= NULL;
	UndoIDS 				= _R(IDS_NOTYPE);
	BroadcastLayerChanges 	= TRUE;
	pOpUndoLayer			= NULL;
	pOpRedoLayer			= NULL;
}

/********************************************************************************************

>	BOOL OpLayerGalChange::Init()

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	4/8/94
	Inputs:		-
	Outputs:	-
	Returns:	TRUE if the operation could be successfully initialised 
				FALSE if no more memory could be allocated 
				
	Purpose:	OpLayerGalChange initialiser method
	Errors:		ERROR will be called if there was insufficient memory to allocate the 
				operation.
	SeeAlso:	-

********************************************************************************************/

BOOL OpLayerGalChange::Init()
{
	return (
			RegisterOpDescriptor(
	 							0,
	 							_R(IDS_LAYERCHANGEOP),
								CC_RUNTIME_CLASS(OpLayerGalChange),
	 							OPTOKEN_LAYERGALCHANGE,
	 							OpLayerGalChange::GetState,
	 							0,	/* help ID */
	 							_R(IDBBL_LAYERCHANGEOP),
	 							0	/* bitmap ID */
								) &&
			RegisterOpDescriptor(
	 							0,
	 							_R(IDS_DELETEPAGEBACKGROUND),
								CC_RUNTIME_CLASS(OpDeletePageBackground),
	 							OPTOKEN_DELETEPAGEBACKGROUND,
	 							OpDeletePageBackground::GetState,
	 							0,			// help ID
	 							0,			// bubble help id
	 							0			// bitmap ID
								)
			// special frame operations
								&&
PORTNOTE("galleries", "Disabled frame stuff")
#ifndef EXCLUDE_FROM_XARALX
			RegisterOpDescriptor(
								0,								// Tool ID 
	 							_R(IDS_SELECTSTARTFRAME),			// String resource ID
								CC_RUNTIME_CLASS(OpSelectStartFrame),	// Runtime class
	 							OPTOKEN_FRAME_STARTFRAME,		// Token string
	 							OpSelectStartFrame::GetState,	// GetState function
	 							0,								// help ID
								_R(IDBBL_SELECTSTARTFRAME),			// bubble help
								_R(IDD_ANIMATIONBAR),				// resource ID
								_R(IDC_PREVIEW_STARTFRAME),			// control ID
								SYSTEMBAR_ANIMATION,			// Bar ID
								TRUE,							// Recieve system messages
								FALSE,							// Smart duplicate operation
								TRUE,							// Clean operation
								NULL,							// String for one copy only error
								(DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags
								)
								&&
			RegisterOpDescriptor(
								0,								// Tool ID 
	 							_R(IDS_SELECTENDFRAME),				// String resource ID
								CC_RUNTIME_CLASS(OpSelectEndFrame),	// Runtime class
	 							OPTOKEN_FRAME_ENDFRAME,			// Token string
	 							OpSelectEndFrame::GetState,	// GetState function
	 							0,								// help ID
								_R(IDBBL_SELECTENDFRAME),			// bubble help
								_R(IDD_ANIMATIONBAR),				// resource ID
								_R(IDC_PREVIEW_ENDFRAME),			// control ID
								SYSTEMBAR_ANIMATION,			// Bar ID
								TRUE,							// Recieve system messages
								FALSE,							// Smart duplicate operation
								TRUE,							// Clean operation
								NULL,							// String for one copy only error
								(DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags
								)
								&&
			RegisterOpDescriptor(
								0,								// Tool ID 
	 							_R(IDS_SELECTPREVFRAME),			// String resource ID
								CC_RUNTIME_CLASS(OpSelectPrevFrame),	// Runtime class
	 							OPTOKEN_FRAME_PREVFRAME,		// Token string
	 							OpSelectPrevFrame::GetState,	// GetState function
	 							0,								// help ID
								_R(IDBBL_SELECTPREVFRAME),			// bubble help
								_R(IDD_ANIMATIONBAR),				// resource ID
								_R(IDC_PREVIEW_PREVFRAME),			// control ID
								SYSTEMBAR_ANIMATION,			// Bar ID
								TRUE,							// Recieve system messages
								FALSE,							// Smart duplicate operation
								TRUE,							// Clean operation
								NULL,							// String for one copy only error
								(DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags
								)
								&&
			RegisterOpDescriptor(
								0,								// Tool ID 
	 							_R(IDS_SELECTNEXTFRAME),			// String resource ID
								CC_RUNTIME_CLASS(OpSelectNextFrame),	// Runtime class
	 							OPTOKEN_FRAME_NEXTFRAME,		// Token string
	 							OpSelectNextFrame::GetState,	// GetState function
	 							0,								// help ID
								_R(IDBBL_SELECTNEXTFRAME),			// bubble help
								_R(IDD_ANIMATIONBAR),				// resource ID
								_R(IDC_PREVIEW_NEXTFRAME),			// control ID
								SYSTEMBAR_ANIMATION,			// Bar ID
								TRUE,							// Recieve system messages
								FALSE,							// Smart duplicate operation
								TRUE,							// Clean operation
								NULL,							// String for one copy only error
								(DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags
								)
								&&
			RegisterOpDescriptor(
								0,								// Tool ID 
	 							_R(IDS_NEWFRAME),					// String resource ID
								CC_RUNTIME_CLASS(OpCreateNewFrame),	// Runtime class
	 							OPTOKEN_FRAME_NEWFRAME,			// Token string
	 							OpCreateNewFrame::GetState,		// GetState function
	 							0,								// help ID
								_R(IDBBL_NEWFRAME),					// bubble help
								_R(IDD_ANIMATIONBAR),				// resource ID
								_R(IDC_FRAME_NEWFRAME),				// control ID
								SYSTEMBAR_ANIMATION,			// Bar ID
								TRUE,							// Recieve system messages
								FALSE,							// Smart duplicate operation
								TRUE,							// Clean operation
								NULL,							// String for one copy only error
								(DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags
								)
								&&
			RegisterOpDescriptor(
								0,								// Tool ID 
	 							_R(IDS_COPYFRAME),					// String resource ID
								CC_RUNTIME_CLASS(OpCopyFrame),	// Runtime class
	 							OPTOKEN_FRAME_COPYFRAME,		// Token string
	 							OpCopyFrame::GetState,			// GetState function
	 							0,								// help ID
								_R(IDBBL_COPYFRAME),				// bubble help
								_R(IDD_ANIMATIONBAR),				// resource ID
								_R(IDC_FRAME_COPYFRAME),			// control ID
								SYSTEMBAR_ANIMATION,			// Bar ID
								TRUE,							// Recieve system messages
								FALSE,							// Smart duplicate operation
								TRUE,							// Clean operation
								NULL,							// String for one copy only error
								(DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags
								)
								&&
			RegisterOpDescriptor(
								0,								// Tool ID 
	 							_R(IDS_DELETEFRAME),				// String resource ID
								CC_RUNTIME_CLASS(OpDeleteFrame),// Runtime class
	 							OPTOKEN_FRAME_DELETEFRAME,		// Token string
	 							OpDeleteFrame::GetState,		// GetState function
	 							0,								// help ID
								_R(IDBBL_DELETEFRAME),				// bubble help
								_R(IDD_ANIMATIONBAR),				// resource ID
								_R(IDC_FRAME_DELETEFRAME),			// control ID
								SYSTEMBAR_ANIMATION,			// Bar ID
								TRUE,							// Recieve system messages
								FALSE,							// Smart duplicate operation
								TRUE,							// Clean operation
								NULL,							// String for one copy only error
								(DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags
								)
								&&
#endif // EXCLUDE_FROM_XARALX
								TRUE
			);
}               
    
/********************************************************************************************

>	OpState	OpLayerGalChange::GetState(String_256*, OpDescriptor*)

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	4/8/94
	Inputs:		-
	Outputs:	-
	Returns:	The state of the OpLayerGalChange operation
	Purpose:	For finding the OpLayerGalChange's state. 
	Errors:		-
	SeeAlso:	-

********************************************************************************************/

OpState	OpLayerGalChange::GetState(String_256* UIDescription, OpDescriptor*)
{
	OpState OpSt;  
 	return(OpSt);   
}

/********************************************************************************************

>	void OpLayerGalChange::DoWithParam(OpDescriptor*,OpParam* pOpParam)

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	4/8/94
	Inputs:		OpDescriptor (unused)
				pOpParam - this is really a ptr to an OpLayerGalParam
	Outputs:	-
	Returns:	-
	Purpose:	Performs the layer change operation defined by ((OpLayerGalParam*)pOpParam)->Reason.
				It handles the creation, deletion, changing, and moving of the layer provided.

	Errors:		-
	SeeAlso:	-

********************************************************************************************/
// The bounding rectangle of the current layer must be invalidated in all the following cases. 

// If the visible status has changed 
// If the Quality level has changed 
// If the layer has been deleted 
// If the z-order of the layer has changed

			
void OpLayerGalChange::DoWithParam(OpDescriptor*, OpParam* pOpParam)
{   
	OpLayerGalParam* pOpLayerGalParam = (OpLayerGalParam*)pOpParam;

	pSpread = pOpLayerGalParam->GetParentSpread();
	Reason  = pOpLayerGalParam->GetReason();

	Layer* 				pLayer 		= pOpLayerGalParam->pLayer;
	Node*				pContextNode= pOpLayerGalParam->pContextNode;
	AttachNodeDirection	AttDir		= pOpLayerGalParam->AttDir;
	LayerStatus			NewStatus 	= pOpLayerGalParam->Status;

	BOOL FrameLayer = FALSE;

	switch (Reason)
	{
		//--------------------------------------------------------------------------------------------
		// Select a Frame layer
		case (FRAME_SELECT):
			// Check for being given a null layer or an already active layer
			if (pLayer == NULL || pLayer->IsActive())
				goto EndOperation;

PORTNOTE("galleries", "disabled frame gallery")
#ifndef EXCLUDE_FROM_XARALX
			// Make the layer we have been passed the active one
			FrameSGallery::MakeActiveLayer(pLayer);
#endif
			UndoIDS = _R(IDS_FRAME_UNDO_SELECTNEW);
			break;
		//--------------------------------------------------------------------------------------------
		// Create a new layer
		case (FRAME_NEW):
			FrameLayer = TRUE;
		case (LAYER_NEW):
			{
				// Attempt to create a new layer node 
				ALLOC_WITH_FAIL(pLayer, (new Layer()), this); 	      
				if (pLayer == NULL)
					goto EndOperation; // We were unable to create a new layer so 
									   // abort the operation 

				// Set the new layer's status  
				pLayer->SetLayerStatus(NewStatus); 

				// Set the frame layer flag according to the operation type i.e FRAME_NEW = set flag
				if (FrameLayer)
				{
					pLayer->SetFrame(TRUE);
					pLayer->SetEdited(TRUE);
				}

				// Insert new layer in the tree
				// Rule: if there is a guide layer at the top, then place the new layer
				// beneath this layer, otherwise, put the new layer at the top.
				Layer* pLastLayer = pSpread->FindLastLayer();
				if(pLastLayer && pLastLayer->IsGuide())
				{
					// this layer is a guide layer - get the next one
					pLastLayer = pLastLayer->FindPrevLayer();
				}
				Node* pNodeToInsert;
				if(pLastLayer)
				{
					pNodeToInsert = pLastLayer;
				}
				else
				{
					// what?! can't find a Last Layer to use?
					pNodeToInsert = pContextNode;
				}

				if (DoInsertNewNode(pLayer, pLastLayer, NEXT, FALSE))
				{
PORTNOTE("galleries", "Disabled frame gallery")
#ifndef EXCLUDE_FROM_XARALX
					if (FrameLayer)
						FrameSGallery::MakeActiveLayer(pLayer);
					else
#endif
						LayerSGallery::MakeActiveLayer(pLayer);

					// Note the layer inserted so we can clear any selection on the layer when this op is undone
					pOpUndoLayer = pLayer;
					pLayer->EnsureUniqueLayerID();
				}
			}

			if (FrameLayer)
				UndoIDS = _R(IDS_FRAME_UNDO_NEW);
			else
				UndoIDS = _R(IDS_LAYER_UNDO_NEW);
			break;

		//--------------------------------------------------------------------------------------------
		// Delete a layer
		case (FRAME_DELETE):
			FrameLayer = TRUE;
		case (LAYER_DELETE):
		case (PAGEBACKGROUND_DEFAULT):
			{
				// This doesn't seem to be an important ensure as it works when the layer
				// is not active
				// Disabled 10/4/97
				//ERROR3IF(pLayer->IsActive(),"Deleting layer, yet it is not active");

				// We need to find 'prev' and 'next' before we delete the layer
				Layer* pPrevLayer = pLayer->FindPrevLayer();
				Layer* pNextLayer = pLayer->FindNextLayer();

				if (pLayer->IsVisible())
				{
					if (!DoInvalidateLayerRegion(pLayer))
						goto EndOperation;
				}

				NodeRenderableInk::DeselectAllOnLayer(pLayer); 

				if (!DoHideNode(pLayer,TRUE)) // Hide the node 
					goto EndOperation;

				// Note the layer inserted so we can clear any selection on the layer when this op is redone
				// i.e. deleted again after a redo
				pOpRedoLayer = pLayer;

				// If the last layer has been deleted, create a new one and make it the active layer
				if (pSpread->FindFirstLayer() == NULL)
				{
					Layer* pFirstLayer;

					ALLOC_WITH_FAIL(pFirstLayer, (new Layer()), this); 	      
					if (pFirstLayer == NULL)
						goto EndOperation; // We were unable to create a new layer so 
										   // abort the operation 

					// Set the new layer's status and ID  
					pFirstLayer->SetActive(TRUE);
					pFirstLayer->GetLayerStatus().StringLayerID = LayerSGallery::CreateUniqueLayerID(pSpread);

					// Make it the last child of the spread
					if (DoInsertNewNode(pFirstLayer,pSpread,LASTCHILD,FALSE,TRUE,TRUE,TRUE))
					{
						// Note the layer inserted so we can clear any selection on the layer when this op is undone
						// i.e. deleted after an undo
						pOpUndoLayer = pLayer;
					}
				}
				else
				{
					// if we've deleted the active layer, make one of the others active
					if (pLayer->IsActive())
					{
						Layer* pNewActiveLayer = pNextLayer;

						if (pNewActiveLayer == NULL)
							pNewActiveLayer = pPrevLayer;

						if (pNewActiveLayer != NULL)
						{
PORTNOTE("galleries", "disabled frame gallery")
#ifndef EXCLUDE_FROM_XARALX
							if (FrameLayer)
								FrameSGallery::MakeActiveLayer(pNewActiveLayer);
							else
#endif
								LayerSGallery::MakeActiveLayer(pNewActiveLayer);
						}

						ERROR3IF(pNewActiveLayer == NULL,"Can't find another layer to make active");

						// Make sure that when it comes back (through an undo) it is not flagged as active
						pLayer->SetActive(FALSE);
					}
				}
			}

			if (FrameLayer)
				UndoIDS = _R(IDS_FRAME_UNDO_DELETE);
			else
			{
				if (Reason == LAYER_DELETE)
					UndoIDS = _R(IDS_LAYER_UNDO_DELETE);
				else
					UndoIDS = _R(IDS_UNDO_DEFAULTBACKGROUND);
			}
			break;

		//--------------------------------------------------------------------------------------------
		// Change a layer's status (i.e. it's layer attributes)
		case (LAYER_CHANGE_NAME):
			UndoIDS = _R(IDS_LAYER_UNDO_CHANGENAME);
			// Fall through!!!!
//		case (LAYER_CHANGE):
			{
				// if UndoIDS has not been changed via the LAYER_CHANGE_NAME entry point,
				// change it to something relevent
				if (UndoIDS == _R(IDS_NOTYPE)) UndoIDS = _R(IDS_LAYER_UNDO_CHANGE);

				// Try to create an action to restore the attribute changes we 
				// are about to make 
			   	ChangeLyrAttribAction* UndoAttribChngAction;                          

				if ( ChangeLyrAttribAction::Init(this,                    
								 	      	  &UndoActions,
									      	  sizeof(InvalidateRegionAction),  
											  pLayer->GetLayerStatus(),
											  pLayer, 
							 			  	  ( Action**)(&UndoAttribChngAction))
							 			  	  != AC_FAIL) 
				{
					LayerStatus OldStatus = pLayer->GetLayerStatus();

					// Get the state of the layer before the change
					BOOL PrevVisible = pLayer->IsVisible();
					BOOL PrevLocked  = pLayer->IsLocked();
					BOOL PrevOutline = pLayer->IsOutline();

					// This is the real state of the visible flag before the change
					BOOL PrevVisibleReal = pLayer->GetVisibleFlagState();

					// change the layer's status info
					pLayer->SetLayerStatus(NewStatus);

					// Get the state of the layer after the change
					BOOL PostVisible = pLayer->IsVisible();
					BOOL PostLocked  = pLayer->IsLocked();
					BOOL PostOutline = pLayer->IsOutline();

					// This is the real state of the visible flag after the change
					BOOL PostVisibleReal = pLayer->GetVisibleFlagState();

					// If the visibility flag has changed, or if visible and the outline state has changed,
					// then do a redraw.
					if ((PrevVisibleReal != PostVisibleReal) ||	(PostVisible && (PrevOutline != PostOutline)))
					{
						if (!DoInvalidateLayerRegion(pLayer))
							goto EndOperation;
					} 

					// If become invisible or become locked, then remove the selections on the layer 
					if ( ((PrevVisible != PostVisible) && !PostVisible) ||
						 ((PrevLocked  != PostLocked)  && PostLocked) )
					{
						NodeRenderableInk::DeselectAllOnLayer(pLayer); 
					} 
					pLayer->EnsureUniqueLayerID();
				}
				else 
					goto EndOperation; // We have failed 

			}
			break;

		//--------------------------------------------------------------------------------------------
		// Move the layer somewhere else
		case (FRAME_MOVE):
			FrameLayer = TRUE;
		case (LAYER_MOVE):
			// Move the layer to the new pos
			if(!DoMoveNode(pLayer, pContextNode, AttDir))
				goto EndOperation; 

			GetApplication()->UpdateSelection();

			// Horrible bodge that ensures that the layer that moves remains the active layer.
			// The DoMoveNode() call above causes a hidden node to be generated that references a layer.
			// This in turn generates a LAYERSCHANGED spread message that causes the layer gallery to do
			// a validity check to ensure that there's an active layer on the spread.
			// If there isn't an active layer (which there isn't in this case because it's just been
			// hidden) the check selects the first layer in the spread.
			// Not easy to fix properly, but easy to bodge it.
			if (FrameLayer)
			{
				// Ensure that the frame layer flag is on
				pLayer->SetFrame(TRUE);
				pLayer->SetEdited(TRUE);
PORTNOTE("galleries", "Disabled frame gallery")
#ifndef EXCLUDE_FROM_XARALX
				FrameSGallery::MakeActiveLayer(pLayer);
#endif
			}
			else
				LayerSGallery::MakeActiveLayer(pLayer);

			pOpUndoLayer = pLayer;
			pOpRedoLayer = pLayer;

			// Invalidate the region if the layer is visible
			if (pOpLayerGalParam->MoveRedraw)
			{
				if (!DoInvalidateLayerRegion(pLayer))
					goto EndOperation;
			}

			if (pOpLayerGalParam->ToggleBackground)
				LayerStateAction::Init(this,&UndoActions,*pOpLayerGalParam);

			if (FrameLayer)
				UndoIDS = _R(IDS_FRAME_UNDO_MOVE);
			else
				UndoIDS = _R(IDS_LAYER_UNDO_MOVE);
			break;

		//--------------------------------------------------------------------------------------------
		// Copy the layer 
		case (FRAME_COPY):
			FrameLayer = TRUE;
		case (LAYER_COPY):
			{
				BOOL ok = TRUE;
				Layer* pCopyOfLayer = NULL;

				if (pLayer == NULL)
					goto EndOperation;


				// The following lump of code makes sure that the layer being copied does not 
				// contain the insertion node, otherwise it will be copied in the new layer,
				// resulting in the doc having two insertion nodes. (Markn 17/10/96)
				/*
				{
					BaseDocument* pBaseDoc = pLayer->FindOwnerDoc();

					if (pBaseDoc != NULL && IS_A(pBaseDoc,Document))
					{
						Document* pDoc = (Document*)pBaseDoc;
						InsertionNode* pInsertNode = pDoc->GetInsertionPosition();
						if (pInsertNode != NULL)
						{
							Layer* pInsertLayer = (Layer*)pInsertNode->FindParent(CC_RUNTIME_CLASS(Layer));
							if (pInsertLayer == pLayer)
							{
								pInsertNode->UnlinkNodeFromTree();
								delete pInsertNode;
								pInsertNode = NULL;
							}
						}
					}
				}
				*/

				// Copy the layer and all its children, without placing the copy in the tree
				CALL_WITH_FAIL(pLayer->NodeCopy((Node**)&pCopyOfLayer), this, ok);
				if (!ok) goto EndOperation; 

				//Graham 1/8/97: Clear the text tool's internal record of the focus story
				//This is a bug fix
				TextStory::SetFocusStory(NULL);

				// Set the new layer's status  
				pCopyOfLayer->SetLayerStatus(NewStatus); 

				// Set the frame layer flag according to the operation type i.e FRAME_NEW = set flag
				if (FrameLayer)
				{
					pCopyOfLayer->SetFrame(TRUE);
					pCopyOfLayer->SetEdited(TRUE);
				}

				// Insert layer and its children in the tree somewhere
				// Rule: if there is a guide layer at the top, then place the new layer
				// beneath this layer, otherwise, put the new layer at the top.
				Layer* pLastLayer = pSpread->FindLastLayer();
				if(pLastLayer && pLastLayer->IsGuide())
				{
					// this layer is a guide layer - get the next one
					// (there will (ought to be) only one guide layer...)
					pLastLayer = pLastLayer->FindPrevLayer();
				}
				Node* pNodeToInsert;
				if(pLastLayer)
				{
					pNodeToInsert = pLastLayer;
				}
				else
				{
					// what?! can't find a Last Layer to use?
					pNodeToInsert = pContextNode;
				}

				if (!DoInsertNewNode(pCopyOfLayer, pNodeToInsert, NEXT, FALSE))
				{
					// Tidy up if we fail
					pCopyOfLayer->CascadeDelete(); 
					delete pCopyOfLayer; 
					goto EndOperation; 
				} 

				// Call PostDuplicate so things sort their lives out.
				Node* pCurrent = pCopyOfLayer->FindFirstDepthFirst();
				while (pCurrent!=NULL && ok)
				{
					ok = pCurrent->PostDuplicate(this);
					pCurrent = pCurrent->FindNextDepthFirst(pCopyOfLayer);
				}
				if (!ok) goto EndOperation; 
			
				if (!DoInvalidateLayerRegion(pCopyOfLayer))
					goto EndOperation;

				// Note the layer inserted so we can clear any selection on the layer when this op is undone
				// i.e. when the copied layer is removed after an undo
				pOpUndoLayer = pCopyOfLayer;

				// Make it the active layer
PORTNOTE("galleries", "Disabled frame gallery")
#ifndef EXCLUDE_FROM_XARALX
				if (FrameLayer)
					FrameSGallery::MakeActiveLayer(pCopyOfLayer);
				else
#endif
					LayerSGallery::MakeActiveLayer(pCopyOfLayer);

				NodeRenderableInk::DeselectAllOnLayer(pLayer);
				pCopyOfLayer->EnsureUniqueLayerID();
			}

			if (FrameLayer)
				UndoIDS = _R(IDS_FRAME_UNDO_COPY);
			else
				UndoIDS = _R(IDS_LAYER_UNDO_COPY);
			break;

		//--------------------------------------------------------------------------------------------
		// Toggle the layer's background flag
		case (LAYER_TOGGLEBACKGROUND):
			LayerStateAction::Init(this, &UndoActions, *pOpLayerGalParam);
			BroadcastLayerChanges = FALSE;
			UndoIDS = _R(IDS_LAYER_UNDO_MOVE);
			break;

		//--------------------------------------------------------------------------------------------
		// Change the layer's visibility
		case (LAYER_VISIBLE):
			LayerStateAction::Init(this, &UndoActions, *pOpLayerGalParam);
			BroadcastLayerChanges = FALSE;
			UndoIDS = _R(IDS_LAYER_UNDO_VISIBLE);
			break;

		//--------------------------------------------------------------------------------------------
		// Change the layer's locked state
		case (LAYER_LOCKED):
			LayerStateAction::Init(this, &UndoActions, *pOpLayerGalParam);
			BroadcastLayerChanges = FALSE;
			UndoIDS = _R(IDS_LAYER_UNDO_LOCKED);
			break;

		//--------------------------------------------------------------------------------------------
		// Change the layer's doc's 'all visible' state
		case (FRAME_ALLVISIBLE):
			FrameLayer = TRUE;
		case (LAYER_ALLVISIBLE):
			LayerStateAction::Init(this, &UndoActions, *pOpLayerGalParam);
			BroadcastLayerChanges = FALSE;
			if (FrameLayer)
				UndoIDS = _R(IDS_FRAME_UNDO_ALLVISIBLE);
			else
				UndoIDS = _R(IDS_LAYER_UNDO_ALLVISIBLE);
			break;

		//--------------------------------------------------------------------------------------------
		// Change the layer's doc's 'multilayer' state
		case (FRAME_MULTILAYER):
			FrameLayer = TRUE;
		case (LAYER_MULTILAYER):
			LayerStateAction::Init(this, &UndoActions, *pOpLayerGalParam);
			BroadcastLayerChanges = FALSE;
			if (FrameLayer)
				UndoIDS = _R(IDS_FRAME_UNDO_MULTILAYER);
			else
				UndoIDS = _R(IDS_LAYER_UNDO_MULTILAYER);
			break;

		//--------------------------------------------------------------------------------------------
		// Change the layer's name, visibility & editability, all on one go
		case (LAYER_CHANGE):
			LayerStateAction::Init(this, &UndoActions, *pOpLayerGalParam);
			//BroadcastLayerChanges = FALSE;
			UndoIDS = _R(IDS_OPCHANGELAYERPROPERTIES);
			break;

		//--------------------------------------------------------------------------------------------
		// Change the layer's solid state
		case (LAYER_SOLID):
// Cannot do this as this causes the gallery items to be destructed whilst handling
// clicks on one of the items.
//			// Check that all visible layers are actually frame layers
//			FrameSGallery::EnsureFrameLayerIntegrity(pSpread);
			// Set up the action
			LayerStateAction::Init(this, &UndoActions, *pOpLayerGalParam);
			BroadcastLayerChanges = FALSE;
			UndoIDS = _R(IDS_LAYER_UNDO_SOLID);
			break;
		//--------------------------------------------------------------------------------------------
		// Change the layer's solid state
		case (LAYER_OVERLAY):
//			// Check that all visible layers are actually frame layers
//			FrameSGallery::EnsureFrameLayerIntegrity(pSpread);
			// Set up the action
			LayerStateAction::Init(this, &UndoActions, *pOpLayerGalParam);
			BroadcastLayerChanges = FALSE;
			UndoIDS = _R(IDS_LAYER_UNDO_OVERLAY);
			break;

		//--------------------------------------------------------------------------------------------
		// Change the layer's active state
		case (LAYER_ACTIVE):
			// Set up the action
			LayerStateAction::Init(this, &UndoActions, *pOpLayerGalParam);
			BroadcastLayerChanges = FALSE;
			UndoIDS = _R(IDS_LAYER_UNDO_ACTIVE);
			break;

		// Trap any other reasons here
		default:
			ERROR3("Unknown OpLayerGalChange reason code");
			break;
	}

	if (BroadcastLayerChanges)
	{
		BROADCAST_TO_ALL(SpreadMsg(pSpread,SpreadMsg::LAYERCHANGES));
	}

 	EndOperation:

	ERROR3IF(UndoIDS == 0,"The undo ID string is zero. No too useful!");
 	End(); 
}

/********************************************************************************************

>	BOOL OpLayerGalChange::DoInvalidateLayerRegion(Layer* pLayer)

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	21/9/95
	Inputs:		pLayer = ptr to layer
	Outputs:	-
	Returns:	TRUE for success, FALSE otherwise
	Purpose:	This invalidates the areas of the screen covered by the given layer
				This copes with guidelines if the given layer is a guides layer

				We have to do guidelines separately, because guidelines don't get included in the bounding
				rect of the layer, hence DoInvalidateNodeRegion(pLayer) won't work
	Errors:		-
	SeeAlso:	-

********************************************************************************************/

BOOL OpLayerGalChange::DoInvalidateLayerRegion(Layer* pLayer)
{
	ERROR2IF(pLayer  == NULL,FALSE, "pLayer is NULL");
	ERROR2IF(pSpread == NULL,FALSE,"pSpread is NULL");

	BOOL ok = TRUE;

	if (pLayer->IsGuide())
	{
		Node* pNode = pLayer->FindFirstChild(CC_RUNTIME_CLASS(NodeGuideline));
		while (pNode != NULL && ok)
		{
			DocRect Rect = ((NodeGuideline*)pNode)->GetRenderRect();
			ok = DoInvalidateRegion(pSpread,Rect);

			pNode = pNode->FindNext(CC_RUNTIME_CLASS(NodeGuideline));
		}
	}

	if (ok) ok = DoInvalidateNodeRegion(pLayer, TRUE);

	return ok;
}

/********************************************************************************************

>	void OpLayerGalChange::GetOpName(String_256* OpName) 

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	5/8/94
	Inputs:		-
	Outputs:	The undo string for the operation
	Returns:	
	Purpose:	The GetOpName fn is overridden so that we return back a description 
				appropriate to the type of attribute that the operation applies. 
					
	Errors:		-
	SeeAlso:	-

********************************************************************************************/

void OpLayerGalChange::GetOpName(String_256* OpName) 
{ 
	*OpName = String_256(UndoIDS);
}  


/********************************************************************************************

>	void OpLayerGalChange::Undo() 

	Author:		Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
	Created:	4/8/94
	Inputs:		-
	Outputs:	-
	Returns:	-
	Purpose:	The overloaded Undo operation refreshes the layer details in the layer 
				manager   
	Errors:		-
	SeeAlso:	-

********************************************************************************************/

BOOL OpLayerGalChange::Undo() 
{
	// Do some stuff before the undo takes place, relevent to the operation being undone
	switch (Reason)
	{
		// Only LAYER_NEW and LAYER_COPY need to worry if pOpUndoLayer is NULL
		// LAYER_DELETE op only creates a pOpUndoLayer ptr after the last layer is deleted and
		// automatically replaced by a new blank layer.

		case FRAME_NEW:
		case FRAME_COPY:
		case LAYER_NEW:
		case LAYER_COPY:

			ERROR3IF(pOpUndoLayer == NULL,"The op's undo layer ptr is NULL");

			// **** Fall through...

		case FRAME_DELETE:
		case LAYER_DELETE:
		case PAGEBACKGROUND_DEFAULT:

			// If undoing, make sure there are no selected nodes on the layer before
			// it disappears
			if (pOpUndoLayer != NULL && pOpUndoLayer->FindParent() != NULL)
				NodeRenderableInk::DeselectAllOnLayer(pOpUndoLayer);

			// **** Fall through...

		case FRAME_MOVE:
		case LAYER_MOVE:

			// All the above reasons generate hidden nodes, so the HideNode and ShowNode code
			// will broadcast layer changes on undo and redo (hopefully!)
			BroadcastLayerChanges = FALSE;
			break;

		default:
			break;
	}

	BOOL Result = Operation::Undo(); 
	if (Result)
	{
		// Do some stuff after the undo takes place, relevent to the operation being undone
		switch (Reason)
		{
			// When moving layers about, we need to make sure the layer moved remains the active layer
			case FRAME_MOVE:
			case LAYER_MOVE:
				GetApplication()->UpdateSelection();
				if (pOpUndoLayer != NULL)
				{
PORTNOTE("galleries", "Disabled frame gallery")
#ifndef EXCLUDE_FROM_XARALX
					if (Reason == FRAME_MOVE)
						FrameSGallery::MakeActiveLayer(pOpUndoLayer);
					else
#endif
						LayerSGallery::MakeActiveLayer(pOpUndoLayer);
					BroadcastLayerChanges = TRUE;
				}
				break;
			default:
				break;
		}		

		if (BroadcastLayerChanges)
		{
			BROADCAST_TO_ALL(SpreadMsg(pSpread,SpreadMsg::LAYERCHANGES));
		}
	}
	return (Result); 
}		

/********************************************************************************************

>	void OpLayerGalChange::Redo()

	Author:		Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
	Created:	4/8/94
	Inputs:		-
	Outputs:	-
	Returns:	-
	Purpose:	The overloaded Redo operation refreshes the layer details in the layer
				manager 
	Errors:		-
	SeeAlso:	-

********************************************************************************************/

BOOL OpLayerGalChange::Redo()
{
	// Do some stuff before the redo takes place, relevent to the operation being redone
	switch (Reason)
	{
		case FRAME_DELETE:
		case LAYER_DELETE:
		case PAGEBACKGROUND_DEFAULT:

			ERROR3IF(pOpRedoLayer == NULL,"The op's redo layer ptr is NULL");

			// If redoing a layer delete, make sure there are no selected nodes on the layer before
			// it disappears
			if (pOpRedoLayer != NULL && pOpRedoLayer->FindParent() != NULL)
				NodeRenderableInk::DeselectAllOnLayer(pOpRedoLayer);

			// **** Fall through...

		case FRAME_NEW:
		case FRAME_COPY:
		case FRAME_MOVE:
		case LAYER_NEW:
		case LAYER_COPY:
		case LAYER_MOVE:

			// All the above reasons generate hidden nodes, so the HideNode and ShowNode code
			// will broadcast layer changes on undo and redo (hopefully!)
			BroadcastLayerChanges = FALSE;
			break;

		default:
			break;
	}

	BOOL Result = Operation::Redo(); 
	if (Result)
	{
		// Do some stuff after the redo takes place, relevent to the operation being redone
		switch (Reason)
		{
			// When moving layers about, we need to make sure the layer moved remains the active layer
			case FRAME_MOVE:
			case LAYER_MOVE:
				GetApplication()->UpdateSelection();
				if (pOpRedoLayer != NULL)
				{
PORTNOTE("galleries", "Disabled frame gallery")
#ifndef EXCLUDE_FROM_XARALX
					if (Reason == FRAME_MOVE)
						FrameSGallery::MakeActiveLayer(pOpRedoLayer);
					else
#endif
						LayerSGallery::MakeActiveLayer(pOpRedoLayer);
					BroadcastLayerChanges = TRUE;
				}
				break;

			default:
				break;
		}		

 		if (BroadcastLayerChanges)
		{
 			BROADCAST_TO_ALL(SpreadMsg(pSpread,SpreadMsg::LAYERCHANGES));
		}
	}
	return (Result); 
}

/********************************************************************************************

>	static BOOL OpLayerGalChange::IsFrameMode()

	Author:		Ranbir_Rana (Xara Group Ltd) <camelotdev@xara.com>
	Created:	21/10/97
	Inputs:		-
	Outputs:	-
	Returns:	TRUE if the document is frame based, else FALSE.
	Purpose:	
	
********************************************************************************************/

BOOL OpLayerGalChange::IsFrameMode()
{
	// Flag variables.
	BOOL FramedDoc = FALSE;		// Flag to determine the document type.
	
	// Get a ptr to the selected spread
	Spread* pSpread = Document::GetSelectedSpread();

	// Ensure a valid spread ptr.
	if(pSpread)
	{
		// Are there any frame layers?
		Layer* pFrameLayer = pSpread->FindFirstFrameLayer();	

		//If a frame layer exists, then this is an animation doc.
		if (pFrameLayer)
			FramedDoc = TRUE;
	}

	return FramedDoc;
}

//------------------------------------------------------------------------
//------------------------------------------------------------------------
//------------------------------------------------------------------------

// The layer stuff dialog
/********************************************************************************************

>	LayerNameDlg::LayerNameDlg(): DialogOp(LayerNameDlg::IDD, LayerNameDlg::Mode) 


	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	9/8/94
	Inputs:		-
	Outputs:	-
	Returns:	-
	Purpose:	LayerNameDlg constructor. Creates a non-undoable operation
	Errors:		-
	SeeAlso:	-

********************************************************************************************/
																				

LayerNameDlg::LayerNameDlg(): DialogOp(LayerNameDlg::IDD, LayerNameDlg::Mode) 
{   
	pLayer  = NULL;
	pSpread = NULL;
}        

/********************************************************************************************

>	MsgResult LayerNameDlg::Message( CDlgMessage DlgMsg, CGadgetID Gadget)

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	9/8/94
	Inputs:		-
	Outputs:	-
	Returns:	-
	Purpose:	Handles all the scale dialog's messages 
	Errors:		-
	SeeAlso:	-

********************************************************************************************/

MsgResult LayerNameDlg::Message(Msg* Message)
{
	if (IS_OUR_DIALOG_MSG(Message))
	{
		DialogMsg* Msg = (DialogMsg*)Message;
		BOOL EndDialog = FALSE;

		switch (Msg->DlgMsg)
		{
			case DIM_CREATE:
				ShowLayerDetails();
				LayerNameDlg::IsOpen = TRUE;
				LayerNameDlg::pLayerNameDlg = this;
				SetKeyboardFocus(_R(IDC_LAYER_NAME));
				HighlightText (_R(IDC_LAYER_NAME));
				break;
				
			case DIM_COMMIT:
				EndDialog = TRUE;
				CommitDialogValues();
				break;

			case DIM_SOFT_COMMIT:
				//TRACE( _T("Rgt OK handling here\n"));
				break; 

			case DIM_CANCEL:
				EndDialog = TRUE;
				break;

		    case DIM_LFT_BN_CLICKED:
				break; 

			case DIM_TEXT_CHANGED:
				break;

			default:
				break;
		}

		if (EndDialog)	// Dialog communication over 
		{			   // Isn't this pretty?
			Close();  // Close the dialog 
			End(); 	 // Destroy dialog 

			LayerNameDlg::IsOpen 		= FALSE;	// We no longer have a current layer name dialog
			LayerNameDlg::pLayerNameDlg = NULL;		// so reset the static vars
			return (DLG_EAT_IF_HUNGRY(Msg)); 
	   	}
	}
//	return OK; 

	// Pass everything on to the base class . . .
	return DialogOp::Message(Message);
}  


/********************************************************************************************

>	OpState	LayerNameDlg::GetState(String_256*, OpDescriptor*)

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	9/8/94
	Inputs:		-
	Outputs:	-
	Returns:	-
	Purpose:	LayerNameDlg GetState method
	Errors:		-
	SeeAlso:	-

********************************************************************************************/

OpState	LayerNameDlg::GetState(String_256*, OpDescriptor*)
{    
	OpState OpSt;
	return(OpSt);
}
		 
/********************************************************************************************

>	BOOL LayerNameDlg::Init()

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	9/8/94
	Inputs:		-
	Outputs:	-
	Returns:	-
	Purpose:	LayerNameDlg Init method
	Errors:		-
	SeeAlso:	-

********************************************************************************************/



BOOL LayerNameDlg::Init()
{  
	return (RegisterOpDescriptor(
								0,
								_R(IDS_LAYERNAMEDLG),
								CC_RUNTIME_CLASS(LayerNameDlg),
								OPTOKEN_LAYERNAMEDLG,
								LayerNameDlg::GetState,
								0,	// help ID
								0   // bubble ID
								)
			); 
}   
 
/********************************************************************************************

>	static void LayerNameDlg::StartUp(LayerDlgParam* pParam)

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	9/8/94
	Inputs:		pParam - ptr to all the info the dlg needs in order to do its stuff
	Outputs:	-
	Returns:	-
	Purpose:	Starts up a LayerNameDlg using the OPTOKEN_LAYERNAMEDLG op token
	Errors:		-
	SeeAlso:	-

********************************************************************************************/

void LayerNameDlg::StartUp(LayerDlgParam* pParam)
{
	if (!LayerNameDlg::IsOpen)
	{
		OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_LAYERNAMEDLG); 
		if (pOpDesc != NULL)
			pOpDesc->Invoke((OpParam*)pParam);
		else
		{
			ERROR3("Couldn't find OPTOKEN_LAYERNAMEDLG op descriptor");
		}
	}
	else if (LayerNameDlg::pLayerNameDlg != NULL)
		LayerNameDlg::pLayerNameDlg->BringToTop();
		// SetActiveWindow(LayerNameDlg::pLayerNameDlg->WindowID);
}

	   
/********************************************************************************************

>	BOOL LayerNameDlg::Create()

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	9/8/94
	Inputs:		-
	Outputs:	-
	Returns:	TRUE if successful, else FALSE
	Purpose:	LayerNameDlg create method 
	Errors:		-
	SeeAlso:	-

********************************************************************************************/

	   
BOOL LayerNameDlg::Create()
{
	if (DialogOp::Create())
	{
		//ShowLayerDetails();
		return TRUE;
	}
	else
		return FALSE;

}

/********************************************************************************************

>	void LayerNameDlg::DoWithParam(OpDescriptor*,OpParam* pOpParam)

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	9/8/94
	Inputs:		pOpParam = ptr to a OpLayerGalReason struct, cast as an OpParam* 
	Outputs:	-
	Returns:	-
	Purpose:	Creates then opens the dialog 
	Errors:		-
	SeeAlso:	-

********************************************************************************************/


void LayerNameDlg::DoWithParam(OpDescriptor*,OpParam* pOpParam)
{
	// If there's already one layer name dlg open, return.
	if (LayerNameDlg::IsOpen)
		return;

	LayerDlgParam* pParam = (LayerDlgParam*)pOpParam;

	// Why are you creating me. I need to know, God damn it!
	Reason = pParam->GetReason();

	// Extract the spread and layer in question
	pSpread = pParam->GetSpread();
	pLayer  = pParam->GetLayer();

	// If we have a layer but not a spread, find the spread via the given layer
	if (pLayer != NULL && pSpread == NULL)
		pSpread = pLayer->FindParentSpread();

	BOOL ok=FALSE;
	
	switch (Reason)
	{
		// If  we're changing the layer's name or copying it, we need both a layer and a spread
		case LAYER_CHANGE_NAME:
		case LAYER_COPY:
			ERROR3IF(pLayer  == NULL, "I don't have a layer");
			ERROR3IF(pSpread == NULL, "I dont' have a spread");
			ok = ((pLayer != NULL) && (pSpread != NULL));
			break;

		case LAYER_NEW:
			ERROR3IF(pSpread == NULL, "I dont' have a spread");
			ok = (pSpread != NULL);
			break;

		default:
			ERROR3("The layer name dialog can't process the given reason");
			ok = FALSE;
			break;
	}

	if (ok) ok = Create();
//	if (ok)	Open();

	if (!ok)			// Could not create 
	{
		InformError(0,_R(IDS_OK));
  		End(); 		   	// End the operation 
	}
//	else
//	{
//    	LayerNameDlg::IsOpen 		= TRUE;
//    	LayerNameDlg::pLayerNameDlg = this;
//	}
}


/********************************************************************************************

>	void LayerNameDlg::ShowLayerDetails()

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	9/8/94
	Inputs:		- 
	Outputs:	-
	Returns:	-
	Purpose:	Shows layer details in the dialog
	Errors:		-
	SeeAlso:	-

********************************************************************************************/

void LayerNameDlg::ShowLayerDetails()
{
	String_256 Name;

	switch (Reason)
	{
		case LAYER_CHANGE_NAME:
			Name = pLayer->GetLayerID();
			break;

		case LAYER_COPY:
			CreateUniqueLayerCopyName(pLayer->GetLayerID(), &Name);
			break;
			break;

		case LAYER_NEW:
			Name = LayerSGallery::CreateUniqueLayerID(pSpread);
			break;

		default:
			ERROR3("Unknown OpLayerGalReason reason");
			break;
	}

	SetStringGadgetValue(_R(IDC_LAYER_NAME),Name);
}



/********************************************************************************************
>	static void LayerNameDlg::CreateUniqueLayerCopyName(const String_256& strName,
												 		String_256* pCopyName)
	Author:		Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
	Created:	30/6/95
	Inputs:		strName			the name of the layer to be copied			
	Outputs:	pCopyName		the name of copy of the layer, which is unique
	Purpose:	Generates a unique name for a layer to be copied.
	SeeAlso:	LayerNameDlg::ShowLayerDetails
********************************************************************************************/

void LayerNameDlg::CreateUniqueLayerCopyName(const String_256& strName, String_256* pCopyName)
{
	// First, check for junk inputs.
	ERROR3IF(pCopyName == NULL,
				"Null output String_256* in LayerNameDlg::CreateUniqueLayerCopyName");

	// The rest of this function is a complete bodge, because to do this properly would
	// mean a rewrite of the brain-damaged way that layers are named, copied, and
	// identified as unique.  So what I'm going to do is prepend a "Copy of " string
	// and make sure it doesn't overflow when I do.
	pCopyName->Load(_R(IDS_LAYERGAL_COPYOF));
	String_256 strNewName;
	if ((strName.Length() + pCopyName->Length()) >= pCopyName->MaxLength())
	{
		// We must truncate so it won't overflow.
		strName.Left(&strNewName, pCopyName->MaxLength() - pCopyName->Length());
	}
	else
	{
		// We don't need to truncate.
		strNewName = strName;
	}

	// Prepend and return the result.
	*pCopyName += strNewName;
}



/********************************************************************************************

>	void LayerNameDlg::CommitDialogValues()

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	9/8/94
	Inputs:		- 
	Outputs:	-
	Returns:	-
	Purpose:	Takes the values in the dialog and sets the Layer object
				accordingly.
				Called when the OK button is selected
	Errors:		-
	SeeAlso:	-

********************************************************************************************/

void LayerNameDlg::CommitDialogValues()
{
	String_256 NewName;
//	TCHAR* pD = NewName;
	BOOL Valid;

	// Get the string from the layer name dialog
	NewName = GetStringGadgetValue(_R(IDC_LAYER_NAME),&Valid);

	// If we're changing the layer's name, but the name hasn't changed, 
	// return without doing anything
	if (Reason == LAYER_CHANGE_NAME)
	{
		if (pLayer->GetLayerID() == NewName)
			return;
	}

	// Initialise the param structure
	OpLayerGalParam Param(Reason, pSpread);
	Param.pLayer = pLayer;

	// Change the name to the new name
	Param.Status.StringLayerID = NewName;

	// If we are copying or creating a new the layer, set up the context node 
	// and where to place it relative to the context node
	if (Reason == LAYER_COPY || Reason == LAYER_NEW)
	{
		Param.pContextNode  = pSpread;
		Param.AttDir		= LASTCHILD;
	}

	// Invoke the operation
	OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_LAYERGALCHANGE); 
	if (pOpDesc != NULL)
		pOpDesc->Invoke((OpParam*)&Param);
	else
	{
		ERROR3("Couldn't find OPTOKEN_LAYERGALCHANGE op descriptor");
	}
}

//-----------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------

// OpDisplayLayerGallery - the operation that is used to display the layers gallery

/********************************************************************************************

>	BOOL OpDisplayLayerGallery::Init()

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	11/8/94
	Inputs:		-
	Outputs:	-
	Returns:	TRUE if the operation could be successfully initialised 
				FALSE if no more memory could be allocated 
				
	Purpose:	OpDisplayLayerGallery initialiser method
	Errors:		ERROR will be called if there was insufficient memory to allocate the 
				operation.
	SeeAlso:	-

********************************************************************************************/

BOOL OpDisplayLayerGallery::Init()
{
	return (RegisterOpDescriptor(
	 							0,
	 							_R(IDS_DISPLAY_LAYER_GALLERY),
								CC_RUNTIME_CLASS(OpDisplayLayerGallery),
	 							OPTOKEN_DISPLAYLAYERGALLERY,
	 							OpDisplayLayerGallery::GetState,
	 							0,	/* help ID */
	 							_R(IDBBL_DISPLAY_LAYER_GALLERY),
				 				_R(IDC_BTN_SGLAYER), // UINT32 resourceID = 0,	// resource ID
								_R(IDC_BTN_SGLAYER), // UINT32 controlID = 0,	// control ID
								SYSTEMBAR_ILLEGAL,	  // SystemBarType GroupBarID = SYSTEMBAR_ILLEGAL,	// group bar ID
				 				TRUE,	  // BOOL ReceiveMessages = TRUE,	// BODGE
				 				FALSE,	  // BOOL Smart = FALSE,
				 				TRUE,	  // BOOL Clean = TRUE,   
								NULL,	  // OpDescriptor *pVertOpDesc = NULL,
								0,	  // UINT32 OneOpenInstID = 0,		
								0,	  // UINT32 AutoStateFlags = 0,
								TRUE	  // BOOL fCheckable = FALSE
								)
								);
}               
    
/********************************************************************************************

>	OpState	OpDisplayLayerGallery::GetState(String_256*, OpDescriptor*)

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	11/8/94
	Inputs:		-
	Outputs:	-
	Returns:	The state of the OpDisplayLayerGallery operation
	Purpose:	For finding the OpDisplayLayerGallery's state. 
	Errors:		-
	SeeAlso:	-

********************************************************************************************/

OpState	OpDisplayLayerGallery::GetState(String_256* UIDescription, OpDescriptor*)
{
	// The Layer gallery op has been modified so that 
	// it can only be opened on a layer based document.
	
	OpState OpSt;  

	// Flag variables.
	BOOL LayerDoc = TRUE;		// Flag to determine whether this is a layer document.

	// Get a ptr to the selected spread
	Spread* pSpread = Document::GetSelectedSpread();

	// Ensure a valid spread ptr.
	if(pSpread)
	{
		// Are there any frame layers?
		Layer* pFrameLayer = pSpread->FindFirstFrameLayer();	

		//If a frame layer exists, then this is an animation doc.
		if (pFrameLayer)
			LayerDoc = FALSE;
	}

	if(LayerDoc)
	{
		// If the gallery is currenty open, then the menu item should be ticked
		SuperGallery* pSuperGallery = SuperGallery::FindSuperGallery(_R(IDD_LAYERSGALLERY));

		if (pSuperGallery != NULL)
		{
			if (pSuperGallery->GetRuntimeClass() == CC_RUNTIME_CLASS(LayerSGallery))
			OpSt.Ticked = pSuperGallery->IsVisible();
		}

		// If there are no open documents, you can't toggle the gallery
		OpSt.Greyed = (Document::GetSelected() == NULL);
	}
	else
	{
		// This is a frame document, so set the menu item to the correct state.
		OpSt.Ticked = FALSE;
		OpSt.Greyed	= TRUE;
		*UIDescription = String_256 (_R(IDS_NO_LAYERS));
	}

	return(OpSt);   
}

/********************************************************************************************

>	void OpDisplayLayerGallery::Do(OpDescriptor*)

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	11/8/94
	Inputs:		-
	Outputs:	-
	Returns:	-
	Purpose:	Displays the layers gallery
	Errors:		-
	SeeAlso:	-

********************************************************************************************/

void OpDisplayLayerGallery::Do(OpDescriptor*)
{
	SuperGallery* pSuperGallery = SuperGallery::FindSuperGallery(_R(IDD_LAYERSGALLERY));

	if (!pSuperGallery) pSuperGallery = new LayerSGallery;

	if (pSuperGallery != NULL)
	{
		if (pSuperGallery->GetRuntimeClass() == CC_RUNTIME_CLASS(LayerSGallery))
		{
			// Toggle the visible state of the gallery window
			pSuperGallery->SetVisibility( !pSuperGallery->IsVisible() );
		}
		else
		{
			ERROR3("Got the layer gallery but it's not of the LayerSGallery class");
		}

		SGInit::UpdateGalleryButton(_R(OPTOKEN_DISPLAYLAYERGALLERY), pSuperGallery->IsVisible());
	}

	ERROR3IF(pSuperGallery == NULL,"Couldn't find the layer gallery bar");

	End();
}

PORTNOTE("galleries", "disable frame gallery")
#ifndef EXCLUDE_FROM_XARALX
//-----------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------

// OpDisplayFrameGallery - the operation that is used to display the frame gallery

/********************************************************************************************

>	BOOL OpDisplayFrameGallery::Init()

	Author:		Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
	Created:	16/4/97
	Inputs:		-
	Outputs:	-
	Returns:	TRUE if the operation could be successfully initialised 
				FALSE if no more memory could be allocated 
				
	Purpose:	OpDisplayFrameGallery initialiser method
	Errors:		ERROR will be called if there was insufficient memory to allocate the 
				operation.
	SeeAlso:	-

********************************************************************************************/

BOOL OpDisplayFrameGallery::Init()
{
	return (RegisterOpDescriptor(
	 							0,
	 							_R(IDS_DISPLAY_FRAME_GALLERY),
								CC_RUNTIME_CLASS(OpDisplayFrameGallery),
	 							OPTOKEN_DISPLAYFRAMEGALLERY,
	 							OpDisplayFrameGallery::GetState,
	 							_R(IDH_Gallery_Frame),	/* help ID */
	 							_R(IDBBL_DISPLAY_FRAME_GALLERY),
	 							0	/* bitmap ID */));
}               
    
/********************************************************************************************

>	OpState	OpDisplayFrameGallery::GetState(String_256*, OpDescriptor*)

	Author:		Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
	Created:	16/4/97
	Inputs:		-
	Outputs:	-
	Returns:	The state of the OpDisplayFrameGallery operation
	Purpose:	For finding the OpDisplayFrameGallery's state. 
	Errors:		-
	SeeAlso:	-

********************************************************************************************/

OpState	OpDisplayFrameGallery::GetState(String_256* UIDescription, OpDescriptor*)
{
	// The frame gallery op has been modified so that 
	// it can only be opened on a frame based document.

	OpState OpSt;

#ifdef WEBSTER
		
	// If the gallery is currenty open, then the menu item should be ticked
	SuperGallery* pSuperGallery = SuperGallery::FindSuperGallery(_R(IDD_LAYERSGALLERY));

	if (pSuperGallery != NULL)
	{
		if (pSuperGallery->GetRuntimeClass() == CC_RUNTIME_CLASS(FrameSGallery))
			OpSt.Ticked = pSuperGallery->IsVisible();
	}

	// If there are no open documents, you can't toggle the gallery
	OpSt.Greyed = (Document::GetSelected() == NULL);

#else

	// Flag variables.
	BOOL FramedDoc = FALSE;		// Flag to determine whether this is a framelayer(animation) document.

	// Get a ptr to the selected spread
	Spread* pSpread = Document::GetSelectedSpread();

	// Ensure a valid spread ptr.
	if(pSpread)
	{
		// Are there any frame layers?
		Layer* pFrameLayer = pSpread->FindFirstFrameLayer();	

		//If a frame layer exists, then this is an animation doc.
		if (pFrameLayer)
			FramedDoc = TRUE;
	}

	// If this is an animation Doc, then set the correct menu item state.
	if(FramedDoc)
	{
		// If the gallery is currenty open, then the menu item should be ticked
		String_32 Name(_R(IDS_FRAMEGAL_GALLNAME));
		SuperGallery* pSuperGallery = SuperGallery::FindSuperGallery(Name);

		if (pSuperGallery != NULL)
		{
			if (pSuperGallery->GetRuntimeClass() == CC_RUNTIME_CLASS(FrameSGallery))
				OpSt.Ticked = pSuperGallery->IsVisible();
		}

		// If there are no open documents, you can't toggle the gallery
		OpSt.Greyed = (Document::GetSelected() == NULL);
	}
	else
	{
		// This is a layer document, so the Frame Gallery isn't needed.
		//	Set up item up as greyed and give a reason.
		OpSt.Ticked = FALSE;
		OpSt.Greyed	= TRUE;
		*UIDescription = String_256 (_R(IDS_NO_FRAMES));
	}

#endif

	// Lets go back..
	return(OpSt);   
}

/********************************************************************************************

>	void OpDisplayFrameGallery::Do(OpDescriptor*)

	Author:		Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
	Created:	16/4/97
	Inputs:		-
	Outputs:	-
	Returns:	-
	Purpose:	Displays the frame gallery
	Errors:		-
	SeeAlso:	-

********************************************************************************************/

void OpDisplayFrameGallery::Do(OpDescriptor*)
{
	String_32 Name(_R(IDS_FRAMEGAL_GALLNAME));
	SuperGallery* pSuperGallery = SuperGallery::FindSuperGallery(Name);

	if (pSuperGallery != NULL)
	{
		if (pSuperGallery->GetRuntimeClass() == CC_RUNTIME_CLASS(FrameSGallery))
		{
			GIFAnimationPropertyTabs::SetFrameGalleryOpen(FALSE);

			// Toggle the visible state of the gallery window
			pSuperGallery->SetVisibility( !pSuperGallery->IsVisible() );
		}
		else
		{
			ERROR3("Got the frame gallery but it's not of the LayerSGallery class");
		}

		SGInit::UpdateGalleryButton(_R(OPTOKEN_DISPLAYFRAMEGALLERY), pSuperGallery->IsVisible());

		GIFAnimationPropertyTabs::SetFrameGalleryOpen(TRUE);
	}

	ERROR3IF(pSuperGallery == NULL,"Couldn't find the frame gallery bar");

	End();
}
#endif

//-----------------------------------------------------
//-----------------------------------------------------
//-----------------------------------------------------
//-----------------------------------------------------

/********************************************************************************************

>	LayerStateAction::LayerStateAction()

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	7/3/95
	Inputs:		-
	Outputs:	-
	Returns:	-
	Purpose:	Constructor for the action
	Errors:		-
	SeeAlso:	-

********************************************************************************************/

LayerStateAction::LayerStateAction()
{
}


/********************************************************************************************

>	ActionCode LayerStateAction::Init(UndoableOperation* pOp,
										ActionList* pActionList,
										OpLayerGalParam EntryParam)

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	7/3/95
	Inputs:		pOp  		= ptr to the operation to which this action belongs
				pActionList = ptr to action list to which this action should be added
				Param		= Contains all the info needed to change the layer
	Outputs:	-
	Returns:	ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
	Purpose:	This is the function which creates an instance of this action. If there is no room 
				in the undo buffer (which is determined by the base class Init function called within)
				the function will either return AC_NO_RECORD which means the operation can continue, 
				but no undo information needs to be stored, or AC_OK which means the operation should
				continue AND record undo information. If the function returns AC_FAIL, there was not 
				enough memory to record the undo information, and the user has decided not to continue
				with the operation.

				This changes a flag associated with the layer to the value in 'NewState' in an
				undoable way
	Errors:		-
	SeeAlso:	Action::Init()

********************************************************************************************/



ActionCode LayerStateAction::Init(	UndoableOperation* pOp,
									ActionList* pActionList,
									OpLayerGalParam EntryParam)
{
	UINT32 ActSize = sizeof(LayerStateAction);

	LayerStateAction* pNewAction;
	ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(LayerStateAction),(Action**)&pNewAction);

	if (Ac != AC_FAIL && pNewAction != NULL)
	{
		pNewAction->Param = EntryParam;
		OpLayerGalParam& Param = pNewAction->Param;

		switch (Param.GetReason())
		{
			case LAYER_VISIBLE:
				ERROR3IF(Param.pLayer == NULL,"Param.pLayer == NULL");

				if (Param.pLayer != NULL)
					LayerSGallery::DoChangeVisible(Param.pLayer,Param.NewState);
				break;

			case LAYER_LOCKED:
				ERROR3IF(Param.pLayer == NULL,"Param.pLayer == NULL");

				if (Param.pLayer != NULL)
					LayerSGallery::DoChangeLocked(Param.pLayer,Param.NewState);
				break;

			case LAYER_ALLVISIBLE:
			case FRAME_ALLVISIBLE:
				if (Param.pLayerSGal != NULL)
				{
					Param.pLayerSGal->DoChangeAllVisible(Param.NewState);
					Param.pLayerSGal->ForceRedrawOfList();
				}
				break;

			case LAYER_MULTILAYER:
			case FRAME_MULTILAYER:
				if (Param.pLayerSGal != NULL)
				{
					Param.pLayerSGal->DoChangeMultilayer(Param.NewState);
					Param.pLayerSGal->ForceRedrawOfList();
				}
				break;

			case FRAME_MOVE:
			case LAYER_MOVE:
			case LAYER_TOGGLEBACKGROUND:
				ERROR3IF(Param.pLayer == NULL,"Param.pLayer == NULL");
				ERROR3IF(Param.pLayerSGal == NULL,"Param.pLayerSGal == NULL");

				if (Param.pLayer != NULL)
				{
					if (Param.GetReason() == FRAME_MOVE)
					{
						Param.pLayer->SetBackground(FALSE);
						Param.pLayer->SetPrintable(!Param.pLayer->IsPrintable());
					}
					else
					{
						Param.pLayer->SetBackground(!Param.pLayer->IsBackground());
						Param.pLayer->SetPrintable(!Param.pLayer->IsPrintable());
					}
					// Cause the layer gallery items to be recreated
					Param.pLayerSGal->CreateNewSubtree(Param.pLayer->FindDocument());
				}
				break;

			case LAYER_CHANGE:
				ERROR3IF(Param.pLayer == NULL,"Param.pLayer == NULL");

				if (Param.pLayer != NULL)
				{
					Param.OldVisibleState 	= Param.pLayer->IsVisible();
					Param.OldLockedState 	= Param.pLayer->IsLocked();
					Param.OldName 			= Param.pLayer->GetLayerID();

					LayerSGallery::DoChangeVisible(Param.pLayer,Param.VisibleState);
					LayerSGallery::DoChangeLocked(Param.pLayer,Param.LockedState);
					Param.pLayer->SetLayerID(Param.NewName);
				}
				break;

			case LAYER_SOLID:
				ERROR3IF(Param.pLayer == NULL,"Param.pLayer == NULL");

				if (Param.pLayer != NULL)
				{
PORTNOTE("galleries", "Disabled frame gallery")
#ifndef EXCLUDE_FROM_XARALX
					FrameSGallery::DoChangeSolid(Param.pLayer,Param.NewState);
#endif
					Param.pLayer->SetEdited(TRUE);
					Param.pLayer->SetFrame(TRUE);	// double check this
#ifdef _DEBUG
					// Tell the frame gallery to update its display of the frame
					BROADCAST_TO_ALL(LayerMsg(Param.pLayer, LayerMsg::REDRAW_LAYER));
#endif
				}
				break;

			case LAYER_OVERLAY:
				ERROR3IF(Param.pLayer == NULL,"Param.pLayer == NULL");

				if (Param.pLayer != NULL)
				{
PORTNOTE("galleries", "Disabled frame gallery")
#ifndef EXCLUDE_FROM_XARALX
					FrameSGallery::DoChangeOverlay(Param.pLayer,Param.NewState);
#endif
					Param.pLayer->SetEdited(TRUE);
					Param.pLayer->SetFrame(TRUE);	// double check this
#ifdef _DEBUG
					// Tell the frame gallery to update its display of the frame
					BROADCAST_TO_ALL(LayerMsg(Param.pLayer, LayerMsg::REDRAW_LAYER));
#endif
				}
				break;

			case LAYER_MAKEFRAME:
				ERROR3IF(Param.pLayer == NULL,"Param.pLayer == NULL");
				if (Param.pLayer != NULL)
				{
					Param.pLayer->SetFrame(Param.NewState);
				}
				break;

			case LAYER_ACTIVE:
				ERROR3IF(Param.pLayer == NULL,"Param.pLayer == NULL");
				if (Param.pLayer != NULL)
				{
					Param.pLayer->SetActive(Param.NewState);

					// Ensure that the gallery is updated with the new active layer details
					BROADCAST_TO_ALL(LayerMsg(Param.pLayer, LayerMsg::UPDATE_ACTIVE_LAYER));
				}
				break;

			default:
				ERROR3("Unknown Reason code");
				break;
		}
	}

	return Ac;
}

/********************************************************************************************

>	ActionCode LayerStateAction::Execute();

	Author:		Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
	Created:	7/3/95
	Inputs:		-
	Outputs:	-
	Returns:	ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL
	Purpose:	Executes the action.  
				Puts the action's layer's visible state to the opposite setting.
	Errors:		-
	SeeAlso:	Action::Init()

********************************************************************************************/

ActionCode LayerStateAction::Execute()
{
	ActionCode Ac = AC_FAIL;

	if (pOperation->IS_KIND_OF(UndoableOperation))
	{
		Param.NewState = !Param.NewState;

		// Swap LAYER_CHANGE vars
		Swap(Param.VisibleState,Param.OldVisibleState);
		Swap(Param.LockedState, Param.OldLockedState);
		String_256 Str 		= Param.OldName;
		Param.OldName 		= Param.NewName;
		Param.NewName 		= Str;

		Ac = LayerStateAction::Init((UndoableOperation*)pOperation,pOppositeActLst,Param);

		if (Ac != AC_FAIL)
		{
			LayerSGallery* 	pGal = Param.pLayerSGal;

			if (pGal != NULL)
			{
				pGal->ForceRedrawOfList();

				Document* pDoc = GetWorkingDoc();

				if (pDoc != NULL && pGal->IsVisible())
				{
					pGal->SetBoolGadgetSelected(_R(IDC_BTN_MULTILAYER),!(pDoc->IsMultilayer() == 0));
					pGal->SetBoolGadgetSelected(_R(IDC_BTN_ALLVISIBLE),!(pDoc->IsAllVisible() == 0));
				}
			}
		}
	}
	else
	{
		ERROR3("LayerStateAction::Execute() called with op that's not an undoable op");
	}

	return Ac;
}

LayerStateAction::~LayerStateAction()
{
}
