TOOL_ACTIONs are handled with transitions, no handlers needed in the event loops

There used to be a number of TOOL_ACTIONs that had entries both in
SetTransitions() and the event loop, which seemed redundant and
troublesome.
Now it is not necessary anymore, transitions setup is enough to execute
associated actions.
This commit is contained in:
Maciej Suminski 2017-01-18 09:04:11 +01:00
parent 2eefa11732
commit 75fb04d650
11 changed files with 306 additions and 335 deletions

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* Copyright (C) 2013-2017 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
@ -164,13 +164,11 @@ struct TOOL_MANAGER::TOOL_STATE
*this = *stateStack.top();
delete stateStack.top();
stateStack.pop();
return true;
}
else
{
cofunc = NULL;
return false;
}
}
@ -534,9 +532,11 @@ void TOOL_MANAGER::dispatchInternal( const TOOL_EVENT& aEvent )
for( TOOL_STATE* st : ( m_toolState | boost::adaptors::map_values ) )
{
bool handled = false;
// no state handler in progress - check if there are any transitions (defined by
// Go() method that match the event.
if( !st->pendingWait && !st->transitions.empty() )
if( !st->transitions.empty() )
{
for( TRANSITION& tr : st->transitions )
{
@ -559,11 +559,16 @@ void TOOL_MANAGER::dispatchInternal( const TOOL_EVENT& aEvent )
if( !st->cofunc->Running() )
finishTool( st ); // The couroutine has finished immediately?
handled = true;
// there is no point in further checking, as transitions got cleared
break;
}
}
}
if( handled )
break; // only the first tool gets the event
}
}
@ -656,10 +661,6 @@ bool TOOL_MANAGER::finishTool( TOOL_STATE* aState, bool aDeactivate )
{
bool shouldDeactivate = false;
// Reset VIEW_CONTROLS only if the most recent tool is finished
if( m_activeTools.empty() || m_activeTools.front() == aState->theTool->GetId() )
m_viewControls->Reset();
if( !aState->Pop() ) // if there are no other contexts saved on the stack
{
// find the tool and deactivate it
@ -669,12 +670,14 @@ bool TOOL_MANAGER::finishTool( TOOL_STATE* aState, bool aDeactivate )
if( tool != m_activeTools.end() )
{
shouldDeactivate = true;
m_viewControls->Reset();
if( aDeactivate )
m_activeTools.erase( tool );
}
}
// Set transitions to be ready for future TOOL_EVENTs
aState->theTool->SetTransitions();
return shouldDeactivate;

View File

@ -1,7 +1,7 @@
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013-2015 CERN
* Copyright (C) 2013-2017 CERN
* Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
@ -109,37 +109,6 @@ void LENGTH_TUNER_TOOL::Reset( RESET_REASON aReason )
}
void LENGTH_TUNER_TOOL::handleCommonEvents( const TOOL_EVENT& aEvent )
{
if( aEvent.IsAction( &ACT_RouterOptions ) )
{
DIALOG_PNS_SETTINGS settingsDlg( m_frame, m_router->Settings() );
if( settingsDlg.ShowModal() == wxID_OK )
{
// FIXME: do we need an explicit update?
}
}
PNS::MEANDER_PLACER_BASE* placer = static_cast<PNS::MEANDER_PLACER_BASE*>( m_router->Placer() );
if( !placer )
return;
if( aEvent.IsAction( &ACT_Settings ) )
{
PNS::MEANDER_SETTINGS settings = placer->MeanderSettings();
DIALOG_PNS_LENGTH_TUNING_SETTINGS settingsDlg( m_frame, settings, m_router->Mode() );
if( settingsDlg.ShowModal() )
{
placer->UpdateSettings( settings );
}
m_savedMeanderSettings = placer->MeanderSettings();
}
}
void LENGTH_TUNER_TOOL::updateStatusPopup( PNS_TUNE_STATUS_POPUP& aPopup )
{
wxPoint p = wxGetMousePosition();
@ -151,6 +120,7 @@ void LENGTH_TUNER_TOOL::updateStatusPopup( PNS_TUNE_STATUS_POPUP& aPopup )
aPopup.Move( p );
}
void LENGTH_TUNER_TOOL::performTuning()
{
if( m_startItem )
@ -224,8 +194,6 @@ void LENGTH_TUNER_TOOL::performTuning()
placer->SpacingStep( 1 );
m_router->Move( end, NULL );
}
handleCommonEvents( *evt );
}
m_router->StopRouting();
@ -254,6 +222,13 @@ int LENGTH_TUNER_TOOL::TuneDiffPairSkew( const TOOL_EVENT& aEvent )
}
void LENGTH_TUNER_TOOL::SetTransitions()
{
Go( &LENGTH_TUNER_TOOL::routerOptionsDialog, ACT_RouterOptions.MakeEvent() );
Go( &LENGTH_TUNER_TOOL::meanderSettingsDialog, ACT_Settings.MakeEvent() );
}
int LENGTH_TUNER_TOOL::mainLoop( PNS::ROUTER_MODE aMode )
{
// Deselect all items
@ -286,8 +261,6 @@ int LENGTH_TUNER_TOOL::mainLoop( PNS::ROUTER_MODE aMode )
updateStartItem( *evt );
performTuning();
}
handleCommonEvents( *evt );
}
m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
@ -299,3 +272,35 @@ int LENGTH_TUNER_TOOL::mainLoop( PNS::ROUTER_MODE aMode )
return 0;
}
int LENGTH_TUNER_TOOL::routerOptionsDialog( const TOOL_EVENT& aEvent )
{
DIALOG_PNS_SETTINGS settingsDlg( m_frame, m_router->Settings() );
if( settingsDlg.ShowModal() == wxID_OK )
{
// FIXME: do we need an explicit update?
}
return 0;
}
int LENGTH_TUNER_TOOL::meanderSettingsDialog( const TOOL_EVENT& aEvent )
{
PNS::MEANDER_PLACER_BASE* placer = static_cast<PNS::MEANDER_PLACER_BASE*>( m_router->Placer() );
if( !placer )
return 0;
PNS::MEANDER_SETTINGS settings = placer->MeanderSettings();
DIALOG_PNS_LENGTH_TUNING_SETTINGS settingsDlg( m_frame, settings, m_router->Mode() );
if( settingsDlg.ShowModal() )
placer->UpdateSettings( settings );
m_savedMeanderSettings = placer->MeanderSettings();
return 0;
}

View File

@ -1,7 +1,7 @@
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013-2015 CERN
* Copyright (C) 2013-2017 CERN
* Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* Author: Maciej Suminski <maciej.suminski@cern.ch>
@ -39,14 +39,17 @@ public:
int TuneSingleTrace( const TOOL_EVENT& aEvent );
int TuneDiffPair( const TOOL_EVENT& aEvent );
int TuneDiffPairSkew( const TOOL_EVENT& aEvent );
int ClearMeanders( const TOOL_EVENT& aEvent );
void SetTransitions() override;
private:
void performTuning();
int mainLoop( PNS::ROUTER_MODE aMode );
void handleCommonEvents( const TOOL_EVENT& aEvent );
void updateStatusPopup( PNS_TUNE_STATUS_POPUP& aPopup );
int routerOptionsDialog( const TOOL_EVENT& aEvent );
int meanderSettingsDialog( const TOOL_EVENT& aEvent );
PNS::MEANDER_SETTINGS m_savedMeanderSettings;
};

View File

@ -235,7 +235,7 @@ void TOOL_BASE::updateStartItem( TOOL_EVENT& aEvent )
}
void TOOL_BASE::updateEndItem( TOOL_EVENT& aEvent )
void TOOL_BASE::updateEndItem( const TOOL_EVENT& aEvent )
{
VECTOR2I mp = m_ctls->GetMousePosition();
VECTOR2I p = getView()->ToWorld( mp );

View File

@ -63,7 +63,7 @@ protected:
virtual ITEM* pickSingleItem( const VECTOR2I& aWhere, int aNet = -1, int aLayer = -1 );
virtual void highlightNet( bool aEnabled, int aNetcode = -1 );
virtual void updateStartItem( TOOL_EVENT& aEvent );
virtual void updateEndItem( TOOL_EVENT& aEvent );
virtual void updateEndItem( const TOOL_EVENT& aEvent );
void deleteTraces( ITEM* aStartItem, bool aWholeTrack );
MSG_PANEL_ITEMS m_panelItems;

View File

@ -1,7 +1,7 @@
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013 CERN
* Copyright (C) 2013-2017 CERN
* Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
@ -60,50 +60,50 @@ using namespace std::placeholders;
using namespace KIGFX;
using boost::optional;
static TOOL_ACTION ACT_NewTrack( "pcbnew.InteractiveRouter.NewTrack", AS_CONTEXT,
static const TOOL_ACTION ACT_NewTrack( "pcbnew.InteractiveRouter.NewTrack", AS_CONTEXT,
TOOL_ACTION::LegacyHotKey( HK_ADD_NEW_TRACK ),
_( "New Track" ), _( "Starts laying a new track." ), add_tracks_xpm );
static TOOL_ACTION ACT_EndTrack( "pcbnew.InteractiveRouter.EndTrack", AS_CONTEXT, WXK_END,
static const TOOL_ACTION ACT_EndTrack( "pcbnew.InteractiveRouter.EndTrack", AS_CONTEXT, WXK_END,
_( "End Track" ), _( "Stops laying the current track." ), checked_ok_xpm );
static TOOL_ACTION ACT_AutoEndRoute( "pcbnew.InteractiveRouter.AutoEndRoute", AS_CONTEXT, 'F',
static const TOOL_ACTION ACT_AutoEndRoute( "pcbnew.InteractiveRouter.AutoEndRoute", AS_CONTEXT, 'F',
_( "Auto-end Track" ), _( "Automagically finishes currently routed track." ) );
static TOOL_ACTION ACT_Drag( "pcbnew.InteractiveRouter.Drag", AS_CONTEXT,
static const TOOL_ACTION ACT_Drag( "pcbnew.InteractiveRouter.Drag", AS_CONTEXT,
TOOL_ACTION::LegacyHotKey( HK_DRAG_TRACK_KEEP_SLOPE ),
_( "Drag Track/Via" ), _( "Drags a track or a via." ), drag_track_segment_xpm );
static TOOL_ACTION ACT_PlaceThroughVia( "pcbnew.InteractiveRouter.PlaceVia",
static const TOOL_ACTION ACT_PlaceThroughVia( "pcbnew.InteractiveRouter.PlaceVia",
AS_CONTEXT, TOOL_ACTION::LegacyHotKey( HK_ADD_THROUGH_VIA ),
_( "Place Through Via" ),
_( "Adds a through-hole via at the end of currently routed track." ),
via_xpm );
static TOOL_ACTION ACT_PlaceBlindVia( "pcbnew.InteractiveRouter.PlaceBlindVia",
static const TOOL_ACTION ACT_PlaceBlindVia( "pcbnew.InteractiveRouter.PlaceBlindVia",
AS_CONTEXT, TOOL_ACTION::LegacyHotKey( HK_ADD_BLIND_BURIED_VIA ),
_( "Place Blind/Buried Via" ),
_( "Adds a blind or buried via at the end of currently routed track."),
via_buried_xpm );
static TOOL_ACTION ACT_PlaceMicroVia( "pcbnew.InteractiveRouter.PlaceMicroVia",
static const TOOL_ACTION ACT_PlaceMicroVia( "pcbnew.InteractiveRouter.PlaceMicroVia",
AS_CONTEXT, TOOL_ACTION::LegacyHotKey( HK_ADD_MICROVIA ),
_( "Place Microvia" ), _( "Adds a microvia at the end of currently routed track." ),
via_microvia_xpm );
static TOOL_ACTION ACT_CustomTrackWidth( "pcbnew.InteractiveRouter.CustomTrackViaSize",
static const TOOL_ACTION ACT_CustomTrackWidth( "pcbnew.InteractiveRouter.CustomTrackViaSize",
AS_CONTEXT, 'Q',
_( "Custom Track/Via Size" ),
_( "Shows a dialog for changing the track width and via size." ),
width_track_xpm );
static TOOL_ACTION ACT_SwitchPosture( "pcbnew.InteractiveRouter.SwitchPosture", AS_CONTEXT,
static const TOOL_ACTION ACT_SwitchPosture( "pcbnew.InteractiveRouter.SwitchPosture", AS_CONTEXT,
TOOL_ACTION::LegacyHotKey( HK_SWITCH_TRACK_POSTURE ),
_( "Switch Track Posture" ),
_( "Switches posture of the currently routed track." ),
change_entry_orient_xpm );
static TOOL_ACTION ACT_SetDpDimensions( "pcbnew.InteractiveRouter.SetDpDimensions",
static const TOOL_ACTION ACT_SetDpDimensions( "pcbnew.InteractiveRouter.SetDpDimensions",
AS_CONTEXT, 'P',
_( "Differential Pair Dimensions..." ),
_( "Sets the width and gap of the currently routed differential pair." ),
@ -251,12 +251,6 @@ bool ROUTER_TOOL::Init()
void ROUTER_TOOL::Reset( RESET_REASON aReason )
{
TOOL_BASE::Reset( aReason );
Go( &ROUTER_TOOL::RouteSingleTrace, COMMON_ACTIONS::routerActivateSingle.MakeEvent() );
Go( &ROUTER_TOOL::RouteDiffPair, COMMON_ACTIONS::routerActivateDiffPair.MakeEvent() );
Go( &ROUTER_TOOL::DpDimensionsDialog, COMMON_ACTIONS::routerActivateDpDimensionsDialog.MakeEvent() );
Go( &ROUTER_TOOL::SettingsDialog, COMMON_ACTIONS::routerActivateSettingsDialog.MakeEvent() );
Go( &ROUTER_TOOL::InlineDrag, COMMON_ACTIONS::routerInlineDrag.MakeEvent() );
}
@ -306,46 +300,7 @@ void ROUTER_TOOL::handleCommonEvents( const TOOL_EVENT& aEvent )
break;
}
}
else
#endif
if( aEvent.IsAction( &ACT_RouterOptions ) )
{
DIALOG_PNS_SETTINGS settingsDlg( m_frame, m_router->Settings() );
if( settingsDlg.ShowModal() == wxID_OK )
{
// FIXME: do we need an explicit update?
}
}
else if( aEvent.IsAction( &ACT_SetDpDimensions ) )
{
PNS::SIZES_SETTINGS sizes = m_router->Sizes();
DIALOG_PNS_DIFF_PAIR_DIMENSIONS settingsDlg( m_frame, sizes );
if( settingsDlg.ShowModal() )
{
m_router->UpdateSizes( sizes );
}
}
else if( aEvent.IsAction( &ACT_CustomTrackWidth ) )
{
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
DIALOG_TRACK_VIA_SIZE sizeDlg( m_frame, bds );
if( sizeDlg.ShowModal() )
{
bds.UseCustomTrackViaSize( true );
m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged );
}
}
else if( aEvent.IsAction( &COMMON_ACTIONS::trackViaSizeChanged ) )
{
PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
sizes.ImportCurrent( m_board->GetDesignSettings() );
m_router->UpdateSizes( sizes );
}
}
@ -387,8 +342,19 @@ void ROUTER_TOOL::switchLayerOnViaPlacement()
}
bool ROUTER_TOOL::onViaCommand( TOOL_EVENT& aEvent, VIATYPE_T aType )
int ROUTER_TOOL::onViaCommand( const TOOL_EVENT& aEvent )
{
VIATYPE_T viaType = VIA_THROUGH;
if( aEvent.IsAction( &ACT_PlaceThroughVia ) )
viaType = VIA_THROUGH;
else if( aEvent.IsAction( &ACT_PlaceBlindVia ) )
viaType = VIA_BLIND_BURIED;
else if( aEvent.IsAction( &ACT_PlaceMicroVia ) )
viaType = VIA_MICROVIA;
else
wxASSERT_MSG( false, "Unhandled via type" );
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
const int layerCount = bds.GetCopperLayerCount();
@ -404,27 +370,27 @@ bool ROUTER_TOOL::onViaCommand( TOOL_EVENT& aEvent, VIATYPE_T aType )
if( !m_router->IsPlacingVia() )
{
// Cannot place microvias or blind vias if not allowed (obvious)
if( ( aType == VIA_BLIND_BURIED ) && ( !bds.m_BlindBuriedViaAllowed ) )
if( ( viaType == VIA_BLIND_BURIED ) && ( !bds.m_BlindBuriedViaAllowed ) )
{
DisplayError( m_frame, _( "Blind/buried vias have to be enabled in the design settings." ) );
return false;
}
if( ( aType == VIA_MICROVIA ) && ( !bds.m_MicroViasAllowed ) )
if( ( viaType == VIA_MICROVIA ) && ( !bds.m_MicroViasAllowed ) )
{
DisplayError( m_frame, _( "Microvias have to be enabled in the design settings." ) );
return false;
}
// Can only place through vias on 2-layer boards
if( ( aType != VIA_THROUGH ) && ( layerCount <= 2 ) )
if( ( viaType != VIA_THROUGH ) && ( layerCount <= 2 ) )
{
DisplayError( m_frame, _( "Only through vias are allowed on 2 layer boards." ) );
return false;
}
// Can only place microvias if we're on an outer layer, or directly adjacent to one
if( ( aType == VIA_MICROVIA ) && ( currentLayer > In1_Cu ) && ( currentLayer < layerCount - 2 ) )
if( ( viaType == VIA_MICROVIA ) && ( currentLayer > In1_Cu ) && ( currentLayer < layerCount - 2 ) )
{
DisplayError( m_frame, _( "Microvias can be placed only between the outer layers " \
"(F.Cu/B.Cu) and the ones directly adjacent to them." ) );
@ -433,14 +399,14 @@ bool ROUTER_TOOL::onViaCommand( TOOL_EVENT& aEvent, VIATYPE_T aType )
}
// Convert blind/buried via to a through hole one, if it goes through all layers
if( aType == VIA_BLIND_BURIED && ( ( currentLayer == B_Cu ) || ( currentLayer == F_Cu ) )
if( viaType == VIA_BLIND_BURIED && ( ( currentLayer == B_Cu ) || ( currentLayer == F_Cu ) )
&& ( ( pairTop == B_Cu && pairBottom == F_Cu )
|| ( pairTop == F_Cu && pairBottom == B_Cu ) ) )
{
aType = VIA_THROUGH;
viaType = VIA_THROUGH;
}
switch( aType )
switch( viaType )
{
case VIA_THROUGH:
sizes.SetViaDiameter( bds.GetCurrentViaSize() );
@ -475,7 +441,7 @@ bool ROUTER_TOOL::onViaCommand( TOOL_EVENT& aEvent, VIATYPE_T aType )
break;
}
sizes.SetViaType( aType );
sizes.SetViaType( viaType );
m_router->UpdateSizes( sizes );
m_router->ToggleViaPlacement();
@ -484,7 +450,7 @@ bool ROUTER_TOOL::onViaCommand( TOOL_EVENT& aEvent, VIATYPE_T aType )
m_router->Move( m_endSnapPoint, m_endItem ); // refresh
return false;
return 0;
}
@ -582,18 +548,6 @@ void ROUTER_TOOL::performRouting()
m_router->Move( m_endSnapPoint, m_endItem );
m_startItem = NULL;
}
else if( evt->IsAction( &ACT_PlaceThroughVia ) )
{
onViaCommand( *evt, VIA_THROUGH );
}
else if( evt->IsAction( &ACT_PlaceBlindVia ) )
{
onViaCommand( *evt, VIA_BLIND_BURIED );
}
else if( evt->IsAction( &ACT_PlaceMicroVia ) )
{
onViaCommand( *evt, VIA_MICROVIA );
}
else if( evt->IsAction( &ACT_SwitchPosture ) )
{
m_router->FlipPosture();
@ -615,8 +569,6 @@ void ROUTER_TOOL::performRouting()
}
else if( evt->IsCancel() || evt->IsActivate() || evt->IsUndoRedo() )
break;
handleCommonEvents( *evt );
}
finishInteractive();
@ -647,13 +599,33 @@ int ROUTER_TOOL::SettingsDialog( const TOOL_EVENT& aEvent )
DIALOG_PNS_SETTINGS settingsDlg( m_frame, m_router->Settings() );
if( settingsDlg.ShowModal() )
{
m_savedSettings = m_router->Settings();
}
return 0;
}
void ROUTER_TOOL::SetTransitions()
{
Go( &ROUTER_TOOL::RouteSingleTrace, COMMON_ACTIONS::routerActivateSingle.MakeEvent() );
Go( &ROUTER_TOOL::RouteDiffPair, COMMON_ACTIONS::routerActivateDiffPair.MakeEvent() );
Go( &ROUTER_TOOL::DpDimensionsDialog, COMMON_ACTIONS::routerActivateDpDimensionsDialog.MakeEvent() );
Go( &ROUTER_TOOL::SettingsDialog, COMMON_ACTIONS::routerActivateSettingsDialog.MakeEvent() );
Go( &ROUTER_TOOL::InlineDrag, COMMON_ACTIONS::routerInlineDrag.MakeEvent() );
Go( &ROUTER_TOOL::onViaCommand, ACT_PlaceThroughVia.MakeEvent() );
Go( &ROUTER_TOOL::onViaCommand, ACT_PlaceBlindVia.MakeEvent() );
Go( &ROUTER_TOOL::onViaCommand, ACT_PlaceMicroVia.MakeEvent() );
// TODO is not this redundant? the same actions can be used for menus and hotkeys
Go( &ROUTER_TOOL::SettingsDialog, ACT_RouterOptions.MakeEvent() );
Go( &ROUTER_TOOL::DpDimensionsDialog, ACT_SetDpDimensions.MakeEvent() );
Go( &ROUTER_TOOL::CustomTrackWidthDialog, ACT_CustomTrackWidth.MakeEvent() );
Go( &ROUTER_TOOL::onTrackViaSizeChanged, COMMON_ACTIONS::trackViaSizeChanged.MakeEvent() );
}
int ROUTER_TOOL::RouteSingleTrace( const TOOL_EVENT& aEvent )
{
m_frame->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Route Track" ) );
@ -732,8 +704,6 @@ int ROUTER_TOOL::mainLoop( PNS::ROUTER_MODE aMode )
{
deleteTraces( m_startItem, false );
}
handleCommonEvents( *evt );
}
frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
@ -863,3 +833,28 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
return 0;
}
int ROUTER_TOOL::CustomTrackWidthDialog( const TOOL_EVENT& aEvent )
{
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
DIALOG_TRACK_VIA_SIZE sizeDlg( m_frame, bds );
if( sizeDlg.ShowModal() )
{
bds.UseCustomTrackViaSize( true );
m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged );
}
return 0;
}
int ROUTER_TOOL::onTrackViaSizeChanged( const TOOL_EVENT& aEvent )
{
PNS::SIZES_SETTINGS sizes( m_router->Sizes() );
sizes.ImportCurrent( m_board->GetDesignSettings() );
m_router->UpdateSizes( sizes );
return 0;
}

View File

@ -1,7 +1,7 @@
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013-2014 CERN
* Copyright (C) 2013-2017 CERN
* Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* Author: Maciej Suminski <maciej.suminski@cern.ch>
@ -38,11 +38,14 @@ public:
int RouteDiffPair( const TOOL_EVENT& aEvent );
int InlineDrag( const TOOL_EVENT& aEvent );
// TODO make this private?
int DpDimensionsDialog( const TOOL_EVENT& aEvent );
int SettingsDialog( const TOOL_EVENT& aEvent );
int CustomTrackWidthDialog( const TOOL_EVENT& aEvent );
void SetTransitions() override;
private:
int mainLoop( PNS::ROUTER_MODE aMode );
int getDefaultWidth( int aNetCode );
@ -55,7 +58,10 @@ private:
int getStartLayer( const PNS::ITEM* aItem );
void switchLayerOnViaPlacement();
bool onViaCommand( TOOL_EVENT& aEvent, VIATYPE_T aType );
int onViaCommand( const TOOL_EVENT& aEvent );
int onTrackViaSizeChanged( const TOOL_EVENT& aEvent );
int onLayerChanged( const TOOL_EVENT& aEvent );
bool prepareInteractive();
bool finishInteractive();

View File

@ -251,19 +251,10 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
{
wxPoint modPoint = getModificationPoint( selection );
if( evt->IsAction( &COMMON_ACTIONS::rotate ) )
if( evt->IsAction( &COMMON_ACTIONS::remove ) )
{
Rotate( aEvent );
}
else if( evt->IsAction( &COMMON_ACTIONS::flip ) )
{
Flip( aEvent );
}
else if( evt->IsAction( &COMMON_ACTIONS::remove ) )
{
Remove( aEvent );
break; // exit the loop, as there is no further processing for removed items
// exit the loop, as there is no further processing for removed items
break;
}
else if( evt->IsAction( &COMMON_ACTIONS::duplicate ) )
{
@ -408,6 +399,7 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
// TODO selectionModified
m_toolMgr->RunAction( COMMON_ACTIONS::editModifiedSelection, true );
editFrame->Refresh();
return 0;
}
@ -438,6 +430,7 @@ int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent )
m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true );
m_toolMgr->RunAction( COMMON_ACTIONS::editModifiedSelection, true );
getEditFrame<PCB_BASE_EDIT_FRAME>()->Refresh();
return 0;
}

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* Copyright (C) 2013-2017 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
@ -212,8 +212,7 @@ bool POINT_EDITOR::Init()
}
auto& menu = m_selectionTool->GetToolMenu().GetMenu();
menu.AddItem( COMMON_ACTIONS::pointEditorAddCorner,
POINT_EDITOR::addCornerCondition );
menu.AddItem( COMMON_ACTIONS::pointEditorAddCorner, POINT_EDITOR::addCornerCondition );
menu.AddItem( COMMON_ACTIONS::pointEditorRemoveCorner,
std::bind( &POINT_EDITOR::removeCornerCondition, this, _1 ) );
@ -277,22 +276,7 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
if ( !modified )
updateEditedPoint( *evt );
if( evt->IsAction( &COMMON_ACTIONS::pointEditorAddCorner ) )
{
addCorner( controls->GetCursorPosition() );
updatePoints();
}
else if( evt->IsAction( &COMMON_ACTIONS::pointEditorRemoveCorner ) )
{
if( m_editedPoint )
{
removeCorner( m_editedPoint );
updatePoints();
}
}
else if( evt->IsDrag( BUT_LEFT ) && m_editedPoint )
if( evt->IsDrag( BUT_LEFT ) && m_editedPoint )
{
if( !modified )
{
@ -320,11 +304,6 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
updatePoints();
}
else if( evt->IsAction( &COMMON_ACTIONS::editModifiedSelection ) )
{
updatePoints();
}
else if( evt->IsMouseUp( BUT_LEFT ) )
{
controls->SetAutoPan( false );
@ -551,6 +530,9 @@ void POINT_EDITOR::finishItem() const
void POINT_EDITOR::updatePoints()
{
if( !m_editPoints )
return;
EDA_ITEM* item = m_editPoints->GetParent();
switch( item->Type() )
@ -723,125 +705,11 @@ EDIT_POINT POINT_EDITOR::get45DegConstrainer() const
}
void POINT_EDITOR::addCorner( const VECTOR2I& aBreakPoint )
{
EDA_ITEM* item = m_editPoints->GetParent();
PCB_BASE_EDIT_FRAME* frame = getEditFrame<PCB_BASE_EDIT_FRAME>();
BOARD_COMMIT commit( frame );
if( item->Type() == PCB_ZONE_AREA_T )
{
ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
CPolyLine* outline = zone->Outline();
commit.Modify( zone );
// Handle the last segment, so other segments can be easily handled in a loop
unsigned int nearestIdx = outline->GetCornersCount() - 1, nextNearestIdx = 0;
SEG side( VECTOR2I( outline->GetPos( nearestIdx ) ),
VECTOR2I( outline->GetPos( nextNearestIdx ) ) );
unsigned int nearestDist = side.Distance( aBreakPoint );
for( int i = 0; i < outline->GetCornersCount() - 1; ++i )
{
side = SEG( VECTOR2I( outline->GetPos( i ) ), VECTOR2I( outline->GetPos( i + 1 ) ) );
unsigned int distance = side.Distance( aBreakPoint );
if( distance < nearestDist )
{
nearestDist = distance;
nearestIdx = i;
nextNearestIdx = i + 1;
}
}
// Find the point on the closest segment
VECTOR2I sideOrigin( outline->GetPos( nearestIdx ) );
VECTOR2I sideEnd( outline->GetPos( nextNearestIdx ) );
SEG nearestSide( sideOrigin, sideEnd );
VECTOR2I nearestPoint = nearestSide.NearestPoint( aBreakPoint );
// Do not add points that have the same coordinates as ones that already belong to polygon
// instead, add a point in the middle of the side
if( nearestPoint == sideOrigin || nearestPoint == sideEnd )
nearestPoint = ( sideOrigin + sideEnd ) / 2;
outline->InsertCorner( nearestIdx, nearestPoint.x, nearestPoint.y );
commit.Push( _( "Add a zone corner" ) );
}
else if( item->Type() == PCB_LINE_T || item->Type() == PCB_MODULE_EDGE_T )
{
bool moduleEdge = item->Type() == PCB_MODULE_EDGE_T;
DRAWSEGMENT* segment = static_cast<DRAWSEGMENT*>( item );
if( segment->GetShape() == S_SEGMENT )
{
commit.Modify( segment );
SEG seg( segment->GetStart(), segment->GetEnd() );
VECTOR2I nearestPoint = seg.NearestPoint( aBreakPoint );
// Move the end of the line to the break point..
segment->SetEnd( wxPoint( nearestPoint.x, nearestPoint.y ) );
// and add another one starting from the break point
DRAWSEGMENT* newSegment;
if( moduleEdge )
{
EDGE_MODULE* edge = static_cast<EDGE_MODULE*>( segment );
assert( edge->Type() == PCB_MODULE_EDGE_T );
assert( edge->GetParent()->Type() == PCB_MODULE_T );
newSegment = new EDGE_MODULE( *edge );
}
else
{
newSegment = new DRAWSEGMENT( *segment );
}
newSegment->ClearSelected();
newSegment->SetStart( wxPoint( nearestPoint.x, nearestPoint.y ) );
newSegment->SetEnd( wxPoint( seg.B.x, seg.B.y ) );
commit.Add( newSegment );
commit.Push( _( "Split segment" ) );
}
}
}
void POINT_EDITOR::removeCorner( EDIT_POINT* aPoint )
{
EDA_ITEM* item = m_editPoints->GetParent();
if( item->Type() == PCB_ZONE_AREA_T )
{
PCB_BASE_FRAME* frame = getEditFrame<PCB_BASE_FRAME>();
BOARD_COMMIT commit( frame );
ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
CPolyLine* outline = zone->Outline();
commit.Modify( zone );
for( int i = 0; i < outline->GetCornersCount(); ++i )
{
if( VECTOR2I( outline->GetPos( i ) ) == aPoint->GetPosition() )
{
outline->DeleteCorner( i );
setEditedPoint( NULL );
commit.Push( _( "Remove a zone corner" ) );
break;
}
}
}
}
void POINT_EDITOR::SetTransitions()
{
Go( &POINT_EDITOR::addCorner, COMMON_ACTIONS::pointEditorAddCorner.MakeEvent() );
Go( &POINT_EDITOR::removeCorner, COMMON_ACTIONS::pointEditorRemoveCorner.MakeEvent() );
Go( &POINT_EDITOR::modifiedSelection, COMMON_ACTIONS::editModifiedSelection.MakeEvent() );
Go( &POINT_EDITOR::OnSelectionChange, SELECTION_TOOL::SelectedEvent );
Go( &POINT_EDITOR::OnSelectionChange, SELECTION_TOOL::UnselectedEvent );
}
@ -882,3 +750,137 @@ bool POINT_EDITOR::removeCornerCondition( const SELECTION& )
return m_editedPoint != NULL;
}
int POINT_EDITOR::addCorner( const TOOL_EVENT& aEvent )
{
EDA_ITEM* item = m_editPoints->GetParent();
PCB_BASE_EDIT_FRAME* frame = getEditFrame<PCB_BASE_EDIT_FRAME>();
const VECTOR2I& cursorPos = getViewControls()->GetCursorPosition();
BOARD_COMMIT commit( frame );
if( item->Type() == PCB_ZONE_AREA_T )
{
ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
CPolyLine* outline = zone->Outline();
commit.Modify( zone );
// Handle the last segment, so other segments can be easily handled in a loop
unsigned int nearestIdx = outline->GetCornersCount() - 1, nextNearestIdx = 0;
SEG side( VECTOR2I( outline->GetPos( nearestIdx ) ),
VECTOR2I( outline->GetPos( nextNearestIdx ) ) );
unsigned int nearestDist = side.Distance( cursorPos );
for( int i = 0; i < outline->GetCornersCount() - 1; ++i )
{
side = SEG( VECTOR2I( outline->GetPos( i ) ), VECTOR2I( outline->GetPos( i + 1 ) ) );
unsigned int distance = side.Distance( cursorPos );
if( distance < nearestDist )
{
nearestDist = distance;
nearestIdx = i;
nextNearestIdx = i + 1;
}
}
// Find the point on the closest segment
VECTOR2I sideOrigin( outline->GetPos( nearestIdx ) );
VECTOR2I sideEnd( outline->GetPos( nextNearestIdx ) );
SEG nearestSide( sideOrigin, sideEnd );
VECTOR2I nearestPoint = nearestSide.NearestPoint( cursorPos );
// Do not add points that have the same coordinates as ones that already belong to polygon
// instead, add a point in the middle of the side
if( nearestPoint == sideOrigin || nearestPoint == sideEnd )
nearestPoint = ( sideOrigin + sideEnd ) / 2;
outline->InsertCorner( nearestIdx, nearestPoint.x, nearestPoint.y );
commit.Push( _( "Add a zone corner" ) );
}
else if( item->Type() == PCB_LINE_T || item->Type() == PCB_MODULE_EDGE_T )
{
bool moduleEdge = item->Type() == PCB_MODULE_EDGE_T;
DRAWSEGMENT* segment = static_cast<DRAWSEGMENT*>( item );
if( segment->GetShape() == S_SEGMENT )
{
commit.Modify( segment );
SEG seg( segment->GetStart(), segment->GetEnd() );
VECTOR2I nearestPoint = seg.NearestPoint( cursorPos );
// Move the end of the line to the break point..
segment->SetEnd( wxPoint( nearestPoint.x, nearestPoint.y ) );
// and add another one starting from the break point
DRAWSEGMENT* newSegment;
if( moduleEdge )
{
EDGE_MODULE* edge = static_cast<EDGE_MODULE*>( segment );
assert( edge->Type() == PCB_MODULE_EDGE_T );
assert( edge->GetParent()->Type() == PCB_MODULE_T );
newSegment = new EDGE_MODULE( *edge );
}
else
{
newSegment = new DRAWSEGMENT( *segment );
}
newSegment->ClearSelected();
newSegment->SetStart( wxPoint( nearestPoint.x, nearestPoint.y ) );
newSegment->SetEnd( wxPoint( seg.B.x, seg.B.y ) );
commit.Add( newSegment );
commit.Push( _( "Split segment" ) );
}
}
updatePoints();
return 0;
}
int POINT_EDITOR::removeCorner( const TOOL_EVENT& aEvent )
{
if( !m_editedPoint )
return 0;
EDA_ITEM* item = m_editPoints->GetParent();
if( item->Type() == PCB_ZONE_AREA_T )
{
PCB_BASE_FRAME* frame = getEditFrame<PCB_BASE_FRAME>();
BOARD_COMMIT commit( frame );
ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item );
CPolyLine* outline = zone->Outline();
commit.Modify( zone );
for( int i = 0; i < outline->GetCornersCount(); ++i )
{
if( VECTOR2I( outline->GetPos( i ) ) == m_editedPoint->GetPosition() )
{
outline->DeleteCorner( i );
setEditedPoint( NULL );
commit.Push( _( "Remove a zone corner" ) );
break;
}
}
updatePoints();
}
return 0;
}
int POINT_EDITOR::modifiedSelection( const TOOL_EVENT& aEvent )
{
updatePoints();
return 0;
}

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* Copyright (C) 2013-2017 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
@ -116,6 +116,11 @@ private:
///> Condition to display "Remove corner" context menu entry.
bool removeCornerCondition( const SELECTION& aSelection );
/// TOOL_ACTION handlers
int addCorner( const TOOL_EVENT& aEvent );
int removeCorner( const TOOL_EVENT& aEvent );
int modifiedSelection( const TOOL_EVENT& aEvent );
};
#endif

View File

@ -217,52 +217,11 @@ int SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
}
}
else if( evt->IsAction( &COMMON_ACTIONS::selectionCursor ) )
{
selectCursor( true );
}
else if( evt->IsAction( &COMMON_ACTIONS::find ) )
{
find( *evt );
}
else if( evt->IsAction( &COMMON_ACTIONS::findMove ) )
{
findMove( *evt );
}
else if( evt->IsAction( &COMMON_ACTIONS::selectItem ) )
{
SelectItem( *evt );
}
else if( evt->IsAction( &COMMON_ACTIONS::unselectItem ) )
{
UnselectItem( *evt );
}
else if( evt->IsCancel() || evt->Action() == TA_UNDO_REDO_PRE ||
evt->IsAction( &COMMON_ACTIONS::selectionClear ) )
else if( evt->IsCancel() || evt->Action() == TA_UNDO_REDO_PRE )
{
clearSelection();
}
else if( evt->IsAction( &COMMON_ACTIONS::selectConnection ) )
{
selectConnection( *evt );
}
else if( evt->IsAction( &COMMON_ACTIONS::selectCopper ) )
{
selectCopper( *evt );
}
else if( evt->IsAction( &COMMON_ACTIONS::selectNet ) )
{
selectNet( *evt );
}
else if( evt->Action() == TA_CONTEXT_MENU_CLOSED )
{
if( m_preliminary )