// $Id: plugopun.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============================ */ // #include "camtypes.h" #include "plugopun.h" // useful plug-in related items #include "plugop.h" // useful plug-in related items //#include "plugres.h" // _R(IDS_PLUGIN_FAMILY) #include "plugmngr.h" // main plug-in manager //#include "app.h" // GetApplication() - in camtypes.h [AUTOMATICALLY REMOVED] //#include "simon.h" // _R(IDS_NO_DOC) _R(IDS_NO_OBJECTS_SELECTED) #include "nodebmp.h" // NodeBitmap //#include "fillattr.h" // AttrFillGeometry - in camtypes.h [AUTOMATICALLY REMOVED] // Place any IMPLEMENT type statements here CC_IMPLEMENT_DYNCREATE(PlugInUndoOp, SelOperation); CC_IMPLEMENT_DYNCREATE(ActionApplyPlugInToBitmap, Action) // We want better memory tracking #define new CAM_DEBUG_NEW /******************************************************************* > PlugInUndoOp::PlugInUndoOp() : SelOperation() Author: Neville_Humphrys (Xara Group Ltd) Created: 21/1/97 Inputs: Outputs: Returns: Purpose: Constructor for PlugInUndoOp operation. It is undoable. Errors: None *******************************************************************/ PlugInUndoOp::PlugInUndoOp() : SelOperation() { m_pOpDesc = NULL; } /******************************************************************************************** > static BOOL PlugInUndoOp::Init() Author: Neville_Humphrys (Xara Group Ltd) Created: 21/1/97 Returns: TRUE if the Op was started ok Purpose: Creates all the opDescriptors that call this operation. ********************************************************************************************/ BOOL PlugInUndoOp::Init() { BOOL ok = TRUE; // Set up some standard operations // ok = ok && RegisterOpToken(OPTOKEN_PLUGINS, _R(IDS_PLUGINS)); // ok = ok && RegisterOpToken(OPTOKEN_PHOTOSHOP_PLUGINS, _R(IDS_PHOTOSHOP_PLUGINS)); // ok = ok && RegisterOpToken(OPTOKEN_PHOTOSHOP_APPLYLAST, _R(IDS_PHOTOSHOP_APPLYLAST)); // ok = ok && RegisterOpToken(OPTOKEN_PLUGINONE, _R(IDS_PLUGIN_ONE)); // ok = ok && RegisterOpToken(OPTOKEN_PLUGINTWO, _R(IDS_PLUGIN_TWO)); // ok = ok && RegisterOpToken(OPTOKEN_PLUGINTHREE, _R(IDS_PLUGIN_THREE)); return ok; } /******************************************************************************************** > static BOOL PlugInUndoOp::RegisterOpToken(TCHAR *OpToken, const String_64& NewMenuText, CCRuntimeClass* pClass = CC_RUNTIME_CLASS(PlugInUndoOp)) Author: Neville_Humphrys (Xara Group Ltd) Created: 21/1/97 Inputs: OpToken the OpToken for the operation NewMenuText the text for the menu item for this operation pClass the runtime class to use, defaults to PlugInUndoOp. gs the GetState function to use Returns: TRUE if the Op was registered ok Purpose: Allows OpDescriptors to be defined to the operation system. ********************************************************************************************/ BOOL PlugInUndoOp::RegisterOpToken(TCHAR *OpToken, const String_64& NewMenuText, CCRuntimeClass* pClass, pfnGetState gs) { // Try to create the OpDescriptor PlugInOpDescriptor* pOpDesc = new PlugInOpDescriptor(OpToken, NewMenuText, pClass, gs); if (pOpDesc == NULL) return FALSE; return TRUE; } /******************************************************************************************** > static BOOL PlugInUndoOp::RegisterOpToken(TCHAR *OpToken, UINT32 MenuTextID, CCRuntimeClass* pClass = CC_RUNTIME_CLASS(PlugInUndoOp), pfnGetState gs = PlugInUndoOp::GetState) Author: Neville_Humphrys (Xara Group Ltd) Created: 21/1/97 Inputs: OpToken the OpToken for the operation MenuTextId the text for the menu item for this operation pClass the runtime class to use, defaults to PlugInUndoOp. gs the GetState function to use Returns: TRUE if the Op was registered ok Purpose: Allows OpDescriptors to be defined to the operation system. ********************************************************************************************/ BOOL PlugInUndoOp::RegisterOpToken(TCHAR *OpToken, UINT32 MenuTextID, CCRuntimeClass* pClass, pfnGetState gs) { // register some option descriptors if (!UndoableOperation::RegisterOpDescriptor( 0, // Tool ID MenuTextID, // String resource ID pClass, // Runtime class OpToken, // Token string gs, // GetState function NULL, // help ID NULL, // bubble help NULL, // resource ID NULL, // control ID SYSTEMBAR_ILLEGAL, // Bar ID TRUE, // Recieve system messages FALSE, // Smart duplicate operation FALSE, // Clean operation // NULL, // No vertical counterpart (not present in undoable versions) NULL, // String for one copy only error (DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags )) return FALSE; return TRUE; } /******************************************************************************************** > static OpState PlugInUndoOp::GetState(String_256*, OpDescriptor*) Author: Neville_Humphrys (Xara Group Ltd) Created: 21/1/97 Inputs: Outputs: String - if MenuItem is enabled Then return the name of the operation to be undone Else return the reason why it is disabled Returns: OpState the state of the operation Purpose: To provide greying and ticking functionality for the operation. Errors: None ********************************************************************************************/ OpState PlugInUndoOp::GetState(String_256*, OpDescriptor* OpDesc) { // At present, this item is always available. OpState OpSt; return OpSt; } /******************************************************************************************** > virtual void Operation::GetOpName(String_256* pOpName) Author: Neville_Humphrys (Xara Group Ltd) Created: 11/3/97 Outputs: The name of the operation Purpose: To get the name of the operation to put on the undo/redo menu items. We overide the baseclass version which tries to use the runtime class of this class to work out the OpDescriptor it was invoked with. Of course, we use one operation with multiple OpDescriptors and so this is not good enough. Unfortunately the operation class does not seem to save away the OpDescriptor that invoked it and so we must do this and then use this to track down the text to use. ********************************************************************************************/ void PlugInUndoOp::GetOpName(String_256* pOpName) { if (pOpName == NULL) return; // Use our stored copy of the OpDescriptor and ask it for the text if (m_pOpDesc) m_pOpDesc->GetText(pOpName, OP_UNDO_TEXT); } /******************************************************************************************** > virtual void PlugInUndoOp::Do(OpDescriptor*) Author: Neville_Humphrys (Xara Group Ltd) Created: 21/1/97 Inputs: pOpDesc the OpDescriptor of the item to invoke Outputs: None Returns: None Purpose: Invokes the plug-in specified by the OpDescriptor. Errors: if no OpDescriptor is supplied ********************************************************************************************/ void PlugInUndoOp::Do(OpDescriptor* pOpDesc) { if (pOpDesc == NULL) { ERROR3IF(pOpDesc == NULL,"PlugInUndoOp::Do null OpDescriptor"); return; } //ERROR3("PlugInUndoOp - do"); // Store away a copy of the OpDescriptor for later use m_pOpDesc = pOpDesc; // Search the plug-ins list for the specified plug-in and invoke it PlugInManager* pManager = GetApplication()->GetPlugInManager(); if (pManager == NULL) return; PlugInItem * pPlugIn = pManager->GetFirstPlugIn(); String_32 OpToken; while (pPlugIn) { OpToken = pPlugIn->GetUniqueID(); OpToken += pPlugIn->GetPlugInName(); if (pOpDesc->Token == OpToken) { // Do Something break; } pPlugIn = pManager->GetNextPlugIn(pPlugIn); } // If we reached here then everything has happened ok and we can just end the // operation and exit End(); return; } /******************************************************************************************* > static BOOL PlugInUndoOp::FindBitmapInSelection(KernelBitmap * pFoundBitmap = NULL, KernelBitmapRef ** ppFoundBitmapRef = NULL, NodeBitmap ** ppFoundNode = NULL, AttrFillGeometry ** ppFoundFillAttribute = NULL) Author: Neville_Humphrys (Xara Group Ltd) Created: 21/1/97 Inputs: None Outputs: if supplied, it will return a pointer to the bitmap that is in the selection if supplied, it will return a pointer to the bitmap ref that is in the selection if supplied, it will return a pointer to the node bitmap that is in the selection if supplied, it will return a pointer to the fill geometry that is in the selection Returns: TRUE if succeeded in finding a bitmap, FALSE if not Purpose: Find out if there is a valid bitmap in the selection and return useful information to the caller. SeeAlso: - *******************************************************************************************/ /* This should be in RANGE for God's sake! BOOL PlugInUndoOp::FindBitmapInSelection(KernelBitmap ** ppFoundBitmap, KernelBitmapRef ** ppFoundBitmapRef, NodeBitmap ** ppFoundNode, AttrFillGeometry ** ppFoundFillAttribute) { SelRange *pSelRange = GetApplication()->FindSelection(); if (pSelRange == NULL) return FALSE; Range Sel(*pSelRange); Node* pFirstSelectedNode = Sel.FindFirst(); KernelBitmap * pBitmap = NULL; KernelBitmapRef* pBitmapRef = NULL; if (pFirstSelectedNode != NULL) // No nodes selected so End { Node* pCurrentNode = pFirstSelectedNode; Node* pNextCurrent = NULL; // Do all bitmaps. OK this should pick up the fill as well. Never mind while (pCurrentNode != NULL) { pNextCurrent = Sel.FindNext(pCurrentNode); if ( (pCurrentNode->IsSelected()) && (pCurrentNode->GetRuntimeClass() == CC_RUNTIME_CLASS(NodeBitmap)) ) { NodeBitmap * pNodeBmp = (NodeBitmap *)(pCurrentNode); pBitmap = pNodeBmp->GetBitmap(); pBitmapRef = pNodeBmp->GetBitmapRef(); // If the caller wanted it, return the found bitmap to them if (ppFoundBitmap) *ppFoundBitmap = pBitmap; // ditto found bitmap ref if (ppFoundBitmapRef) *ppFoundBitmapRef = pBitmapRef; // ditto found node if (ppFoundNode) *ppFoundNode = pNodeBmp; // ditto found fill attribute if (ppFoundFillAttribute) *ppFoundFillAttribute = NULL; return TRUE; } pCurrentNode = pNextCurrent; } } // Find the first Fill Attribute in the selection AttrFillGeometry* pAttrNode = AttrFillGeometry::FindFirstSelectedAttr(); while (pAttrNode != NULL) { if (pAttrNode->IsKindOf(CC_RUNTIME_CLASS(AttrBitmapColourFill))) { pBitmap = pAttrNode->GetBitmap(); pBitmapRef = pAttrNode->GetBitmapRef(); // If the caller wanted it, return the found bitmap to them if (ppFoundBitmap) *ppFoundBitmap = pBitmap; // ditto found bitmap ref if (ppFoundBitmapRef) *ppFoundBitmapRef = pBitmapRef; // ditto found node if (ppFoundNode) *ppFoundNode = NULL; // ditto found fill attribute if (ppFoundFillAttribute) *ppFoundFillAttribute = pAttrNode; return TRUE; } // Check the next fill pAttrNode = AttrFillGeometry::FindNextSelectedAttr(); } // If the caller wanted it, return the found bitmap to them if (ppFoundBitmap) *ppFoundBitmap = NULL; // ditto found bitmap ref if (ppFoundBitmapRef) *ppFoundBitmapRef = NULL; // ditto found node if (ppFoundNode) *ppFoundNode = NULL; // ditto found fill attribute if (ppFoundFillAttribute) *ppFoundFillAttribute = NULL; return FALSE; } */ /******************************************************************************************** ********************************************************************************************/ /******************************************************************************************** > ActionApplyPlugInToBitmap::ActionApplyPlugInToBitmap() Author: Neville_Humphrys (Xara Group Ltd) Created: 21/1/97 Purpose: ActionApplyPlugInToBitmap constructor ********************************************************************************************/ ActionApplyPlugInToBitmap::ActionApplyPlugInToBitmap() { m_pDocument = NULL; m_pBitmap = NULL; m_pBitmapRef = NULL; m_pFoundNode = NULL; m_pFoundFillAttribute = NULL; } /******************************************************************************************** > ActionApplyPlugInToBitmap::~ActionApplyPlugInToBitmap() Author: Neville_Humphrys (Xara Group Ltd) Created: 21/1/97 Purpose: ActionApplyPlugInToBitmap destructor ********************************************************************************************/ ActionApplyPlugInToBitmap::~ActionApplyPlugInToBitmap() { } /******************************************************************************************** > virtual ActionCode ActionApplyPlugInToBitmap::Execute() Author: Neville_Humphrys (Xara Group Ltd) Created: 21/1/97 Inputs: - Outputs: ActionCode indicating if the action was successfully executed or not Returns: - Purpose: Executes the ActionApplyPlugInToBitmap to go and apply a new bitmap to the currently selected fill or node bitmap and generate another ActionApplyPlugInToBitmap to undo this change. Forces a redraw of the fill or node. ********************************************************************************************/ ActionCode ActionApplyPlugInToBitmap::Execute() { ActionApplyPlugInToBitmap ApplyPlugInAct; ActionCode ActCode = AC_FAIL; // Get the details on the stored bitmap node or fill so that we can use this to undo what we // are about to try and do KernelBitmap * pBitmap = NULL; KernelBitmapRef * pBitmapRef = NULL; if (m_pDocument != NULL && m_pBitmap != NULL && m_pBitmapRef != NULL) { // Note the bitmap currently in use on that fill or node if (m_pFoundNode != NULL) { pBitmap = m_pFoundNode->GetBitmap(); pBitmapRef = m_pFoundNode->GetBitmapRef(); } else if (m_pFoundFillAttribute != NULL) { pBitmap = m_pFoundFillAttribute->GetBitmap(); pBitmapRef = m_pFoundFillAttribute->GetBitmapRef(); } else { ERROR3("Called ActionApplyPlugInToBitmap::Execute with no node or fill selected!"); return AC_FAIL; } } else { ERROR3("Called ActionApplyPlugInToBitmap::Execute with no selected bitmap in the range!"); return AC_FAIL; } if (pBitmap == NULL || pBitmapRef == NULL) { ERROR3("Called ActionApplyPlugInToBitmap::Execute with no selected bitmap in the range!"); return AC_FAIL; } // Create an action to restore the changes we are about to make ActCode = ActionApplyPlugInToBitmap::Init( pOperation, pOppositeActLst, sizeof(ActionApplyPlugInToBitmap), m_pDocument, pBitmap, pBitmapRef, m_pFoundNode, m_pFoundFillAttribute, ( Action**)(&ApplyPlugInAct), m_bUpdateAspect ); if (ActCode != AC_FAIL) { // Make sure we have quite a few valid items before even attempting to continue if (m_pDocument != NULL && m_pBitmap != NULL && m_pBitmapRef != NULL) { // Change that bitmap if (m_pFoundNode != NULL) { if (m_bUpdateAspect) { // Ensure that the aspect ratio of the new bitmap is retained // (Must be done before the new bitmap is attached) m_pFoundNode->SetAspectRatio(m_pBitmap->GetWidth(), m_pBitmap->GetHeight(), TRUE); } // Its a node bitmap so change its bitmap reference to be the new one m_pBitmapRef->Attach(m_pBitmap, m_pDocument); BROADCAST_TO_ALL(BitmapListChangedMsg(m_pBitmap->GetParentBitmapList(), m_pBitmap)); // Say that the bitmap has changed ((UndoableOperation*)pOperation)->DoInvalidateNodeRegion((NodeRenderableInk*)m_pFoundNode, TRUE); } else if (m_pFoundFillAttribute != NULL) { // Its a bitmap fill so change its bitmap reference to be the new one m_pBitmapRef->Attach(m_pBitmap, m_pDocument); BROADCAST_TO_ALL(BitmapListChangedMsg(m_pBitmap->GetParentBitmapList(), m_pBitmap)); } else { ERROR3("Called ActionApplyPlugInToBitmap::Execute with no node or fill selected!"); return AC_FAIL; } } } return (ActCode); } /******************************************************************************************** > ActionCode ActionApplyPlugInToBitmap::Init( Operation* const pOp, ActionList* pActionList, UINT32 ActionSize, Document *pDocument, KernelBitmap *pBitmap, KernelBitmapRef *pBitmapRef, NodeBitmap * pFoundNode, AttrFillGeometry * pFoundFillAttribute, Action** NewAction) Author: Neville_Humphrys (Xara Group Ltd) Created: 21/1/97 Inputs: pOp: The operation to which the action should be added pActionList: The action list in the operation object ActionSize: The size of the action in bytes. This should be the total size of the action (including any objects pointed to by the action). pDocument: The target document which contains the bitmap pBmp: The target bitmap to have the plug-in applied to pBitmapRef: The target bitmap reference to be changed pFoundNode: The possible target nodebitmap or NULL pFoundFillAttribute: The possible target attribute or null. Outputs: NewAction: A pointer to the action if it could be allocated. Returns: AC_FAIL: There was not enough room in the operation history for the action and the user did not wish to continue. Usually End() should be called in this situation. AC_NORECORD: There was not enough room in the operation history for the action, but the user requested that he wished to continue without undo. AC_OK : The action was successfully initialised and added to the operation. Purpose: To check that there is sufficient room for the action in the operation history, and if there is, then to add the action to the operations action list. The function calls the Action::Init function passing the runtime class of an ActionApplyPlugInToBitmap. Errors: - SeeAlso: Action::Init; PlugInUndoOp; ********************************************************************************************/ ActionCode ActionApplyPlugInToBitmap::Init( Operation* const pOp, ActionList* pActionList, UINT32 ActionSize, Document *pDocument, KernelBitmap *pBitmap, KernelBitmapRef *pBitmapRef, NodeBitmap * pFoundNode, AttrFillGeometry * pFoundFillAttribute, Action** NewAction, BOOL bUpdateAspect) { ActionCode Ac = (Action::Init(pOp, pActionList, ActionSize, CC_RUNTIME_CLASS(ActionApplyPlugInToBitmap), NewAction)); if (*NewAction != NULL) { ActionApplyPlugInToBitmap *ACC = (ActionApplyPlugInToBitmap*) (*NewAction); ACC->m_pDocument = pDocument; ACC->m_pBitmap = pBitmap; ACC->m_pBitmapRef = pBitmapRef; ACC->m_pFoundNode = pFoundNode; ACC->m_pFoundFillAttribute = pFoundFillAttribute; ACC->m_bUpdateAspect = bUpdateAspect; } return (Ac); } /******************************************************************************************** ********************************************************************************************/