OpEditFill Class Reference

This operation edits an AttrLinearFill already in the tree. It is normally started when the Tool detects a drag on one of its selected blobs. More...

#include <opgrad.h>

Inheritance diagram for OpEditFill:

OpApplyAttribToSelected OpApplyAttrib SelOperation UndoableOperation Operation MessageHandler ListItem CCObject SimpleCCObject List of all members.

Public Member Functions

 OpEditFill ()
 Dummy Contrustor.
void DoCreate (DocCoord &, Spread *, AttrFillGeometry *)
 

void DoDrag (DocCoord &, Spread *, AttrFillGeometry *, FillControl ControlHit)
 
  • Notes: Phil, 16-09-2005 This code relies on the attributea pplication code using DoHideNode and DoShowNode to record changes to the attributes. By recording the attributes in this way when they are first applied, the undo history contains pointers to them and the dragging code can then modify those attributes in the knowledge that the op history is now pointing at the modified attributes. It should really be changed to use OpApplyAttrInteractive. That would reduce the complexity of the following functions enormously and would be more consistent, smaller and possibly faster. There are too many different ways of "solid dragging" things and they should all: Record current tree state at start of drag Modify tree during drag Produce permanent Undo information at the end, using the same logic as would be used in the simple, parametric or outline drag case

virtual void DragPointerMove (DocCoord PointerPos, ClickModifiers ClickMods, Spread *, BOOL bSolidDrag)
 Recalculates the GradFill according to the new position of the corner that is being dragged, EORs it to the screen and keeps the Parallelogram up to date.
virtual void DragPointerIdle (DocCoord PointerPos, ClickModifiers ClickMods, Spread *, BOOL bSolidDrag)
 Recalculates the GradFill according to the new position of the corner that is being dragged, EORs it to the screen and keeps the Parallelogram up to date.
virtual void DragFinished (DocCoord PointerPos, ClickModifiers ClickMods, Spread *, BOOL Success, BOOL bSolidDrag)
 If the drag was a success then a copy of the original node in the tree is created and updated GradFill built. The original NodeGradFill is hidden and the new one if inserted into the tree. If any of these things fail then the operation will fail.
virtual BOOL DragKeyPress (KeyPress *pKeyPress, BOOL bSolidDrag)
 Allows the Fill Edit operation to respond to key presses.
virtual void DragModeChanged (BOOL bSolidDrag)
 Find out if any of the key modifiers are being pressed when the mouse is not moving.
void RenderDragBlobs (DocRect, Spread *, BOOL bSolidDrag)
 Renders the GradFill as it will look if the drag were to end. If we failed to create the GradFill earlier, it will draw a bounding rect.
BOOL GetStatusLineText (String_256 *pText, Spread *pSpread, DocCoord DocPos, ClickModifiers ClickMods)
 Gets the status text during the editing of a fill.
AttrFillGeometryGetGradFill ()

Static Public Member Functions

static BOOL Init ()
 Register this operation into the list of all operations.
static OpState GetState (String_256 *Description, OpDescriptor *)
 Used for greying etc of an operation.

Static Public Attributes

static BOOL InteractiveDragUpdate = TRUE
static BOOL ContinuousEOR = TRUE
static BOOL CreateFill = FALSE
static UINT32 IdleFillDelay = 200

Protected Member Functions

DocRect GetDragBlobRect ()
 This function finds the bounding rect that the parallelogram of the NodeGradFill we are using for EOR renderings parallelogram fits in.
void RedrawFills (ClickModifiers &ClickMods)
 Forces a redraw on the edited fills.
void CheckForCompoundRedraw ()
 Check to see if the redraw needs to invalidate a compound parent. (eg. a blend).
BOOL ApplyNewFill ()
 Applies the newly created fill to the selection.
BOOL ApplyEditedFill ()
 Applies the edited fill, back to the editing objects.
void SelectAllBlobs ()
 Selects all the Start or End fill blobs.
void RenderFinalBlobs (DocRect, Spread *, BOOL bSolidDrag)
 Renders the GradFill as it will look if the drag were to end. If we failed to create the GradFill earlier, it will draw a bounding rect.
void RenderSelectionFillBlobs (SelRange *, DocRect, Spread *)
 Renders the GradFill as it will look if the drag were to end. If we failed to create the GradFill earlier, it will draw a bounding rect.
void RenderInitSelectionBlobs (SelRange *, DocRect, Spread *)
 Renders the GradFill as it will look if the drag were to end. If we failed to create the GradFill earlier, it will draw a bounding rect.
void RenderInitBlobs (DocRect, Spread *, BOOL bSolidDrag)
 Renders the GradFill as it will look if the drag were to end. If we failed to create the GradFill earlier, it will draw a bounding rect.
double FindAspectRatio ()
 Find the aspect ratio of the bitmap we are creating.

Protected Attributes

AttrFillGeometryGradFill
AttrFillGeometryFillClone
SpreadStartSpread
FillControl DragControl
BaseDocumentpFillsDoc
DocRect LastDragRect
BOOL InvalidateAll
BOOL InvalidateCompound
NodepCompound
BOOL DragIsIdle
BOOL DoneIdleRedraw
MonotonicTime Time
BOOL ShowDragBlobs
BOOL DontDrawBlobs
BOOL AlwaysFail
BOOL ApplyAtEnd
BOOL ShouldApplyNewFill
BOOL ForceAspectLock
BOOL IsRequired
BOOL CheckForCompound
BOOL CallAllowOp
FlagState TranspState
List AttrGroups
double AspectRatio
DocCoord AnchorPos
DocCoord LastMousePosition

Private Member Functions

 CC_DECLARE_DYNCREATE (OpEditFill)

Detailed Description

This operation edits an AttrLinearFill already in the tree. It is normally started when the Tool detects a drag on one of its selected blobs.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/7/94

Definition at line 215 of file opgrad.h.


Constructor & Destructor Documentation

OpEditFill::OpEditFill  ) 
 

Dummy Contrustor.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
1/6/94

Definition at line 183 of file opgrad.cpp.

00184 {
00185     // Initialise everything
00186     AlwaysFail          = TRUE;
00187     ApplyAtEnd          = TRUE;
00188     ForceAspectLock     = FALSE;
00189     CreateFill          = FALSE;
00190     IsRequired          = TRUE;
00191     ShouldApplyNewFill  = FALSE;
00192     CheckForCompound    = TRUE;
00193     CallAllowOp         = FALSE;
00194 
00195     InvalidateAll       = TRUE;
00196     InvalidateCompound  = FALSE;
00197 
00198     DragIsIdle          = FALSE;
00199     DoneIdleRedraw      = FALSE;
00200 
00201     ShowDragBlobs       = TRUE;
00202     DontDrawBlobs       = FALSE;
00203 
00204     EditFinished        = FALSE;
00205 
00206     AspectRatio = 1;
00207 }


Member Function Documentation

BOOL OpEditFill::ApplyEditedFill  )  [protected]
 

Applies the edited fill, back to the editing objects.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/5/95
Returns:
TRUE if fill was applied ok.

Definition at line 1447 of file opgrad.cpp.

01448 {
01449     // Put all the fills back like they were so undo will work
01450     ListItem* pAttrPtr = AttrFillGeometry::HitList.GetHead();
01451     while (pAttrPtr != NULL)
01452     {
01453         AttrFillGeometry* pAttr = (AttrFillGeometry*)((NodeAttributePtrItem*)pAttrPtr)->NodeAttribPtr;
01454 
01455         if (pAttr != GradFill)
01456         {
01457             pAttr->SetStartPoint(FillClone->GetStartPoint());
01458             pAttr->SetEndPoint(FillClone->GetEndPoint());
01459             pAttr->SetEndPoint2(FillClone->GetEndPoint2());
01460             pAttr->SetColourRamp(FillClone->GetColourRamp());
01461         }
01462 
01463         pAttrPtr = AttrFillGeometry::HitList.GetNext(pAttrPtr);
01464     }
01465 
01466     SelRange *Selection = Camelot.FindSelection();
01467 
01468     DocRect Bounds;
01469     if (Selection != NULL && Selection->Count()>0)
01470         Bounds = Selection->GetBoundingRect();
01471     else
01472         Bounds = GetDragBlobRect();
01473 
01474     // Give the attribute a bounding rect
01475     GradFill->SetBoundingRect(Bounds);
01476 
01477     BeginSlowJob(-1, FALSE);
01478     AttributeManager::SendMessages = FALSE;
01479 
01480     // Now replace all the edited attributes with the new one
01481     AttributeManager::ReplaceAttributes(GradFill, &AttrFillGeometry::HitList);
01482     AttrFillGeometry::HitList.DeleteAll();
01483 
01484 //  BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::COLOURATTCHANGED)); 
01485 //  BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::NONCOLOURATTCHANGED)); 
01486     AttributeManager::SendMessages = TRUE;
01487     EndSlowJob();
01488 
01489     return TRUE;
01490 }

BOOL OpEditFill::ApplyNewFill  )  [protected]
 

Applies the newly created fill to the selection.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/5/95
Returns:
TRUE if fill was applied ok.

Definition at line 1278 of file opgrad.cpp.

01279 {
01280     ShouldApplyNewFill = FALSE;
01281 
01282     SelRange* pSel = GetApplication()->FindSelection();
01283     Range SelRng(*pSel);
01284     // >>Webster
01285     BOOL bShowProgress = TRUE;
01286 #ifndef EXCLUDE_FROM_XARALX 
01287     if (GetKeyState(CAMKEY(LBUTTON)) & 0x80)
01288         bShowProgress = FALSE;
01289 #endif
01290     // << Webster
01291 
01292     if (bShowProgress)
01293         BeginSlowJob(-1, FALSE);
01294 
01295     ObjChangeFlags cFlags;
01296     cFlags.Attribute = TRUE;
01297     ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this);
01298     ObjChange.SetRetainCachedData(TRUE);
01299 
01300     if (!pSel->AllowOp(&ObjChange))
01301     {
01302         if (bShowProgress)
01303             EndSlowJob();
01304         return FALSE;
01305     }
01306 
01307     DoStartSelOp(FALSE,FALSE, TRUE,TRUE);
01308 
01309     // Before we apply the attribute to the selection we must localise all attributes
01310     // with the same type that we are going to apply. If we don't do this then the
01311     // tree will be left in an invalid state. 
01312 
01313     AttrTypeSet AttrTypes; 
01314     AttrTypes.AddToSet((GradFill->GetAttributeType())); 
01315 
01316     // Invalidate before
01317     if (!DoInvalidateRegions(&SelRng, 
01318                              GradFill, 
01319                              TRUE,
01320                              NULL,
01321                              FALSE))  //Mutators have to include bounds
01322     {
01323         if (bShowProgress)
01324             EndSlowJob();
01325         return FALSE;
01326     }
01327     
01328     if (!DoLocaliseForAttrChange(&SelRng, &AttrTypes))
01329     {
01330         if (bShowProgress)
01331             EndSlowJob();
01332         return FALSE;
01333     }
01334 
01335     // Apply the new fill to the selection
01336     //GradFill->SetColourRamp (
01337     
01338     //pAttr->SetColourRamp ((ColourRamp*) GradFill->GetFillRamp ());
01339     ApplyToSelection(GradFill, TRUE);
01340 
01341     // Having applied the attributes, we  must now try and factor out the newly 
01342     // applied attributes
01343     if (!DoFactorOutAfterAttrChange(&SelRng, 
01344                                     &AttrTypes))
01345     {
01346         if (bShowProgress)
01347             EndSlowJob();
01348         return FALSE;
01349     }
01350 
01351     // Invalidate after
01352     if (!DoInvalidateRegions(&SelRng, 
01353                              GradFill, 
01354                              TRUE,
01355                              NULL,
01356                              FALSE))  //Mutators have to include bounds
01357     {
01358         if (bShowProgress)
01359             EndSlowJob();
01360         return FALSE;
01361     }
01362 
01363     AttrTypes.DeleteAll();
01364 
01365     if (Document::GetSelected())
01366         Document::GetSelected()->SetModified(TRUE);
01367 
01368     ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,this);
01369 ObjChange.SetRetainCachedData(TRUE);    // Tell TextStory not to invalidate everything in OnChildChange
01370     if (!UpdateChangedNodes(&ObjChange))
01371     {
01372         if (bShowProgress)
01373             EndSlowJob();
01374         return FALSE;
01375     }
01376 
01377     // Get the 'actual' fills back, so we can continue to drag them
01378     AttrFillGeometry* pFill = AttrFillGeometry::FindFirstSelectedAttr(GradFill->GetAttributeType());
01379 //  AttrFillGeometry* pFillToEdit = pFill;
01380 
01381     // Build a list of them
01382     while (pFill)
01383     {
01384         BOOL InList = FALSE;
01385 
01386         // We may have already hit this attribute if the selection is
01387         // inside a parent and have common attributes, so we need to
01388         // check and make sure this attribute is NOT in the list
01389         // already.
01390 
01391         if (!AttrFillGeometry::HitList.IsEmpty())
01392         {
01393             ListItem* pItem = AttrFillGeometry::HitList.GetHead();
01394 
01395             while (pItem)
01396             {
01397                 NodeAttributePtrItem* NodePtr = (NodeAttributePtrItem*)pItem;
01398 
01399                 if (NodePtr->NodeAttribPtr == pFill)
01400                 {
01401                     // Ignore this one, we've hit it already
01402                     InList = TRUE;
01403                     break;
01404                 }
01405 
01406                 pItem = AttrFillGeometry::HitList.GetNext(pItem);
01407             }
01408         }
01409 
01410         if (!InList)
01411         {
01412             // Add this to the list of fills to edit
01413             ListItem* pAttr = new NodeAttributePtrItem;
01414             if (pAttr == NULL)
01415             {
01416                 if (bShowProgress)
01417                     EndSlowJob();
01418                 return FALSE;
01419             }
01420 
01421             ERROR3IF(pFill->IsADefaultAttr(), "Default attr in hit list");
01422             ((NodeAttributePtrItem*)pAttr)->NodeAttribPtr = pFill;
01423 
01424             AttrFillGeometry::HitList.AddTail(pAttr);
01425         }
01426 
01427         pFill = AttrFillGeometry::FindNextSelectedAttr(GradFill->GetAttributeType());
01428     }
01429 
01430     if (bShowProgress)
01431         EndSlowJob();
01432 
01433     return TRUE;
01434 }

OpEditFill::CC_DECLARE_DYNCREATE OpEditFill   )  [private]
 

void OpEditFill::CheckForCompoundRedraw  )  [protected]
 

Check to see if the redraw needs to invalidate a compound parent. (eg. a blend).

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
3/5/95

Definition at line 801 of file opgrad.cpp.

00802 {
00803     CheckForCompound = FALSE;
00804 
00805     pFillsDoc = StartSpread->FindOwnerDoc();
00806 
00807     if (AttrFillGeometry::HitList.GetCount() == GetApplication()->FindSelection()->Count() ||
00808         AttrFillGeometry::HitList.GetCount() > 10)
00809     {
00810         // If we are dragging all selected fills, or if there are
00811         // more than 10 of them, then we'll just invalidate the 
00812         // whole selection, 'cus it's much quicker
00813         InvalidateAll = TRUE;
00814     }
00815     else
00816     {
00817         // We will invalidate just the edited fills
00818         InvalidateAll = FALSE;
00819     }
00820 
00821     InvalidateCompound = FALSE;
00822 
00823     if (AttrFillGeometry::HitList.GetCount() == 1)
00824     {
00825         // If just one Fill is being dragged, then check to see if
00826         // it's a 'Select Inside' of a Compound object.
00827 
00828         // If it is, then we'll need to update the whole compound parent.
00829 
00830         ListItem* pAttrPtr = AttrFillGeometry::HitList.GetHead();
00831         AttrFillGeometry* pGrad = (AttrFillGeometry*)((NodeAttributePtrItem*)pAttrPtr)->NodeAttribPtr;
00832 
00833         Node* pParent = pGrad->FindParent();
00834         if (pParent == NULL)
00835         {
00836             InvalidateAll = TRUE;
00837             return;
00838         }
00839     
00840         if (pParent->IsCompound())
00841         {
00842             // The parent is compound, so we'll just update that
00843             InvalidateAll = TRUE;
00844             InvalidateCompound = TRUE;
00845             pCompound = pParent;
00846         }
00847 
00848         // Is the parent a blend object, or is there one
00849         // further up the tree ?
00850         while (pParent != NULL && !pParent->IsLayer())
00851         {
00852             if (pParent->IS_KIND_OF(NodeBlend) || pParent->ShouldITransformWithChildren())
00853             {
00854                 // Found a blend, so we'll have to invalidate it
00855                 // each time we want to re-draw
00856                 InvalidateAll = TRUE;
00857                 InvalidateCompound = TRUE;
00858                 pCompound = pParent;
00859 
00860                 // We will call allowop, to invalidate the blend
00861                 CallAllowOp = TRUE;
00862 
00863                 // Don't break out yet, 'cus we need to invalidate
00864                 // the highest blend in the tree
00865             }
00866             
00867             pParent = pParent->FindParent();
00868         }
00869     }
00870 }

void OpEditFill::DoCreate DocCoord Start,
Spread pSpread,
AttrFillGeometry pGrad
 

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/7/94
Parameters:
Start - The starting position of the drag [INPUTS] pSpread - The spread that the drag started over pElip - The NodeGradFill that is being edited

Definition at line 222 of file opgrad.cpp.

00223 {
00224     ERROR3IF(pGrad == NULL, "Fill pointer is NULL in OpEditFill::DoCreate()");
00225 
00226     if (pGrad == NULL)
00227     {
00228         // Nothing to create !!
00229         FailAndExecute();
00230         End();
00231         return;
00232     }
00233 
00234     // DMc - do the attribute to change
00235     m_pAttr = (NodeAttribute *)pGrad;
00236 
00237     AlwaysFail = FALSE;
00238     
00239     // DMc - set this to TRUE
00240     ApplyAtEnd = FALSE;
00241     ForceAspectLock = TRUE;
00242     CreateFill = TRUE;
00243 
00244     // Get a description of the attribute being applied so that we can use it to create the 
00245     // undo string. 
00246     UndoAttribStrID = pGrad->GetAttrNameID();
00247     AttrFillGeometry::HitList.DeleteAll();
00248 
00249     SelRange* pSel = GetApplication()->FindSelection(); 
00250     if (pSel && pSel->Count() > 0)
00251     {
00252         // Check it's ok to apply to this object
00253         ObjChangeFlags cFlags;
00254         cFlags.Attribute = TRUE;
00255         ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this);
00256 ObjChange.SetRetainCachedData(TRUE);        // Don't let nodes releasecached data - we will handle that!
00257         if (!pSel->AllowOp(&ObjChange))
00258         {
00259             delete pGrad;
00260             FailAndExecute();
00261             End();
00262             return;
00263         }
00264     }
00265 
00266     AttrFillGeometry* pFillToEdit = pGrad;
00267 
00268     // Now check to make sure someone in the selection will accept this attribute
00269     if (AttributeManager::CanBeAppliedToSelection(pGrad, &AttrGroups))
00270     {
00271         // We're gunna apply to at least one object
00272         IsRequired = TRUE;
00273 
00274         // Flag that we need to apply the fill, either when we try
00275         // and do an interective redraw, or at the end
00276         ShouldApplyNewFill = TRUE;
00277 
00278         // Remove all the existing selection fill blobs
00279         DocRect SelBounds = pSel->GetBlobBoundingRect();
00280         RenderInitSelectionBlobs(pSel, SelBounds, pSpread);
00281     }
00282     else
00283     {
00284         // This attribute is not required by any of the selection,
00285         // but we will continue, without actually applying anything,
00286         // and set the 'current' attribute instead
00287         IsRequired = FALSE;
00288         AttributeManager::pLastNodeAppliedTo = NULL;
00289     }
00290 
00291     // Snap the actual mouse position to the grid if needed
00292     DocView::SnapSelected(pSpread, &Start);
00293 
00294     // Initialise the Control Points
00295     pFillToEdit->SetStartPoint(&Start);
00296     pFillToEdit->SetEndPoint(&Start);
00297     pFillToEdit->SetEndPoint2(&Start);
00298 
00299     // Call the edit code
00300     DoDrag(Start, pSpread, pFillToEdit, FILLCONTROL_ENDPOINT);
00301 }

void OpEditFill::DoDrag DocCoord Start,
Spread pSpread,
AttrFillGeometry pGrad,
FillControl  ControlHit
 

  • Notes: Phil, 16-09-2005 This code relies on the attributea pplication code using DoHideNode and DoShowNode to record changes to the attributes. By recording the attributes in this way when they are first applied, the undo history contains pointers to them and the dragging code can then modify those attributes in the knowledge that the op history is now pointing at the modified attributes. It should really be changed to use OpApplyAttrInteractive. That would reduce the complexity of the following functions enormously and would be more consistent, smaller and possibly faster. There are too many different ways of "solid dragging" things and they should all: Record current tree state at start of drag Modify tree during drag Produce permanent Undo information at the end, using the same logic as would be used in the simple, parametric or outline drag case

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/7/94
Parameters:
Start - The starting position of the drag [INPUTS] pSpread - The spread that the drag started over pElip - The NodeGradFill that is being edited

Definition at line 330 of file opgrad.cpp.

00331 {
00332     ERROR3IF(ControlHit > NUMCONTROLPOINTS && 
00333         !ISA_RAMPINDEX(ControlHit), "Invalid control point in OpEditFill::DoDrag()");
00334     ERROR3IF(pGrad == NULL, "Fill pointer is NULL in OpEditFill::DoDrag()");
00335 
00336     if (pGrad == NULL)
00337     {
00338         // Nothing to edit !!
00339         FailAndExecute();
00340         End();
00341         return;
00342     }
00343 
00344     // Various starting positions
00345     StartSpread = pSpread;
00346     DragControl = ControlHit;
00347 
00348     // Keep a copy of the old fill, so we can put it back later if necessary
00349     CCRuntimeClass* ObjectType = pGrad->GetRuntimeClass();
00350     FillClone = (AttrFillGeometry*)ObjectType->CreateObject();
00351     *FillClone = *pGrad;
00352 
00353     // and make another copy to actually edit
00354     ObjectType = pGrad->GetRuntimeClass();
00355     GradFill = (AttrFillGeometry*)ObjectType->CreateObject();
00356     *GradFill = *pGrad;
00357 
00358     pParentOfFill = (NodeRenderableInk*) pGrad->FindParent ();
00359     pTheFill = pGrad;
00360 
00361     if (CreateFill)
00362         delete pGrad;   // Not needed any more
00363 
00364     AspectRatio = FindAspectRatio();
00365 
00366     AnchorPos = Start;
00367     LastMousePosition = Start;
00368 
00369     DontDrawBlobs = FALSE;
00370     DragIsIdle = FALSE;
00371     DoneIdleRedraw = FALSE;
00372 
00373 //  ShowDragBlobs = ContinuousEOR;
00374     ShowDragBlobs = !DocView::SolidDragging;
00375 
00376     if (!IsRequired)            // Always show blobs if we're gunna
00377         ShowDragBlobs = TRUE;   // set the current attribute
00378 
00379     AttrFillGeometry::DraggedFill = NULL;
00380     AttrFillGeometry::EditedFill  = GradFill;
00381 
00382     // And tell the Dragging system that we need drags to happen
00383     StartDrag(DRAGTYPE_AUTOSCROLL, NULL, NULL, TRUE, TRUE);         // We support solid dragging
00384 }

void OpEditFill::DragFinished DocCoord  PointerPos,
ClickModifiers  ClickMods,
Spread ,
BOOL  Success,
BOOL  bSolidDrag
[virtual]
 

If the drag was a success then a copy of the original node in the tree is created and updated GradFill built. The original NodeGradFill is hidden and the new one if inserted into the tree. If any of these things fail then the operation will fail.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/7/94
Parameters:
PointerPos - The current position of the mouse [INPUTS] ClickMods - Which buttons and modifiers are held down pSpread - The Spread that the mouse is over now. Success - TRUE if the drag was completed sucessfully.

Reimplemented from Operation.

Definition at line 1014 of file opgrad.cpp.

01015 {   
01016     EditFinished = TRUE;
01017     
01018     double APixel;
01019 
01020     // Flag to say if everything has worked
01021     BOOL IsOk = FALSE;
01022 
01023     // First Rub out the old Drag blobs
01024     if (!DontDrawBlobs && AttrFillGeometry::DraggedFill != NULL)
01025     {
01026         if (!(ISA_RAMPINDEX(DragControl)))
01027         {
01028             RenderDragBlobs(GradFill->GetBlobBoundingRect(), StartSpread, bSolidDrag);
01029         }
01030         else
01031         {
01032             if (ISA_RAMPINDEX (DragControl))
01033             {
01034                 GradFill->DisableBoundsRedraw ();
01035             }
01036             RenderDragBlobs(GradFill->GetBlobBoundingRect(), StartSpread, bSolidDrag);
01037             if (ISA_RAMPINDEX (DragControl))
01038             {
01039                 GradFill->EnableBoundsRedraw ();
01040             }
01041         }
01042     }
01043 
01044     DontDrawBlobs = FALSE;
01045     BOOL HaveFailed = FALSE;
01046 
01047     Document* pDoc = Document::GetSelected();
01048 
01049     // check for a fill ramp drag
01050     if (ISA_RAMPINDEX(DragControl))
01051     {
01052         if (Success)
01053         {
01054             if (GradFill->GetColourRamp())
01055             {
01056                 GradFill->GetColourRamp()->SortRamp();
01057             }
01058         }
01059     }
01060 
01061     // End the Drag                             
01062     if (!EndDrag())
01063     {
01064         delete FillClone;
01065         delete GradFill;
01066         goto EndOperation;
01067     }
01068 
01069     if (*GradFill->GetStartPoint() == *GradFill->GetEndPoint())
01070         Success = FALSE;
01071     
01072     APixel = (DocView::GetSelected()->GetScaledPixelWidth()).MakeDouble();
01073 
01074     // If the pointer has moved less than a few pixels, then just do a click
01075     if (PointerPos.Distance(AnchorPos) <= APixel*2)
01076         Success = FALSE;
01077 
01078     // If PointerPos is equal to AnchorPos, then it must have just been a click
01079     if (!Success || (PointerPos == AnchorPos))
01080     {
01081         if (AttrFillGeometry::DraggedFill)
01082         {
01083             // We must have actually dragged a bit,
01084             // so make sure we tidy everying, and then render
01085             // the old fill blobs back on
01086             AttrFillGeometry::DraggedFill = NULL;
01087             AttrFillGeometry::EditedFill = NULL;
01088 
01089             // Failed, so put all the fills back like they were,
01090             // if we have changed them.
01091             if (!(*GradFill == *FillClone))
01092             {
01093                 *GradFill = *FillClone;
01094 
01095                 ListItem* pAttrPtr = AttrFillGeometry::HitList.GetHead();
01096                 while (pAttrPtr != NULL)
01097                 {
01098                     AttrFillGeometry* pAttr = (AttrFillGeometry*)((NodeAttributePtrItem*)pAttrPtr)->NodeAttribPtr;
01099 ERROR3IF(pAttr->IsADefaultAttr(), "Default attr in hit list");
01100 
01101                     pAttr->SetStartPoint(FillClone->GetStartPoint());
01102                     pAttr->SetEndPoint(FillClone->GetEndPoint());
01103                     pAttr->SetEndPoint2(FillClone->GetEndPoint2());
01104 
01105                     NodeRenderableInk* pParent = (NodeRenderableInk*)pAttr->FindParent();
01106                     ERROR3IF(pParent==NULL, "Can't find parent of edited attribute");
01107                     if (pParent && pAttr->IsEffectAttribute())  // IsValidEffectAttr?
01108                     {
01109 //                      Node* pGrandParent = pParent->FindParent();
01110 //                      if (pGrandParent && pGrandParent->IsBounded())
01111 //                          ((NodeRenderableBounded*)pGrandParent)->ReleaseCached(TRUE, FALSE); // Parents only
01112                         pParent->ReleaseCached(TRUE, FALSE, FALSE, TRUE);   // Parents and derived data only
01113                     }
01114                     else
01115                         pParent->ReleaseCached();
01116 
01117                     pAttrPtr = AttrFillGeometry::HitList.GetNext(pAttrPtr);
01118                 }
01119 
01120                 // Redraw the old fills back
01121                 DocRect SelBounds = GetApplication()->FindSelection()->GetBlobBoundingRect();
01122 
01123                 DocView::GetSelected()->ForceRedraw(StartSpread, SelBounds);
01124             }
01125 
01126         }
01127         else
01128         {
01129             // We didn't drag anything, so it must have just been a click
01130             if (ClickMods.Adjust && ClickMods.Constrain)
01131             {
01132                 // Cntrl/Shift/Click will select all Start or End blobs
01133                 SelectAllBlobs();
01134             }
01135 
01136             // Tell the world that a fill blob has been selected
01137             BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::COLOURATTCHANGED)); 
01138         }
01139 
01140         AttrFillGeometry::LastRenderedMesh = NULL;
01141         AttrFillGeometry::HitList.DeleteAll();
01142 
01143         delete FillClone;
01144         delete GradFill;
01145         goto EndOperation;      // This will fail the op
01146     }
01147 
01148     // We have edited the fill ok, so we'll draw the blobs back on
01149     AttrFillGeometry::DraggedFill = NULL;
01150 
01151     if (IsRequired)
01152         RenderFinalBlobs(GetDragBlobRect(), StartSpread, bSolidDrag);
01153 
01154     if (AlwaysFail)
01155     {
01156         // If we just edited a fill, then we don't want any undo info,
01157         // so we'll fail the op now (and discard the Actions), before we
01158         // apply the edited fill
01159         FailAndExecute();
01160         HaveFailed = TRUE;  // no need to fail at the end
01161     }
01162 
01163     // if the drag was a sucess then make a grad fill
01164     if (Success && (!GetDragBlobRect().IsEmpty()))
01165     {
01166         AttrFillGeometry::EditedFill = NULL;
01167         AttrFillGeometry::DraggedFill = NULL;
01168     
01169         if (ApplyAtEnd)
01170         {
01171             // Update all the edited fills
01172             ApplyEditedFill();
01173 
01174             delete FillClone;
01175             delete GradFill;
01176         }
01177         else
01178         {
01179             if (ShouldApplyNewFill)
01180             {
01181                 ApplyNewFill();
01182             }
01183 
01184             BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::COLOURATTCHANGED)); 
01185             BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::NONCOLOURATTCHANGED)); 
01186 
01187             SelRange *Selection = Camelot.FindSelection();
01188             DocRect Bounds;
01189             if (Selection != NULL && Selection->Count()>0)
01190                 Bounds = Selection->GetBoundingRect();
01191             else
01192                 Bounds = GetDragBlobRect();
01193 
01194             GradFill->SetBoundingRect(Bounds);
01195 
01196             // Ensure we update all the fills
01197             if (!AttrFillGeometry::HitList.IsEmpty())
01198             {
01199                 ListItem* pAttrPtr = AttrFillGeometry::HitList.GetHead();
01200 
01201                 while (pAttrPtr != NULL)
01202                 {
01203                     AttrFillGeometry* pAttr = (AttrFillGeometry*)((NodeAttributePtrItem*)pAttrPtr)->NodeAttribPtr;
01204 ERROR3IF(pAttr->IsADefaultAttr(), "Default attr in hit list");
01205 
01206                     // Update the control points on the other fills
01207                     pAttr->SetStartPoint(GradFill->GetStartPoint());
01208                     pAttr->SetEndPoint(GradFill->GetEndPoint());
01209                     pAttr->SetEndPoint2(GradFill->GetEndPoint2());
01210 
01211                     // Give the attribute a bounding rect
01212                     pAttr->SetBoundingRect(Bounds);
01213 
01214                     // We need to ensure that we force a redraw at the end of the drag
01215                     // because redraws during the drag will have been done with QuickRender turned
01216                     // on and so some slow objects may not have rendered themselves
01217                     // fully.
01218                     if (bSolidDrag)
01219                     {
01220                         Node* pParent = pAttr->FindParent();
01221                         if (pParent && pParent->IsBounded())
01222                         {
01223 ((NodeRenderableBounded*)pParent)->ReleaseCached(TRUE, FALSE, !pAttr->IsEffectAttribute(), TRUE);
01224                             DoInvalidateNodeRegion((NodeRenderableBounded*)pParent, FALSE, TRUE, FALSE, FALSE); // Do not recache
01225                             // (SelOperation::DoApply will have called ReleaseCached as needed)
01226                         }
01227                     }
01228 
01229                     pAttrPtr = AttrFillGeometry::HitList.GetNext(pAttrPtr);
01230                 }
01231             }
01232             AttributeManager& AttrMgr = pDoc->GetAttributeMgr();
01233 
01234             if (AttrMgr.WeShouldMakeAttrCurrent(IsRequired,GradFill,&AttrGroups))
01235             {
01236                 AttributeManager::UpdateCurrentAttr(GradFill, TRUE, &AttrGroups);
01237             }
01238 
01239             delete FillClone;
01240             delete GradFill;
01241         }
01242 
01243         IsOk = TRUE;
01244     }
01245 
01246 EndOperation:
01247 
01248     // DMc - should inform all nodes at the end of a drag too
01249     AttrFillGeometry::EditedFill = NULL;
01250     AttrFillGeometry::DraggedFill = NULL;
01251     AttrFillGeometry::HitList.DeleteAll();
01252     CreateFill = FALSE;
01253 
01254     // Don't forget the AttrGroups List
01255     AttrGroups.DeleteAll();
01256 
01257     // If something went wrong, then fail (if we haven't already)
01258     if (!IsOk && !HaveFailed)
01259     {
01260         FailAndExecute();
01261     }
01262 
01263     // always call end
01264     End();
01265 }

BOOL OpEditFill::DragKeyPress KeyPress pKeyPress,
BOOL  bSolidDrag
[virtual]
 

Allows the Fill Edit operation to respond to key presses.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
4/5/95
Parameters:
pKeyPress - Object describing the nature of the keypress. [INPUTS]

Reimplemented from Operation.

Definition at line 936 of file opgrad.cpp.

00937 {
00938     if (pKeyPress->GetVirtKey() == CAMKEY(TAB) && 
00939         pKeyPress->IsPress() &&
00940         !pKeyPress->IsRepeat())
00941     {
00942         // Toggle the continuous EOR flag
00943         ContinuousEOR = !ContinuousEOR;
00944         ShowDragBlobs = ContinuousEOR;
00945 
00946         String_256 DragText;
00947         ClickModifiers ClickMods;
00948 
00949         // Now update the Status line to show the mode change
00950         GetStatusLineText(&DragText, StartSpread, LastMousePosition, ClickMods);
00951         GetApplication()->UpdateStatusBarText(&DragText);
00952         
00953         return TRUE;
00954     }
00955     return FALSE;
00956 }

void OpEditFill::DragModeChanged BOOL  bSolidDrag  )  [virtual]
 

Find out if any of the key modifiers are being pressed when the mouse is not moving.

Author:
Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/12/2003
Parameters:
pKeyPress - pointer to a keypress object [INPUTS]
Returns:
TRUE if it handled the keypress, FALSE otherwise

Reimplemented from Operation.

Definition at line 974 of file opgrad.cpp.

00975 {
00976 /*  DocView* pDocView = DocView::GetSelected();
00977     BlobManager* pBlobManager = Camelot.GetBlobManager();
00978     ENSURE(pBlobManager, "Can't get BlobManager");
00979 
00980     // Toggle the continuous EOR flag
00981     ContinuousEOR = !bSolidDrag;
00982     ShowDragBlobs = ContinuousEOR;
00983 
00984     String_256 DragText;
00985     ClickModifiers ClickMods;
00986 
00987     // Now update the Status line to show the mode change
00988     GetStatusLineText(&DragText, StartSpread, LastMousePosition, ClickMods);
00989     GetApplication()->UpdateStatusBarText(&DragText);
00990 */
00991 }

void OpEditFill::DragPointerIdle DocCoord  PointerPos,
ClickModifiers  ClickMods,
Spread pSpread,
BOOL  bSolidDrag
[virtual]
 

Recalculates the GradFill according to the new position of the corner that is being dragged, EORs it to the screen and keeps the Parallelogram up to date.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/7/94
Parameters:
PointerPos - The current position of the mouse [INPUTS] ClickMods - Which buttons and modifiers are held down pSpread - The Spread that the mouse is over now.

Reimplemented from Operation.

Definition at line 888 of file opgrad.cpp.

00889 {   
00890     if (!DragIsIdle)
00891     {
00892         // The Mouse has just become idle, so we'll reset the timer.
00893         DragIsIdle = TRUE;
00894         DoneIdleRedraw = FALSE;
00895         Time.Sample();
00896     }       
00897     else
00898     {
00899         // Has the Mouse been idle for long enough ?
00900         if (Time.Elapsed(IdleFillDelay))
00901         {
00902             if (DontDrawBlobs)
00903             {
00904                 // If we are not redrawing the EOR blobs constantly,
00905                 // then we will stick them back on when the mouse
00906                 // has been idle for a while.
00907                 DontDrawBlobs = FALSE;
00908                 DragIsIdle = FALSE;
00909                 RenderDragBlobs(LastDragRect, StartSpread, bSolidDrag);
00910             }
00911             else
00912             {
00913                 // If we ARE redrawing the blobs, then we'll try and redraw
00914                 // the fills when the mouse has been idle for a while.
00915                 if (InteractiveDragUpdate && !DoneIdleRedraw)
00916                 {
00917                     RedrawFills(ClickMods);
00918                     DoneIdleRedraw = TRUE;
00919                 }
00920             }
00921         }
00922     }
00923 }

void OpEditFill::DragPointerMove DocCoord  PointerPos,
ClickModifiers  ClickMods,
Spread pSpread,
BOOL  bSolidDrag
[virtual]
 

Recalculates the GradFill according to the new position of the corner that is being dragged, EORs it to the screen and keeps the Parallelogram up to date.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/7/94
Parameters:
PointerPos - The current position of the mouse [INPUTS] ClickMods - Which buttons and modifiers are held down pSpread - The Spread that the mouse is over now.

Reimplemented from Operation.

Definition at line 402 of file opgrad.cpp.

00403 {
00404     if (ISA_RAMPINDEX(DragControl) && !bSolidDrag)
00405     {
00406         GradFill->DisableRampRedraw();
00407     }
00408     
00409     if (EditFinished)
00410         return;
00411 
00412     if (ForceAspectLock)
00413         ClickMods.Adjust = TRUE;
00414 
00415     DragIsIdle = FALSE;
00416     DoneIdleRedraw = FALSE;
00417 
00418     // Snap the actual mouse position to the grid if needed
00419     DocView::SnapSelected(pSpread, &PointerPos);
00420 
00421     if (AttrFillGeometry::DraggedFill == NULL)
00422     {
00423         double APixel = (DocView::GetSelected()->GetScaledPixelWidth()).MakeDouble();
00424 
00425         // I