/******************************************************************************************** > OpState OpBaseConvertPathSegment::BaseGetState(INT32 PathType) Author: Peter_Arnold (Xara Group Ltd) <*****@*****.**> Created: 16/8/95 Inputs: Type of the path that ends a segment Returns: The tick/grey state of OpBaseConvertPathSegment and derived classes Purpose: For finding the state of this op SeeAlso: OpState ********************************************************************************************/ OpState OpBaseConvertPathSegment::BaseGetState(INT32 PathType) { OpState OpSt; #ifndef STANDALONE SelRange* Selected = GetApplication()->FindSelection(); if ((Document::GetSelected() == NULL) || (Selected == NULL) ) { // There is no selected document or selrange is invalid OpSt.Greyed = TRUE; return OpSt; } Node* pNode = Selected->FindFirst(); BOOL FoundSegment = FALSE; BOOL AllConverted = TRUE; BOOL PrevSelected = FALSE; while ((pNode != NULL) && AllConverted) { if (pNode->IsNodePath() && ((NodePath*)pNode)->IsPathAllowable()) { Path* ThisPath = &(((NodePath*)pNode)->InkPath); PathFlags* Flags = ThisPath->GetFlagArray(); PathVerb* Verbs = ThisPath->GetVerbArray(); INT32 UsedSlots = ThisPath->GetNumCoords(); PrevSelected = FALSE; for (INT32 i=0; i<UsedSlots; i++) { if (Flags[i].IsEndPoint) { if (Flags[i].IsSelected) { if (PrevSelected && ((Verbs[i] & ~PT_CLOSEFIGURE) != PT_MOVETO) ) { FoundSegment = TRUE; if ((Verbs[i] & ~PT_CLOSEFIGURE) != PathType) AllConverted = FALSE; } PrevSelected = TRUE; } else { PrevSelected = FALSE; } } } } pNode = Selected->FindNext(pNode); } OpSt.Greyed = !FoundSegment; OpSt.Ticked = AllConverted && FoundSegment; #endif // #ifdef STANDALONE return OpSt; }
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); }
BOOL NativePrefsDlg::InitDialog () { ERROR2IF ( mpParams == NULL, FALSE, "NativePrefsDlg::InitDialog called after duff initialisation?!" ); //First, do we have a selection? Application *pApp = GetApplication(); ERROR2IF(pApp == NULL, FALSE,"NativePrefsDlg::InitDialog - no application!"); SelRange *pRange = pApp->FindSelection(); ERROR2IF(pRange == NULL, FALSE,"NativePrefsDlg::InitDialog - no selection range!"); DocRect ClipRect = pRange->GetBoundingRect(); BOOL fThereIsASelection=!ClipRect.IsEmpty(); //Now, is there a selection? if (fThereIsASelection) { // Yes. So ungrey both the buttons for selecting the nodes to export. EnableGadget(_R(IDC_NATIVEOPTS_SELECT), TRUE); EnableGadget(_R(IDC_NATIVEOPTS_DRAWING), TRUE); //Now, which of those buttons should be selected? switch ( mpParams->GetExportSel () ) { case SELECTION: // Choose the export pair of buttons. SetLongGadgetValue(_R(IDC_NATIVEOPTS_SELECT), FALSE); SetLongGadgetValue(_R(IDC_NATIVEOPTS_DRAWING), TRUE); break; default: case DRAWING: // Choose the export pair of buttons. SetLongGadgetValue(_R(IDC_NATIVEOPTS_SELECT), TRUE); SetLongGadgetValue(_R(IDC_NATIVEOPTS_DRAWING), FALSE); break; } } else { //No. So grey the SELECTION button and ungrey //the DRAWING button EnableGadget(_R(IDC_NATIVEOPTS_SELECT), FALSE); EnableGadget(_R(IDC_NATIVEOPTS_DRAWING), TRUE); // And we must select the DRAWING button for the export area controls. SetLongGadgetValue(_R(IDC_NATIVEOPTS_SELECT), TRUE); SetLongGadgetValue(_R(IDC_NATIVEOPTS_DRAWING), FALSE); } return TRUE; }
OpState OpNudge::GetState(String_256* UIDescription, OpDescriptor*) { OpState OpSt; SelRange* pSelRange = GetApplication()->FindSelection(); if (pSelRange != NULL && pSelRange->FindFirst() != NULL) OpSt.Greyed = FALSE; else OpSt.Greyed = TRUE; return (OpSt); }
void SelectionState::DeselectAll(BOOL RenderBlobs) { // Find the selected objects in the tree; SelRange* Selected = GetApplication()->FindSelection(); ERROR3IF( Selected==NULL, "Selection object is null in DeselectAll()"); // Get the selected spread Spread* pSpread = Document::GetSelectedSpread(); ERROR3IF(pSpread == NULL,"NULL selected spread"); // Make sure that we have a spread and a selection if (pSpread == NULL || Selected == NULL) return; // Find first selected node #if !defined(EXCLUDE_FROM_RALPH) Node* pFirstSelectedNode = Selected->FindFirst(); // If there is a selection, EOR blobs off, deselect nodes, and inform everybody if (pFirstSelectedNode != NULL && RenderBlobs) { // Go though and render all the EOR blobs off the screen // Find the Blob Manager BlobManager* BlobMgr = GetApplication()->GetBlobManager(); ENSURE( BlobMgr!=NULL, "Blob Manager unexpectedly not there."); // Render all the blobs BlobMgr->RenderOff(NULL, pFirstSelectedNode->FindParentSpread()); 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); } #endif DeselectAll(pSpread->FindFirstChild()); // Selection cache is no longer valid, so update and tell everyone that it has changed // *Note*, This used to be 'Selected->Update(TRUE)', but I (Will) removed the TRUE, so // that a message is NOT broadcast. This should only be called from an operation, // and the op will send a message when it ends. Selected->Update(); }
void LiveEffectsTool::OnMouseMove(DocCoord Coord, Spread* pSpread, ClickModifiers mods) { // Stub out this function if the tool isn't wanted #ifndef NO_ADVANCED_TOOLS // We are interested in any selected paths that the cursor is over // we will also be needing the current docview SelRange* Selected = GetApplication()->FindSelection(); Node* pNode = Selected->FindFirst(); // Check to see if the selection is on the same spread as the mouse if (pNode!=NULL) { // Get the spread and return if it is different from the one with the cursor Spread* pNodeSpread = pNode->FindParentSpread(); if (pNodeSpread!=pSpread) return; } // Find the Blob manager, so we can find out how big a rect to use BlobManager* pBlobMgr = GetApplication()->GetBlobManager(); if (pBlobMgr==NULL) return; // Find the Rect round the mouse pos that counts as a hit DocRect BlobRect; pBlobMgr->GetBlobRect(Coord, &BlobRect); // Work out the square of the distance that we will count as 'close' to the line INT32 Range = BlobRect.Width() / 2; Range *= Range; // // loop through the selection // while (pNode!=NULL) // { // // Now find the next selected node // pNode = Selected->FindNext(pNode); // } // We did not find anything good, so set the cursor to the normal one ChangeCursor(pNormalCursor); // And set the status bar text StatusMsg.Load(_R(IDS_LIVEEFFECTSTART), Tool::GetModuleID(GetID())); GetApplication()->UpdateStatusBarText(&StatusMsg); #endif // NO_ADVANCED_TOOLS }
/******************************************************************************************** > OpState OpMakeStroke::GetState(String_256*, OpDescriptor*) Author: Richard_Millican (Xara Group Ltd) <*****@*****.**> Created: 04/03/97 Inputs: - Outputs: - Returns: The state of the OpMakeStroke Purpose: For finding the OpMakeStroke's state. ********************************************************************************************/ OpState OpMakeStroke::GetState(String_256* UIDescription, OpDescriptor*) { OpState OpSt; SelRange *pSelRange = GetApplication()->FindSelection(); // Set up the ObjChangeParam so we can ask the selected nodes if they mind being deleted ObjChangeFlags cFlags(TRUE); ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,NULL); // Will one or more selected nodes allow this op? if (!pSelRange->AllowOp(&ObjChange,FALSE)) OpSt.Greyed = TRUE; return(OpSt); }
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; }
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); }
/******************************************************************************************** > 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; }
void LiveEffectsTool::OnClick( DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods, Spread* pSpread ) { // Stub out this function if the tool isn't wanted #ifndef NO_ADVANCED_TOOLS if (ClickMods.Menu) return; // Don't do anything if the user clicked the Menu button // See if there is already a drag going on if (Operation::GetCurrentDragOp()!=NULL) return; // If we get a click, treat it like a mouse move, allowing the tool to set up // any info that is passed to the operation in the drag // NEW 17/4/2000 Now we also want to click-select in the Freehand tool if (Click==CLICKTYPE_SINGLE) { OnMouseMove(PointerPos, pSpread, ClickMods); DragTool::OnClick (PointerPos, Click, ClickMods, pSpread); } if (Click == CLICKTYPE_UP) { // so long as we are not interfering with any drawing operations we will // try and change the selection //if (JoinInfo.pJoinPath == NULL) { DragTool::OnClick (PointerPos, Click, ClickMods, pSpread); SelRange* pSelRange = GetApplication()->FindSelection(); if (pSelRange) pSelRange->MakePartialSelectionWhole(TRUE, FALSE, TRUE); BROADCAST_TO_ALL(CommonAttrsChangedMsg); } } #endif // NO_ADVANCED_TOOLS }
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(); }
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 }
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); }
BOOL OpNudge::IsNudgeOK(BOOL dx,BOOL dy) { // Get the selection SelRange* pSel = GetApplication()->FindSelection(); ERROR2IF(pSel == NULL,FALSE,"Awooga, NULL sel range"); // Find out the bounding rectangle of the selection DocRect BoundingRect = pSel->GetBoundingRect(); // Find out the Pasteboard rect DocRect PasteRect; Spread* pSpread = pOurDoc->GetSelectedSpread(); if (pSpread==NULL) PasteRect = BoundingRect; else { // Try to make the pasteboard grow if necessary to include the new object position // This is very quick if the pasteboard is large enough already. pSpread->ExpandPasteboardToInclude(BoundingRect); // And re-read the bounding rectangle of the selection, as the pasteboard resize may have // caused the origin of our entire coordinate space to have moved! Argh! BoundingRect = pSel->GetBoundingRect(); // BoundingRect.Translate(dx,dy); // This is in Document Coords, so we need to convert it PasteRect = pSpread->GetPasteboardRect(); pSpread->DocCoordToSpreadCoord(&PasteRect); } // Assume the nudge will be OK. BOOL NudgeOK = TRUE; if (PasteRect.ContainsRect(BoundingRect)) { // Untranslated bounds fit inside pasteboard rect, so we must complain if the bounds // do not fit *after* translation // Translate the bounds by the nudge values BoundingRect.Translate(dx,dy); // Do the translated bounds still fit entirely in the pasteboard rect? NudgeOK = PasteRect.ContainsRect(BoundingRect); } else { // The original bounds overlap the pasteboard rect, so we must complain if the user // nudges the bounds completely out of sight if (PasteRect.IsIntersectedWith(BoundingRect)) { // The original bounds intersect with the pasteboard rect BoundingRect.Translate(dx,dy); // Only allow the nudge if the translated bounds still overlap with the spread. NudgeOK = PasteRect.IsIntersectedWith(BoundingRect); } } // If the nudge is OK, we may need to scroll the DocView? /* Jim, 12/9/96 - removed this because we don't want to scroll to show opn nudges if (NudgeOK) { DocCoord Coord(0,0); // If nudging left or right, pick the min or max X coord if (dx != 0) { if (dx < 0) Coord.x = BoundingRect.lox; else Coord.x = BoundingRect.hix; } // If nudging up or down, pick the max or min Y coord if (dy != 0) { if (dy < 0) Coord.y = BoundingRect.loy; else Coord.y = BoundingRect.hiy; } // If we have picked a coord, ensure that this coord is visible in the selected spread // of the selected DocView if (Coord != DocCoord(0,0)) { DocView* pDocView = DocView::GetSelected(); if (pDocView != NULL) pDocView->ScrollToShow(&Coord); } } */ return NudgeOK; }
void LiveEffectsTool::SelectChange(BOOL isSelected) { // Stub out this function if the tool isn't wanted #ifndef NO_ADVANCED_TOOLS if (isSelected) { //MessageBox(NULL, "SelectChange 1", "Debug", MB_OK); // Load the cursors if (!LoadCursors()) InformError(); // Update the list of plug-ins //MessageBox(NULL, "SelectChange 2", "Debug", MB_OK); XPEHost::UpdateEditorsList(); //MessageBox(NULL, "SelectChange 3", "Debug", MB_OK); SelRange* pSelRange = GetApplication()->FindSelection(); if (pSelRange) pSelRange->MakePartialSelectionWhole(TRUE, FALSE, TRUE); ScreenChanged(FALSE); //MessageBox(NULL, "SelectChange 4", "Debug", MB_OK); // Find the blob manager ready for later BlobManager* BlobMgr = GetApplication()->GetBlobManager(); // Create and display my info bar please if (m_pInfoBarOp != NULL) { m_pInfoBarOp->Create(); m_pInfoBarOp->SetToolActiveState(TRUE); } // Make sure that Objects blobs are on if (BlobMgr != NULL) { // Decide which blobs to display BlobStyle MyBlobs; MyBlobs.Object = TRUE; // tell the blob manager BlobMgr->ToolInterest(MyBlobs); } //MessageBox(NULL, "SelectChange 5", "Debug", MB_OK); } else { // Deselection of the tool // Get rid of all the tools cursors RemoveCursors(); // Close any open XPE editing XPEHost::EndEditLiveEffect(); // Hide and destroy my info bar please if (m_pInfoBarOp != NULL) { m_pInfoBarOp->SetToolActiveState(FALSE); // Close any open dialogs related to the info bar here m_pInfoBarOp->Delete(); } // ensure that the colour picker is working // SetColourEditorProcessing(TRUE); // ensure any tool object blobs are removed. BlobManager* BlobMgr = GetApplication()->GetBlobManager(); if (BlobMgr != NULL) { BlobStyle bsRemoves; bsRemoves.ToolObject = TRUE; BlobMgr->RemoveInterest(bsRemoves); } } #endif // NO_ADVANCED_TOOLS }
void OpBreakAtPoints::Do(OpDescriptor*) { // Obtain the current selections SelRange* Selected = GetApplication()->FindSelection(); NodePath* pSplitNode; // Now, because we're going to be doing mad things to the selection, we have to make a list // of all the selected nodes, so that adding nodes into the tree won't confuse us List* NodeList = Selected->MakeListOfNodes(); NodeListItem* CurItem = (NodeListItem*)(NodeList->GetHead()); if (!CurItem) goto FailAndDeleteList; if (!DoStartSelOp(TRUE,TRUE)) goto FailAndDeleteList; while (CurItem) { // get a pointer to the NodePath NodePath* pThisNode = (NodePath*)(CurItem->pNode); // Only interested in NodePaths that have a sub selection, and that will allow the op to happen if ((IS_A(pThisNode,NodePath) || IS_A(pThisNode,NodeBlendPath)) && pThisNode->InkPath.IsSubSelection()) { // Find out how many nodes this op will reproduce INT32 NumSplinters = pThisNode->InkPath.NumSplinters(); BOOL DoThisNode = FALSE; 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. ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this); DoThisNode = pThisNode->AllowOp(&ObjChange); } if (DoThisNode) { BOOL ok; Node* pnode; // Copy the nodepath and all its children, without placing the copy in the tree CALL_WITH_FAIL(pThisNode->NodeCopy(&pnode), this, ok); if (!ok) goto DeleteList; pSplitNode = (NodePath*)pnode; // remove the fill from this path as we're about to open it pSplitNode->InkPath.IsFilled = FALSE; // Now stick the new path into the tree CALL_WITH_FAIL ( DoInsertNewNode(pSplitNode, pThisNode, NEXT, TRUE, FALSE), this,ok ); if (!ok) goto DeleteListAndPath; // Now breakup this copy of the path where necessary Path* pChildPath; INT32 split; do { // Create a new path, ready for split ALLOC_WITH_FAIL(pChildPath, new Path, this); if (!pChildPath) goto DeleteList; // Now split the path, possibly into two pieces. split = pSplitNode->InkPath.BreakInTwo(pChildPath); if (split==-1) { InformError(_R(IDS_OUT_OF_MEMORY), _R(IDS_OK)); delete pChildPath; goto FailAndDeleteList; } /* Karim 05/12/2000 No longer required - see code addition at the bottom of this loop. if (split==1) { delete pChildPath; continue; } */ if (split>1) { // update the split paths bounding rectangle pSplitNode->InvalidateBoundingRect(); // Create a new nodepath. NodePath* pChildNode; ALLOC_WITH_FAIL(pChildNode, new NodePath(), this); if (!pChildNode) { delete pChildPath; goto DeleteList; } // make room for the new path in the node path. CALL_WITH_FAIL ( pChildNode->SetUpPath(pChildPath->GetNumCoords(),12), this,ok ); if (!ok) { delete pChildNode; delete pChildPath; goto DeleteList; } // now copy the path data in there. pChildNode->InkPath.CopyPathDataFrom(pChildPath); delete pChildPath; // Clear the selection flag from the first element in both the split // and child paths. All others apart from the last will be unselected // by definition. Also select the last element in the child (pSplitNode->InkPath.GetFlagArray())[0].IsSelected = FALSE; (pChildNode->InkPath.GetFlagArray())[0].IsSelected = FALSE; (pChildNode->InkPath.GetFlagArray())[(pChildNode->InkPath.GetNumCoords()-1)].IsSelected = TRUE; pChildNode->InkPath.IsFilled = FALSE; // now, copy all attributes from the parent split to the child split Node* pAttr = pSplitNode->FindFirstChild(); while (pAttr != NULL) { if (pAttr->IsKindOf(CC_RUNTIME_CLASS(NodeAttribute))) { Node* pAttrCopy; CALL_WITH_FAIL(pAttr->NodeCopy(&pAttrCopy), this,ok); if (!ok) { pChildNode->CascadeDelete(); delete pChildNode; goto DeleteList; } pAttrCopy->AttachNode(pChildNode, FIRSTCHILD); } pAttr = pAttr->FindNext(); } for (INT32 loop = 0; loop < pChildNode->InkPath.GetNumCoords(); loop ++) { pChildNode->InkPath.GetVerbArray()[loop] = pChildNode->InkPath.GetVerbArray()[loop] & ~PT_CLOSEFIGURE; } // Now stick the new path into the tree CALL_WITH_FAIL ( DoInsertNewNode(pChildNode, pSplitNode, NEXT, TRUE, FALSE), this,ok ); if (!ok) { pChildNode->CascadeDelete(); delete pChildNode; goto DeleteList; } pSplitNode = pChildNode; } // Karim 05/12/2000 // Fix for memory leak. else { delete pChildPath; } } while (split); // Clear out any remaining closefigures on the last bit of the path for (INT32 loop = 0; loop < pSplitNode->InkPath.GetNumCoords(); loop ++) { pSplitNode->InkPath.GetVerbArray()[loop] = pSplitNode->InkPath.GetVerbArray()[loop] & ~PT_CLOSEFIGURE; } // Now we've broken up this path, let's hide it CALL_WITH_FAIL(DoHideNode(pThisNode,TRUE), this, ok) if (!ok) goto DeleteList; } } CurItem = (NodeListItem*)(NodeList->GetNext(CurItem)); }
/******************************************************************************************** > 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(); }
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; }
/******************************************************************************************** > BOOL MakeBitmapFilter::DoCreateBitmap(Operation *pOp, Document *pDoc, KernelBitmap** ppBitmap) Author: Will_Cowling (Xara Group Ltd) <*****@*****.**> Created: 11/6/96 Purpose: Exports the current selection as a bitmap, via the virtual fns of the inherited class. Returns: TRUE if worked, FALSE if failed. SeeAlso: GetExportOptions; PrepareToExport; ExportRenderNodes; CleanUpAfterExport; ********************************************************************************************/ BOOL MakeBitmapFilter::DoCreateBitmap(Operation *pOp, Document *pDoc, KernelBitmap** ppBitmap) { ERROR3IF(ppBitmap == NULL, "NULL bitmap pointer passed to MakeBitmapFilter::DoCreateBitmap"); if (ppBitmap == NULL) return FALSE; pTheBitmap = NULL; *ppBitmap = NULL; // Set the bitmap pointer to null just in case, usually only used by DoExportBitmap pExportBitmap = NULL; // Get pointer to the spread to export. PORTNOTE("spread", "Multi-spread warning!") pSpread = GetFirstSpread(pDoc); // remember the document in the class variable TheDocument = pDoc; // We must now check if there is a selection present so that we can set up whether the // user gets the choice of exporting the selection, drawing or spread if there is a // selection present OR just a choice between the spread or drawing if no selection is // present. // If have a caret selected in a text story then the selection will be almost zero so trap // this case as well. RangeControl rg = GetApplication()->FindSelection()->GetRangeControlFlags(); rg.PromoteToParent = TRUE; GetApplication()->FindSelection()->Range::SetRangeControl(rg); SelRange Rng(*(GetApplication()->FindSelection())); // now, run through the selection selecting all nodes under all compound nodes // if we don't do this then all compound nodes aren't rendered correctly with transparent // bitmaps Node * pNode = Rng.FindFirst(FALSE); while (pNode) { pNode->SetSelected(FALSE); pNode->SetSelected(TRUE); pNode = Rng.FindNext(pNode, FALSE); } rg.PromoteToParent = FALSE; GetApplication()->FindSelection()->Range::SetRangeControl(rg); GetApplication()->UpdateSelection(); DocRect ClipRect = GetApplication()->FindSelection()->GetBoundingRect(); SelectionType Selection = DRAWING; if ( ClipRect.IsEmpty() || ClipRect.Width() < MinExportSize || ClipRect.Height() < MinExportSize) Selection = DRAWING; // no selection present, so choose drawing by default else Selection = SELECTION; // selection present, so choose this by default if (Selection != SELECTION) { BOOL UseDrawingBounds = TRUE; SelRange* pSel = GetApplication()->FindSelection(); if (pSel && pSel->Count()==1) { // Only one thing selected ... Is it the Text Caret per chance ? Node* pSelNode = pSel->FindFirst(); if (pSelNode && pSelNode->IsAVisibleTextNode()) { VisibleTextNode* pTextNode = (VisibleTextNode*)pSelNode; if (pTextNode->IsACaret()) { // Aha! It's the Caret that's selected. // We'll use the bounds of the parent text line instead then ... Node* pTextLine = pTextNode->FindParent(); ERROR3IF(!IS_A(pTextLine, TextLine), "Caret doesn't have a parent text line in DoCreateBitmap"); // Get the bounds of the text line ClipRect = ((TextLine*)pTextLine)->GetBoundingRect(); Selection = SELECTION; UseDrawingBounds = FALSE; } } } if (UseDrawingBounds) { // Work out the size of the rectangle encompassing the drawing (visible layers only) ClipRect = GetSizeOfDrawing(pSpread); } } // Create somewhere to put the user options and fill them up MakeBitmapExportOptions* pMakeBmpExportOptions = (MakeBitmapExportOptions*)CreateExportOptions(); if (pMakeBmpExportOptions == NULL) { Error::SetError(_R(IDS_OUT_OF_MEMORY)); return FALSE; } pMakeBmpExportOptions->RetrieveDefaults(); pMakeBmpExportOptions->SetDepth(32); // create bmp copies shoulda always default to being 32 bit pMakeBmpExportOptions->SetSelectionType(Selection); // Set the BaseBitmapFilter member so we can use base class functionality - blurghh SetExportOptions(pMakeBmpExportOptions); BOOL ok = GetExportOptions( (BitmapExportOptions*)pMakeBmpExportOptions ); BOOL IsAnimation = BmapPrevDlg::m_pExportOptions == NULL; BaseBitmapFilter * pNewFilter = this; BitmapExportOptions * pExportOptions = BmapPrevDlg::m_pExportOptions; if (!IsAnimation) { pNewFilter = pExportOptions->FindBitmapFilterForTheseExportOptions(); // from the exporting point of view we should always have been using png options // set them to the png options for the export part if (pNewFilter) pNewFilter->SetExportOptions(pExportOptions); // gets the real export options that the prevdlg has set up for us BmapPrevDlg::m_pExportOptions = NULL; // take responsibility for this data } else { // the animation export didn't bring up the dlg so never set BmapPrevDlg::m_pExportOptions // so continue with these options pExportOptions = (BitmapExportOptions*)pMakeBmpExportOptions; } SetExportOptions(pExportOptions); if (!ok) { SetExportOptions(NULL); // deletes the filter ptr and nulls it delete pExportOptions; return FALSE; // if cancelled } //////////////// SMFIX pExportOptions->MarkValid(); SetDepthToRender(pExportOptions->GetDepth()); // Set up device context and render region for this export. // This will show a progress hourglass for the objects being rendered // THis will now also write the data out to file via our ExportRenderNodes function if (!PrepareToExport(pSpread, pExportOptions->GetDepth(), pExportOptions->GetDPI(), pExportOptions->GetSelectionType(), pExportOptions->GetDither())) { pNewFilter->SetExportOptions(NULL); SetExportOptions(NULL); delete pExportOptions; CleanUpAfterExport(); return FALSE; } RenderInStrips = FALSE; if (!ExportRender(ExportRegion)) { pNewFilter->SetExportOptions(NULL); // deletes the filter ptr and nulls it SetExportOptions(NULL); delete pExportOptions; CleanUpAfterExport(); return FALSE; } // Now get the converted 32Bit BMP pTheBitmap = GetTheBitmap(pExportOptions); // if we`ve got a transparency index AND we`ve got a 32 Bit Render region with alpha channel info // then we can quickly do if(pExportOptions->GetDepth() <= 8 && pExportOptions->GetTransparencyIndex() != -1 && pTheBitmap) { // What we do now is to go throught the bitmap setting the relavent pixels to transparent // depending on the alpha channel info held in the 32 bit version. if(!ApplyTransparentColoursToBitmap(pTheBitmap,pExportOptions)) { pNewFilter->SetExportOptions(NULL); // deletes the filter ptr and nulls it return FALSE; } // Now make sure the bitmap knows that it has a transparent colour! pTheBitmap->SetTransparencyIndex(pExportOptions->GetTransparencyIndex()); } // Set pointer to the bitmap we have created *ppBitmap = pTheBitmap; pNewFilter->SetExportOptions(NULL); // deletes the filter ptr and nulls it SetExportOptions(NULL); delete pExportOptions; CleanUpAfterExport(); return *ppBitmap != NULL; //////////////// SMFIX }