diff --git a/common/drawpanel_gal.cpp b/common/drawpanel_gal.cpp index 3549455245..ee0de205c7 100644 --- a/common/drawpanel_gal.cpp +++ b/common/drawpanel_gal.cpp @@ -38,6 +38,9 @@ #include #include +#include +#include + #ifdef __WXDEBUG__ #include #endif /* __WXDEBUG__ */ @@ -54,6 +57,7 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin m_currentGal = GAL_TYPE_NONE; m_view = NULL; m_painter = NULL; + m_eventDispatcher = NULL; SwitchBackend( aGalType, true ); SetBackgroundStyle( wxBG_STYLE_CUSTOM ); @@ -83,6 +87,19 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin Connect( wxEVT_PAINT, wxPaintEventHandler( EDA_DRAW_PANEL_GAL::onPaint ), NULL, this ); Connect( wxEVT_SIZE, wxSizeEventHandler( EDA_DRAW_PANEL_GAL::onSize ), NULL, this ); + /* Generic events for the Tool Dispatcher */ + + Connect( wxEVT_MOTION, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_LEFT_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_LEFT_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_RIGHT_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_RIGHT_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_MIDDLE_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_MIDDLE_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_MOUSEWHEEL, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_KEY_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + Connect( wxEVT_KEY_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + m_timeStamp = 0; } @@ -121,8 +138,8 @@ void EDA_DRAW_PANEL_GAL::Refresh( bool eraseBackground, const wxRect* rect ) // Framerate limiter wxLongLong currentTimeStamp = wxGetLocalTimeMillis(); - if( currentTimeStamp - m_timeStamp < ( 1000 / FPS_LIMIT ) ) - return; + // if( currentTimeStamp - m_timeStamp < ( 1000 / FPS_LIMIT ) ) + // return; m_timeStamp = currentTimeStamp; #ifdef __WXDEBUG__ @@ -131,6 +148,8 @@ void EDA_DRAW_PANEL_GAL::Refresh( bool eraseBackground, const wxRect* rect ) prof_start( &time, false ); #endif /* __WXDEBUG__ */ + printf("Refresh!\n"); + m_gal->BeginDrawing(); m_gal->SetBackgroundColor( KiGfx::COLOR4D( 0.0, 0.0, 0.0, 1.0 ) ); m_gal->ClearScreen(); @@ -193,3 +212,20 @@ void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType, bool aUseShaders ) m_currentGal = aGalType; m_useShaders = aUseShaders; } + +void EDA_DRAW_PANEL_GAL::onEvent( wxEvent& aEvent ) +{ + if(!m_eventDispatcher) + { + aEvent.Skip(); + return; + } else { + printf("evType %d\n", aEvent.GetEventType()); + m_eventDispatcher->DispatchWxEvent(aEvent); + } +} + +KiGfx::VIEW_CONTROLS* EDA_DRAW_PANEL_GAL::GetViewControls() const +{ + return m_viewControls; +} \ No newline at end of file diff --git a/include/class_drawpanel_gal.h b/include/class_drawpanel_gal.h index b6a63306f9..764f4d8020 100644 --- a/include/class_drawpanel_gal.h +++ b/include/class_drawpanel_gal.h @@ -36,12 +36,14 @@ #include class BOARD; +class TOOL_DISPATCHER; namespace KiGfx { class GAL; class VIEW; class WX_VIEW_CONTROLS; +class VIEW_CONTROLS; class PAINTER; }; @@ -74,13 +76,21 @@ public: KiGfx::GAL* GetGAL() { return m_gal; } void SetView( KiGfx::VIEW* aView ) { m_view = aView; } + KiGfx::VIEW* GetView() const { return m_view; } + KiGfx::VIEW_CONTROLS* GetViewControls() const; virtual void Refresh( bool eraseBackground = true, const wxRect* rect = NULL ); + void SetEventDispatcher(TOOL_DISPATCHER *aEventDispatcher) + { + m_eventDispatcher = aEventDispatcher; + } + protected: void onPaint( wxPaintEvent& WXUNUSED( aEvent ) ); void onSize( wxSizeEvent& aEvent ); + void onEvent( wxEvent& aEvent ); KiGfx::GAL* m_gal; ///< Interface for drawing objects on a 2D-surface KiGfx::VIEW* m_view; ///< Stores view settings (scale, center, etc.) @@ -91,6 +101,7 @@ protected: GalType m_currentGal; ///< Currently used GAL bool m_useShaders; ///< Are shaders used? (only for OpenGL GAL) wxLongLong m_timeStamp; + TOOL_DISPATCHER* m_eventDispatcher; }; #endif diff --git a/include/wxBasePcbFrame.h b/include/wxBasePcbFrame.h index 842b9059d6..09677f5daf 100644 --- a/include/wxBasePcbFrame.h +++ b/include/wxBasePcbFrame.h @@ -56,7 +56,8 @@ class ZONE_SETTINGS; class PCB_PLOT_PARAMS; class FP_LIB_TABLE; class FPID; - +class TOOL_MANAGER; +class TOOL_DISPATCHER; /** * class PCB_BASE_FRAME @@ -94,6 +95,10 @@ protected: /// main window. wxAuiToolBar* m_auxiliaryToolBar; + TOOL_MANAGER *m_toolManager; + TOOL_DISPATCHER *m_toolDispatcher; + + void setupTools(); void updateGridSelectBox(); void updateZoomSelectBox(); virtual void unitsChangeRefresh(); diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index 7d9845e4ef..6730815c3b 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -65,7 +65,6 @@ class PARSE_ERROR; class IO_ERROR; class FP_LIB_TABLE; - /** * class PCB_EDIT_FRAME * the main frame for Pcbnew @@ -118,6 +117,8 @@ protected: bool m_useCmpFileForFpNames; ///< is true, use the .cmp file from CvPcb, else use the netlist // to know the footprint name of components. + void onGenericCommand( wxCommandEvent& aEvent ); + // we'll use lower case function names for private member functions. void createPopUpMenuForZones( ZONE_CONTAINER* edge_zone, wxMenu* aPopMenu ); void createPopUpMenuForFootprints( MODULE* aModule, wxMenu* aPopMenu ); diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index fa681e4faf..16d0ee1e5d 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -216,6 +216,10 @@ set(PCBNEW_CLASS_SRCS zones_polygons_test_connections.cpp zones_test_and_combine_areas.cpp class_footprint_wizard.cpp + + tools/selection_tool.cpp + tools/selection_area.cpp + tools/pcb_tools.cpp ) set(PCBNEW_SRCS ${PCBNEW_AUTOROUTER_SRCS} ${PCBNEW_CLASS_SRCS} ${PCBNEW_DIALOGS}) diff --git a/pcbnew/basepcbframe.cpp b/pcbnew/basepcbframe.cpp index 9580ea9e6c..edc02934df 100644 --- a/pcbnew/basepcbframe.cpp +++ b/pcbnew/basepcbframe.cpp @@ -54,6 +54,8 @@ #include #include +#include +#include // Configuration entry names. static const wxString UserGridSizeXEntry( wxT( "PcbUserGrid_X" ) ); @@ -79,7 +81,7 @@ BEGIN_EVENT_TABLE( PCB_BASE_FRAME, EDA_DRAW_FRAME ) EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_PADS_SKETCH, PCB_BASE_FRAME::OnUpdatePadDrawMode ) EVT_UPDATE_UI( ID_ON_GRID_SELECT, PCB_BASE_FRAME::OnUpdateSelectGrid ) EVT_UPDATE_UI( ID_ON_ZOOM_SELECT, PCB_BASE_FRAME::OnUpdateSelectZoom ) - + EVT_UPDATE_UI_RANGE( ID_ZOOM_IN, ID_ZOOM_PAGE, PCB_BASE_FRAME::OnUpdateSelectZoom ) END_EVENT_TABLE() @@ -91,6 +93,8 @@ PCB_BASE_FRAME::PCB_BASE_FRAME( wxWindow* aParent, ID_DRAWFRAME_TYPE aFrameType, EDA_DRAW_FRAME( aParent, aFrameType, aTitle, aPos, aSize, aStyle, aFrameName ) { m_Pcb = NULL; + m_toolManager = NULL; + m_toolDispatcher = NULL; m_DisplayPadFill = true; // How to draw pads m_DisplayViaFill = true; // How to draw vias @@ -111,6 +115,8 @@ PCB_BASE_FRAME::PCB_BASE_FRAME( wxWindow* aParent, ID_DRAWFRAME_TYPE aFrameType, m_galCanvas = new EDA_DRAW_PANEL_GAL( this, -1, wxPoint( 0, 0 ), m_FrameSize, EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL ); + setupTools(); + m_auxiliaryToolBar = NULL; } @@ -185,6 +191,11 @@ void PCB_BASE_FRAME::SetBoard( BOARD* aBoard ) view->RecacheAllItems( true ); if( m_galCanvasActive ) m_galCanvas->Refresh(); + + // update the tool manager with the new board and its view. + if(m_toolManager) + m_toolManager->SetEnvironment( m_Pcb, view, m_galCanvas->GetViewControls(), this); + } } @@ -796,6 +807,7 @@ void PCB_BASE_FRAME::LoadSettings() wxASSERT( i < KiGfx::VIEW::VIEW_MAX_LAYERS ); view->SetLayerOrder( GalLayerOrder[i], i ); + view->SetLayerTarget( i, KiGfx::TARGET_NONCACHED ); } // Netnames are drawn only when scale is sufficient (level of details) diff --git a/pcbnew/menubar_pcbframe.cpp b/pcbnew/menubar_pcbframe.cpp index 5f87f1d8cb..28073bbbd8 100644 --- a/pcbnew/menubar_pcbframe.cpp +++ b/pcbnew/menubar_pcbframe.cpp @@ -298,6 +298,12 @@ void PCB_EDIT_FRAME::ReCreateMenuBar() _( "Reset text size and width of all module fields to current defaults" ), KiBitmap( reset_text_xpm ) ); + editMenu->AppendSeparator(); + + AddMenuItem( editMenu, ID_SELECTION_TOOL, + _( "Select Tool" ), + _( "Interactive selection and drag&drop tool." ) ); + /** Create View menu **/ wxMenu* viewMenu = new wxMenu; diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index 8a3e663359..67bfa67666 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -59,6 +59,8 @@ #include #include +#include +#include #if defined(KICAD_SCRIPTING) || defined(KICAD_SCRIPTING_WXPYTHON) #include @@ -116,6 +118,12 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME ) EVT_MENU( wxID_EXIT, PCB_EDIT_FRAME::OnQuit ) // menu Config + + /* Tom's hacks start */ + EVT_MENU ( ID_SELECTION_TOOL, PCB_EDIT_FRAME::onGenericCommand ) + EVT_TOOL ( ID_SELECTION_TOOL, PCB_EDIT_FRAME::onGenericCommand ) + /* Tom's hacks end */ + EVT_MENU( ID_PCB_DRAWINGS_WIDTHS_SETUP, PCB_EDIT_FRAME::OnConfigurePcbOptions ) EVT_MENU( ID_CONFIG_REQ, PCB_EDIT_FRAME::Process_Config ) EVT_MENU( ID_PCB_LIB_TABLE_EDIT, PCB_EDIT_FRAME::Process_Config ) @@ -472,9 +480,10 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( wxWindow* parent, const wxString& title, DisplayError( this, msg ); } } + + setupTools(); } - PCB_EDIT_FRAME::~PCB_EDIT_FRAME() { m_RecordingMacros = -1; diff --git a/pcbnew/pcbnew_id.h b/pcbnew/pcbnew_id.h index a5babb0348..02e1ea6cda 100644 --- a/pcbnew/pcbnew_id.h +++ b/pcbnew/pcbnew_id.h @@ -367,6 +367,8 @@ enum pcbnew_ids ID_FOOTPRINT_WIZARD_SELECT_WIZARD, ID_FOOTPRINT_WIZARD_EXPORT_TO_BOARD, + ID_SELECTION_TOOL + }; #endif // PCBNEW_ID_H_ diff --git a/pcbnew/tools/pcb_tools.cpp b/pcbnew/tools/pcb_tools.cpp new file mode 100644 index 0000000000..7843d6d7ec --- /dev/null +++ b/pcbnew/tools/pcb_tools.cpp @@ -0,0 +1,55 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 CERN + * @author Tomasz Wlostowski + * + * 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 +#include + +#include +#include + +#include +#include + +#include +#include + +#include "selection_tool.h" + +void PCB_BASE_FRAME::setupTools() +{ + // create the manager and dispatcher. Route draw panel events to the dispatcher. + m_toolManager = new TOOL_MANAGER; + m_toolDispatcher = new TOOL_DISPATCHER_PCBNEW( m_toolManager, this ); + m_galCanvas->SetEventDispatcher (m_toolDispatcher); + + // register our selection tool. + m_toolManager->RegisterTool(new SELECTION_TOOL); + +} + +void PCB_EDIT_FRAME::onGenericCommand(wxCommandEvent &aEvent) +{ + m_toolDispatcher->DispatchWxCommand(aEvent); +} + diff --git a/pcbnew/tools/selection_area.cpp b/pcbnew/tools/selection_area.cpp new file mode 100644 index 0000000000..717a09bfc6 --- /dev/null +++ b/pcbnew/tools/selection_area.cpp @@ -0,0 +1,62 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 CERN + * @author Tomasz Wlostowski + * + * 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 + +#include + +#include "selection_area.h" + +using namespace KiGfx; + +const BOX2I SELECTION_AREA::ViewBBox() const +{ + BOX2I tmp; + tmp.SetOrigin(m_origin); + tmp.SetEnd(m_end); + tmp.Normalize(); + return tmp; +} + +void SELECTION_AREA::ViewGetLayers( int aLayers[], int& aCount ) const +{ + aLayers[0] = SelectionLayer; + aCount = 1; +} + +void SELECTION_AREA::ViewDraw( int aLayer, GAL* aGal, const BOX2I& aVisibleArea ) const +{ + VECTOR2D width = m_view->ToWorld( VECTOR2D(1.0, 1.0), false ); // fixme: pixel-sized stroke width setting? + aGal->SetLineWidth( width.x ); + aGal->SetStrokeColor(COLOR4D(1.0, 1.0, 0.4, 1.0)); + aGal->SetFillColor(COLOR4D(0.3, 0.3, 0.5, 0.3)); + aGal->SetIsStroke(true); + aGal->SetIsFill(true); + aGal->SetLayerDepth(100.0); + aGal->DrawRectangle(m_origin, m_end); +} + +SELECTION_AREA::SELECTION_AREA(): + EDA_ITEM(NOT_USED) // this item is never added to a BOARD so it needs no type. + {} \ No newline at end of file diff --git a/pcbnew/tools/selection_area.h b/pcbnew/tools/selection_area.h new file mode 100644 index 0000000000..f4677f40a7 --- /dev/null +++ b/pcbnew/tools/selection_area.h @@ -0,0 +1,76 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 CERN + * @author Tomasz Wlostowski + * + * 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 + */ + +#ifndef __SELECTION_AREA_H +#define __SELECTION_AREA_H + +#include +#include + +#include + +#include +#include +#include + +/** + * Class SELECTION_AREA + * + * Represents a selection area (currently a rectangle) in a VIEW. + */ +class SELECTION_AREA : public EDA_ITEM +{ + public: + static const int SelectionLayer = 126; // fixme: define globally + + SELECTION_AREA(); + ~SELECTION_AREA() {}; + + virtual const BOX2I ViewBBox() const; + + void ViewDraw( int aLayer, KiGfx::GAL* aGal, const BOX2I& aVisibleArea ) const; + void ViewGetLayers( int aLayers[], int& aCount ) const; + + void SetOrigin ( VECTOR2I aOrigin ) + { + m_origin = aOrigin; + } + + void SetEnd ( VECTOR2I aEnd ) + { + m_end = aEnd; + } + + void Show(int x, std::ostream& st) const + { + + } + + private: + + + VECTOR2I m_origin, m_end; +}; + +#endif diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp new file mode 100644 index 0000000000..a872fbb46c --- /dev/null +++ b/pcbnew/tools/selection_tool.cpp @@ -0,0 +1,276 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 CERN + * @author Tomasz Wlostowski + * + * 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 +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include "selection_tool.h" +#include "selection_area.h" + +using namespace KiGfx; +using boost::optional; + + +SELECTION_TOOL::SELECTION_TOOL() : + TOOL_INTERACTIVE( "pcbnew.InteractiveSelection" ) + { + m_selArea = new SELECTION_AREA; + + } + + +SELECTION_TOOL::~SELECTION_TOOL() +{ + if(m_selArea) + delete m_selArea; +} + + +void SELECTION_TOOL::Reset() +{ + // the tool launches upon reception of activate ("pcbnew.InteractiveSelection") + Go(&SELECTION_TOOL::Main, TOOL_EVENT(TC_Command, TA_ActivateTool, GetName())); //"pcbnew.InteractiveSelection")); +} + +int SELECTION_TOOL::Main(TOOL_EVENT& aEvent) +{ + + // Main loop: keep receiving events + while(OPT_TOOL_EVENT evt = Wait ()) + { + + if(evt->IsCancel ()) + return 0; + + // single click? Select single object + if( evt->IsClick (MB_Left) ) + selectSingle(evt->Position(), evt->Modifier( MB_ModShift )); + + // drag with LMB? Select multiple objects (or at least draw a selection box) + if (evt->IsDrag ( MB_Left )) + selectMultiple(); + } + + return 0; +} + +void SELECTION_TOOL::toggleSelection ( BOARD_ITEM * aItem, bool aAdditive ) +{ + + if(m_selectedItems.find(aItem) != m_selectedItems.end()) + { + aItem->ViewSetHighlighted(false); + m_selectedItems.erase(aItem); + } else { + if(!aAdditive) + clearSelection(); + aItem->ViewSetHighlighted(true); + m_selectedItems.insert(aItem); + } +} + +void SELECTION_TOOL::clearSelection () +{ + BOOST_FOREACH(BOARD_ITEM *item, m_selectedItems) + { + item->ViewSetHighlighted(false); + } + + m_selectedItems.clear(); +} + + +void SELECTION_TOOL::selectSingle( const VECTOR2I &aWhere, bool aAdditive ) +{ + BOARD *pcb = getModel (PCB_T); + BOARD_ITEM *item; + GENERAL_COLLECTORS_GUIDE guide = getEditFrame()->GetCollectorsGuide(); + GENERAL_COLLECTOR collector; + + collector.Collect(pcb, GENERAL_COLLECTOR::AllBoardItems , wxPoint(aWhere.x, aWhere.y), guide); + + switch (collector.GetCount()) + { + case 0: + if(!aAdditive) + clearSelection(); + break; + case 1: + toggleSelection( collector[0], aAdditive ); + break; + default: + item = disambiguationMenu(&collector); + if(item) + toggleSelection(item, aAdditive ); + break; + } +} + + +BOARD_ITEM* SELECTION_TOOL::pickSmallestComponent( GENERAL_COLLECTOR* aCollector ) +{ + int count = aCollector->GetPrimaryCount(); // try to use preferred layer + if( 0 == count ) count = aCollector->GetCount(); + + for( int i = 0; iType() != PCB_MODULE_T ) + return NULL; + } + + // all are modules, now find smallest MODULE + + int minDim = 0x7FFFFFFF; + int minNdx = 0; + + for( int i = 0; iGetBoundingBox().GetWidth(); + int ly = module->GetBoundingBox().GetHeight(); + + int lmin = std::min( lx, ly ); + + if( lmin < minDim ) + { + minDim = lmin; + minNdx = i; + } + } + + return (*aCollector)[minNdx]; +} + +void SELECTION_TOOL::handleHighlight( const VECTOR2D& aP ) +{ + +} + +void SELECTION_TOOL::selectMultiple() +{ + OPT_TOOL_EVENT evt; + VIEW *v = getView(); + + v->Add(m_selArea); + + while (evt = Wait()) + { + if(evt->IsCancel()) + break; + + if(evt->IsDrag( MB_Left )) + { + m_selArea->SetOrigin( evt->DragOrigin() ); + m_selArea->SetEnd( evt->Position() ); + m_selArea->ViewSetVisible(true); + m_selArea->ViewUpdate(VIEW_ITEM::APPEARANCE | VIEW_ITEM::GEOMETRY); + + + v->SetLayerVisible( SELECTION_AREA::SelectionLayer ); + v->SetLayerOrder( SELECTION_AREA::SelectionLayer, 1000); + v->SetLayerTarget( SELECTION_AREA::SelectionLayer, TARGET_OVERLAY ); + } + + if(evt->IsMouseUp( MB_Left )) + { + m_selArea->ViewSetVisible(false); + break; + } + } + + + v->Remove(m_selArea); +} + + +BOARD_ITEM *SELECTION_TOOL::disambiguationMenu ( GENERAL_COLLECTOR *aCollector ) +{ + CONTEXT_MENU cmenu; + OPT_TOOL_EVENT evt ; + BOARD_ITEM *current = NULL; + + cmenu.SetTitle( _("Clarify selection")); + + int limit = std::min( 10, aCollector->GetCount() ); + + for( int i = 0; iGetSelectMenuText(); + cmenu.Add(text, i); + } + + SetContextMenu(&cmenu, CMENU_NOW); + + while (evt = Wait()) + { + + + if(evt->Action() == TA_ContextMenuUpdate ) + { + if(current) + current->ViewSetHighlighted(false); + + int id = *evt->GetCommandId(); + if(id >= 0) + { + current = (*aCollector) [id]; + current->ViewSetHighlighted(true); + } else + current = NULL; + + + } else if(evt->Action() == TA_ContextMenuChoice ) { + + optional id = evt->GetCommandId(); + + if(current) + current->ViewSetHighlighted(false); + + if(id && (*id >= 0)) + { + current = (*aCollector) [*id]; + current->ViewSetHighlighted(true); + return current; + } + return NULL; + } + + + } + + return NULL; +} \ No newline at end of file diff --git a/pcbnew/tools/selection_tool.h b/pcbnew/tools/selection_tool.h new file mode 100644 index 0000000000..b226be85cc --- /dev/null +++ b/pcbnew/tools/selection_tool.h @@ -0,0 +1,71 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 CERN + * @author Tomasz Wlostowski + * + * 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 + */ + +#ifndef __SELECTION_TOOL_H +#define __SELECTION_TOOL_H + +#include + +#include +#include + +class SELECTION_AREA; +class BOARD_ITEM; +class GENERAL_COLLECTOR; + + +/** + * Class SELECTION_AREA + * + * Our sample selection tool: currently supports: + * - pick single objects (click LMB) + * - add objects to existing selection (Shift+LMB) + * - draw selection box (drag LMB) + * + * WORK IN PROGRESS. CONSIDER AS A DEMO! + */ + +class SELECTION_TOOL : public TOOL_INTERACTIVE +{ + public: + SELECTION_TOOL (); + ~SELECTION_TOOL (); + + void Reset(); + int Main(TOOL_EVENT& aEvent); + + private: + void selectSingle( const VECTOR2I &aWhere, bool aAdditive ); + void selectMultiple (); + void handleHighlight( const VECTOR2D& aP ); + BOARD_ITEM* disambiguationMenu ( GENERAL_COLLECTOR* aItems ); + BOARD_ITEM* pickSmallestComponent( GENERAL_COLLECTOR* aCollector ); + void toggleSelection ( BOARD_ITEM * aItem, bool aAdditive ); + void clearSelection (); + + std::set m_selectedItems; + SELECTION_AREA *m_selArea; +}; + +#endif