diff options
Diffstat (limited to 'pcbnew/tools/pcb_editor_control.cpp')
-rw-r--r-- | pcbnew/tools/pcb_editor_control.cpp | 792 |
1 files changed, 792 insertions, 0 deletions
diff --git a/pcbnew/tools/pcb_editor_control.cpp b/pcbnew/tools/pcb_editor_control.cpp new file mode 100644 index 0000000..15a0fc6 --- /dev/null +++ b/pcbnew/tools/pcb_editor_control.cpp @@ -0,0 +1,792 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 CERN + * @author Maciej Suminski <maciej.suminski@cern.ch> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <boost/bind.hpp> + +#include "pcb_editor_control.h" +#include "common_actions.h" +#include <tool/tool_manager.h> + +#include "selection_tool.h" +#include "picker_tool.h" + +#include <painter.h> +#include <project.h> +#include <pcbnew_id.h> +#include <wxPcbStruct.h> +#include <class_board.h> +#include <class_zone.h> +#include <class_draw_panel_gal.h> +#include <class_module.h> +#include <class_mire.h> +#include <ratsnest_data.h> +#include <collectors.h> +#include <zones_functions_for_undo_redo.h> + +#include <view/view_group.h> +#include <view/view_controls.h> +#include <origin_viewitem.h> + +#include <boost/bind.hpp> + + +class ZONE_CONTEXT_MENU : public CONTEXT_MENU +{ +public: + ZONE_CONTEXT_MENU() + { + SetIcon( add_zone_xpm ); + SetUpdateHandler( boost::bind( &ZONE_CONTEXT_MENU::update, this ) ); + Add( COMMON_ACTIONS::zoneFill ); + Add( COMMON_ACTIONS::zoneFillAll ); + Add( COMMON_ACTIONS::zoneUnfill ); + Add( COMMON_ACTIONS::zoneUnfillAll ); + Add( COMMON_ACTIONS::zoneMerge ); + } + +private: + void update() + { + SELECTION_TOOL* selTool = getToolManager()->GetTool<SELECTION_TOOL>(); + + // lines like this make me really think about a better name for SELECTION_CONDITIONS class + bool mergeEnabled = ( SELECTION_CONDITIONS::MoreThan( 1 ) && + /*SELECTION_CONDITIONS::OnlyType( PCB_ZONE_AREA_T ) &&*/ + SELECTION_CONDITIONS::SameNet( true ) && + SELECTION_CONDITIONS::SameLayer() )( selTool->GetSelection() ); + + Enable( getMenuId( COMMON_ACTIONS::zoneMerge ), mergeEnabled ); + } +}; + + +PCB_EDITOR_CONTROL::PCB_EDITOR_CONTROL() : + TOOL_INTERACTIVE( "pcbnew.EditorControl" ), m_frame( NULL ), m_zoneMenu( NULL ) +{ + m_placeOrigin = new KIGFX::ORIGIN_VIEWITEM( KIGFX::COLOR4D( 0.8, 0.0, 0.0, 1.0 ), + KIGFX::ORIGIN_VIEWITEM::CIRCLE_CROSS ); + m_probingSchToPcb = false; +} + + +PCB_EDITOR_CONTROL::~PCB_EDITOR_CONTROL() +{ + delete m_placeOrigin; + delete m_zoneMenu; +} + + +void PCB_EDITOR_CONTROL::Reset( RESET_REASON aReason ) +{ + m_frame = getEditFrame<PCB_EDIT_FRAME>(); + + if( aReason == MODEL_RELOAD || aReason == GAL_SWITCH ) + { + m_placeOrigin->SetPosition( getModel<BOARD>()->GetAuxOrigin() ); + getView()->Remove( m_placeOrigin ); + getView()->Add( m_placeOrigin ); + } +} + + +bool PCB_EDITOR_CONTROL::Init() +{ + SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); + + if( selTool ) + { + m_zoneMenu = new ZONE_CONTEXT_MENU; + m_zoneMenu->SetTool( this ); + selTool->GetMenu().AddMenu( m_zoneMenu, _( "Zones" ), false, + SELECTION_CONDITIONS::OnlyType( PCB_ZONE_AREA_T ) ); + } + + return true; +} + + +// Track & via size control +int PCB_EDITOR_CONTROL::TrackWidthInc( const TOOL_EVENT& aEvent ) +{ + BOARD* board = getModel<BOARD>(); + int widthIndex = board->GetDesignSettings().GetTrackWidthIndex() + 1; + + if( widthIndex >= (int) board->GetDesignSettings().m_TrackWidthList.size() ) + widthIndex = board->GetDesignSettings().m_TrackWidthList.size() - 1; + + board->GetDesignSettings().SetTrackWidthIndex( widthIndex ); + board->GetDesignSettings().UseCustomTrackViaSize( false ); + + wxUpdateUIEvent dummy; + m_frame->OnUpdateSelectTrackWidth( dummy ); + m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged ); + + return 0; +} + + +int PCB_EDITOR_CONTROL::TrackWidthDec( const TOOL_EVENT& aEvent ) +{ + BOARD* board = getModel<BOARD>(); + int widthIndex = board->GetDesignSettings().GetTrackWidthIndex() - 1; + + if( widthIndex < 0 ) + widthIndex = 0; + + board->GetDesignSettings().SetTrackWidthIndex( widthIndex ); + board->GetDesignSettings().UseCustomTrackViaSize( false ); + + wxUpdateUIEvent dummy; + m_frame->OnUpdateSelectTrackWidth( dummy ); + m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged ); + + return 0; +} + + +int PCB_EDITOR_CONTROL::ViaSizeInc( const TOOL_EVENT& aEvent ) +{ + BOARD* board = getModel<BOARD>(); + int sizeIndex = board->GetDesignSettings().GetViaSizeIndex() + 1; + + if( sizeIndex >= (int) board->GetDesignSettings().m_ViasDimensionsList.size() ) + sizeIndex = board->GetDesignSettings().m_ViasDimensionsList.size() - 1; + + board->GetDesignSettings().SetViaSizeIndex( sizeIndex ); + board->GetDesignSettings().UseCustomTrackViaSize( false ); + + wxUpdateUIEvent dummy; + m_frame->OnUpdateSelectViaSize( dummy ); + m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged ); + + return 0; +} + + +int PCB_EDITOR_CONTROL::ViaSizeDec( const TOOL_EVENT& aEvent ) +{ + BOARD* board = getModel<BOARD>(); + int sizeIndex = board->GetDesignSettings().GetViaSizeIndex() - 1; + + if( sizeIndex < 0 ) + sizeIndex = 0; + + board->GetDesignSettings().SetViaSizeIndex( sizeIndex ); + board->GetDesignSettings().UseCustomTrackViaSize( false ); + + wxUpdateUIEvent dummy; + m_frame->OnUpdateSelectViaSize( dummy ); + m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged ); + + return 0; +} + + +int PCB_EDITOR_CONTROL::PlaceModule( const TOOL_EVENT& aEvent ) +{ + MODULE* module = NULL; + KIGFX::VIEW* view = getView(); + KIGFX::VIEW_CONTROLS* controls = getViewControls(); + BOARD* board = getModel<BOARD>(); + + // Add a VIEW_GROUP that serves as a preview for the new item + KIGFX::VIEW_GROUP preview( view ); + view->Add( &preview ); + + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); + controls->ShowCursor( true ); + controls->SetSnapping( true ); + + Activate(); + m_frame->SetToolID( ID_PCB_MODULE_BUTT, wxCURSOR_HAND, _( "Add footprint" ) ); + + // Main loop: keep receiving events + while( OPT_TOOL_EVENT evt = Wait() ) + { + VECTOR2I cursorPos = controls->GetCursorPosition(); + + if( evt->IsCancel() || evt->IsActivate() ) + { + if( module ) + { + board->Delete( module ); // it was added by LoadModuleFromLibrary() + module = NULL; + + preview.Clear(); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + controls->ShowCursor( true ); + } + else + break; + + if( evt->IsActivate() ) // now finish unconditionally + break; + } + + else if( module && evt->Category() == TC_COMMAND ) + { + if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) + { + module->Rotate( module->GetPosition(), m_frame->GetRotationAngle() ); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) + { + module->Flip( module->GetPosition() ); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + } + + else if( evt->IsClick( BUT_LEFT ) ) + { + if( !module ) + { + // Pick the module to be placed + module = m_frame->LoadModuleFromLibrary( wxEmptyString, + m_frame->Prj().PcbFootprintLibs(), + true, NULL ); + if( module == NULL ) + continue; + + module->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); + + // Add all the drawable parts to preview + preview.Add( module ); + module->RunOnChildren( boost::bind( &KIGFX::VIEW_GROUP::Add, &preview, _1 ) ); + + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + else + { + // Place the selected module + module->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) ); + view->Add( module ); + module->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + + m_frame->OnModify(); + m_frame->SaveCopyInUndoList( module, UR_NEW ); + + // Remove from preview + preview.Remove( module ); + module->RunOnChildren( boost::bind( &KIGFX::VIEW_GROUP::Remove, &preview, _1 ) ); + module = NULL; // to indicate that there is no module that we currently modify + } + + bool placing = ( module != NULL ); + + controls->SetAutoPan( placing ); + controls->CaptureCursor( placing ); + controls->ShowCursor( !placing ); + } + + else if( module && evt->IsMotion() ) + { + module->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + } + + controls->ShowCursor( false ); + controls->SetSnapping( false ); + controls->SetAutoPan( false ); + controls->CaptureCursor( false ); + view->Remove( &preview ); + + m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); + + return 0; +} + + +int PCB_EDITOR_CONTROL::ToggleLockModule( const TOOL_EVENT& aEvent ) +{ + SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); + const SELECTION& selection = selTool->GetSelection(); + bool clearSelection = selection.Empty(); + + if( clearSelection ) + m_toolMgr->RunAction( COMMON_ACTIONS::selectionCursor, true ); + + for( int i = 0; i < selection.Size(); ++i ) + { + if( selection.Item<BOARD_ITEM>( i )->Type() == PCB_MODULE_T ) + { + MODULE* module = selection.Item<MODULE>( i ); + module->SetLocked( !module->IsLocked() ); + } + } + + if( clearSelection ) + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); + + return 0; +} + + +int PCB_EDITOR_CONTROL::PlaceTarget( const TOOL_EVENT& aEvent ) +{ + KIGFX::VIEW* view = getView(); + KIGFX::VIEW_CONTROLS* controls = getViewControls(); + BOARD* board = getModel<BOARD>(); + PCB_TARGET* target = new PCB_TARGET( board ); + + // Init the new item attributes + target->SetLayer( Edge_Cuts ); + target->SetWidth( board->GetDesignSettings().m_EdgeSegmentWidth ); + target->SetSize( Millimeter2iu( 5 ) ); + VECTOR2I cursorPos = controls->GetCursorPosition(); + target->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); + + // Add a VIEW_GROUP that serves as a preview for the new item + KIGFX::VIEW_GROUP preview( view ); + preview.Add( target ); + view->Add( &preview ); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); + controls->SetSnapping( true ); + + Activate(); + m_frame->SetToolID( ID_PCB_MIRE_BUTT, wxCURSOR_PENCIL, _( "Add layer alignment target" ) ); + + // Main loop: keep receiving events + while( OPT_TOOL_EVENT evt = Wait() ) + { + cursorPos = controls->GetCursorPosition(); + + if( evt->IsCancel() || evt->IsActivate() ) + break; + + else if( evt->IsAction( &COMMON_ACTIONS::incWidth ) ) + { + target->SetWidth( target->GetWidth() + WIDTH_STEP ); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + + else if( evt->IsAction( &COMMON_ACTIONS::decWidth ) ) + { + int width = target->GetWidth(); + + if( width > WIDTH_STEP ) + { + target->SetWidth( width - WIDTH_STEP ); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + } + + else if( evt->IsClick( BUT_LEFT ) ) + { + assert( target->GetSize() > 0 ); + assert( target->GetWidth() > 0 ); + + view->Add( target ); + board->Add( target ); + target->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + + m_frame->OnModify(); + m_frame->SaveCopyInUndoList( target, UR_NEW ); + + preview.Remove( target ); + + // Create next PCB_TARGET + target = new PCB_TARGET( *target ); + preview.Add( target ); + } + + else if( evt->IsMotion() ) + { + target->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + } + + delete target; + + controls->SetSnapping( false ); + view->Remove( &preview ); + + m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); + + return 0; +} + + +// Zone actions +int PCB_EDITOR_CONTROL::ZoneFill( const TOOL_EVENT& aEvent ) +{ + SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); + const SELECTION& selection = selTool->GetSelection(); + RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); + + for( int i = 0; i < selection.Size(); ++i ) + { + assert( selection.Item<BOARD_ITEM>( i )->Type() == PCB_ZONE_AREA_T ); + + ZONE_CONTAINER* zone = selection.Item<ZONE_CONTAINER>( i ); + m_frame->Fill_Zone( zone ); + zone->SetIsFilled( true ); + ratsnest->Update( zone ); + zone->ViewUpdate(); + } + + ratsnest->Recalculate(); + + return 0; +} + + +int PCB_EDITOR_CONTROL::ZoneFillAll( const TOOL_EVENT& aEvent ) +{ + BOARD* board = getModel<BOARD>(); + RN_DATA* ratsnest = board->GetRatsnest(); + + for( int i = 0; i < board->GetAreaCount(); ++i ) + { + ZONE_CONTAINER* zone = board->GetArea( i ); + m_frame->Fill_Zone( zone ); + zone->SetIsFilled( true ); + ratsnest->Update( zone ); + zone->ViewUpdate(); + } + + ratsnest->Recalculate(); + + return 0; +} + + +int PCB_EDITOR_CONTROL::ZoneUnfill( const TOOL_EVENT& aEvent ) +{ + SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); + const SELECTION& selection = selTool->GetSelection(); + RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); + + for( int i = 0; i < selection.Size(); ++i ) + { + assert( selection.Item<BOARD_ITEM>( i )->Type() == PCB_ZONE_AREA_T ); + + ZONE_CONTAINER* zone = selection.Item<ZONE_CONTAINER>( i ); + zone->SetIsFilled( false ); + zone->ClearFilledPolysList(); + ratsnest->Update( zone ); + zone->ViewUpdate(); + } + + ratsnest->Recalculate(); + + return 0; +} + + +int PCB_EDITOR_CONTROL::ZoneUnfillAll( const TOOL_EVENT& aEvent ) +{ + BOARD* board = getModel<BOARD>(); + RN_DATA* ratsnest = board->GetRatsnest(); + + for( int i = 0; i < board->GetAreaCount(); ++i ) + { + ZONE_CONTAINER* zone = board->GetArea( i ); + zone->SetIsFilled( false ); + zone->ClearFilledPolysList(); + ratsnest->Update( zone ); + zone->ViewUpdate(); + } + + ratsnest->Recalculate(); + + return 0; +} + + +int PCB_EDITOR_CONTROL::ZoneMerge( const TOOL_EVENT& aEvent ) +{ + SELECTION selection = m_toolMgr->GetTool<SELECTION_TOOL>()->GetSelection(); + BOARD* board = getModel<BOARD>(); + RN_DATA* ratsnest = board->GetRatsnest(); + KIGFX::VIEW* view = getView(); + + if( selection.Size() < 2 ) + return 0; + + PICKED_ITEMS_LIST changes; + int netcode = -1; + + // Loop through all combinations + for( int ia1 = 0; ia1 < selection.Size() - 1; ++ia1 ) + { + ZONE_CONTAINER* curr_area = dynamic_cast<ZONE_CONTAINER*>( selection.Item<EDA_ITEM>( ia1 ) ); + + if( !curr_area ) + continue; + + netcode = curr_area->GetNetCode(); + + EDA_RECT b1 = curr_area->Outline()->GetBoundingBox(); + bool mod_ia1 = false; + + for( int ia2 = selection.Size() - 1; ia2 > ia1; --ia2 ) + { + ZONE_CONTAINER* area2 = dynamic_cast<ZONE_CONTAINER*>( selection.Item<EDA_ITEM>( ia2 ) ); + + if( !area2 ) + continue; + + if( area2->GetNetCode() != netcode ) + continue; + + if( curr_area->GetPriority() != area2->GetPriority() ) + continue; + + if( curr_area->GetIsKeepout() != area2->GetIsKeepout() ) + continue; + + if( curr_area->GetLayer() != area2->GetLayer() ) + continue; + + EDA_RECT b2 = area2->Outline()->GetBoundingBox(); + + if( b1.Intersects( b2 ) ) + { + EDA_ITEM* backup = curr_area->Clone(); + bool ret = board->TestAreaIntersection( curr_area, area2 ); + + if( ret && board->CombineAreas( &changes, curr_area, area2 ) ) + { + mod_ia1 = true; + selection.items.RemovePicker( ia2 ); + + ITEM_PICKER picker( curr_area, UR_CHANGED ); + picker.SetLink( backup ); + changes.PushItem( picker ); + } + else + { + delete backup; + } + } + } + + if( mod_ia1 ) + --ia1; // if modified, we need to check it again + } + + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); + m_frame->SaveCopyInUndoList( changes, UR_UNSPECIFIED ); + + for( unsigned i = 0; i < changes.GetCount(); ++i ) + { + ITEM_PICKER picker = changes.GetItemWrapper( i ); + BOARD_ITEM* item = static_cast<BOARD_ITEM*>( picker.GetItem() ); + + if( picker.GetStatus() == UR_DELETED ) + { + view->Remove( item ); + ratsnest->Remove( item ); + } + else if( picker.GetStatus() == UR_CHANGED ) + { + item->ViewUpdate( KIGFX::VIEW_ITEM::ALL ); + m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, item ); + } + } + + return 0; +} + + +int PCB_EDITOR_CONTROL::CrossProbePcbToSch( const TOOL_EVENT& aEvent ) +{ + if( m_probingSchToPcb ) + { + m_probingSchToPcb = false; + return 0; + } + + SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>(); + const SELECTION& selection = selTool->GetSelection(); + + if( selection.Size() == 1 ) + m_frame->SendMessageToEESCHEMA( selection.Item<BOARD_ITEM>( 0 ) ); + + return 0; +} + + +int PCB_EDITOR_CONTROL::CrossProbeSchToPcb( const TOOL_EVENT& aEvent ) +{ + BOARD_ITEM* item = aEvent.Parameter<BOARD_ITEM*>(); + + if( item ) + { + m_probingSchToPcb = true; + getView()->SetCenter( VECTOR2D( item->GetPosition() ) ); + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); + + // If it is a pad and the net highlighting tool is enabled, highlight the net + if( item->Type() == PCB_PAD_T && m_frame->GetToolId() == ID_PCB_HIGHLIGHT_BUTT ) + { + int net = static_cast<D_PAD*>( item )->GetNetCode(); + m_toolMgr->RunAction( COMMON_ACTIONS::highlightNet, false, net ); + } + else + // Otherwise simply select the corresponding item + { + m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, item ); + } + } + + return 0; +} + + +static bool setDrillOrigin( KIGFX::VIEW* aView, PCB_BASE_FRAME* aFrame, + KIGFX::ORIGIN_VIEWITEM* aItem, const VECTOR2D& aPosition ) +{ + aFrame->SetAuxOrigin( wxPoint( aPosition.x, aPosition.y ) ); + aItem->SetPosition( aPosition ); + aView->MarkDirty(); + + return true; +} + + +int PCB_EDITOR_CONTROL::DrillOrigin( const TOOL_EVENT& aEvent ) +{ + Activate(); + + PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>(); + assert( picker ); + + m_frame->SetToolID( ID_PCB_PLACE_OFFSET_COORD_BUTT, wxCURSOR_PENCIL, _( "Adjust zero" ) ); + picker->SetClickHandler( boost::bind( setDrillOrigin, getView(), m_frame, m_placeOrigin, _1 ) ); + picker->Activate(); + Wait(); + + return 0; +} + +/** + * Function highlightNet() + * Looks for a BOARD_CONNECTED_ITEM in a given spot, and if one is found - it enables + * highlight for its net. + * @param aPoint is the point where an item is expected (world coordinates). + */ +static bool highlightNet( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition ) +{ + KIGFX::RENDER_SETTINGS* render = aToolMgr->GetView()->GetPainter()->GetSettings(); + GENERAL_COLLECTORS_GUIDE guide = static_cast<PCB_BASE_FRAME*>( aToolMgr->GetEditFrame() )->GetCollectorsGuide(); + BOARD* board = static_cast<BOARD*>( aToolMgr->GetModel() ); + GENERAL_COLLECTOR collector; + int net = -1; + + // Find a connected item for which we are going to highlight a net + collector.Collect( board, GENERAL_COLLECTOR::PadsTracksOrZones, + wxPoint( aPosition.x, aPosition.y ), guide ); + bool enableHighlight = ( collector.GetCount() > 0 ); + + // Obtain net code for the clicked item + if( enableHighlight ) + net = static_cast<BOARD_CONNECTED_ITEM*>( collector[0] )->GetNetCode(); + + // Toggle highlight when the same net was picked + if( net > 0 && net == render->GetHighlightNetCode() ) + enableHighlight = !render->IsHighlightEnabled(); + + if( enableHighlight != render->IsHighlightEnabled() || net != render->GetHighlightNetCode() ) + { + render->SetHighlight( enableHighlight, net ); + aToolMgr->GetView()->UpdateAllLayersColor(); + } + + return true; +} + + +int PCB_EDITOR_CONTROL::HighlightNet( const TOOL_EVENT& aEvent ) +{ + int netcode = aEvent.Parameter<long>(); + + if( netcode > 0 ) + { + KIGFX::RENDER_SETTINGS* render = m_toolMgr->GetView()->GetPainter()->GetSettings(); + render->SetHighlight( true, netcode ); + m_toolMgr->GetView()->UpdateAllLayersColor(); + } + else + { + // No net code specified, pick the net code belonging to the item under the cursor + highlightNet( m_toolMgr, getView()->ToWorld( getViewControls()->GetMousePosition() ) ); + } + + return 0; +} + + +int PCB_EDITOR_CONTROL::HighlightNetCursor( const TOOL_EVENT& aEvent ) +{ + Activate(); + + PICKER_TOOL* picker = m_toolMgr->GetTool<PICKER_TOOL>(); + assert( picker ); + + m_frame->SetToolID( ID_PCB_HIGHLIGHT_BUTT, wxCURSOR_PENCIL, _( "Highlight net" ) ); + picker->SetClickHandler( boost::bind( highlightNet, m_toolMgr, _1 ) ); + picker->SetSnapping( false ); + picker->Activate(); + Wait(); + + return 0; +} + + +void PCB_EDITOR_CONTROL::SetTransitions() +{ + // Track & via size control + Go( &PCB_EDITOR_CONTROL::TrackWidthInc, COMMON_ACTIONS::trackWidthInc.MakeEvent() ); + Go( &PCB_EDITOR_CONTROL::TrackWidthDec, COMMON_ACTIONS::trackWidthDec.MakeEvent() ); + Go( &PCB_EDITOR_CONTROL::ViaSizeInc, COMMON_ACTIONS::viaSizeInc.MakeEvent() ); + Go( &PCB_EDITOR_CONTROL::ViaSizeDec, COMMON_ACTIONS::viaSizeDec.MakeEvent() ); + + // Zone actions + Go( &PCB_EDITOR_CONTROL::ZoneFill, COMMON_ACTIONS::zoneFill.MakeEvent() ); + Go( &PCB_EDITOR_CONTROL::ZoneFillAll, COMMON_ACTIONS::zoneFillAll.MakeEvent() ); + Go( &PCB_EDITOR_CONTROL::ZoneUnfill, COMMON_ACTIONS::zoneUnfill.MakeEvent() ); + Go( &PCB_EDITOR_CONTROL::ZoneUnfillAll, COMMON_ACTIONS::zoneUnfillAll.MakeEvent() ); + Go( &PCB_EDITOR_CONTROL::ZoneMerge, COMMON_ACTIONS::zoneMerge.MakeEvent() ); + + // Placing tools + Go( &PCB_EDITOR_CONTROL::PlaceTarget, COMMON_ACTIONS::placeTarget.MakeEvent() ); + Go( &PCB_EDITOR_CONTROL::PlaceModule, COMMON_ACTIONS::placeModule.MakeEvent() ); + + // Other + Go( &PCB_EDITOR_CONTROL::ToggleLockModule, COMMON_ACTIONS::toggleLockModule.MakeEvent() ); + Go( &PCB_EDITOR_CONTROL::CrossProbePcbToSch, SELECTION_TOOL::SelectedEvent ); + Go( &PCB_EDITOR_CONTROL::CrossProbeSchToPcb, COMMON_ACTIONS::crossProbeSchToPcb.MakeEvent() ); + Go( &PCB_EDITOR_CONTROL::DrillOrigin, COMMON_ACTIONS::drillOrigin.MakeEvent() ); + Go( &PCB_EDITOR_CONTROL::HighlightNet, COMMON_ACTIONS::highlightNet.MakeEvent() ); + Go( &PCB_EDITOR_CONTROL::HighlightNetCursor, COMMON_ACTIONS::highlightNetCursor.MakeEvent() ); +} + + +const int PCB_EDITOR_CONTROL::WIDTH_STEP = 100000; |