// **************************************************************************** // // Function Name: RSingleSelection::GetRotateHandle( ) // // Description: Retrieves a vector rect representing the rotation handle. // // Returns: Nothing // // Exceptions: Nothing // // **************************************************************************** // void RSingleSelection::GetRotateHandle( RRealVectorRect& rotateHandleRect ) const { // Get the bounding rect YSelectionBoundingRect boundingRect; GetSelectionBoundingRect( boundingRect ); RRealPoint centerPoint = boundingRect.GetCenterPoint( ); R2dTransform transform( boundingRect.GetTransform( ) ); transform.PostTranslate( centerPoint.m_x-boundingRect.m_TopLeft.m_x, centerPoint.m_y-boundingRect.m_TopLeft.m_y ); // Break the transform into its components YAngle angle; YRealDimension xScale; YRealDimension yScale; transform.Decompose( angle, xScale, yScale ); // Figure out where to end the line RRealPoint lineEndPoint = GetRotateHandleCenterPoint( ); YRealDimension distance = centerPoint.Distance( lineEndPoint ); if ( xScale < 0 ) xScale = -xScale; rotateHandleRect.Set( RRealSize(distance/xScale,1), transform ); // Convert to device units RRealSize handleSize( kRotateHandleHitSize/2, kRotateHandleHitSize/2 ); ::DeviceUnitsToLogicalUnits( handleSize, *m_pView ); rotateHandleRect.Inflate( handleSize ); }
// **************************************************************************** // // Function Name: RSingleSelection::DrawRotateHandle( ) // // Description: Draws the rotation line and handle // // Returns: Nothing // // Exceptions: Memory // // **************************************************************************** // void RSingleSelection::DrawRotateHandle( RDrawingSurface& drawingSurface, const R2dTransform& transform, const RIntRect& ) const { // Get the bounding rect YSelectionBoundingRect boundingRect; GetSelectionBoundingRect( boundingRect ); // Get the center point; this will be one end point of the rotate handle line RRealPoint centerPoint = boundingRect.GetCenterPoint( ); // Get the other end point RRealPoint lineEndPoint = GetRotateHandleCenterPoint( ); // Draw the line drawingSurface.MoveTo( centerPoint, transform ); drawingSurface.LineTo( lineEndPoint, transform ); // Now draw the rotate handle // Convert to device units ::LogicalUnitsToDeviceUnits( lineEndPoint, *m_pView ); // Now build the rotate handle, using this point as the middle of the left side RRealRect rotateHandleRect; rotateHandleRect.m_Left = lineEndPoint.m_x - ( kRotateHandleRenderSize / 2 ); rotateHandleRect.m_Top = lineEndPoint.m_y - ( kRotateHandleRenderSize / 2 ); rotateHandleRect.m_Right = lineEndPoint.m_x + ( kRotateHandleRenderSize / 2 ) + 1; rotateHandleRect.m_Bottom = lineEndPoint.m_y + ( kRotateHandleRenderSize / 2 ) + 1; ::DeviceUnitsToLogicalUnits( rotateHandleRect, *m_pView ); // Now draw the rotate handle rotateHandleRect *= transform; drawingSurface.FillRectangle( rotateHandleRect ); }
// **************************************************************************** // // Function Name: RSingleSelection::GetRotateHandleCenterPoint( ) // // Description: Retrieves the center point of the rotate handle // // Returns: See above // // Exceptions: Nothing // // **************************************************************************** // RRealPoint RSingleSelection::GetRotateHandleCenterPoint( ) const { // Get the bounding rect and center point YSelectionBoundingRect boundingRect; GetSelectionBoundingRect( boundingRect ); RRealPoint centerPoint = boundingRect.GetCenterPoint( ); // We are going to use ratios of similar triangles to calculate the position of the rotate handle YRealDimension deltaX = boundingRect.m_BottomRight.m_x - boundingRect.m_BottomLeft.m_x; YRealDimension deltaY = boundingRect.m_BottomRight.m_y - boundingRect.m_BottomLeft.m_y; YRealDimension deltaXPrime = deltaX * ( 0.5 + kRotateHandleLineLengthRatio ); YRealDimension deltaYPrime = deltaY * ( 0.5 + kRotateHandleLineLengthRatio ); return RRealPoint( centerPoint.m_x + deltaXPrime, centerPoint.m_y + deltaYPrime ); }
// **************************************************************************** // // Function Name: RRotateSelectionTracker::BeginTracking( ) // // Description: Called when tracking begins; ie. when the mouse button goes // down. // // Returns: Nothing // // Exceptions: None // // **************************************************************************** // void RRotateSelectionTracker::BeginTracking( const RRealPoint& mousePoint, YModifierKey modifierKeys ) { // Remove the selection m_pSelection->Remove( FALSE ); // Get the controlling object RSingleSelection* pHitObject = m_pSelection->GetHitSingleSelection( mousePoint ); TpsAssert( pHitObject, "No hit object!" ); // Save the original handle point m_TrackingOriginalHandlePoint = pHitObject->GetRotateHandleCenterPoint( ); // Get its bounding rect YSelectionBoundingRect objectBoundingRect; pHitObject->GetObjectBoundingRect( objectBoundingRect ); // Save away the initial rotation angle of the controlling object. We might // need it to do constraining RRealSize delta = m_TrackingOriginalHandlePoint - objectBoundingRect.GetCenterPoint( ); m_ControllingObjectInitialAngle = ::atan2( -delta.m_dy, delta.m_dx ); // Get the center of the selection and use it as the center of rotation YSelectionBoundingRect boundingRect; m_pSelection->GetSelectionBoundingRect( boundingRect ); m_TrackingRotationCenter = boundingRect.GetCenterPoint( ); // Compute the initial angle delta = m_TrackingOriginalHandlePoint - m_TrackingRotationCenter; m_TrackingInitialRotationAngle = ::atan2( delta.m_dy, delta.m_dx ); // If the appropriate modifiey key is down, constrain the rotation m_fConstrainRotation = static_cast<BOOLEAN>( modifierKeys & kRotateConstrainModifier ); // Call the base class RSelectionTracker::BeginTracking( mousePoint, modifierKeys ); }
// **************************************************************************** // // Function Name: RCompositeSelection::GetSelectionBoundingRect( ) // // Description: Retrieves the bounding rect of this selection // // Returns: Nothing // // Exceptions: Memory // // **************************************************************************** // void RCompositeSelection::GetSelectionBoundingRect( YSelectionBoundingRect& boundingRect ) const { // Get the first bounding rect YSelectionCollectionIterator iterator = m_SelectionCollection.Start( ); ( *iterator )->GetSelectionBoundingRect( boundingRect ); RRealRect unionRect = boundingRect.m_TransformedBoundingRect; ++iterator; // Union in the rest of the bounding rects for( ; iterator != m_SelectionCollection.End( ); ++iterator ) { ( *iterator )->GetSelectionBoundingRect( boundingRect ); unionRect.Union( unionRect, boundingRect.m_TransformedBoundingRect ); } // Set the rect boundingRect.Set( unionRect ); }
// **************************************************************************** // // Function Name: RResizeSelectionTracker::BeginTracking( ) // // Description: Called when tracking begins; ie. when the mouse button goes // down. // // Returns: Nothing // // Exceptions: None // // **************************************************************************** // void RResizeSelectionTracker::BeginTracking( const RRealPoint& mousePoint, YModifierKey modifierKeys ) { // Remove the selection m_pSelection->Remove( FALSE ); // Get the hit object RSingleSelection* pHitObject = m_pSelection->GetHitSingleSelection( mousePoint ); TpsAssert( pHitObject, "No hit object!" ); // Get its selection bounding rect YSelectionBoundingRect selectionBoundingRect; pHitObject->GetSelectionBoundingRect( selectionBoundingRect ); // Get the bounding rect of the actual object YSelectionBoundingRect objectBoundingRect; pHitObject->GetObjectBoundingRect( objectBoundingRect ); // Calculate the minimum scale factor RRealSize minimumObjectSize = pHitObject->GetObjectMinimumSize( ); RRealSize maximumObjectSize = pHitObject->GetObjectMaximumSize( ); RRealSize currentObjectSize = objectBoundingRect.WidthHeight( ); m_MinimumScaleFactor.m_dx = minimumObjectSize.m_dx / currentObjectSize.m_dx; m_MinimumScaleFactor.m_dy = minimumObjectSize.m_dy / currentObjectSize.m_dy; m_MaximumScaleFactor.m_dx = maximumObjectSize.m_dx / currentObjectSize.m_dx; m_MaximumScaleFactor.m_dy = maximumObjectSize.m_dy / currentObjectSize.m_dy; // Hit test to figure out what kind of resizing we are doing RSelection::EHitLocation eHitLocation = m_pSelection->HitTest( mousePoint ); // Get the center and start of scaling RRealPoint selectionScalingCenter; switch( eHitLocation ) { case RSelection::kTopLeftResizeHandle : selectionScalingCenter = selectionBoundingRect.m_BottomRight; m_ScalingCenter = objectBoundingRect.m_BottomRight; m_MouseDownPoint = objectBoundingRect.m_TopLeft; break; case RSelection::kTopRightResizeHandle : selectionScalingCenter = selectionBoundingRect.m_BottomLeft; m_ScalingCenter = objectBoundingRect.m_BottomLeft; m_MouseDownPoint = objectBoundingRect.m_TopRight; break; case RSelection::kBottomRightResizeHandle : selectionScalingCenter = selectionBoundingRect.m_TopLeft; m_ScalingCenter = objectBoundingRect.m_TopLeft; m_MouseDownPoint = objectBoundingRect.m_BottomRight; break; case RSelection::kBottomLeftResizeHandle : selectionScalingCenter = selectionBoundingRect.m_TopRight; m_ScalingCenter = objectBoundingRect.m_TopRight; m_MouseDownPoint = objectBoundingRect.m_BottomLeft; break; case RSelection::kLeftResizeHandle : ::midpoint(selectionScalingCenter,selectionBoundingRect.m_TopRight,selectionBoundingRect.m_BottomRight); ::midpoint(m_ScalingCenter,objectBoundingRect.m_TopRight,objectBoundingRect.m_BottomRight); ::midpoint(m_MouseDownPoint,objectBoundingRect.m_TopLeft,objectBoundingRect.m_BottomLeft); m_fFixVertical = TRUE; break; case RSelection::kTopResizeHandle : ::midpoint(selectionScalingCenter,selectionBoundingRect.m_BottomLeft,selectionBoundingRect.m_BottomRight); ::midpoint(m_ScalingCenter,objectBoundingRect.m_BottomLeft,objectBoundingRect.m_BottomRight); ::midpoint(m_MouseDownPoint,objectBoundingRect.m_TopLeft,objectBoundingRect.m_TopRight); m_fFixHorizontal = TRUE; break; case RSelection::kRightResizeHandle : ::midpoint(selectionScalingCenter,selectionBoundingRect.m_TopLeft,selectionBoundingRect.m_BottomLeft); ::midpoint(m_ScalingCenter,objectBoundingRect.m_TopLeft,objectBoundingRect.m_BottomLeft); ::midpoint(m_MouseDownPoint,objectBoundingRect.m_TopRight,objectBoundingRect.m_BottomRight); m_fFixVertical = TRUE; break; case RSelection::kBottomResizeHandle : ::midpoint(selectionScalingCenter,selectionBoundingRect.m_TopLeft,selectionBoundingRect.m_TopRight); ::midpoint(m_ScalingCenter,objectBoundingRect.m_TopLeft,objectBoundingRect.m_TopRight); ::midpoint(m_MouseDownPoint,objectBoundingRect.m_BottomLeft,objectBoundingRect.m_BottomRight); m_fFixHorizontal = TRUE; break; default : TpsAssert( NULL, "Tracker is not resizing." ); } // Save the difference between the size of the selection and object rects m_RectDelta = selectionScalingCenter - m_ScalingCenter; // Determine if we should maintain aspect ratio or not. Ask the component what its default // behavior is, and invert that if the conrol key is down m_fMaintainAspectRatio = pHitObject->MaintainAspectRatioIsDefault( ); if( pHitObject->CanChangeDefaultAspect( ) && ( modifierKeys & kAspectModifier ) ) m_fMaintainAspectRatio = static_cast<BOOLEAN>( !m_fMaintainAspectRatio ); // If we are fixing either Vertical or Horizontal dimension, we can't be // maintaining aspect ratio if ( m_fFixVertical || m_fFixHorizontal ) m_fMaintainAspectRatio = FALSE; // Save the inverse transform of the object m_InverseTransform = objectBoundingRect.GetTransform( ); m_InverseTransform.Invert( ); // Call the base class RSelectionTracker::BeginTracking( mousePoint, modifierKeys ); }
// **************************************************************************** // // Function Name: RSingleSelection::GetResizeSelectionHandle( ) // // Description: Retrieves a vector rect representing requested resize handle. // // Returns: Nothing // // Exceptions: Memory // // **************************************************************************** // void RSingleSelection::GetResizeSelectionHandle( RRealRect& rHandle, const R2dTransform& transform, EHitLocation eHit, BOOLEAN fRender ) const { RRealPoint point; YSelectionBoundingRect boundingRect; RIntSize outsetSize = (fRender)? RRealSize( kCornerResizeHandleRenderSize, kCornerResizeHandleRenderSize ) : RRealSize( kResizeHandleHitSize, kResizeHandleHitSize ); // Get the bounding rectangle GetSelectionBoundingRect( boundingRect ); // Get the proper point to transform switch ( eHit ) { case kLeftResizeHandle: ::midpoint( point, boundingRect.m_TopLeft, boundingRect.m_BottomLeft ); outsetSize.m_dx = Max( kEdgeResizeHandleRenderSize, YIntDimension(outsetSize.m_dx/2) ); break; case kTopResizeHandle: ::midpoint( point, boundingRect.m_TopLeft, boundingRect.m_TopRight ); outsetSize.m_dy = Max( kEdgeResizeHandleRenderSize, YIntDimension(outsetSize.m_dy/2) ); break; case kRightResizeHandle: ::midpoint( point, boundingRect.m_TopRight, boundingRect.m_BottomRight ); outsetSize.m_dx = Max( kEdgeResizeHandleRenderSize, YIntDimension(outsetSize.m_dx/2) ); break; case kBottomResizeHandle: ::midpoint( point, boundingRect.m_BottomLeft, boundingRect.m_BottomRight ); outsetSize.m_dy = Max( kEdgeResizeHandleRenderSize, YIntDimension(outsetSize.m_dy/2) ); break; case kTopLeftResizeHandle: point = boundingRect.m_TopLeft; break; case kTopRightResizeHandle: point = boundingRect.m_TopRight; break; case kBottomLeftResizeHandle: point = boundingRect.m_BottomLeft; break; case kBottomRightResizeHandle: point = boundingRect.m_BottomRight; break; default : TpsAssertAlways( "Asking for the selection handle of invalid type" ); point = boundingRect.GetCenterPoint(); } RIntSize halfOutset( outsetSize.m_dx/2, outsetSize.m_dy/2); ::LogicalUnitsToDeviceUnits( point, *m_pView ); rHandle.m_Left = point.m_x - halfOutset.m_dx; rHandle.m_Top = point.m_y - halfOutset.m_dy; rHandle.m_Right = point.m_x + outsetSize.m_dx - halfOutset.m_dx; rHandle.m_Bottom = point.m_y + outsetSize.m_dy - halfOutset.m_dy; ::DeviceUnitsToLogicalUnits( rHandle, *m_pView ); rHandle *= transform; }