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

	SampleObjectTool.cpp
	
	Copyright © 2001 Nemetschek North America
	All Rights Reserved.
************************************************************/

#include <VWSDK.h>
#include "MCCoordTypes.h"
#include "CustomObjects.h"
#include <GSString.h>

// Constants
const short kPrefType 			= 1;		// mode-bar group number
const short kPrefMode 			= 1;		// mode-bar button number
const short kPrefModeIconID 	= 11004;	// mode-bar button icon id

// Define a structure we can use to remember data between calls.
struct SampleUserData {
	Str255 objectName;
};


//------------------------------------------------------------
#if GS_WIN || GS_MAC_MACHO
extern "C" long GS_EXTERNAL_ENTRY plugin_main(long action, long message1, long message2, long &userData, CallBackPtr cbp)
#elif GS_MAC_CFM
extern "C" long GS_EXTERNAL_ENTRY main(long action, long message1, long message2, long &userData, CallBackPtr cbp)
#endif
{
	GSExternalSetup(cbp);

	long returnVal = 0L;
	
	switch (action) {
		case kToolDisplayContextualHelp:{
			
			TXString* helpIdentifier = (TXString*) message1;
			if (helpIdentifier) {
				*helpIdentifier = "com.yourcompany.help.tool.UNIQUENUMBERHERE";
				return kToolEventHandled;
			}
			break;
		}	
		case kToolInitGlobals : {
		
			//	The workspace that contains this tool is being opened.  This action is called
			//	so the tool can allocate and initialize any persistent data.
			//
			//	Do not allocate data using operator new.  On Windows this memory is disposed when the DLL is unloaded between calls
			//	Use GS_NewPtr(CALLBACKPTR, size_t size) and GS_DisposePtr(CALLBACKPTR, void* p) to allocate
			//	and destroy persistent data.
			
			//	Init the name of the associated Plug-in Object that this tool creates.  Something like "Sample Object".
			void* rawMemory = GS_NewPtr(gCBP, sizeof(SampleUserData));
			if (rawMemory != NULL) {
				SampleUserData* myData = (SampleUserData*) new(rawMemory) SampleUserData();	// construct with 'placement new'

				//GS_GetResourceString(gCBP, 11000, 1, myData->objectName);
				Str63 universalName, localName;
				short version;
				GetCustomObjectName(universalName, localName, version);
				StringCopy(universalName, myData->objectName, sizeof(Str63));	// copy universal name, will be used to create the object later.
				userData = (long)myData;
			}
			else {
				userData = nil;
			}

			break;
		}
		case kToolDisposeGlobals : {
			
			//	The workspace that contains this tool is being closed.  This action is 
			//	called so the tool can free any allocated memory.

			// Destruct explicitly since 'placement new' was used
			if (userData) {
				SampleUserData* myData = (SampleUserData*) userData;
				myData->~SampleUserData();
				GS_DisposePtr(gCBP, myData);
				userData = nil;
			}
			break;
		}
		case kToolDoSetup : {
		
			//	This tool is being made the active tool.
			//	Check the message1 parameter for setUp context.  If message1 == kSetupSetdownPauseRestoreFlag then the
			//	tool is being restored from a temporary pause  If message1 == 0 then the tool is being initially
			//	set up. 

			// Add preference button to mode bar.		
			GS_AddButtonMode(gCBP,kPrefModeIconID);	

			break;
		}
		case kToolDoSetDown : {
	
			//	The tool is being deactivated. VectorWorks is switching the active tool.
			//	Check the message1 parameter for setUp context.  If message1 == kSetupSetdownPauseRestoreFlag then the
			//	tool is being temporarily paused.  If message1 == 0 then the tool is being set down for good.
			break;
		}
		case kToolGetCursor : {

			//	This action is called by the framework to get the cursor for the tool.
			 
			MCObjectHandle overObject = nil; 
			short overPart;
			long code;
			
			GS_TrackTool(cbp, overObject, overPart, code);
			if (overObject)
				returnVal = 147;
			else
				returnVal = 103;
			break;
		}
		case kToolGetStatus: {
			
			//	This action is called so the Tool can return to the system the current state 
			//	of the tool.  Return the result of one of the following callbacks:
			//return	GS_OnePointToolStatus(cbp);			// 	The tool is a one point tool.
			//return		GS_TwoPointToolStatus(cbp);		// 	The tool is a two point tool.
			//return		GS_ThreePointToolStatus(cbp);	// 	The tool is a three point tool.
			//returnVal = GS_PolyToolStatus(cbp);				// 	The tool is a multi - point tool.
			
			//	A tool can also return one of the following constants:
			//	kToolCompleted, kToolCollectingPoints, or kToolWaitingForFirstPoint.
			
			returnVal = GS_OnePointToolStatus(cbp);
			break;
		}
		case kToolPointAdded: {
			
			//	This action is called when the tool gets a mouse down in the content of 
			//	the drawing.  This action is also called for a click drag mouse up.  A tool point
			//	has just been added.
			
			break;
		}
		case kToolPointRemoved: {
			
			//	This action is called whenever the tool framework removes a tool point for 
			//	any reason.  Ue this action to clean up any state that becomes stale with 
			//	the removal of a tool point.
			break;
		}		
		case kToolMouseMove: {
		
			//	This action is called when the tool gets a mouse move in the content of 
			//	the drawing.  If the tool has the screenBasedCursor flag set it gets 
			//	kToolMouseMove action calls whenever the mouse moves a pixel.  If the tool 
			//	does not set the screenBasedCursor flag, it gets called whenever the 
			//	smartcursor snaps to a new point.
			break;
		}
		case kToolDraw: {
			//	This action is called when the tool needs to draw.  The framework calls this draw 
			//	action handling expecting the tool to draw itself.  Tools use the GS_GetToolPt## 
			//	callbacks to determine the current state of the tool and draw itself appropriately.
			
			GS_Default2DToolDraw(cbp);
			break;
		}
		case kToolHandleComplete: {
		
			//	This action is called when the tool has signified, through a kToolGetStatus 
			//	return value, that the tool is complete.  This is where the tool makes changes 
			//	to the drawing.  kToolHandleComplete action handling is the most likely 
			//	location for UNDO callbacks.
			
			// This sample tool will place an instance of an SDK Plug-in Object in the drawing.

			SampleUserData* myData = (SampleUserData*)userData;
			if (myData != NULL) {
				GS_DeselectAll(gCBP);

				// Create multiple-Undo event. (The primitives will be added by internal code.)
				WorldPt where;
				long numPts = GS_GetNumToolPts(gCBP);
				GS_GetToolPt2D(gCBP, numPts - 1, where);	// point index is 0-based.

				GS_SetUndoMethod(gCBP, kUndoSwapObjects);
				//PStr31 undoName;
				//GS_NameUndoEvent(gCBP, undoName);

				// Create a Plug-in Object
				MCObjectHandle theObject = GS_CreateCustomObject(gCBP, myData->objectName, where);	// Create
				if (theObject) {
				}

				// End the multiple-Undo event.
				GS_EndUndoEvent(gCBP);

				if (theObject) {
					GS_SelectObject(gCBP, theObject);	
				}
			}
			break;
		}
		case kToolDoModeEvent : {
		
			//	This action is called when the user invokes a mode bar event.
			//	The argument "message1" indicates which mode group was clicked in, 
			//	and "message2" holds the button in that group that was hit.
			long modeGroup = message1;
			long modeButton = message2;
			switch (modeGroup) {
				case kPrefType:
					{
						SampleUserData* myData = (SampleUserData*)userData;
						if (myData != NULL) {

							// Create multiple-Undo event.
							// The primitives will be added by internal code.
							GS_SetUndoMethod(gCBP, kUndoSwapObjects);
							//GS_NameUndoEvent(gCBP, undoName);
	
							// constants for prefWhen argument defined in MiniCadCallbacks.h.
							MCObjectHandle	parmFormat = GS_DefineCustomObject(gCBP, myData->objectName, kCustomObjectPrefAlways);
	
							// End the multiple-Undo event.
							GS_EndUndoEvent(gCBP);

						}
					}
				default:
					break;
			}

			break;
		}
		case kToolDrawingDoubleClick: {
		
			//	This action is called whenever the user double-clicks in the content of the 
			//	drawing window with more two or more Tool points.
			//
			//	Here we return the GS_PolyToolStatus result.  See kToolGetStatus above.
			if (GS_GetNumToolPts(cbp) == 1)
				returnVal = kToolSwitchToCursor;
			else
				returnVal = kToolCompleted;
			break;
		}
		case kToolDoDoubleClick : {
		
			//	This action is called when the user double-clicks on the tool icon in a 
			//	tool palette.  This is not the same as kToolDrawingDoubleClick above.
			break;
		}
	}

	GSExternalSetdown (0L);

	return returnVal;
}

