OpNewRegShape Class Reference

Provides an operation for the regular shape tool to use to create and insert a new shape into the document tree (with undo etc...). More...

#include <oprshape.h>

Inheritance diagram for OpNewRegShape:

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

Public Types

enum  CreateMode { RADIUS, DIAMETER, BOUNDS }

Public Member Functions

 OpNewRegShape ()
 Constructor. This simply sets a few of the operation flags.
void DoDrag (Spread *pSpread, DocCoord Anchor, INT32 NumSides, CreateMode DragMode, BOOL Circular, BOOL Stellated, BOOL Curved)
 Starts dragging from the coordinate passed in. For RADIUS mode you are dragging the major axes from a fixed centre point For DIAMETER mode you are dragging the major axes, the centre point is the midpoint of the line between the start and current points. For BOUNDS mode you are dragging a bounding box. The major and minor axes just touch the edge of the box.
virtual void DragPointerMove (DocCoord PointerPos, ClickModifiers ClickMods, Spread *, BOOL bSolidDrag)
 Takes the pointer position of the corner of the shape being dragged and redisplays the outline.
virtual void DragFinished (DocCoord PointerPos, ClickModifiers ClickMods, Spread *, BOOL Success, BOOL bSolidDrag)
 Ends the drag and creates a rectangle using the dimensions and position of the outline rectangle produced by the dragging system. It also ends the operation.
void RenderDragBlobs (DocRect, Spread *, BOOL bSolidDrag)
 Draws an EORed version of the current shape.

Static Public Member Functions

static BOOL Declare ()
 Adds the operation to the list of all known operations.
static OpState GetState (String_256 *Description, OpDescriptor *)
 Find out the state of the new regular shape at the specific time.

Private Member Functions

BOOL CompleteOperation ()
 Does all the work in building the undo etc. It builds a shape and inserts it into the tree.
void InflateShape (DocRect *Bounds, DocCoord *NewCentre, DocCoord *NewMajor, DocCoord *NewMinor)
 NewMajor and NewMinor are initially positioned half way along the top and halfway down the righthand side of the Bounds rect respectivly, Their positions are then increased so that the shape path passes through their previous positions.

Private Attributes

NodeRegularShapeNewShape
SpreadStartSpread
DocCoord StartPoint
DocCoord LastPoint
CreateMode CreationMode
CursorpCursor
BOOL IsShiftDown
DocCoord RecentrePoint

Detailed Description

Provides an operation for the regular shape tool to use to create and insert a new shape into the document tree (with undo etc...).

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/11/94

Definition at line 122 of file oprshape.h.


Member Enumeration Documentation

enum OpNewRegShape::CreateMode
 

Enumerator:
RADIUS 
DIAMETER 
BOUNDS 

Definition at line 128 of file oprshape.h.

00128 { RADIUS, DIAMETER, BOUNDS };


Constructor & Destructor Documentation

OpNewRegShape::OpNewRegShape  ) 
 

Constructor. This simply sets a few of the operation flags.

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

Definition at line 142 of file oprshape.cpp.

00143 {
00144     pCursor = NULL;
00145     IsShiftDown = FALSE;
00146 }


Member Function Documentation

BOOL OpNewRegShape::CompleteOperation  )  [private]
 

Does all the work in building the undo etc. It builds a shape and inserts it into the tree.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/11/94
Returns:
TRUE if the operation worked, FALSE if not

Definition at line 455 of file oprshape.cpp.

00456 {
00457     // We will only create the shape if it is bigger than a blob rect at the current scale
00458     DocRect temp;
00459     GetApplication()->GetBlobManager()->GetBlobRect(StartPoint, &temp);
00460     if (temp.ContainsCoord(LastPoint))
00461     {
00462         return FALSE;
00463     }
00464 
00465     // Find the document for this operation.
00466     Document* pDoc = GetWorkingDoc();
00467     if (pDoc==NULL)
00468     {
00469         TRACEALL( _T("OpNewRegShape::CompleteOperation has no working document.")); 
00470         return FALSE;
00471     }
00472 
00473     // Apply a few attributes
00474     if (!(pDoc->GetAttributeMgr().ApplyCurrentAttribsToNode((NodeRenderableInk*)NewShape)))
00475         return FALSE;
00476 
00477     // Delete any applied join attribute
00478     NodeAttribute* pAppliedJoin = NewShape->GetChildAttrOfType(CC_RUNTIME_CLASS(AttrJoinType));
00479     if (pAppliedJoin != NULL) 
00480     {
00481         pAppliedJoin->CascadeDelete();
00482         delete pAppliedJoin;
00483     }
00484 
00485     // Apparently all shapes should have mitre joins.
00486     AttrJoinType* pMitreJoin = new AttrJoinType(NewShape, LASTCHILD);
00487     if (pMitreJoin == NULL)
00488         return FALSE;
00489     pMitreJoin->Value.JoinType = MitreJoin;
00490 
00491     // Try and start the the operation
00492     if (!DoStartSelOp(FALSE))
00493         return FALSE;
00494 
00495     // Ok, add it in and invalidate the region
00496     if (!DoInsertNewNode(NewShape, StartSpread, TRUE))
00497         return FALSE;
00498 
00499     // Finally, make sure we haven't added the new object partially off the spread
00500     StartSpread->ExpandPasteboardToInclude(NewShape->GetBoundingRect());
00501 
00502     // all worked
00503     return TRUE;
00504 }

BOOL OpNewRegShape::Declare  )  [static]
 

Adds the operation to the list of all known operations.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/11/94
Returns:
TRUE if all went OK, False otherwise

Definition at line 614 of file oprshape.cpp.

00615 {
00616     return (RegisterOpDescriptor(
00617                                 0, 
00618                                 _R(IDS_NEWREGULARSHAPEOP),
00619                                 CC_RUNTIME_CLASS(OpNewRegShape), 
00620                                 OPTOKEN_NEWREGSHAPE,
00621                                 OpNewRegShape::GetState));
00622 
00623 }

void OpNewRegShape::DoDrag Spread pSpread,
DocCoord  Anchor,
INT32  NumSides,
CreateMode  DragMode,
BOOL  Circular,
BOOL  Stellated,
BOOL  Curved
 

Starts dragging from the coordinate passed in. For RADIUS mode you are dragging the major axes from a fixed centre point For DIAMETER mode you are dragging the major axes, the centre point is the midpoint of the line between the start and current points. For BOUNDS mode you are dragging a bounding box. The major and minor axes just touch the edge of the box.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/11/94
Parameters:
pSpread - The spread that the drag was started on [INPUTS] Anchor - starting position of the drag NumSides - the number of sides the new regular shape should have (0 implies an ellipse) CreateMode - the way the drag and the new object should interact. Either RADIUS, DIAMETER or BOUNDS Circular - TRUE to base the created shape on a circle, FALSE if it is a polygon Curved - TRUE if the created shape has rounded corners.

Definition at line 172 of file oprshape.cpp.

00174 {
00175     DocView::SnapCurrent(pSpread, &Anchor);
00176 
00177     // We had better take a note of the starting point of the drag.
00178     StartSpread = pSpread;
00179     StartPoint = Anchor;
00180     LastPoint = Anchor;
00181     CreationMode = DragMode;
00182     
00183     // Create the shape that is to be dragged around.
00184     NewShape = new (NodeRegularShape);
00185 
00186     if ((NewShape == NULL) || !NewShape->SetUpShape() )
00187     {
00188         InformError(_R(IDS_OUT_OF_MEMORY), _R(IDS_OK));
00189         return;
00190     }
00191 
00192     // And make sure it is filled in
00193     NewShape->SetNumSides(NumSides);
00194 
00195     const DocCoord Origin(0,0);
00196     NewShape->SetCentrePoint(Origin);
00197     NewShape->SetMajorAxes(Origin);
00198     NewShape->SetMinorAxes(Origin);
00199 
00200     NewShape->SetCircular(Circular);
00201     NewShape->SetStellated(Stellated);
00202     NewShape->SetPrimaryCurvature(Curved);
00203     NewShape->SetStellationCurvature(Curved);
00204 
00205     Matrix InitialMat(StartPoint.x, StartPoint.y);
00206     NewShape->SetTransformMatrix(&InitialMat);
00207 
00208     // Eor the rectangle on for the first time
00209     DocRect EditPathBBox = NewShape->GetBoundingRect();
00210     RenderDragBlobs(EditPathBBox, StartSpread, FALSE);
00211 
00212     // And tell the Dragging system that we need drags to happen
00213     StartDrag( DRAGTYPE_AUTOSCROLL, NULL, &Anchor, FALSE );
00214 }

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

Ends the drag and creates a rectangle using the dimensions and position of the outline rectangle produced by the dragging system. It also ends the operation.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/11/94
Parameters:
PointerPos - The position of the mouse at the end of the drag [INPUTS] ClickMods - the key modifiers being pressed pSpread - The spread that the drag finished on Success - TRUE if the drag was terminated properly, FALSE if it was ended with the escape key being pressed
See also:
ClickModifiers

Reimplemented from Operation.

Definition at line 409 of file oprshape.cpp.

00411 {
00412     // Start a slow job
00413     BeginSlowJob();
00414 
00415     // End the Drag                             
00416     EndDrag();
00417 
00418     // First Rub out the old box
00419     DocRect EditPathBBox = NewShape->GetBoundingRect();
00420     RenderDragBlobs(EditPathBBox, StartSpread, bSolidDrag);
00421         
00422     // If we should carry on, then do it
00423     BOOL Worked = FALSE;
00424     if ( Success && (StartPoint != PointerPos) ) 
00425         Worked = CompleteOperation();
00426 
00427     // if it did not work or the user pressed ESCAPE then fail
00428     if (!Worked)
00429     {
00430         // It did not work, so we had better recover
00431         NewShape->CascadeDelete();
00432         delete NewShape;
00433 
00434         FailAndExecute();
00435     }
00436 
00437     End();
00438 }

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

Takes the pointer position of the corner of the shape being dragged and redisplays the outline.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/11/94
Parameters:
PointerPos - The current position of the mouse in Doc Coords [INPUTS] ClickMods - Which key modifiers are being pressed pSpread - The spread that the mouse pointer is over
See also:
ClickModifiers

Reimplemented from Operation.

Definition at line 234 of file oprshape.cpp.

00236 {
00237     // Rub out the old shape
00238     DocRect EditPathBBox = NewShape->GetBoundingRect();
00239     RenderDragBlobs(DocRect(0,0,0,0), StartSpread, bSolidDrag);
00240 
00241     // make sure the rect does not wrap around the edge of the spread
00242     if (pSpread != StartSpread)
00243         PointerPos = MakeRelativeToSpread(StartSpread, pSpread, PointerPos);
00244 
00245     // If the SHIFT key is down then drop into RADIUS mode
00246     CreateMode TempCreationMode = CreationMode;
00247     if (ClickMods.Adjust && CreationMode == DIAMETER)
00248         TempCreationMode = RADIUS;
00249     if (ClickMods.Adjust && ClickMods.Constrain && CreationMode == BOUNDS)
00250         TempCreationMode = RADIUS;
00251 
00252     // Now see if we should constrain the point
00253     if (ClickMods.Constrain)
00254     {
00255         // If we are in bounds creation mode then we want to restrict to 45, 135 225, and 315 degrees
00256         // This stops thin shapes (ie zero wdith or height)
00257         if (TempCreationMode == BOUNDS)
00258         {
00259             double length = StartPoint.Distance(PointerPos);
00260         
00261             if (length != 0.0)
00262             {
00263                 DocCoord Offset = PointerPos - StartPoint; 
00264                 double rotangle = atan2((double)Offset.y, (double)Offset.x);
00265 
00266                 if ((rotangle >= 0) && (rotangle <= PI/2))
00267                     rotangle = PI/4;
00268                 if (rotangle > PI/2)
00269                     rotangle = 3*(PI/4);
00270                 if ((rotangle < 0) && (rotangle >= -PI/2))
00271                     rotangle = -PI/4;
00272                 if (rotangle < -PI/2)
00273                     rotangle = -3*(PI/4);
00274 
00275                 PointerPos.x = StartPoint.x + (INT32)length; 
00276                 PointerPos.y = StartPoint.y; 
00277 
00278                 Trans2DMatrix Trans(StartPoint, rotangle*(180/PI));
00279                 Trans.Transform(&PointerPos, 1);
00280             }
00281         }
00282         else
00283         {
00284             DocCoord Centre = NewShape->GetCentrePoint();
00285             if (TempCreationMode == DIAMETER)
00286                 Centre = StartPoint;
00287             DocView::ConstrainToAngle(Centre, &PointerPos);
00288         }
00289     }
00290 
00291     // snap to the grid too
00292     DocView::SnapCurrent(pSpread, &PointerPos);
00293 
00294     // Change our shape to fit the current mouse position
00295     switch (TempCreationMode)
00296     {
00297         case RADIUS:
00298         {   // The major axes point is the current mouse pos rotated around the centre point by  
00299             // 180 degrees.  The minor point is the same point rotated by a further 90 degrees
00300             DocCoord OldCentre = NewShape->GetCentrePoint();
00301             DocCoord NewMajor = PointerPos - OldCentre;
00302             DocCoord NewMinor = PointerPos - OldCentre;
00303             Trans2DMatrix Trans1(DocCoord(0,0), -180);
00304             Trans1.Transform(&NewMajor, 1);
00305             Trans2DMatrix Trans2(DocCoord(0,0), -270);
00306             Trans2.Transform(&NewMinor, 1);
00307             NewShape->SetMajorAxes(NewMajor);
00308             NewShape->SetMinorAxes(NewMinor);
00309             NewShape->SetCentrePoint(DocCoord(0,0));
00310             Matrix InitialMat(OldCentre.x, OldCentre.y);
00311             NewShape->SetTransformMatrix(&InitialMat);
00312             break;
00313         }
00314         case DIAMETER:
00315         {   // The centre point is the midpoint of the line from the start point to the current point.
00316             // The major axes is positioned so that a vertex is on the starting position.
00317             // The minor axes is the major axes rotated by -90 degrees.
00318             DocCoord NewCentre;
00319             NewCentre.x = (StartPoint.x + PointerPos.x) / 2;
00320             NewCentre.y = (StartPoint.y + PointerPos.y) / 2;
00321             NewShape->SetCentrePoint(DocCoord(0,0));
00322             DocCoord NewMajor = PointerPos - NewCentre;
00323             Trans2DMatrix Trans1(DocCoord(0,0), 180-(180.0/NewShape->GetNumSides()));
00324             Trans1.Transform(&NewMajor, 1);
00325             NewShape->SetMajorAxes(NewMajor);
00326             DocCoord NewMinor = NewMajor;
00327             Trans2DMatrix Trans2(DocCoord(0,0), -90);
00328             Trans2.Transform(&NewMinor, 1);
00329             NewShape->SetMinorAxes(NewMinor);
00330             Matrix InitialMat(NewCentre.x, NewCentre.y);
00331             NewShape->SetTransformMatrix(&InitialMat);
00332             break;
00333         }
00334         case BOUNDS:
00335         {   
00336             DocCoord NewCentre;
00337             DocCoord NewMajor;
00338             DocCoord NewMinor;
00339             // If SHIFT is down then we need to reposition the shape in a similar way to the old
00340             // rectangle tool
00341             if (ClickMods.Adjust)
00342             {
00343                 if (!IsShiftDown)
00344                 {
00345                     IsShiftDown = TRUE;
00346                     RecentrePoint.x = (StartPoint.x + PointerPos.x) / 2;
00347                     RecentrePoint.y = (StartPoint.y + PointerPos.y) / 2;
00348                 }
00349                 DocRect BoundsRect(RecentrePoint, RecentrePoint);
00350                 BoundsRect.IncludePoint(PointerPos);
00351                 BoundsRect.IncludePoint(RecentrePoint + (RecentrePoint - PointerPos));
00352                 InflateShape(&BoundsRect, &NewCentre, &NewMajor, &NewMinor);
00353             }
00354             else
00355             {
00356                 if (IsShiftDown)
00357                 {
00358                     IsShiftDown = FALSE;
00359                     StartPoint = RecentrePoint + (RecentrePoint - PointerPos);
00360                 }
00361 
00362                 DocRect BoundsRect(StartPoint, StartPoint);
00363                 BoundsRect.IncludePoint(PointerPos);
00364                 InflateShape(&BoundsRect, &NewCentre, &NewMajor, &NewMinor);
00365             }
00366 
00367             NewShape->SetCentrePoint(DocCoord(0,0));    
00368             NewShape->SetMajorAxes(NewMajor - NewCentre);    
00369             NewShape->SetMinorAxes(NewMinor - NewCentre);    
00370             Matrix InitialMat(NewCentre.x, NewCentre.y);
00371             NewShape->SetTransformMatrix(&InitialMat);
00372             break;
00373         }
00374         default:
00375             ERROR3("Unknown creation type");
00376     }
00377 
00378     // Put the Eor back on again for the new shape
00379     EditPathBBox = NewShape->GetBoundingRect();
00380     RenderDragBlobs(EditPathBBox, StartSpread, bSolidDrag);
00381 
00382     BROADCAST_TO_ALL(ShapeEditedMsg(NewShape, pSpread));
00383 
00384     LastPoint = PointerPos;
00385 }

OpState OpNewRegShape::GetState String_256 Description,
OpDescriptor
[static]
 

Find out the state of the new regular shape at the specific time.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/11/94
Parameters:
- [OUTPUTS]
Returns:
Ungreyed, Unticked

Definition at line 638 of file oprshape.cpp.

00639 {
00640     OpState Blobby;
00641     
00642     return Blobby;
00643 }

void OpNewRegShape::InflateShape DocRect Bounds,
DocCoord NewCentre,
DocCoord NewMajor,
DocCoord NewMinor
[private]
 

NewMajor and NewMinor are initially positioned half way along the top and halfway down the righthand side of the Bounds rect respectivly, Their positions are then increased so that the shape path passes through their previous positions.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/1/95
Parameters:
Bounds - The bounding box of the initial shape [INPUTS] NewCenter - the centre point of the shape NewMajor - the proposed new major point NewMinor - the proposed new major point
NewMajor and NewMinor may have been repositioned [OUTPUTS]
Returns:
-

Definition at line 526 of file oprshape.cpp.

00527 {
00528     // Set their initial positions
00529     NewCentre->x = (Bounds->lo.x + Bounds->hi.x) / 2;
00530     NewCentre->y = (Bounds->lo.y + Bounds->hi.y) / 2;
00531     NewMajor->x = (Bounds->lo.x + Bounds->hi.x) / 2;
00532     NewMajor->y = Bounds->hi.y;
00533     NewMinor->x = Bounds->hi.x;
00534     NewMinor->y = (Bounds->lo.y + Bounds->hi.y) / 2;
00535     
00536     // Move them if required
00537     if (!NewShape->IsCircular())
00538     {
00539         DocCoord MajorRender = *NewMajor;
00540         DocCoord MinorRender = *NewMinor;
00541         double radius = NewCentre->Distance(*NewMajor);
00542         double SideA = cos(PI/NewShape->GetNumSides())*radius;
00543         if (SideA != 0.0)
00544         {
00545             DocCoord Update = DocCoord::PositionPointFromRatio(*NewCentre, *NewMajor, radius/SideA);
00546             NewMajor->y = Update.y;
00547         }
00548 
00549         if ( ((NewShape->GetNumSides() % 2) == 0) && (((NewShape->GetNumSides()/2) % 2) == 0) )
00550         {
00551             radius = NewCentre->Distance(*NewMinor);
00552             SideA = cos(PI/NewShape->GetNumSides())*radius;
00553             if (SideA != 0.0)
00554             {
00555                 DocCoord Update = DocCoord::PositionPointFromRatio(*NewCentre, *NewMinor, radius/SideA);
00556                 NewMinor->x = Update.x;
00557             }
00558         }
00559     }
00560 }

void OpNewRegShape::RenderDragBlobs DocRect  Rect,
Spread pSpread,
BOOL  bSolidDrag
[virtual]
 

Draws an EORed version of the current shape.

Author:
Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/11/94
Parameters:
Rect - The region that needs the blobs to be drawn [INPUTS] pSpread - The spread that the drawing will happen on

Reimplemented from Operation.

Definition at line 576 of file oprshape.cpp.

00577 {
00578     // If being called from DocView::RenderView, then the spread could be wrong - so
00579     // convert the rectangle if necessary.
00580     if (pSpread != StartSpread)
00581     {
00582         Rect.lo = MakeRelativeToSpread(StartSpread, pSpread, Rect.lo);
00583         Rect.hi = MakeRelativeToSpread(StartSpread, pSpread, Rect.hi);
00584     }
00585 
00586     // start a rendering loop
00587     RenderRegion* pRegion = DocView::RenderOnTop(NULL, pSpread, ClippedEOR);
00588     while (pRegion)
00589     {
00590         // Set the line colour 
00591         pRegion -> SetFillColour(COLOUR_NONE);
00592         pRegion -> SetLineColour(COLOUR_XORNEW);
00593 
00594         // Draw the outline
00595         NewShape->RenderEorDrag(pRegion);
00596 
00597         // Get the Next render region
00598         pRegion = DocView::GetNextOnTop(NULL);
00599     }
00600 }


Member Data Documentation

CreateMode OpNewRegShape::CreationMode [private]
 

Definition at line 161 of file oprshape.h.

BOOL OpNewRegShape::IsShiftDown [private]
 

Definition at line 163 of file oprshape.h.

DocCoord OpNewRegShape::LastPoint [private]
 

Definition at line 160 of file oprshape.h.

NodeRegularShape* OpNewRegShape::NewShape [private]
 

Definition at line 157 of file oprshape.h.

Cursor* OpNewRegShape::pCursor [private]
 

Definition at line 162 of file oprshape.h.

DocCoord OpNewRegShape::RecentrePoint [private]
 

Definition at line 164 of file oprshape.h.

DocCoord OpNewRegShape::StartPoint [private]
 

Definition at line 159 of file oprshape.h.

Spread* OpNewRegShape::StartSpread [private]
 

Definition at line 158 of file oprshape.h.


The documentation for this class was generated from the following files:
Generated on Sat Nov 10 03:58:30 2007 for Camelot by  doxygen 1.4.4