示例#1
0
OpState	OpBreakAtPoints::GetState(String_256* UIDescription, OpDescriptor*)
{

	OpState OpSt;
	String_256 DisableReason; 

   	OpSt.Greyed = FALSE;
	BOOL FoundSelected = FALSE;

	// Go through the selection until we find a selected point

	SelRange* Selected = GetApplication()->FindSelection();
	Node* pNode = Selected->FindFirst();

	while (pNode)
	{
		if (IS_A(pNode,NodePath) || IS_A(pNode,NodeBlendPath))
		{
			NodePath* pNodePath = (NodePath*)pNode;
			INT32 NumSplinters = pNodePath->InkPath.NumSplinters();

			if (NumSplinters > 0)
			{
				// We need to ask the effected nodes if they (and their parents) can handle this node being replaced
				ObjChangeFlags cFlags;

				if (NumSplinters > 1)
					cFlags.MultiReplaceNode = TRUE;	// Node will be replaced with more than one node.
				else
					cFlags.ReplaceNode = TRUE;		// Node will be replaced with one node only.

				String_32 optokenstring(OPTOKEN_BREAKATPOINTS);
				ObjChangeParamWithToken ObjChange(OBJCHANGE_STARTING,cFlags,pNodePath,NULL,&optokenstring);

				// Will the node allow this op to happen?
				if (pNodePath->AllowOp(&ObjChange,FALSE))
				{
					FoundSelected = TRUE;
					break;
				}
			}
		}
		pNode = Selected->FindNext(pNode);
	}

	// The operation is disabled if there are no complex paths selected

	if (!FoundSelected)
	{
		OpSt.Greyed = TRUE;
		DisableReason = String_256(_R(IDS_NEEDS_SELECTED_POINT));
		*UIDescription = DisableReason;
	}
	
	return(OpSt);   
}
示例#2
0
BOOL ViewContextMenu::AskBlobsForItems( Spread* pSpread,
										DocCoord ClickPos,
										ClickModifiers ClickMods
										)
{
	// Test for a click on a fill attribute first, as they aren't NodeRenderableInks, and so
	// won't be included in the tests below.
//	if (AttrFillGeometry::CheckAttrClick(ClickStart, TypeOfClick, ClickMods, StartSpread))
//	{
//		return TRUE;
//	}

	// Look for a selected object to pass the click to.
	SelRange* pSel = GetApplication()->FindSelection();
	if (pSel==NULL)
		return FALSE;

	Node* pNode = pSel->FindFirst();
	if (pNode == NULL)
		return FALSE;

	// Providing we are displaying object blobs, try passing the click on to each object
	// in the selection.
	BlobManager* pBlobs = GetApplication()->GetBlobManager();
	if (pBlobs && pBlobs->GetCurrentInterest().Object)
	{
		// For all selected objects . . .
		while (pNode != NULL)
		{
			// Is this node ink-renderable?
			if (pNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)))
			{
				// Yes.  Does it want the click?
				if (((NodeRenderableInk*) pNode)->OnBlobPopUp(pSpread, ClickPos, this))
				{
					// An object processed the click, so indicate that there's no more to do.
					return TRUE;
				}
			}

			// Try the next object in the selection.
			pNode = pSel->FindNext(pNode);
		}
	}

	return FALSE;
}
示例#3
0
OpState OpReversePath::GetState (String_256* Description, OpDescriptor*)
{
	OpState OpSt;

 	SelRange*	Selected = GetApplication ()->FindSelection ();

	if ((Document::GetSelected () == NULL) || (Selected == NULL) )
	{	// There is no selected document or selrange is invalid 
		OpSt.Greyed = TRUE;
	   	return (OpSt);
	}

	if (Selected->Count () == 0)	// if there ain't no selection - return cause we ain't
									// going to be reversing anything
	{
		OpSt.Greyed = TRUE;
	   	return (OpSt);
	}

	Node* pNode = Selected->FindFirst ();

	// scan the selection and if even a single DoThisNode fails, then return that the op
	// is greyed immediately ....

	while (pNode != NULL)
	{	// we're only interested in NodePaths which have selected points
		BOOL DoThisNode = pNode->IsNodePath ();
		//if (DoThisNode)
		//	DoThisNode = (((NodePath*)pNode)->InkPath.IsSubSelection());
		if (DoThisNode)
			DoThisNode = (((NodePath*)pNode)->IsPathAllowable ());

		if (DoThisNode)
		{
			pNode = Selected->FindNext (pNode);
		}
		else
		{
			pNode = NULL;
			OpSt.Greyed = TRUE;
		}
	}

	return (OpSt);
}
示例#4
0
/********************************************************************************************
>	BOOL OpMenuSelectPathPoints::DoAction(BOOL SelectPoints)

	Author:		Peter_Arnold (Xara Group Ltd) <*****@*****.**>
	Created:	30/04/95
	Inputs:		SelectPoints - TRUE to select all the points in the path
							 - FALSE to deslect all the points in the path
	Outputs:	-
	Returns:	TRUE/FALSE for success/failure		    
	Purpose:	Common code for selecting or deselecting all the points in all the selected
				paths.
	SeeAlso:	-
********************************************************************************************/
BOOL OpMenuSelectPathPoints::DoAction(BOOL SelectPoints)
{
	SelRange* pSelection = GetApplication()->FindSelection();
	Node* pNode = pSelection->FindFirst();

	// Cycle through all the selected paths
	while (pNode != NULL)
	{
		if (pNode->IsNodePath())
		{
			NodePath* pPath = (NodePath*)pNode;
			Spread* pSpread = pNode->FindParentSpread();
			ERROR2IF(pSpread == NULL, FALSE, "NodePath didn't have a parent spread");

			// Remove the blobs from the path
			RenderRegion* pRegion = DocView::RenderOnTop(NULL, pSpread, ClippedEOR);
			while (pRegion != NULL)
			{
				pPath->RenderObjectBlobs(pRegion);
				pRegion = DocView::GetNextOnTop(NULL);
			}
			
			// Set the selection state
			const INT32 NumCoords = pPath->InkPath.GetNumCoords();
			for (INT32 loop = 0; loop<NumCoords; loop++)
			{
				pPath->InkPath.GetFlagArray()[loop].IsSelected = SelectPoints;
			}

			// Put the blobs back on the path
			pRegion = DocView::RenderOnTop(NULL, pSpread, ClippedEOR);
			while (pRegion != NULL)
			{
				pPath->RenderObjectBlobs(pRegion);
				pRegion = DocView::GetNextOnTop(NULL);
			}

			GetApplication()->UpdateSelection();
		}

	 	pNode = pSelection->FindNext(pNode);
	}

	return TRUE;
}	
示例#5
0
文件: selstate.cpp 项目: vata/xarino
void SelectionState::Restore(BOOL RestoreSelBlobs, BOOL RemoveBlobs) 	     	
{
	DeselectAll(RemoveBlobs); // Deselect all selections

	#ifdef _DEBUG
	UINT32 NumRestored = 0; 	 
	#endif

	 
    // ----------------------------------------------------------------------------------
	// Restore all nodes in the SelNdList
	
	UINT32 i; 

	for (i=0; i < NumNd; i++)
	{
		// Only NodeRenderableInk nodes should be selected
		ENSURE(SelNdList[i]->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)), 
			   "Node to be selected is not a NodeRenderableInk");
			    
		// Ensure node to be selected is not already selected                                
		//ENSURE(!(SelNdList[i]->IsSelected()), "Invalid selected node"); 

		// Select the node 
		SelNdList[i]->SetSelected(TRUE); 
		#ifdef _DEBUG
		NumRestored++; 	 
		#endif	
	}
	   
	// ----------------------------------------------------------------------------------
	// Restore all nodes in the SelNdRngList	  

	Node* Current; 
	   
	for (i=0; i < NumNdRng; i++) 
	{  
		// A SelNdRng shold represent at least two contiguous selected nodes
		ENSURE(SelNdRngList[i].NumSelected >= 2, "Number of nodes in SelNdRng < 2");    

		UINT32 NumNodesSelected = 0; 
		Current = SelNdRngList[i].FirstNode; // First node in range 
		
		// Select the next SelNdRng->NumSelected nodes
		do  
		{   
			ENSURE((Current != NULL), "Node in a SelNdRng is NULL, Has tree changed ?" );  
			// Only NodeRenderableInk nodes should be selected   
			
			ENSURE(Current->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)), 
				   "Selected node is not a NodeRenderableInk"); 

			// [Phil, 11/10/2005] The Current node may be a Caret node
			// because Carets are included in the selection, even when
			// a sub-selection of characters is present, so that attributes
			// optimise correctly within the text story
			// However, the Record function treats them as single selected
			// nodes, not part of a contiguous run of selected nodes to
			// allow for them moving around...
			// So we should ignore carets here
			if (!IS_A(Current, CaretNode))
			{
				// Ensure SelNode not already selected  
				ENSURE(!(Current->IsSelected()), "Invalid selected node");

				Current->SetSelected(TRUE); 	// Set the nodes selected flag
				NumNodesSelected++;
#ifdef _DEBUG
				NumRestored++; 	 
#endif	
			}
			Current = Current->FindNextNonHidden();  
		}
		while (NumNodesSelected != SelNdRngList[i].NumSelected); 
	}

#if !defined(EXCLUDE_FROM_RALPH)
	// Only restore the blobs if any selections have been restored
	if (((NumNdRng != 0) || (NumNd !=0)) && RestoreSelBlobs)	// We need to restore the selection blobs 
	{
		// Find the current selections 
		SelRange* pSel; 
		pSel = GetApplication()->FindSelection();
 
		Current = pSel->FindFirst(); // The first selected node 

		Spread *pSpread = NULL;
		if (Current != NULL)
			pSpread = Current->FindParentSpread();

//		ENSURE(pSpread != NULL, "First selected node does not have a parent spread");
		// It's a legal state to not find a selected node - the layers may all be locked.
		if (pSpread == NULL)
		{
			AttrFillGeometry::LastRenderedMesh = NULL;
			return;
		}

		// Go get the blob manager
		BlobManager* BlobMgr = GetApplication()->GetBlobManager();
		ENSURE( BlobMgr!=NULL, "Blob Manger was not there when we needed him!");
		if (BlobMgr==NULL)
			return;

	    Current = pSel->FindFirst();   // The first selected node 

		while (Current != NULL)
		{
			ENSURE(Current->IsSelected(), "Node not selected"); 
			ENSURE(Current->IsKindOf(CC_RUNTIME_CLASS(NodeRenderable)), 
					"Selected Node not a NodeRenderable"); 

			// Tell the node to add selection blobs
			BlobMgr->RenderMyBlobsOn(NULL, pSpread, (NodeRenderable*)Current);
			
			Current = pSel->FindNext(Current); 	// Get next selected node 
		}

		Tool* pTool = Tool::GetCurrent();
			
		// Get the tool to remove all its blobs before we deselect the nodes.
		// Only do this if the current tool dosent update itself on sel changed messages
		if (pSpread!=NULL && pTool!=NULL && !pTool->AreToolBlobsRenderedOnSelection())
			pTool->RenderToolBlobs(pSpread,NULL);

		AttrFillGeometry::LastRenderedMesh = NULL;
	}
#endif
	
	#ifdef _DEBUG
	//if (IsUserName("Simon"))
	//	TRACE( _T(" Num Restored = %lu\n"), NumRestored);  
	#endif	
	 
}  
示例#6
0
文件: selstate.cpp 项目: vata/xarino
BOOL SelectionState::Record() 	     	 
{   
	// Make sure that Record has not been called before     
	ENSURE(((SelNdList == NULL) && (SelNdRngList == NULL)), "SelectionState::Record called twice"); 
	
	// Find the current selections 
	SelRange* pSel; 
	pSel = GetApplication()->FindSelection();

	Node* StartRange;

	UINT32 SelNdRngListIndex = 0; 
	UINT32 SelNdListIndex = 0; 

	UINT32 NumSelectedNodes = pSel->Count(); 

	if (NumSelectedNodes != 0)
	{

		// At this point we don't know exactly how much memory to allocate for the SelNdRngList
		// and SelNdList. So we allocate two temporary arrays which are more than big enough to
		// store the selection state. When we have completed recording the selection state into 
		// these temporary arrays, we know how big the SelNdRngList and SelNdList should
		// be. so we can allocate memory for these and then copy the data from the temporary 
		// arrays into them.  

		SelNdRng* SelNdRngListTmp = new SelNdRng[NumSelectedNodes];  
	

		if (SelNdRngListTmp == NULL)
		{
			return FALSE; 
		}
	 
		Node** SelNdListTmp = new Node*[NumSelectedNodes]; 		  

		if (SelNdListTmp == NULL)
		{
			delete[] SelNdRngListTmp; 	// Tidy up 
			return FALSE; 
		}

		// Get the first selected node in the tree
		Node * Current = pSel->FindFirst(); 
		Node* Last; 

		BYTE NumAdjacentSel; 			  // Number of contiguous selected nodes   
	
		#ifdef _DEBUG   
		UINT32 NumSel = 0; 
		#endif
	
		// always use the selection object to determine next node to store... this fixes bug #10775 whereby
		// selected Bevel,Contour & Shadow objects were not being restored on Undo
		while (Current != NULL)
		{   
			// At this point Current will always point to the next selected node which needs 
			// recording.      
			// Only NodeRenderableInk nodes should be selected
			ENSURE(Current->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)), 
					"A non NodeRenderableInk node is selected"); 
		
			NumAdjacentSel = 1;    
		
			#ifdef _DEBUG   
			NumSel++;  
			#endif
		        
			StartRange = Current; 
			Last = Current;  
			Current = pSel->FindNext(Current); //next from selection
		
			// if we have at least two contiguous nodes, store as a range
			if (Current && AreContiguous(Last, Current) && !IS_A(Last, CaretNode) && !IS_A(Current, CaretNode))
			{
				SelNdRngListTmp[SelNdRngListIndex].FirstNode = StartRange;   
				do
				{
					if (IS_A(Current, CaretNode))
					{
						// Give Caret it's own selection record but don't break the contiguous range
						SelNdListTmp[SelNdListIndex] = Current;
						SelNdListIndex++; 
						#ifdef _DEBUG   
						NumSel++;  
						#endif
					}
					else
					{
						NumAdjacentSel++; 
						#ifdef _DEBUG   
						NumSel++;  
						#endif
					}
					Last = Current; 
					Current = pSel->FindNext(Current);
	                if (Current == NULL)
	                   	break; 
				} while ((AreContiguous(Last,Current)) && (NumAdjacentSel < 255));      
				// Either there are no more contiguous selected nodes or 
				// we have hit the maximum number of selected nodes that a SelNdRng can 
				// represent.  
				SelNdRngListTmp[SelNdRngListIndex].NumSelected = NumAdjacentSel; 
				SelNdRngListIndex++;
			}
			else  // Store node in the SelNdLst 
			{
				ERROR3IF(StartRange==NULL, "Trying to add NULL pointer to SelNdList\n");
				SelNdListTmp[SelNdListIndex] = StartRange; 
				SelNdListIndex++; 
			}    
		}       
		ERROR3IF(NumSel!=NumSelectedNodes,"Incorrect selection state stored!");
	
		NumNd = SelNdListIndex; 
		NumNdRng = SelNdRngListIndex; 

		if (SelNdRngListIndex != 0) 
		{
			// We have created at least one SelNdRange
	 		SelNdRngList = new SelNdRng[NumNdRng];  
			if (SelNdRngList == NULL)			// Out of memory 
			{
				// Delete the two temporary lists
				delete [] SelNdRngListTmp; 
				delete [] SelNdListTmp; 
				return FALSE; 
			}
		
			// Copy the SelNdRngListTmp to the SelNdRngList  
			memcpy(SelNdRngList, SelNdRngListTmp, sizeof(SelNdRng)*NumNdRng); 
		}

		delete[] SelNdRngListTmp; // No longer required
	
	
		if (SelNdListIndex != 0)
		{
			SelNdList = new Node*[NumNd]; 
			if (SelNdList == NULL)				 // Out of memory 
			{
				delete [] SelNdListTmp; 
				if (SelNdRngList != NULL)		 // We allocated the SelNdRng list
				{
					delete [] SelNdRngList; 
				}
				return FALSE; 
			}
			// copy the SelNdListTmp to the SelNdList 
			memcpy(SelNdList, SelNdListTmp, sizeof(Node*)*NumNd); 
		} 

		delete[] SelNdListTmp; // No longer required
	 
		#ifdef _DEBUG   
		//if (IsUserName("Simon"))
			//TRACE( _T("Number of nodes selected = %lu\n"), NumSel); 
		#endif
	}
	return (TRUE);  
}     
示例#7
0
/********************************************************************************************
>	void OpBaseConvertPathSegment::Do(OpDescriptor*)

	Author:		Peter_Arnold (Xara Group Ltd) <*****@*****.**>
	Created:	16/8/95
	Inputs:		OpDescriptor (unused)
	Purpose:	Performs the common SelRange scanning part of converting path segments.  Calls
				the ProcessSegment function in derived classes to do the actual processing
	Errors:		-
	SeeAlso:	-
********************************************************************************************/
void OpBaseConvertPathSegment::Do(OpDescriptor*)
{   
#ifndef STANDALONE

	// Obtain the current selections and the first node in the selection
	SelRange* Selected = GetApplication()->FindSelection();
	BOOL ok = (Selected != NULL);

	// Start the op
	BeginSlowJob();
	if (ok)
		ok = DoStartSelOp(TRUE,TRUE);

	// Check with the selrange it is ok to run this op
	ObjChangeFlags cFlags;
	ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this);
	if (ok)
	{
		if (!Selected->AllowOp(&ObjChange))
		{
			EndSlowJob();
			FailAndExecute();
			End();
			return;
		}
	}

	Node* pNode = Selected->FindFirst();
	NodePath* ThisPath = NULL;

	while (ok && (pNode != NULL))
	{	// we're only interested in NodePaths which have selected points
		BOOL DoThisNode = pNode->IsNodePath();
		if (DoThisNode)
			DoThisNode = (((NodePath*)pNode)->InkPath.IsSubSelection());
		if (DoThisNode)
			DoThisNode = (((NodePath*)pNode)->IsPathAllowable());

		if 	( DoThisNode )
		{
			// for convenience, cast the pointer to a pointer to a NodePath
			ThisPath = (NodePath*)pNode;

			// First get pointers to the arrays
			PathVerb* Verbs = NULL;
			PathFlags* Flags = NULL;
			DocCoord* Coords = NULL;
			ThisPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
			INT32 NumCoords = ThisPath->InkPath.GetNumCoords();
			BOOL PrevSelected = FALSE;
			INT32 PrevPos = 0;

			// Set the NeedToRender flags
			INT32		loop;
			for (loop = 0; loop < NumCoords; loop++)
			{
				if (Flags[loop].IsEndPoint && Flags[loop].IsSelected)
					Flags[loop].NeedToRender = TRUE;
				else
					Flags[loop].NeedToRender = FALSE;
			}

			// Force a re-draw of the place where the path used to be
			if (ok)
				ok = (RecalcBoundsAction::DoRecalc(this, &UndoActions, ThisPath, TRUE) != AC_FAIL);

			// loop through the points
			for (loop = 0; loop<NumCoords; loop++)
			{
				if (Flags[loop].IsEndPoint)
				{	// its an endpoint
					if (Flags[loop].IsSelected)
					{	// which is selected
						if (PrevSelected && ((Verbs[loop] & ~PT_CLOSEFIGURE) == GetProcessPathType()) )
						{	//  and the previous was selected and it's a processable segment
							if (ok)
								ok = ProcessSegment(ThisPath, &loop, PrevPos);
							// Recache array pointers
							ThisPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
							NumCoords = ThisPath->InkPath.GetNumCoords();
							Flags[loop].NeedToRender = TRUE;
						}
						PrevSelected = TRUE;
						PrevPos = loop;
					}
					else
						PrevSelected = FALSE;
				}
			}

			// Having finished processing this path go round and smooth it.
			DocCoord NewCoord;
			for (loop = 0; (ok && (loop < NumCoords)); loop++)
			{
				if (Verbs[loop] == PT_BEZIERTO && !(Flags[loop].IsEndPoint) && Flags[loop].IsSmooth)
				{
					NewCoord = ThisPath->InkPath.SmoothControlPoint(loop);
					if (ok && (NewCoord != Coords[loop]))
					{
						ok = DoAlterPathElement(ThisPath, loop, NewCoord, Flags[loop], Verbs[loop], FALSE);
						ThisPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
					}
				}
			}

			ThisPath->InvalidateBoundingRect();

			// Force a redraw of the place where the path is now.
			if (ok)
				ok = (RecordBoundsAction::DoRecord(this, &UndoActions, ThisPath, TRUE) != AC_FAIL);
		}
		pNode = Selected->FindNext(pNode);
	}

	if (ok)
	{
		ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,this);
		if (!UpdateChangedNodes(&ObjChange))
		{
			FailAndExecute();
			End();
			return;
		}
	}

	EndSlowJob();

	if (!ok)
	{	
		FailAndExecute();
		InformError();
	}

#endif

	End();
}
示例#8
0
void OpReversePath::Do (OpDescriptor*)
{
	// Obtain the current selections and the first node in the selection
	SelRange* Selected = GetApplication()->FindSelection();
	BOOL ok = (Selected != NULL);

	// Start the op
	BeginSlowJob();
	if (ok)
		ok = DoStartSelOp(TRUE,TRUE);

	// Check with the selrange it is ok to run this op
	ObjChangeFlags cFlags;
	ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this);
	if (ok)
	{
		if (!Selected->AllowOp(&ObjChange))
		{
			EndSlowJob();
			FailAndExecute();
			End();
			return;
		}
	}

	Node* pNode = Selected->FindFirst();
	NodePath* ThisPath = NULL;

	//Document* pDocument = GetWorkingDoc();

	while (ok && (pNode != NULL))
	{	// we're only interested in NodePaths which have selected points
		BOOL DoThisNode = pNode->IsNodePath();
		//if (DoThisNode)
		//	DoThisNode = (((NodePath*)pNode)->InkPath.IsSubSelection());
		if (DoThisNode)
			DoThisNode = (((NodePath*)pNode)->IsPathAllowable());

		if 	( DoThisNode )
		{
			// for convenience, cast the pointer to a pointer to a NodePath
			ThisPath = (NodePath*)pNode;

			// First get pointers to the arrays
			PathVerb* Verbs = NULL;
			PathFlags* Flags = NULL;
			DocCoord* Coords = NULL;
			ThisPath->InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
			INT32 NumCoords = ThisPath->InkPath.GetNumCoords();
//			BOOL PrevSelected = FALSE;
//			INT32 PrevPos = 0;

			ObjChangeFlags cFlags;
			cFlags.TransformNode = TRUE;
			ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,ThisPath,this);
			if (!ThisPath->AllowOp(&ObjChange, TRUE))
			{
				return;
			}

			// Set the NeedToRender flags
			for (INT32 loop = 0; loop < NumCoords; loop++)
			{
				if (Flags[loop].IsEndPoint && Flags[loop].IsSelected)
					Flags[loop].NeedToRender = TRUE;
				else
					Flags[loop].NeedToRender = FALSE;
			}

			// Force a re-draw of the place where the path used to be
			if (ok)
				ok = (RecalcBoundsAction::DoRecalc(this, &UndoActions, ThisPath, TRUE) != AC_FAIL);

			DoReversePath (ThisPath);

			// Force a redraw of the place where the path is now.
			if (ok)
				ok = (RecordBoundsAction::DoRecord(this, &UndoActions, ThisPath, TRUE) != AC_FAIL);
		}
		pNode = Selected->FindNext(pNode);
	}

	if (ok)
	{
		ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,this);
		if (!UpdateChangedNodes(&ObjChange))
		{
			FailAndExecute();
			End();
			return;
		}
	}

	EndSlowJob();

	if (!ok)
	{	
		FailAndExecute();
		InformError();
	}

	End();
}
示例#9
0
BOOL ViewContextMenu::BuildOverView(Spread* pSpread, DocCoord ClickPos, ClickModifiers ClickMods)
{
	ERROR2IF(pSpread==NULL,FALSE,"BuildOverView passed NULL spread pointer");

	BOOL ok = TRUE;

	//---------------------------------------------//
	// First ask selected nodes if they want to supply items and if so show the blob menu...
	if (AskBlobsForItems(pSpread, ClickPos, ClickMods))
	{
		// If they supply items then we won't add the normal items about the selection
		return TRUE;
	}

	//---------------------------------------------//
	// Find what the click was on and show the object menu...
//	NodeRenderableInk* pHitNode = NodeRenderableInk::FindSimpleAtPoint(pSpread, ClickPos);

	NodeRenderableInk* pHitNode = FindNodeAtPoint(pSpread,ClickPos);
	if (pHitNode)
	{
		BOOL HitNodeIsGuideline = IS_A(pHitNode,NodeGuideline);

		if (!HitNodeIsGuideline)		// BODGE so that guidelines (which can't be selected) can have a pop-up menu
		{
			// Now find out if there's just one node selected and if so ask it for some items...
			SelRange* pSel = GetApplication()->FindSelection();
			if (pSel!=NULL)
			{
				Node* pNode = pSel->FindFirst();
				if (pNode && pSel->FindNext(pNode) == NULL)
				{
					// There's only one object selected so let's ask it about itself...
					((NodeRenderableInk*) pNode)->OnNodePopUp(pSpread, ClickPos, this);
				}
			}
		}
		else
			pHitNode->OnNodePopUp(pSpread, ClickPos, this);

		if (!HitNodeIsGuideline)		// BODGE to stop guideline pop-up menus having irrelevant menu items
		{
			// Build the rest of the standard object menu...
			// Effect commands
			ok = ok && BuildEffectCommands();
			// Edit commands
			ok = ok && BuildTransferCommands(TRUE);
			// Arrange commands
		//	WEBSTER-ranbirr-13/11/96
//	#ifndef WEBSTER
			ok = ok && BuildCommand(OPTOKEN_MAKE_SHAPES);
//	#endif //webster
			ok = ok && BuildCommand(OPTOKEN_CONVERTTOBITMAP);
	// WEBSTER-ranbirr-13/11/96
	// Now Taken out by vector stroking code Neville 2/10/97
	#ifdef VECTOR_STROKING
		//	ok = ok && BuildCommand(OPTOKEN_MAKE_STROKE);
	#endif // VECTOR_STROKING
			ok = ok && BuildCommand(OPTOKEN_COMBINESHAPES,TRUE);
			MenuItem* pCombineRoot = GetLastItem();
	//	WEBSTER-ranbirr-13/11/96
//	#ifndef WEBSTER
				ok = ok && BuildCommand(OPTOKEN_ADDSHAPES, FALSE, pCombineRoot);
				ok = ok && BuildCommand(OPTOKEN_SUBTRACTSHAPES, FALSE, pCombineRoot);
				ok = ok && BuildCommand(OPTOKEN_INTERSECTSHAPES, FALSE, pCombineRoot);
				ok = ok && BuildCommand(OPTOKEN_SLICESHAPES, FALSE, pCombineRoot);
//	#endif //webster

	#ifndef WEBSTER
			// Imagesetting submenu
			ok = ok && BuildCommand(OPTOKEN_IMAGESETTING, TRUE);
			pCombineRoot = GetLastItem();
				ok = ok && BuildCommand(OPTOKEN_OVERPRINTFILL,	  FALSE, pCombineRoot);
				ok = ok && BuildCommand(OPTOKEN_OVERPRINTLINE,	  TRUE,  pCombineRoot);
				ok = ok && BuildCommand(OPTOKEN_PRINTONALLPLATES, FALSE, pCombineRoot);
	#endif //webster
			// Utils commands
			ok = ok && BuildCommand(OPTOKEN_WEBADDRESSDLG);
			ok = ok && BuildCommand(OPTOKEN_COLOUREDITDLG, TRUE);
PORTNOTE("other", "Removed brush edit dialog from popup menu")
#ifndef EXCLUDE_FROM_XARALX
			ok = ok && BuildCommand(OPTOKEN_BRUSHEDIT_DLG);
#endif
			ok = ok && BuildCommand(OPTOKEN_SELECTBRUSH);
		}

		return ok;
	}

	//---------------------------------------------//
	// If on white space then show the white space menu...
	// Window commands
//	MENUITEM OPTOKEN_TOOLBARDLG
//		MENUITEM OPTOKEN_VIEWCOLOURBAR		
//		MENUITEM OPTOKEN_VIEWSTATUSBAR
//		MENUITEM OPTOKEN_VIEWSCROLLBARS
//	WEBSTER-ranbirr-13/11/96
#ifndef WEBSTER
	ok = ok && BuildCommand(OPTOKEN_WINDOWNEWVIEW);
	ok = ok && BuildCommand(OPTOKEN_VIEWFULLSCREEN,TRUE);
#else
	ok = ok && BuildCommand(OPTOKEN_WINDOWNEWVIEW,TRUE);
#endif //webster

	// Paste option - we don't need to do the
	// BuildTransferCommands as the Cut and Copy operations
	// are never applicable here...	matt-23/08/2000
	ok = ok && BuildCommand(OPTOKEN_PASTE, TRUE);

	// View quality
	ok = ok && BuildCommand(OPTOKEN_WINDOWQUALITY,FALSE);
	MenuItem* pQualityRoot = GetLastItem();
	ok = ok && BuildCommand(OPTOKEN_QUALITYANTIALIASED, FALSE, pQualityRoot);
	ok = ok && BuildCommand(OPTOKEN_QUALITYNORMAL, FALSE, pQualityRoot);
	ok = ok && BuildCommand(OPTOKEN_QUALITYSIMPLE, FALSE, pQualityRoot);
	ok = ok && BuildCommand(OPTOKEN_QUALITYOUTLINE, FALSE, pQualityRoot);
	// View commands
//	WEBSTER-ranbirr-13/11/96
#ifndef WEBSTER
	ok = ok && BuildCommand(OPTOKEN_SHOWGRID);
	ok = ok && BuildCommand(OPTOKEN_SHOWGUIDES,TRUE);
#else
	ok = ok && BuildCommand(OPTOKEN_SHOWGRID,TRUE);
#endif //webster
//	WEBSTER-ranbirr-13/11/96
#ifndef WEBSTER
	ok = ok && BuildCommand(OPTOKEN_SNAPTOGRID);
	ok = ok && BuildCommand(OPTOKEN_SNAPTOGUIDES);
	ok = ok && BuildCommand(OPTOKEN_SNAPTOOBJECTS,TRUE);
#else
	ok = ok && BuildCommand(OPTOKEN_SNAPTOGRID,TRUE);
#endif //webster
	ok = ok && BuildCommand(OPTOKEN_DELETEPAGEBACKGROUND);
	// Page commands (almost "Properties...")
	ok = ok && BuildCommand(OPTOKEN_PAGESIZEDLG);

	return ok;
}