Skip to content

Bug/Enhancement: Eraser Tool Cannot Erase Rectangles/Circles + Add Perfect Square Modifier #26

@RuntimeRascal

Description

@RuntimeRascal

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 enhancement

Testing:

  • Verify Shift creates perfect squares
  • Verify without Shift creates normal rectangles
  • Test with both left and right Shift keys
  • Ensure existing rectangle behavior unchanged

Acceptance Criteria

Eraser Tool Fix

  • Eraser removes Rectangles on contact
  • Eraser removes Circles/Ellipses on contact
  • Existing Polyline/Line erasing still works
  • Unit tests cover all shape types
  • No performance regression

Rectangle Perfect Squares

  • Holding Shift while drawing constrains to perfect square
  • Releasing Shift returns to normal rectangle mode
  • Both Left Shift and Right Shift work
  • Preview updates in real-time when Shift state changes
  • F1 help documents Shift modifier
  • Unit tests cover Shift modifier behavior

Priority

Eraser Bug: HIGH - Core functionality broken for newer tools
Square Modifier: MEDIUM - Nice-to-have enhancement

Estimated Effort

  • Eraser fix: ~2-3 hours (straightforward bounds checking)
  • Square modifier: ~2-3 hours (keyboard state + constraint logic)
  • Total: ~4-6 hours

Related


Labels: bug, enhancement, eraser-tool, rectangle-tool

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingenhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions