// $Id: tool.cpp 1535 2006-07-25 16:50:32Z 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============================ */ /* */ // Handles lists of Tools loaded from Modules #include "camtypes.h" #include "toollist.h" //#include "ensure.h" //#include "mainfrm.h" //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "tool.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "opdesc.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "dlgmgr.h" //#include "bars.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "basebar.h" //#include "ink.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "keypress.h" //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "blobs.h" #include "toolmsg.h" #include "usercord.h" #define SELECTED TRUE #define DESELECTED FALSE CC_IMPLEMENT_DYNAMIC(ToolsCurrentAttrGroupChangedMsg, Msg); /******************************************************************************************** > class TempToolItem : public ListItem Author: Mark_Neves (Xara Group Ltd) Created: 8/12/94 Purpose: Item that represent a temp tool selection Errors: - SeeAlso: Tool::ActivateTemporaryTool(), Tool::DeactivateTemporaryTool() ********************************************************************************************/ class TempToolItem : public ListItem { CC_DECLARE_MEMDUMP(TempToolItem) public: TempToolItem() { pTempTool = pPrevTool = NULL; } Tool* GetTempTool() { return pTempTool; } void SetTempTool(Tool* pThisTool) { pTempTool = pThisTool; } Tool* GetPrevTool() { return pPrevTool; } void SetPrevTool(Tool* pThisTool) { pPrevTool = pThisTool; } private: Tool* pTempTool; Tool* pPrevTool; }; //------------------------------------------------------------- /******************************************************************************************** > class ToolSwitch : public ListItem Author: Mark_Neves (Xara Group Ltd) Created: 30/8/94 Purpose: Holds a key press that will temporarily switch to another tool Errors: - SeeAlso: - ********************************************************************************************/ class ToolSwitch : public ListItem { CC_DECLARE_MEMDUMP(ToolSwitch) public: ToolSwitch(Tool* pThisTool,KeyPress* pKeyPress,BOOL FromFile); ~ToolSwitch(); Tool* pTool; // The tool KeyPress* pKeyPress; // The key press that will activate the tool BOOL Temp : 1; // TRUE if this switch is temporary BOOL DefFromFile : 1; // TRUE if defined from a file static ToolSwitch* pCurrentToolSwitch; }; // The ToolSwitch that is currently active ToolSwitch* ToolSwitch::pCurrentToolSwitch = NULL; // List of all the tool switching key combinations for all the tools List ToolSwitchList; /******************************************************************************************** > ToolSwitch::ToolSwitch(Tool* pThisTool, KeyPress* pThisKeyPress, BOOL FromFile) Author: Mark_Neves (Xara Group Ltd) Created: 30/8/94 Inputs: pThisTool = the tool this key press will activate pThisKeyPress = ptr to the key press combination that activates the tool FromFile = TRUE if defined from a file, FALSE if a direct definition (usu. direct from a tool) Outputs: - Returns: - Purpose: The constructor. Creates a ToolSwitch object that represents a key press combination that invokes the given tool Errors: - SeeAlso: - ********************************************************************************************/ ToolSwitch::ToolSwitch(Tool* pThisTool, KeyPress* pThisKeyPress, BOOL FromFile) { pTool = pThisTool; pKeyPress = pThisKeyPress; Temp = FALSE; DefFromFile = FromFile; } /******************************************************************************************** > ToolSwitch::~ToolSwitch() Author: Mark_Neves (Xara Group Ltd) Created: 6/9/94 Inputs: 0 Outputs: - Returns: - Purpose: Default destructor. Main job is to delete the key press object it constains Errors: - SeeAlso: - ********************************************************************************************/ ToolSwitch::~ToolSwitch() { if (pKeyPress != NULL) { delete pKeyPress; pKeyPress = NULL; } } //------------------------------------------------------------- // Runtime class support for debug builds CC_IMPLEMENT_MEMDUMP(ToolInfo_v1, CCObject) CC_IMPLEMENT_MEMDUMP(ToolInfo, ToolInfo_v1) CC_IMPLEMENT_MEMDUMP(Tool_v1, CCObject) CC_IMPLEMENT_MEMDUMP(Tool, Tool_v1) CC_IMPLEMENT_MEMDUMP(ToolSwitch,ListItem) CC_IMPLEMENT_MEMDUMP(TempToolItem,ListItem); // Declare smart memory handling in Debug builds #define new CAM_DEBUG_NEW DECLARE_SOURCE("$Revision: 1535 $"); ToolList *Tool::Tools = NULL; Tool* Tool::Current = NULL; // Pointer to the current tool //Tool* Tool::PrevTool = NULL; // Pointer to the temporarily deselected tool when a // tool is temporarily active. BOOL Tool::ToolChanging = FALSE; // TRUE while the current tool is changing BOOL Tool::PendingDeactivateTempTool = FALSE;// TRUE while waiting to deactivate the temporary tool after a drag List Tool::TempToolList; // Holds a record per stacked temp tool UINT32 Tool::InitTool; // Used as a pref - maintains current tool id /******************************************************************************************** > ToolInfo_v1::ToolInfo_v1() Author: Simon_Maneggio (Xara Group Ltd) Created: 10/6/94 Inputs: - Outputs: - Returns: - Purpose: For specifying default tool structure values Errors: - SeeAlso: - ********************************************************************************************/ ToolInfo_v1::ToolInfo_v1() { // When specifying current attributes most of the time we will want to add the // attribute to the NodeRenderableInk current attribute group. CurrentAttributeGroup = CC_RUNTIME_CLASS(NodeRenderableInk); } /******************************************************************************************** > BOOL Tool::InitToolList() Author: Tim_Browse (Xara Group Ltd) Created: 1/7/93 Inputs: - Outputs: - Returns: TRUE if list initialised ok, FALSE otherwise. Purpose: Initialise the static ToolList object which holds all tools that the kernel knows about. Errors: Assert if list is already initialised. ********************************************************************************************/ BOOL Tool::InitToolList() { ENSURE(Tools == NULL, "Attempt to initialise the ToolList more than once"); Tools = new ToolList; return (Tools != NULL); } /******************************************************************************************** > BOOL Tool::InitTools() Author: Andy_Pennell (Xara Group Ltd) Created: 21/6/93 Inputs: None Outputs: None Returns: TRUE if OK, FALSE for catastrophic failure Purpose: Called at the end of initialisation (as it may well need all other initialisations to have been done) to add Tools and Modules to the Kernel's knowledgebase. Errors: None Scope: Public ********************************************************************************************/ BOOL Tool::InitTools() { BOOL Finished; do { // All the tools have been 'new'ed now. We can now ask them to initialise themselves. // If they don't want to, they get 'delete'ed. ToolListItem *Item = (ToolListItem *) Tools->GetHead(); Finished = TRUE; while (Item != NULL) { Tool *Tool = Item->m_pTool; // If this tool exists and has not been initialised yet, then try to // initialise it. If it initialises ok, set the item's flag, and force // another scan of the remaining tools in case one of them depends on // this tool being present. if( NULL != Tool && !Item->m_fInitialised && Tool->Init() ) { Item->m_fInitialised = TRUE; // Tool initialised ok. Finished = FALSE; // At least one more loop to try } // Try the next tool Item = (ToolListItem *) Tools->GetNext(Item); } } while (!Finished); // Delete any un-initialised tools ToolListItem *Item = (ToolListItem *) Tools->GetHead(); while (Item != NULL) { ToolListItem *NextItem = (ToolListItem*) Tools->GetNext(Item); if ((Item->m_pTool != NULL) && (!Item->m_fInitialised)) { // the Tool didn't want to play, so remove it // we've already got the next item, so its OK to kill the old one delete Tools->RemoveItem( Item ); // remove from list & free up } // Try the next tool Item = NextItem; } // default to Selector tool in case we cant find a pref InitTool = TOOLID_SELECTOR; // declare a pref if( Camelot.DeclareSection( _T("InitialTool"), 1 ) ) Camelot.DeclarePref( _T("InitialTool"), _T("InitTool"), &InitTool ); return TRUE; // no error return possible at present } /******************************************************************************************** > static void Tool::SelectFirstTool() Author: Chris_Parks (Xara Group Ltd) Created: 9/1/95 Inputs: - Outputs: - Returns: - Purpose: Selects the tool that is retrieved from the prefs file. If no pref is found will default to Selector Tool - If the appropriate tool can't be found the first will be used instead Errors: - SeeAlso: Tool::InitTools ********************************************************************************************/ void Tool::SelectFirstTool() { // look for the initial tool ToolListItem* pItem = (ToolListItem*) Find(InitTool); // if we can't find it go for the first if(pItem == NULL) pItem = (ToolListItem*) Tools->GetHead(); if (pItem != NULL && pItem->m_pTool != NULL) pItem->m_pTool->SetCurrent(); } /******************************************************************************************** > BOOL Tool::Declare(Tool *NewTool, UINT32 ParentID) Author: Tim_Browse (Xara Group Ltd) Created: 1/7/93 Inputs: NewTool - Pointer to a new Tool and its ID ParentID - Module ID of the module that provides this tool. Outputs: None Returns: Pointer to new tool list item. Purpose: Called by OIL code to declare new tool types. Errors: Will return NULL if invalid ID or same tool ID used twice. ********************************************************************************************/ ToolListItem *Tool::Declare(Tool *NewTool, UINT32 ParentID) { // Try to add the tool to the kernel's list. ToolListItem *NewItem = Tools->Add(NewTool, ParentID); if (NewItem == NULL) { // Tool has invalid ID - print error message and destroy tool. ToolInfo Info; NewTool->Describe(&Info); TRACE( _T("Tool %u is invalid\n"), Info.ID); delete NewTool; } return NewItem; } /******************************************************************************************** > static UINT32 Tool::GetNumTools() Author: Tim_Browse (Xara Group Ltd) Created: 13/9/93 Returns: The number of tools registered with the kernel. Purpose: Find out how many tools have registered and initialised successfully. ********************************************************************************************/ UINT32 Tool::GetNumTools() { if (Tools == NULL) return 0; else return (UINT32) Tools->GetCount(); } /******************************************************************************************** > Tool *Tool::Find(UINT32 id) Author: Tim_Browse (Xara Group Ltd) Created: 1/7/93 Inputs: Tool ID Outputs: None Returns: Pointer to required tool, or NULL if not found. Purpose: Anyone can ask about a tool's presence by its ID. Errors: None ********************************************************************************************/ ToolListItem *Tool::Find(UINT32 ToolID) { // Simple search of list for ID ToolListItem *Item = (ToolListItem *) Tools->GetHead(); while (Item != NULL) { if (Item->m_ToolInfo.ID == ToolID) // Found ID - return pointer to its tool. return Item; Item = (ToolListItem *) Tools->GetNext(Item); } // Not found return NULL; } /******************************************************************************************** > Tool* Tool::FindTool(UINT32 id) Author: Phil_Martin (Xara Group Ltd) Created: 19/11/2004 Inputs: Tool ID Outputs: None Returns: Pointer to required tool, or NULL if not found. Purpose: Anyone can ask about a tool's presence by its ID. But Geez! The caller doesn't want to know about ToolListItems!!! Errors: None ********************************************************************************************/ Tool* Tool::FindTool(UINT32 ToolID) { ToolListItem* pItem = Find(ToolID); if (pItem) return pItem->m_pTool; return NULL; } /******************************************************************************************** > static UINT32 Tool::GetModuleID(UINT32 ToolID) Author: Andy_Pennell (Xara Group Ltd) Created: 20/8/93 Inputs: Tool ID Outputs: None Returns: Module ID of parent module, or 0 if not found. Purpose: Particulary useful for error handling, it allows the owner module ID to be determined given just a tool ID. Errors: 0 if cannot be found. ********************************************************************************************/ UINT32 Tool::GetModuleID(UINT32 ToolID) { if ( ToolID == TOOLID_INVALID ) return 0; // If unknown tool do nothing! const ToolListItem *Tool = Tool::Find(ToolID); if (Tool) return Tool->m_ToolInfo.ParentModuleID; // return ID if found else return 0; // 0=not found } /******************************************************************************************** > void Tool::SetButtons(BOOL State) Author: Chris_Parks (Xara Group Ltd) Created: 6/6/94 Inputs: State to set buttons to Outputs: None Returns: None Purpose: Selects/Deselects the buttons associated with this buttons. Errors: None ********************************************************************************************/ void Tool::SetButtons(BOOL State) { #if !defined(EXCLUDE_FROM_RALPH) String OpToken; camSnprintf(OpToken, 16, _T("TOOL%u"), GetID()); ToolOpDescriptor* ToolOp = (ToolOpDescriptor *) OpDescriptor::FindOpDescriptor(OpToken); // Keep Select state in the OpDescriptor ToolOp->SetCurrentTool(State); List * pGadgetList = new List; if (pGadgetList == 0) { InformError(); return; } //Build list of all controls linked to this Op if (!ToolOp->BuildGadgetList(pGadgetList)) { TRACEUSER( "Chris", _T("Couldn't build gadget list in Tool::SetCurrent\n")); delete pGadgetList; return; } ListItem* pListItem = pGadgetList->GetHead(); while (pListItem != NULL) { // Set the Select State of each gadget GadgetListItem* pGadgetItem = (GadgetListItem*) pListItem; pGadgetItem->pDialogOp->SetLongGadgetValue(pGadgetItem->gidGadgetID, State, FALSE, FALSE); // Do the next control in the list, if any. pListItem = pGadgetList->GetNext(pListItem); } // Don't forget to delete the list afterwards! pGadgetList->DeleteAll(); delete pGadgetList; #endif } /******************************************************************************************** > void Tool::SetCurrent() Author: Mario_Shamtani (Xara Group Ltd) Created: 19/8/93 Inputs: None Outputs: None Returns: None Purpose: Sets the 'this' tool to be the current tool. Errors: None ********************************************************************************************/ void Tool::SetCurrent() { if(Current == this) { // Ensure the buttons are set right Current->SetButtons(SELECTED); return ; } SetToolChangingState(TRUE); // Deselect current tool if (Current) { Current->SetButtons(DESELECTED); Current->SelectChange(FALSE); OpDescriptor::RemoveAllAliases(); } // Find the CurrentAttributeGroup associated with the Tool we are switching away from CCRuntimeClass* OldCurrentAttrGroup = NULL; if (Current) OldCurrentAttrGroup = Current->Parent->m_ToolInfo.CurrentAttributeGroup; // Select new tool. Current = this; SetButtons(SELECTED); // Inform tool that it has been selected. SelectChange(TRUE); // save ID in preference InitTool = GetID(); SetToolChangingState(FALSE); TempToolItem* pTempToolItem = (TempToolItem*)TempToolList.GetHead(); if (pTempToolItem != NULL && pTempToolItem->GetTempTool() != Current) DeleteTempToolList(); // Finally if the CurrentAttributeGroup has changed then tell people if (Parent->m_ToolInfo.CurrentAttributeGroup != OldCurrentAttrGroup) { BROADCAST_TO_ALL(ToolsCurrentAttrGroupChangedMsg); } } /******************************************************************************************** > void Tool::DeinitTools() Author: Andy_Pennell (Xara Group Ltd) Created: 21/6/93 Inputs: None Outputs: None Returns: None Purpose: Deletes all allocated tools. Safe to call more than once. Do NOT try to use any tools after calling this. Errors: None ********************************************************************************************/ void Tool::DeinitTools() { if (Tools != NULL) { // Deselect the current tool, if there is one. if (Current) { Current->SelectChange(FALSE); Current = 0; } // Delete the tool list. delete Tools; Tools = NULL; } ToolSwitchList.DeleteAll(); DeleteTempToolList(); } /******************************************************************************************** > OILTool *Tool::GetOILTool(UINT32 ID) Author: Tim_Browse (Xara Group Ltd) Created: 6/7/93 Inputs: ID - The ID of the Tool Outputs: - Returns: Pointer to the OILTool object for this tool. Purpose: Given a Tool ID, returns a pointer to the OILTool object associated with this tool. Errors: Returns NULL if the associated OILTool object does not exist (maybe the tool ID is invalid?) SeeAlso: ToolListItem ********************************************************************************************/ OILTool *Tool::GetOILTool(UINT32 ID) { /*ToolListItem *Item =*/ Find(ID); // return Item ? Item->m_pOILTool : NULL; return NULL; } /******************************************************************************************** > void Tool::ActivateTemporaryTool(Tool *pTempTool) Author: Tim_Browse (Xara Group Ltd) Created: 04/05/94 Inputs: pTempTool - the tool to be made active. Purpose: Temporarily invoke the specified tool. This is called when the user holds down modifier keys to switch tools - this function remembers the currently active tool and will switch back to it when you call Tool::DeactivateTemporaryTool(). It is ok to keep calling this without first deactivating the temporary tool - the system will correctly remember which tool was originally active and restore it when all DeactivateTemporaryTool() is called. SeeAlso: Tool::DeactivateTemporaryTool ********************************************************************************************/ void Tool::ActivateTemporaryTool(Tool *pTempTool) { // If the current tool is not temporary, then remember it so we can revert // to it when the user lets go of the hot-keys. // NB. We have to make this test so if the user invokes one tool, then another in such // a way that the original tool si not switched back to inbetween, then things will // go wrong and we won't return to the original tool. TempToolItem* pTempToolItem = new TempToolItem; if (pTempToolItem != NULL) { pTempToolItem->SetPrevTool(Current); pTempToolItem->SetTempTool(pTempTool); TempToolList.AddHead(pTempToolItem); // if (PrevTool == NULL) // PrevTool = Current; //Current->SelectChange(FALSE); // Find the instance of the ToolOpDescriptor String_64 OpToken; camSnprintf( OpToken, 64, _T("TOOL%u"), pTempTool->GetID() ); ToolOpDescriptor* ToolOp = (ToolOpDescriptor *) OpDescriptor::FindOpDescriptor(OpToken); // Use the OpDescriptor to invoke the tool (i.e. make it become the selected tool) ToolOp->Invoke(); } } /******************************************************************************************** > void Tool::DeactivateTemporaryTool() Author: Tim_Browse (Xara Group Ltd) Created: 04/05/94 Purpose: Deactivate the temporary tool and restore the original one. SeeAlso: void Tool::DeactivateTemporaryTool() ********************************************************************************************/ void Tool::DeactivateTemporaryTool() { /* // Do nothing if we don't have a previous tool if (PrevTool == NULL) return; // If the previous tool is the current one, don't have to do nowt if (PrevTool == Current) return; */ TempToolItem* pTempToolItem = (TempToolItem*)TempToolList.RemoveHead(); // Only do something if we have a temp tool item if (pTempToolItem != NULL) { UINT32 PrevToolID = pTempToolItem->GetPrevTool()->GetID(); // We don't need this temp tool item any more. delete pTempToolItem; pTempToolItem = NULL; // Find the instance of the ToolOpDescriptor String_64 OpToken; camSnprintf( OpToken, 64, _T("TOOL%u"), PrevToolID ); ToolOpDescriptor* ToolOp = (ToolOpDescriptor *) OpDescriptor::FindOpDescriptor(OpToken); // Use the OpDescriptor to invoke the tool (i.e. make it become the selected tool) ToolOp->Invoke(); } // Not temporary any more // PrevTool = NULL; } /******************************************************************************************** > void Tool::DeleteTempToolList() Author: Mark_Neves (Xara Group Ltd) Created: 8/12/94 Returns: - Purpose: This deletes all temp tool items in the list temp tools. After this call, the temp tool stacking info is lost. This should be called whenever a user selects a new tool directly (i.e. via clicking on the tool icon, a hot key, or menu item). SeeAlso: Tool::ActivateTemporaryTool; Tool::DeactivateTemporaryTool ********************************************************************************************/ void Tool::DeleteTempToolList() { TempToolList.DeleteAll(); } /******************************************************************************************** > BOOL Tool::IsCurrentToolTemporary() Author: Tim_Browse (Xara Group Ltd) Created: 04/05/94 Returns: TRUE if the tool is temporary; FALSE if not. Purpose: Check to see if the currently active tool is permanently or temporarily active. If, e.g. the user is holding down ALT to get the selector tool, then this returns TRUE. SeeAlso: Tool::ActivateTemporaryTool; Tool::DeactivateTemporaryTool ********************************************************************************************/ /* BOOL Tool::IsCurrentToolTemporary() { // If PrevTool is not NULL, then we are waiting for the user to let go of the // modifier keys so we can change back to the original tool. return (PrevTool != NULL); } */ /******************************************************************************************** > void Tool::SetToolChangingState(BOOL state) Author: Mark_Neves (Xara Group Ltd) Created: 25/05/94 Inputs: state - boolean used to set ToolChanging flag Outputs: - Returns: - Purpose: Lets you set the ToolChanging flag SeeAlso: - ********************************************************************************************/ void Tool::SetToolChangingState(BOOL state) { ToolChanging = state; } /******************************************************************************************** > BOOL Tool::IsToolChanging() Author: Mark_Neves (Xara Group Ltd) Created: 25/05/94 Inputs: - Outputs: - Returns: TRUE - tool is in the middle of changing FALSE - oh no it's not! Purpose: Lets you see the state of the ToolChanging flag SeeAlso: - ********************************************************************************************/ BOOL Tool::IsToolChanging() { return (ToolChanging); } /******************************************************************************************** > static BOOL Tool::SwitchTool(KeyPress* pKeyPress) Author: Mark_Neves (Xara Group Ltd) Created: 30/8/94 Inputs: pKeyPress = ptr to the key press that's just occurred Outputs: - Returns: TRUE - the key press caused a tool switch, do not pass on FALSE - no tool switching, see if anyone else wants it Purpose: The place where tool switching takes place. SeeAlso: - ********************************************************************************************/ BOOL Tool::SwitchTool(KeyPress* pKeyPress) { BOOL Processed = FALSE; BOOL DuringADrag = (Operation::GetCurrentDragOp() != NULL); #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX) DuringADrag = (DuringADrag || BaseBar::IsDragging()); #endif ToolSwitch* pToolSwitch = (ToolSwitch*)ToolSwitchList.GetHead(); while (pToolSwitch != NULL && !Processed) { // Is it a tool switch key press? if (*pToolSwitch->pKeyPress == *pKeyPress) { // This key press is a tool switch combination for a tool // Are we waiting to deactivate the temp tool at the end of a drag? if (!PendingDeactivateTempTool) { // We are NOT wait to deactivate the temp tool at the end of a drag, so proceed // pTool is the ptr to the tool in question Tool* pTool = pToolSwitch->pTool; // Is it a "key down" key press? if (pKeyPress->IsPress()) { // It's a "key down" event // Is it the first "key down", or has it auto-repeated? if (!pKeyPress->IsRepeat()) { // It's the first press // is it already the current tool? if (pTool != Current) { // We now have the first "key down" of a tool switch for a tool that // is NOT the current tool // is a drag happening? if (!DuringADrag) { // If we are not doing this during a drag, make it the current tool. // Also, set the Temp flag to FALSE as it may be a permanent change ActivateTemporaryTool(pTool); pToolSwitch->Temp = FALSE; } } else { // We now have the first "key down" of a tool switch for a tool that // IS the current tool // If we are not dragging, deactivate the tool if (!DuringADrag) DeactivateTemporaryTool(); else // Remember to deactivate the tool after the drag has ended PendingDeactivateTempTool = TRUE; } } else { // It's an auto-repeated key press // if the switch belongs to the current tool, and is auto-repeated // make the switch temporary if (pTool == Current) pToolSwitch->Temp = TRUE; } } else { // It's a "key up" event // Does it belong to the current tool? if (pTool == Current) { // "Key up" on a tool switch for the current tool. // If the current tool was selected temporarily, select the previous current tool if (pToolSwitch->Temp) { // If we are not dragging, deactivate the tool if (!DuringADrag) DeactivateTemporaryTool(); else // Remember to deactivate the tool after the drag has ended PendingDeactivateTempTool = TRUE; } } } } // The key press object was a tool switching one, so we have processed the key press Processed = TRUE; } // Get the next tool switch in the list pToolSwitch = (ToolSwitch*)ToolSwitchList.GetNext(pToolSwitch); } return Processed; } /******************************************************************************************** > static void Tool::EndDrag() Author: Mark_Neves (Xara Group Ltd) Created: 5/9/94 Inputs: - Outputs: - Returns: - Purpose: This is called when a drag ends SeeAlso: ServicePendingToolChange ********************************************************************************************/ void Tool::EndDrag() { ServicePendingToolChange(); } /******************************************************************************************** > static void Tool::OnActivateApp(BOOL bActive) Author: Mark_Neves (Xara Group Ltd) Created: 6/2/96 Inputs: bActive - this is ignored Outputs: - Returns: - Purpose: This is called when the app's active state changes SeeAlso: ServicePendingToolChange ********************************************************************************************/ void Tool::OnActivateApp(BOOL bActive) { ServicePendingToolChange(); } /******************************************************************************************** > static void Tool::ServicePendingToolChange() Author: Mark_Neves (Xara Group Ltd) Created: 6/2/96 Inputs: - Outputs: - Returns: - Purpose: This is called when a drag ends, or the app's active state changes This will deactivate the temporary tool if a deactivate key event was encounted during a drag SeeAlso: EndDrag(), OnActivateApp() ********************************************************************************************/ void Tool::ServicePendingToolChange() { if (PendingDeactivateTempTool) { DeactivateTemporaryTool(); PendingDeactivateTempTool = FALSE; } } /******************************************************************************************** > static void Tool::RemoveDirectRegToolSwitches(Tool* pThisTool) Author: Mark_Neves (Xara Group Ltd) Created: 6/9/94 Inputs: pThisTool = the tool in question Outputs: - Returns: - Purpose: This goes through the list of registered tool switches and removes all switches that belong to the given tool and were defined directly, i.e. ones that were NOT defined via a file Errors: - ********************************************************************************************/ void Tool::RemoveDirectRegToolSwitches(Tool* pThisTool) { ToolSwitch* pToolSwitch; ToolSwitch* pNextToolSwitch = (ToolSwitch*)ToolSwitchList.GetHead(); while (pNextToolSwitch != NULL) { pToolSwitch = pNextToolSwitch; pNextToolSwitch = (ToolSwitch*)ToolSwitchList.GetNext(pNextToolSwitch); if (pToolSwitch->pTool == pThisTool && !pToolSwitch->DefFromFile) { // if this tool switch belongs to the given tool // and it was a directly defined one, remove it from // the list and delete it ToolSwitchList.RemoveItem(pToolSwitch); delete pToolSwitch; } } } //------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------- // Empty functions for the default tool. /******************************************************************************************** > BOOL Tool_v1::Init() Author: Andy_Pennell (Xara Group Ltd) Created: 21/6/93 Inputs: - Outputs: - Returns: TRUE if OK, FALSE if tool doesn't want to initialise. Purpose: Called after tool's constructor to ask it whether it wants to exist or not. Each tool is asked in two passes, so that its existence can depend on another tool. If a tool does not want to exist, it should return FALSE, when it will be deleted. Errors: None ********************************************************************************************/ BOOL Tool_v1::Init() { ENSURE(FALSE, "Init called for base tool class!"); return FALSE; // Should never try to instantiate a tool base class } /******************************************************************************************** > Tool_v1::~Tool_v1() Author: Tim_Browse (Xara Group Ltd) Created: 7/7/93 Inputs: - Outputs: - Returns: - Purpose: Destroys the tool, performing any clean-up necessary. Errors: - SeeAlso: - ********************************************************************************************/ Tool_v1::~Tool_v1() { // Null destructor } /******************************************************************************************** > BOOL Tool_v1::Describe(void *Infoptr) Author: Andy_Pennell (Xara Group Ltd) Created: 21/6/93 Inputs: Pointer to area to recieve info Outputs: Info area is updated Returns: None Purpose: Asks a tool for more information. The pointer points to a struct such as ToolInfo_v1 which the tool should fill in. All fields should be filled (NULL is OK for char* variables). The type of the pointer is not explicitly defined so the structure can evolve while keeping backward compatibility. Errors: None ********************************************************************************************/ void Tool_v1::Describe(void *InfoPtr) { ENSURE(FALSE, "Describe called for base tool class!"); // Cast structure into the latest one we understand. ToolInfo_v1 *Info = (ToolInfo_v1 *) InfoPtr; Info->InfoVersion = 1; Info->InterfaceVersion = GetToolInterfaceVersion(); // You should always have this line. // These are all garbage as we should never try to create one of these... Info->Version = 1; Info->ID = TOOLID_INVALID; Info->TextID = 0; // so we never get instantiated Info->Family = Info->Name = Info->Purpose = Info->Author = NULL; } /******************************************************************************************** > void Tool_v1::OnClick(DocCoord PointerPos, ClickType Click, ClickModifiers Mods, Spread* pSpread) Author: Phil_Martin (Xara Group Ltd) Created: 2/7/93 Inputs: Position of click in spread coordinates Click type (single, double or drag) Modifiers (adjusted, constrained, etc...) Pointer to the spread in which the click occurred Outputs: None Returns: None Purpose: This function should be overridden by any tool that wants to receive clicks on the document. When DocView receives a click event from the OIL layer it finds the current tool and calls this function. Errors: None. ********************************************************************************************/ void Tool_v1::OnClick(DocCoord /*PointerPos*/, ClickType /*Click*/, ClickModifiers /*Mods*/, Spread* /*pSpread*/) { ENSURE(FALSE, "OnClick called for base tool class!"); // DO nothing! // Click not handled by base class! } /******************************************************************************************** > void Tool_v1::OnMouseMove(DocCoord mousepos, Spread* pSpread, ClickModifiers) Author: Justin_Flude (Xara Group Ltd) Created: 14 Oct 93 Inputs: Position of the mouse, in spread coordinates Pointer to the spread in which the mouse lies. Which button/keys are down. Outputs: - Returns: - Purpose: This function should be overridden by any tool that wants to receive mouse move messages, when a drag is NOT in progress. For example, tools can use this function to change the mouse cursor as it moves over a "hot spot". The default implementation does nothing. Errors: - ********************************************************************************************/ void Tool_v1::OnMouseMove(DocCoord, Spread*, ClickModifiers) { // Do nothing at all, if you like. It's your tool! } /******************************************************************************************** > BOOL Tool_v1::OnKeyPress(KeyPress* pKeyPress) Author: Mark_Neves (Xara Group Ltd) Created: 30/8/94 Inputs: pKeyPress = Ptr to a platform-indy key press object Outputs: - Returns: TRUE - the key press was processed, so do NOT pass on FALSE - not processed, so let others have a bash Purpose: This function should be overridden by any tool that wants to process key presses. The current tool is the first part of Camelot that gets the chance to process a key press, so tools can override all tool-switching and hot-key combinations if it needs to. Errors: - ********************************************************************************************/ BOOL Tool_v1::OnKeyPress(KeyPress* pKeyPress) { // Return FALSE so the key press gets passed on to others return FALSE; } /******************************************************************************************** > BOOL Tool_v1::OnIdle() Author: Peter_Arnold (Xara Group Ltd) Created: 14/09/94 Inputs: - Outputs: - Returns: TRUE - the tool wants more idle events. FALSE - no more idle events are required. Purpose: This function should be overridden by any tool that wants to do processing on idle events. This processing should be quick (or split into small, quick bits). Once processing is finished FALSE should be returned (although this does not guarentee then function will not be called again). Errors: - ********************************************************************************************/ BOOL Tool_v1::OnIdle() { // Return FALSE to turn off return FALSE; } /******************************************************************************************** > BOOL Tool_v1::GetStatusLineText(String_256* StatusLineText, Spread* pSpread, DocCoord DocPos, ClickModifiers Mods) Author: Ed_Cornes (Xara Group Ltd) Created: 14/11/94 Returns: TRUE if returning valid text Purpose: Each tool should override this function to return valid status line text ********************************************************************************************/ BOOL Tool_v1::GetStatusLineText(String_256* ptext, Spread* pSpread, DocCoord DocPos, ClickModifiers ClickMods) { return FALSE; // defaults to no text } /******************************************************************************************** > BOOL Tool_v1::RegisterToolSwitch(KeyPress* pKeyPress,BOOL FromFile = FALSE) Author: Mark_Neves (Xara Group Ltd) Created: 30/8/94 Inputs: pKeyPress = Ptr to a platform-indy key press object FromFile = TRUE if the tool switch was defined in a file FALSE if it's being registered directly Outputs: - Returns: TRUE - the key press has been registered for temporary switching to this tool FALSE - failed. Either another tool has this combo, or the keypress is invalid Purpose: This allows you to specify a key press that will be used to switch to the tool temporarily. The pKeyPress should be a valid one created by one of its public constructors. If the FromFile flag is TRUE then all registered tool switches for this tool that have been registered directly (i.e. by the tool itself calling this routine with FromFile==FALSE) are deleted. The means that tool switches defined in file take priority over directly defined ones, so that in the future we may allow the user to choose which key presses he wants to temp tool switching. Also means that a tool can have temp switching codes with defs in a file; useful for third party tools who can't get hold of the bound in kernel resource file. Errors: - SeeAlso: KeyPress::KeyPress ********************************************************************************************/ BOOL Tool_v1::RegisterToolSwitch(KeyPress* pKeyPress,BOOL FromFile) { ENSURE(pKeyPress->IsValid(),"Tool trying to register a tool key switch with an invalid key press object"); if (!pKeyPress->IsValid()) return FALSE; Tool* pThisTool = (Tool*)this; if (FromFile) Tool::RemoveDirectRegToolSwitches(pThisTool); ToolSwitch* pToolSwitch = (ToolSwitch*)ToolSwitchList.GetHead(); while (pToolSwitch != NULL) { if (pToolSwitch->pTool == pThisTool) { // if this tool switch has already been assigned for this tool, return TRUE if (*pToolSwitch->pKeyPress == *pKeyPress) { delete pKeyPress; return TRUE; } } else { // If this tool switch belongs to another tool, return FALSE if (*pToolSwitch->pKeyPress == *pKeyPress) return FALSE; } pToolSwitch = (ToolSwitch*)ToolSwitchList.GetNext(pToolSwitch); } // At this point we know that it is safe to assign the tool switch key press for this tool // Make a new tool switch ToolSwitch* pNewToolSwitch = new ToolSwitch(pThisTool,pKeyPress,FromFile); if (pNewToolSwitch != NULL) ToolSwitchList.AddTail(pNewToolSwitch); return (pNewToolSwitch != NULL); } /******************************************************************************************** > virtual BOOL Tool_v1::DragFinished(DragEndType HowEnded) Author: Rik_Heywood (Xara Group Ltd) Created: 26/8/94 Inputs: HowEnded - Describes how the drag ended (an if it was a drag at all really Returns: TRUE if it is OK for the operation to finish doing the things that it was going to do, or FALSE if the tool wants the operation to stop right now. Purpose: Tools that start drag operations can use this function to find out how well the drag went if the operation calls this function. ********************************************************************************************/ BOOL Tool_v1::DragFinished(DragEndType HowEnded) { // Do nothing in the base class version of this function. // Just let the operation get on with what it was doing return TRUE; } /******************************************************************************************** > BOOL Tool_v1::IsCurrent() const Author: Andy_Pennell (Xara Group Ltd) Created: 18/10/94 Returns: TRUE if 'this' is the current tool, FALSE if not. Purpose: Centralised way of doing this. Amazing this function didn't exist before. ********************************************************************************************/ BOOL Tool_v1::IsCurrent() const { if (Tool::GetCurrent() == this) return TRUE; else return FALSE; } /******************************************************************************************** > void Tool_v1::RenderToolBlobs() Author: Rik_Heywood (Xara Group Ltd) Created: 18/8/93 Purpose: This function is called in the main drawing loop to get the tool to render its blobs (ie the centre of rotation for the rotation tool). Since this is the base class version of this function and will be called if the tool does not provide its own RenderToolBlobs function, then it can be assumed that the tool does not need to draw anything, so it does nothing. SeeAlso: DocView::RenderOnTop ********************************************************************************************/ void Tool_v1::RenderToolBlobs(Spread *, DocRect*) { // If the tool does not want to draw anything then it need not have a // RenderToolBlobs function and this one will be called instead. // This draws nothing } /******************************************************************************************** > void Tool_v1::SelectChange(BOOL IsSelected) Author: Tim_Browse (Xara Group Ltd) Created: 11/11/93 Inputs: IsSelected - Indicates whether tool is being selected (TRUE) or deselected (FALSE). Purpose: Used to inform a tool that it is being selected or deselected. Default behaviour is to do nothing. A real tool should update the infobar when the tool is selected - this is usually all a tool will do. ********************************************************************************************/ void Tool_v1::SelectChange(BOOL /*IsSelected*/) { // Override me! } /******************************************************************************************** > void Tool_v1::GetRulerOrigin(Spread* pSpread, UserCoord* pOffsets) Author: Phil_Martin (Xara Group Ltd) Created: 30/Jun/2006 Inputs: pSpread - the spread for which the ruler is displayed Outputs: pOffsets - the desired origin shift in user space (is initialised to 0,0) Purpose: Gives the current tool the chance to change the coordinates displayed on the ruler ********************************************************************************************/ void Tool_v1::GetRulerOrigin(Spread* pSpread, UserCoord* pOffsets) { // Override me if you want! // Note that overriding this function implies that you will ensure the redraw of the rulers // as you enter and leave your tool. } /******************************************************************************************** > void Tool_v1::RenderRulerBlobs(RulerBase* pRuler, UserRect& UpdateRect, BOOL IsBackground) Author: Martin Wuerthner Created: 07/07/06 Inputs: pRuler - the ruler that is currently being redrawn UpdateRect - the rectangle to be updated in user coordinates (with the tool origin applied) IsBackground - whether this is the call before drawing the main blobs or the call after rendering the main blobs Purpose: Gives the current tool the chance to render additional blobs on the ruler Is called twice - once before the standard ruler graphics are rendered (to allow additional background to be drawn) and once afterwards ********************************************************************************************/ void Tool_v1::RenderRulerBlobs(RulerBase* pRuler, UserRect& UpdateRect, BOOL IsBackground) { // Override me if you want! // Note that overriding this function implies that you will ensure the redraw of the rulers // as you enter and leave your tool. } /******************************************************************************************** > virtual BOOL Tool_v1::GetRulerStatusLineText(String_256* pText, UserCoord PointerPos, Spread* pSpread, RulerBase* pRuler) Author: Martin Wuerthner Created: 25/07/2006 Inputs: PointerPos - user coordinates of click on ruler (relative to origin set by tool) pSpread - pointer to spread upon which click occurred pRuler - pointer to ruler which generated click Outputs: pText - status line text set (if return value is TRUE) Returns: TRUE if the text has been set Purpose: Gives the current tool the chance to change the status line text displayed for the ruler ********************************************************************************************/ BOOL Tool_v1::GetRulerStatusLineText(String_256* pText, UserCoord PointerPos, Spread* pSpread, RulerBase* pRuler) { // Override me if you want! return FALSE; } /******************************************************************************************** > virtual BOOL Tool_v1::OnRulerClick( DocCoord PointerPos, ClickType Click, ClickModifiers Mods, Spread* pSpread ) Author: Phil_Martin (Xara Group Ltd) Created: 30/Jun/2006 Inputs: PointerPos - user coordinates of click on ruler (relative to origin set by tool) Click - Type of click enum Mods - Modifier flags struct pSpread - pointer to spread upon which click occurred pRuler - pointer to ruler which generated click Outputs: - Returns: TRUE if this click event was handled FALSE if not Purpose: Gives the current tool the chance to handle ruler clicks in preference to other handlers ********************************************************************************************/ BOOL Tool_v1::OnRulerClick( UserCoord PointerPos, ClickType Click, ClickModifiers Mods, Spread* pSpread, RulerBase* pRuler ) { // Override me if you want! return FALSE; } /******************************************************************************************** > virtual void Tool_v1::CurrentDocViewChange() Author: Justin_Flude (Xara Group Ltd) Created: 10/12/93 Inputs: - Outputs: - Returns: - Purpose: Called for the currently-selected tool when the current DocView changes. Errors: - SeeAlso: - ********************************************************************************************/ //void Tool_v1::CurrentDocViewChange() //{ // // Override me! //} /******************************************************************************************** > virtual void SelectedDocViewChange() Author: Justin_Flude (Xara Group Ltd) Created: 10/12/93 Inputs: - Outputs: - Returns: - Purpose: Called when the selected DocView changes, ie. the user has moved the focus to another document view window. Errors: - SeeAlso: - ********************************************************************************************/ //void Tool_v1::SelectedDocViewChange() //{ // // Override me! //} /******************************************************************************************** > void Tool_v1::UpdateInfoBar() Author: Tim_Browse (Xara Group Ltd) Created: 12/11/93 Purpose: Allows the Tool to update the info bar according to its internal settings and values. Usually called when the info bar is first created and when a new tool becomes selected. ********************************************************************************************/ /* Removed by MarkN 25/7/94 void Tool_v1::UpdateInfoBar() { } */ /******************************************************************************************** > void Tool_v1::HandleInfoBarMessage(CDlgMessage Message, CGadgetID ID) Author: Tim_Browse (Xara Group Ltd) Created: 13/11/93 Inputs: Message - the message (see kernel\dlgtypes.h). ID - the ID of the dialog gadget that generated the message. Purpose: Allows the tool to handle UI events from the info bar. It is similar to the DialogOp::HandleMessage function. SeeAlso: DialogOp::HandleMessage ********************************************************************************************/ // Removed by MarkN 25/7/94 //void Tool_v1::HandleInfoBarMessage(CDlgMessage /* Message*/, CGadgetID /*ID*/) //{ //} /******************************************************************************************** > static ToolListItem* Tool::GetFirstTool() Author: Mario_Shamtani (Xara Group Ltd) Created: 19/8/93 Returns: A pointer to the first tool if list is not empty and NULL otherwise Purpose: returns the first Tool in the list ********************************************************************************************/ ToolListItem* Tool::GetFirstTool() { if (Tool::Tools) return (ToolListItem*) Tool::Tools->GetHead(); else return NULL; } /******************************************************************************************** > static ToolListItem* Tool::GetNextTool( ToolListItem* CurrTool ) Author: Mario_Shamtani (Xara Group Ltd) Created: 19/8/93 Inputs: pointer to last Tool return by GetFirst ot GetNextDescriptor Returns: A pointer to the first tool if list is not empty and NULL otherwise Purpose: return the next Tool in the list ********************************************************************************************/ ToolListItem* Tool::GetNextTool( ToolListItem* CurrTool ) { if (Tool::Tools) return (ToolListItem*) Tool::Tools->GetNext( CurrTool ); else return NULL; } // these two static functions used to be in-lines. They were'nt commented in there either /******************************************************************************************** > Tool *Tool::GetCurrent() Author: Andy_Pennell (Xara Group Ltd) Created: 19/10/94 Returns: A pointer to the current tool, or NULL if there isn't one. Purpose: Determine the current tool. Scope: Public static ********************************************************************************************/ Tool *Tool::GetCurrent() { return Current; } /******************************************************************************************** > void Tool::SetNoCurrent() Author: Andy_Pennell (Xara Group Ltd) Created: 19/10/94 Purpose: Sets no tool as the current tool. Scope: Public static ********************************************************************************************/ void Tool::SetNoCurrent() { if (Current) { Current->SelectChange(FALSE); } Current = NULL; } /******************************************************************************************** > UINT32 Tool::GetCurrentID() Author: Andy_Pennell (Xara Group Ltd) Created: 19/10/94 Returns: The ID of the current tool, or 0 if none is selected. Purpose: Determine the current tool. Scope: Public static ********************************************************************************************/ UINT32 Tool::GetCurrentID() { if (Current) return Current->GetID(); else return 0; }