Commit b05885c2 authored by Maciej Suminski's avatar Maciej Suminski

Refactored drawing tools: lines, circles and arcs.

parent 69c73b0e
...@@ -74,208 +74,49 @@ int DRAWING_TOOL::DrawLine( TOOL_EVENT& aEvent ) ...@@ -74,208 +74,49 @@ int DRAWING_TOOL::DrawLine( TOOL_EVENT& aEvent )
{ {
m_frame->SetToolID( ID_PCB_ADD_LINE_BUTT, wxCURSOR_PENCIL, _( "Add graphic line" ) ); m_frame->SetToolID( ID_PCB_ADD_LINE_BUTT, wxCURSOR_PENCIL, _( "Add graphic line" ) );
return drawSegment( S_SEGMENT, true ); DRAWSEGMENT* line = new DRAWSEGMENT;
}
int DRAWING_TOOL::DrawCircle( TOOL_EVENT& aEvent )
{
m_frame->SetToolID( ID_PCB_CIRCLE_BUTT, wxCURSOR_PENCIL, _( "Add graphic circle" ) );
return drawSegment( S_CIRCLE, false );
}
int DRAWING_TOOL::DrawArc( TOOL_EVENT& aEvent )
{
bool clockwise = true; // drawing direction of the arc
double startAngle = 0.0f; // angle of the first arc line
VECTOR2I cursorPos = m_controls->GetCursorPosition();
DRAWSEGMENT* arc = NULL;
DRAWSEGMENT helperLine;
helperLine.SetShape( S_SEGMENT );
helperLine.SetLayer( Dwgs_User );
helperLine.SetWidth( 1 );
// Add a VIEW_GROUP that serves as a preview for the new item
KIGFX::VIEW_GROUP preview( m_view );
m_view->Add( &preview );
m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear ); while( drawSegment( S_SEGMENT, line ) )
m_controls->ShowCursor( true );
m_controls->SetSnapping( true );
Activate();
m_frame->SetToolID( ID_PCB_ARC_BUTT, wxCURSOR_PENCIL, _( "Add graphic arc" ) );
enum ARC_STEPS
{
SET_ORIGIN = 0,
SET_END,
SET_ANGLE,
FINISHED
};
int step = SET_ORIGIN;
// Main loop: keep receiving events
while( OPT_TOOL_EVENT evt = Wait() )
{ {
cursorPos = m_controls->GetCursorPosition(); line = new DRAWSEGMENT;
if( evt->IsCancel() || evt->IsActivate() )
{
if( step != SET_ORIGIN ) // start from the beginning
{
preview.Clear();
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
delete arc;
step = SET_ORIGIN;
}
else
break;
if( evt->IsActivate() ) // now finish unconditionally
break;
} }
else if( evt->IsKeyPressed() && step != SET_ORIGIN ) setTransitions();
{ m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
int width = arc->GetWidth();
// Modify the new item width
if( evt->KeyCode() == '-' && width > WIDTH_STEP )
arc->SetWidth( width - WIDTH_STEP );
else if( evt->KeyCode() == '=' )
arc->SetWidth( width + WIDTH_STEP );
else if( evt->KeyCode() == '/' )
{
if( clockwise )
arc->SetAngle( arc->GetAngle() - 3600.0 );
else
arc->SetAngle( arc->GetAngle() + 3600.0 );
clockwise = !clockwise;
}
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
}
else if( evt->IsClick( BUT_LEFT ) )
{
switch( step )
{
case SET_ORIGIN:
{
LAYER_ID layer = m_frame->GetScreen()->m_Active_Layer;
if( IsCopperLayer( layer ) ) return 0;
{ }
DisplayInfoMessage( NULL, _( "Graphic not allowed on Copper layers" ) );
--step;
}
else
{
// Init the new item attributes
arc = new DRAWSEGMENT( m_board );
arc->SetShape( S_ARC );
arc->SetAngle( 0.0 );
arc->SetWidth( m_board->GetDesignSettings().m_DrawSegmentWidth );
arc->SetCenter( wxPoint( cursorPos.x, cursorPos.y ) );
arc->SetLayer( layer );
helperLine.SetStart( arc->GetCenter() );
helperLine.SetEnd( arc->GetCenter() );
preview.Add( arc ); int DRAWING_TOOL::DrawCircle( TOOL_EVENT& aEvent )
preview.Add( &helperLine ); {
m_frame->SetToolID( ID_PCB_CIRCLE_BUTT, wxCURSOR_PENCIL, _( "Add graphic circle" ) );
m_controls->SetAutoPan( true ); DRAWSEGMENT* circle = new DRAWSEGMENT;
}
}
break;
case SET_END: while( drawSegment( S_CIRCLE, circle ) )
{
if( wxPoint( cursorPos.x, cursorPos.y ) != arc->GetCenter() )
{ {
VECTOR2D startLine( arc->GetArcStart() - arc->GetCenter() ); circle = new DRAWSEGMENT;
startAngle = startLine.Angle();
arc->SetArcStart( wxPoint( cursorPos.x, cursorPos.y ) );
}
else
--step; // one another chance to draw a proper arc
} }
break;
case SET_ANGLE:
{
if( wxPoint( cursorPos.x, cursorPos.y ) != arc->GetArcStart() )
{
assert( arc->GetAngle() != 0 );
assert( arc->GetArcStart() != arc->GetArcEnd() );
assert( arc->GetWidth() > 0 );
m_view->Add( arc ); setTransitions();
m_board->Add( arc ); m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
arc->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
m_frame->OnModify(); return 0;
m_frame->SaveCopyInUndoList( arc, UR_NEW ); }
preview.Remove( arc );
preview.Remove( &helperLine );
}
else
--step; // one another chance to draw a proper arc
}
break;
}
if( ++step == FINISHED ) int DRAWING_TOOL::DrawArc( TOOL_EVENT& aEvent )
{ {
step = SET_ORIGIN; m_frame->SetToolID( ID_PCB_ARC_BUTT, wxCURSOR_PENCIL, _( "Add graphic arc" ) );
m_controls->SetAutoPan( false );
}
}
else if( evt->IsMotion() ) DRAWSEGMENT* arc = new DRAWSEGMENT;
{
switch( step )
{
case SET_END:
helperLine.SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
arc->SetArcStart( wxPoint( cursorPos.x, cursorPos.y ) );
break;
case SET_ANGLE: while( drawArc( arc ) )
{ {
VECTOR2D endLine( wxPoint( cursorPos.x, cursorPos.y ) - arc->GetCenter() ); arc = new DRAWSEGMENT;
double newAngle = RAD2DECIDEG( endLine.Angle() - startAngle );
// Adjust the new angle to (counter)clockwise setting
if( clockwise && newAngle < 0.0 )
newAngle += 3600.0;
else if( !clockwise && newAngle > 0.0 )
newAngle -= 3600.0;
arc->SetAngle( newAngle );
}
break;
}
// Show a preview of the item
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
}
} }
m_controls->ShowCursor( false );
m_controls->SetSnapping( false );
m_controls->SetAutoPan( false );
m_view->Remove( &preview );
setTransitions(); setTransitions();
m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
...@@ -884,12 +725,11 @@ int DRAWING_TOOL::PlaceModule( TOOL_EVENT& aEvent ) ...@@ -884,12 +725,11 @@ int DRAWING_TOOL::PlaceModule( TOOL_EVENT& aEvent )
} }
int DRAWING_TOOL::drawSegment( int aShape, bool aContinous ) bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT* aGraphic )
{ {
// Only two shapes are currently supported // Only two shapes are currently supported
assert( aShape == S_SEGMENT || aShape == S_CIRCLE ); assert( aShape == S_SEGMENT || aShape == S_CIRCLE );
DRAWSEGMENT* graphic = NULL;
DRAWSEGMENT line45; DRAWSEGMENT line45;
// Add a VIEW_GROUP that serves as a preview for the new item // Add a VIEW_GROUP that serves as a preview for the new item
...@@ -903,7 +743,7 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous ) ...@@ -903,7 +743,7 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous )
Activate(); Activate();
bool direction45 = false; // 45 degrees only mode bool direction45 = false; // 45 degrees only mode
int addedSegments = 0; bool started = false;
// Main loop: keep receiving events // Main loop: keep receiving events
while( OPT_TOOL_EVENT evt = Wait() ) while( OPT_TOOL_EVENT evt = Wait() )
...@@ -912,19 +752,19 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous ) ...@@ -912,19 +752,19 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous )
VECTOR2I cursorPos = m_controls->GetCursorPosition(); VECTOR2I cursorPos = m_controls->GetCursorPosition();
// Enable 45 degrees lines only mode by holding control // Enable 45 degrees lines only mode by holding control
if( direction45 != evt->Modifier( MD_CTRL ) && graphic && aShape == S_SEGMENT ) if( direction45 != evt->Modifier( MD_CTRL ) && started && aShape == S_SEGMENT )
{ {
direction45 = evt->Modifier( MD_CTRL ); direction45 = evt->Modifier( MD_CTRL );
if( direction45 ) if( direction45 )
{ {
preview.Add( &line45 ); preview.Add( &line45 );
make45DegLine( graphic, &line45 ); make45DegLine( aGraphic, &line45 );
} }
else else
{ {
preview.Remove( &line45 ); preview.Remove( &line45 );
graphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
} }
updatePreview = true; updatePreview = true;
...@@ -932,37 +772,28 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous ) ...@@ -932,37 +772,28 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous )
if( evt->IsCancel() || evt->IsActivate() ) if( evt->IsCancel() || evt->IsActivate() )
{ {
if( !graphic )
break;
preview.Clear(); preview.Clear();
updatePreview = true; updatePreview = true;
delete aGraphic;
delete graphic;
graphic = NULL;
m_controls->SetAutoPan( false );
if( evt->IsActivate() ) // now finish unconditionally
break; break;
} }
else if( graphic && evt->IsKeyPressed() ) else if( evt->IsKeyPressed() )
{ {
int width = graphic->GetWidth(); int width = aGraphic->GetWidth();
// Modify the new item width // Modify the new item width
if( evt->KeyCode() == '-' && width > WIDTH_STEP ) if( evt->KeyCode() == '-' && width > WIDTH_STEP ) // TODO change it to TOOL_ACTIONs
graphic->SetWidth( width - WIDTH_STEP ); aGraphic->SetWidth( width - WIDTH_STEP );
else if( evt->KeyCode() == '=' ) else if( evt->KeyCode() == '=' )
graphic->SetWidth( width + WIDTH_STEP ); aGraphic->SetWidth( width + WIDTH_STEP );
updatePreview = true; updatePreview = true;
} }
else if( evt->IsClick( BUT_LEFT ) ) else if( evt->IsClick( BUT_LEFT ) )
{ {
if( !graphic ) if( !started )
{ {
LAYER_ID layer = m_frame->GetScreen()->m_Active_Layer; LAYER_ID layer = m_frame->GetScreen()->m_Active_Layer;
...@@ -973,95 +804,248 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous ) ...@@ -973,95 +804,248 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous )
else else
{ {
// Init the new item attributes // Init the new item attributes
graphic = new DRAWSEGMENT( m_board ); aGraphic->SetShape( (STROKE_T) aShape );
graphic->SetShape( (STROKE_T) aShape ); aGraphic->SetWidth( m_board->GetDesignSettings().m_DrawSegmentWidth );
graphic->SetWidth( m_board->GetDesignSettings().m_DrawSegmentWidth ); aGraphic->SetStart( wxPoint( cursorPos.x, cursorPos.y ) );
graphic->SetStart( wxPoint( cursorPos.x, cursorPos.y ) ); aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
graphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); aGraphic->SetLayer( layer );
graphic->SetLayer( layer );
if( aShape == S_SEGMENT ) if( aShape == S_SEGMENT )
{ {
line45 = *graphic; // used only for direction 45 mode with lines line45 = *aGraphic; // used only for direction 45 mode with lines
line45.SetLayer( layer ); line45.SetLayer( layer );
} }
preview.Add( graphic ); preview.Add( aGraphic );
m_controls->SetAutoPan( true ); m_controls->SetAutoPan( true );
started = true;
} }
} }
else else
{ {
if( graphic->GetEnd() != graphic->GetStart() ) if( aGraphic->GetEnd() != aGraphic->GetStart() )
{ {
assert( graphic->GetLength() > 0 ); assert( aGraphic->GetLength() > 0 );
assert( graphic->GetWidth() > 0 ); assert( aGraphic->GetWidth() > 0 );
m_view->Add( graphic ); m_view->Add( aGraphic );
m_board->Add( graphic ); m_board->Add( aGraphic );
graphic->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); aGraphic->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
m_frame->OnModify(); m_frame->OnModify();
m_frame->SaveCopyInUndoList( graphic, UR_NEW ); m_frame->SaveCopyInUndoList( aGraphic, UR_NEW );
}
else // User has clicked twice in the same spot
{ // a clear sign that the current drawing is finished
delete aGraphic; // but only if at least one graphic was created
started = false; // otherwise - force user to draw more or cancel
}
preview.Remove( graphic ); preview.Clear();
++addedSegments; break;
}
}
if( aContinous ) else if( evt->IsMotion() )
{ {
graphic = new DRAWSEGMENT( *graphic ); // 45 degree lines
if( direction45 && aShape == S_SEGMENT )
make45DegLine( aGraphic, &line45 );
else
aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
updatePreview = true;
}
// Start the new line in the same spot where the previous one has ended if( updatePreview )
graphic->SetStart( graphic->GetEnd() ); preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
}
if( direction45 ) m_controls->ShowCursor( false );
graphic->SetEnd( line45.GetEnd() ); m_controls->SetSnapping( false );
m_controls->SetAutoPan( false );
m_view->Remove( &preview );
return started;
}
preview.Add( graphic );
bool DRAWING_TOOL::drawArc( DRAWSEGMENT* aGraphic )
{
bool clockwise = true; // drawing direction of the arc
double startAngle = 0.0f; // angle of the first arc line
VECTOR2I cursorPos = m_controls->GetCursorPosition();
DRAWSEGMENT helperLine;
helperLine.SetShape( S_SEGMENT );
helperLine.SetLayer( Dwgs_User );
helperLine.SetWidth( 1 );
// Add a VIEW_GROUP that serves as a preview for the new item
KIGFX::VIEW_GROUP preview( m_view );
m_view->Add( &preview );
m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear );
m_controls->ShowCursor( true );
m_controls->SetSnapping( true );
Activate();
enum ARC_STEPS
{
SET_ORIGIN = 0,
SET_END,
SET_ANGLE,
FINISHED
};
int step = SET_ORIGIN;
// Main loop: keep receiving events
while( OPT_TOOL_EVENT evt = Wait() )
{
cursorPos = m_controls->GetCursorPosition();
if( evt->IsCancel() || evt->IsActivate() )
{
preview.Clear();
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
delete aGraphic;
break;
} }
else // start a new graphic
else if( evt->IsKeyPressed() && step != SET_ORIGIN )
{ {
addedSegments = 0; int width = aGraphic->GetWidth();
m_controls->SetAutoPan( false );
graphic = NULL; // Modify the new item width
if( evt->KeyCode() == '-' && width > WIDTH_STEP ) // TODO convert to tool actions
aGraphic->SetWidth( width - WIDTH_STEP );
else if( evt->KeyCode() == '=' )
aGraphic->SetWidth( width + WIDTH_STEP );
else if( evt->KeyCode() == '/' )
{
if( clockwise )
aGraphic->SetAngle( aGraphic->GetAngle() - 3600.0 );
else
aGraphic->SetAngle( aGraphic->GetAngle() + 3600.0 );
clockwise = !clockwise;
} }
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
} }
else if( addedSegments > 0 ) // User has clicked twice in the same spot
{ // a clear sign that the current drawing is finished
preview.Clear(); // but only if at least one graphic was created
// otherwise - force user to draw more or cancel
delete graphic;
graphic = NULL;
m_controls->SetAutoPan( false ); else if( evt->IsClick( BUT_LEFT ) )
{
switch( step )
{
case SET_ORIGIN:
{
LAYER_ID layer = m_frame->GetScreen()->m_Active_Layer;
if( IsCopperLayer( layer ) )
{
DisplayInfoMessage( NULL, _( "Graphic not allowed on Copper layers" ) );
--step;
} }
else
{
// Init the new item attributes
aGraphic->SetShape( S_ARC );
aGraphic->SetAngle( 0.0 );
aGraphic->SetWidth( m_board->GetDesignSettings().m_DrawSegmentWidth );
aGraphic->SetCenter( wxPoint( cursorPos.x, cursorPos.y ) );
aGraphic->SetLayer( layer );
helperLine.SetStart( aGraphic->GetCenter() );
helperLine.SetEnd( aGraphic->GetCenter() );
preview.Add( aGraphic );
preview.Add( &helperLine );
m_controls->SetAutoPan( true );
} }
} }
break;
else if( graphic && evt->IsMotion() ) case SET_END:
{ {
// 45 degree lines if( wxPoint( cursorPos.x, cursorPos.y ) != aGraphic->GetCenter() )
if( direction45 && aShape == S_SEGMENT ) {
make45DegLine( graphic, &line45 ); VECTOR2D startLine( aGraphic->GetArcStart() - aGraphic->GetCenter() );
startAngle = startLine.Angle();
aGraphic->SetArcStart( wxPoint( cursorPos.x, cursorPos.y ) );
}
else else
graphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); --step; // one another chance to draw a proper arc
}
break;
updatePreview = true; case SET_ANGLE:
{
if( wxPoint( cursorPos.x, cursorPos.y ) != aGraphic->GetArcStart() )
{
assert( aGraphic->GetAngle() != 0 );
assert( aGraphic->GetArcStart() != aGraphic->GetArcEnd() );
assert( aGraphic->GetWidth() > 0 );
m_view->Add( aGraphic );
m_board->Add( aGraphic );
aGraphic->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
m_frame->OnModify();
m_frame->SaveCopyInUndoList( aGraphic, UR_NEW );
preview.Remove( aGraphic );
preview.Remove( &helperLine );
}
else
--step; // one another chance to draw a proper arc
}
break;
} }
if( updatePreview ) if( ++step == FINISHED )
break;
}
else if( evt->IsMotion() )
{
switch( step )
{
case SET_END:
helperLine.SetEnd( wxPoint( cursorPos.x, cursorPos.y ) );
aGraphic->SetArcStart( wxPoint( cursorPos.x, cursorPos.y ) );
break;
case SET_ANGLE:
{
VECTOR2D endLine( wxPoint( cursorPos.x, cursorPos.y ) - aGraphic->GetCenter() );
double newAngle = RAD2DECIDEG( endLine.Angle() - startAngle );
// Adjust the new angle to (counter)clockwise setting
if( clockwise && newAngle < 0.0 )
newAngle += 3600.0;
else if( !clockwise && newAngle > 0.0 )
newAngle -= 3600.0;
aGraphic->SetAngle( newAngle );
}
break;
}
// Show a preview of the item
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
} }
}
m_controls->ShowCursor( false ); m_controls->ShowCursor( false );
m_controls->SetSnapping( false ); m_controls->SetSnapping( false );
m_controls->SetAutoPan( false ); m_controls->SetAutoPan( false );
m_view->Remove( &preview ); m_view->Remove( &preview );
setTransitions(); return ( step > SET_ORIGIN );
m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
return 0;
} }
......
...@@ -130,8 +130,18 @@ public: ...@@ -130,8 +130,18 @@ public:
private: private:
///> Starts drawing a selected shape (i.e. DRAWSEGMENT). ///> Starts drawing a selected shape (i.e. DRAWSEGMENT).
///> @param aShape is the type of created shape (@see STROKE_T). ///> @param aShape is the type of created shape (@see STROKE_T).
///> @param aContinous decides if there is only one or multiple shapes to draw. ///> @param aGraphic is an object that is going to be used by the tool for drawing. It has to
int drawSegment( int aShape, bool aContinous ); ///> be already created. The tool deletes the object if it is not added to a BOARD.
///> @return False if the tool was cancelled before the origin was set or origin and end are
///> the same point.
bool drawSegment( int aShape, DRAWSEGMENT* aGraphic );
///> Starts drawing an arc.
///> @param aGraphic is an object that is going to be used by the tool for drawing. It has to
///> be already created. The tool deletes the object if it is not added to a BOARD.
///> @return False if the tool was cancelled before the origin was set or origin and end are
///> the same point.
bool drawArc( DRAWSEGMENT* aGraphic );
///> Draws a polygon, that is added as a zone or a keepout area. ///> Draws a polygon, that is added as a zone or a keepout area.
///> @param aKeepout decides if the drawn polygon is a zone or a keepout area. ///> @param aKeepout decides if the drawn polygon is a zone or a keepout area.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment