Skip to content

Fix eraser tool for rectangles/circles + add shift modifier for perfect squares#29

Merged
RuntimeRascal merged 6 commits intomainfrom
copilot/fix-eraser-tool-functionality
Dec 8, 2025
Merged

Fix eraser tool for rectangles/circles + add shift modifier for perfect squares#29
RuntimeRascal merged 6 commits intomainfrom
copilot/fix-eraser-tool-functionality

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Dec 8, 2025

Eraser tool only removed polylines and lines, ignoring rectangles and circles. Rectangle tool lacked shift-to-constrain functionality present in circle tool.

Changes

Eraser Tool (EraserTool.cs)

  • Added bounds intersection detection for Rectangle and Ellipse shapes using IntersectsWith()
  • Added NaN guards for Canvas.GetLeft/GetTop to handle uninitialized attached properties

Rectangle Tool (RectangleTool.cs)

  • Added shift key detection in OnMouseMove and FinishRectangle to constrain to perfect square
  • Uses Math.Min(width, height) to fit square within dragged bounds (differs from circle tool's Math.Max approach per issue spec)
// Eraser now handles all shape types
else if (element is System.Windows.Shapes.Rectangle rectangle)
{
    double left = Canvas.GetLeft(rectangle);
    double top = Canvas.GetTop(rectangle);
    
    if (!double.IsNaN(left) && !double.IsNaN(top) && ...)
    {
        Rect shapeRect = new Rect(left, top, rectangle.Width, rectangle.Height);
        if (eraserRect.IntersectsWith(shapeRect))
            shouldErase = true;
    }
}

// Rectangle tool constrains to square when shift held
bool isShiftPressed = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);
if (isPerfectSquare)
{
    double size = Math.Min(width, height);
    width = size;
    height = size;
}
Original prompt

This section details on the original issue you should resolve

<issue_title>Eraser Tool Cannot Erase Rectangles/Circles + Add Perfect Square Modifier</issue_title>
<issue_description>## Bug/Enhancement: Eraser Tool Shape Support + Rectangle Perfect Squares

Issues

1. Eraser Tool Cannot Erase Rectangles and Circles (BUG)

Description:
The Eraser tool currently only erases Polylines (pen strokes) and Lines (straight line tool), but does not erase Rectangle or Circle shapes. This creates an inconsistent user experience where some drawn elements cannot be removed.

Current Behavior:

  • ✅ Eraser removes Polylines (Pen tool strokes)
  • ✅ Eraser removes Lines (Line tool)
  • ❌ Eraser does NOT remove Rectangles (Rectangle tool)
  • ❌ Eraser does NOT remove Circles (Circle tool)

Expected Behavior:
All drawn shapes should be erasable with the Eraser tool, regardless of which tool created them.

Impact:

  • Users cannot clean up Rectangle/Circle drawings without clearing the entire canvas (R key)
  • Inconsistent tool behavior reduces usability
  • Workaround: Must use Undo or clear entire canvas

2. Rectangle Tool - Add Perfect Square Modifier (ENHANCEMENT)

Description:
Add Shift modifier to Rectangle tool to constrain proportions and create perfect squares.

Proposed Behavior:

  • Without Shift: Draw any rectangle (current behavior)
  • With Shift held: Constrain to perfect square (width = height)
  • Similar to how image editing tools work (Photoshop, GIMP, etc.)

User Interaction:

  1. Press U to activate Rectangle tool
  2. Click first corner
  3. Hold Shift while moving mouse - preview shows perfect square
  4. Click second corner to finalize square

Proposed Solutions

Part 1: Fix Eraser Tool for Rectangles and Circles

Root Cause:
The EraserTool.cs likely only checks for Polyline and Line shape types in its intersection detection logic.

Implementation:

Update Src/GhostDraw/Tools/EraserTool.cs:

// Current code probably looks like:
if (child is Polyline polyline)
{
    // Check intersection with polyline
}
else if (child is Line line)
{
    // Check intersection with line
}

// Add these cases:
else if (child is Rectangle rectangle)
{
    // Check if eraser bounds intersects with rectangle bounds
    Rect eraserRect = new Rect(position.X - radius, position.Y - radius, 
                                radius * 2, radius * 2);
    Rect shapeRect = new Rect(
        Canvas.GetLeft(rectangle), 
        Canvas.GetTop(rectangle),
        rectangle.Width, 
        rectangle.Height
    );
    
    if (eraserRect.IntersectsWith(shapeRect))
    {
        canvas.Children.Remove(rectangle);
    }
}
else if (child is Ellipse ellipse)
{
    // Check if eraser bounds intersects with ellipse bounds
    Rect eraserRect = new Rect(position.X - radius, position.Y - radius, 
                                radius * 2, radius * 2);
    Rect ellipseRect = new Rect(
        Canvas.GetLeft(ellipse), 
        Canvas.GetTop(ellipse),
        ellipse.Width, 
        ellipse.Height
    );
    
    if (eraserRect.IntersectsWith(ellipseRect))
    {
        canvas.Children.Remove(ellipse);
    }
}

Files to Modify:

  • Src/GhostDraw/Tools/EraserTool.cs - Add Rectangle and Ellipse handling

Testing:

  • Create unit tests in Tests/GhostDraw.Tests/EraserToolTests.cs
  • Verify eraser removes rectangles when cursor overlaps
  • Verify eraser removes circles when cursor overlaps
  • Ensure existing Polyline/Line erasing still works

Part 2: Add Shift Modifier for Perfect Squares

Implementation:

Update Src/GhostDraw/Tools/RectangleTool.cs:

public void OnMouseMove(Point position, Canvas canvas, MouseButtonState leftButtonState)
{
    if (_isCreatingRectangle && _currentRectangle != null && _rectangleStartPoint.HasValue)
    {
        Point start = _rectangleStartPoint.Value;
        double width = Math.Abs(position.X - start.X);
        double height = Math.Abs(position.Y - start.Y);
        
        // Check if Shift is held for perfect square
        bool isShiftHeld = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);
        
        if (isShiftHeld)
        {
            // Constrain to square - use smaller dimension
            double size = Math.Min(width, height);
            width = size;
            height = size;
        }
        
        _currentRectangle.Width = width;
        _currentRectangle.Height = height;
        
        // Position rectangle at correct corner
        Canvas.SetLeft(_currentRectangle, Math.Min(start.X, position.X));
        Canvas.SetTop(_currentRectangle, Math.Min(start.Y, position.Y));
    }
}

Files to Modify:

  • Src/GhostDraw/Tools/RectangleTool.cs - Add Shift key detection and constraint logic

Documentation Updates:

  • README.md - Mention Shift modifier for squares
  • Views/OverlayWindow.xaml - Update F1 help overlay
  • CHANGELOG.md - Document enhance...

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI self-assigned this Dec 8, 2025
Copilot AI and others added 3 commits December 8, 2025 00:49
…t squares

Co-authored-by: RuntimeRascal <2422222+RuntimeRascal@users.noreply.github.com>
Co-authored-by: RuntimeRascal <2422222+RuntimeRascal@users.noreply.github.com>
Co-authored-by: RuntimeRascal <2422222+RuntimeRascal@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix eraser tool to support rectangles and circles Fix eraser tool for rectangles/circles + add shift modifier for perfect squares Dec 8, 2025
Copilot AI requested a review from RuntimeRascal December 8, 2025 00:57
@RuntimeRascal RuntimeRascal marked this pull request as ready for review December 8, 2025 01:27
@RuntimeRascal RuntimeRascal merged commit b1142ef into main Dec 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Eraser Tool Cannot Erase Rectangles/Circles + Add Perfect Square Modifier

2 participants