From 64dfea78b8fc9ed3184ed1cde85d5043ff7d5247 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Tue, 11 Sep 2012 09:33:17 +0200 Subject: [PATCH] Pcbnew: drag functions: serious cleanup and better code. Use now the connectivity functions to find tracks connected to pads, and therefore tracks are now dragged when a end point is inside a pad, not necessary on the pad position. However, drag functions still need more cleanup. --- 3d-viewer/3d_draw_basic_functions.cpp | 2 +- common/displlst.cpp | 2 +- include/wxBasePcbFrame.h | 11 +- include/wxPcbStruct.h | 11 +- pcbnew/CMakeLists.txt | 1 + pcbnew/class_board.cpp | 3 +- pcbnew/class_module.h | 6 + pcbnew/clean.cpp | 14 +- pcbnew/connect.cpp | 9 +- pcbnew/connect.h | 10 +- pcbnew/dialogs/dialog_gendrill.cpp | 2 +- pcbnew/drag.h | 176 +++++++++-- pcbnew/dragsegm.cpp | 420 +++++++++++++++++++------- pcbnew/edit.cpp | 15 +- pcbnew/modedit.cpp | 2 +- pcbnew/modules.cpp | 74 ++--- pcbnew/move-drag_pads.cpp | 281 ++--------------- pcbnew/move_or_drag_track.cpp | 296 ++++-------------- pcbnew/muwave_command.cpp | 2 +- pcbnew/onleftclick.cpp | 6 +- pcbnew/pad_edition_functions.cpp | 256 ++++++++++++++++ pcbnew/pcbnew.cpp | 17 +- pcbnew/pcbnew.h | 1 - 23 files changed, 890 insertions(+), 727 deletions(-) create mode 100644 pcbnew/pad_edition_functions.cpp diff --git a/3d-viewer/3d_draw_basic_functions.cpp b/3d-viewer/3d_draw_basic_functions.cpp index 713fef2aa9..4fd075479d 100644 --- a/3d-viewer/3d_draw_basic_functions.cpp +++ b/3d-viewer/3d_draw_basic_functions.cpp @@ -324,7 +324,7 @@ void Draw3D_ZaxisOblongCylinder( wxPoint aAxis1Pos, wxPoint aAxis2Pos, // Draw the oblong inner cylinder if( aHeight ) Draw3D_VerticalPolygonalCylinder( inner_cornerBuffer, aHeight, - true, aZpos, aBiuTo3DUnits ); + aZpos, true, aBiuTo3DUnits ); // Build the horizontal full polygon shape // (outer polygon shape - inner polygon shape) diff --git a/common/displlst.cpp b/common/displlst.cpp index 531de2a65b..45058ee168 100644 --- a/common/displlst.cpp +++ b/common/displlst.cpp @@ -155,7 +155,7 @@ void EDA_LIST_DIALOG::SortList() { wxArrayString list = m_listBox->GetStrings(); - if( list.IsEmpty() <= 0 ) + if( list.IsEmpty() ) return; list.Sort( SortItems ); diff --git a/include/wxBasePcbFrame.h b/include/wxBasePcbFrame.h index 05cae8b37c..dbf11335fa 100644 --- a/include/wxBasePcbFrame.h +++ b/include/wxBasePcbFrame.h @@ -339,7 +339,16 @@ public: */ void DeletePad( D_PAD* aPad, bool aQuery = true ); - void StartMovePad( D_PAD* Pad, wxDC* DC ); + /** + * Function StartMovePad + * Initialize a drag or move pad command + * @param aPad = the pad to move or drag + * @param aDC = the current device context + * @param aDragConnectedTracks = true to drag connected tracks, + * false to just move the pad + */ + void StartMovePad( D_PAD* aPad, wxDC* aDC, bool aDragConnectedTracks ); + void RotatePad( D_PAD* Pad, wxDC* DC ); void PlacePad( D_PAD* Pad, wxDC* DC ); void Export_Pad_Settings( D_PAD* aPad ); diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index accb2eb734..58d859d5fa 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -937,7 +937,16 @@ public: // Footprint edition (see also PCB_BASE_FRAME) void InstallModuleOptionsFrame( MODULE* Module, wxDC* DC ); - void StartMove_Module( MODULE* module, wxDC* DC ); + + /** + * Function StartMoveModule + * Initialize a drag or move pad command + * @param aModule = the module to move or drag + * @param aDC = the current device context + * @param aDragConnectedTracks = true to drag connected tracks, + * false to just move the module + */ + void StartMoveModule( MODULE* aModule, wxDC* aDC, bool aDragConnectedTracks ); /** * Function DlgGlobalChange_PadSettings diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 9410c14e92..a5aa8379e8 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -184,6 +184,7 @@ set(PCBNEW_CLASS_SRCS netlist_reader_kicad.cpp onleftclick.cpp onrightclick.cpp + pad_edition_functions.cpp pcbnew.cpp pcbnew_config.cpp pcbplot.cpp diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index 0909d49762..57409d3b16 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -1807,8 +1807,9 @@ D_PAD* BOARD::GetPad( std::vector& aPadList, const wxPoint& aPosition, i /** * Function SortPadsByXCoord * is used by GetSortedPadListByXCoord to Sort a pad list by x coordinate value. + * This function is used to build ordered pads lists */ -static bool sortPadsByXthenYCoord( D_PAD* const & ref, D_PAD* const & comp ) +bool sortPadsByXthenYCoord( D_PAD* const & ref, D_PAD* const & comp ) { if( ref->GetPosition().x == comp->GetPosition().x ) return ref->GetPosition().y < comp->GetPosition().y; diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h index 2924d1bb4b..f02866e32c 100644 --- a/pcbnew/class_module.h +++ b/pcbnew/class_module.h @@ -196,6 +196,12 @@ public: void Flip( const wxPoint& aCentre ); + /** + * function IsFlipped + * @return true if the module is flipped, i.e. on the back side of the board + */ + bool IsFlipped() const {return GetLayer() == LAYER_N_BACK; } + bool IsLocked() const { return (m_ModuleStatus & MODULE_is_LOCKED) != 0; diff --git a/pcbnew/clean.cpp b/pcbnew/clean.cpp index 58af530889..b450f0406c 100644 --- a/pcbnew/clean.cpp +++ b/pcbnew/clean.cpp @@ -102,7 +102,7 @@ private: * merge aTrackRef and aCandidate, when possible, * i.e. when they are colinear, same width, and obviously same layer */ - TRACK* mergeColinearSegmentIfPossible( TRACK* aTrackRef, + TRACK* mergeCollinearSegmentIfPossible( TRACK* aTrackRef, TRACK* aCandidate, int aEndType ); }; @@ -489,7 +489,7 @@ bool TRACKS_CLEANER::clean_segments() } } - // delete intermediate points (merging colinear segments) + // merge collinear segments: for( segment = m_Brd->m_Track; segment; segment = nextsegment ) { TRACK* segStart; @@ -533,7 +533,7 @@ bool TRACKS_CLEANER::clean_segments() if( flag ) // We have the starting point of the segment is connected to an other segment { - segDelete = mergeColinearSegmentIfPossible( segment, segStart, FLG_START ); + segDelete = mergeCollinearSegmentIfPossible( segment, segStart, FLG_START ); if( segDelete ) { @@ -574,7 +574,7 @@ bool TRACKS_CLEANER::clean_segments() if( flag & 2 ) // We have the ending point of the segment is connected to an other segment { - segDelete = mergeColinearSegmentIfPossible( segment, segEnd, FLG_END ); + segDelete = mergeCollinearSegmentIfPossible( segment, segEnd, FLG_END ); if( segDelete ) { @@ -593,9 +593,9 @@ bool TRACKS_CLEANER::clean_segments() /** Function used by clean_segments. - * Test alignment of aTrackRef and aCandidate (which must have a common end). + * Test if aTrackRef and aCandidate (which must have a common end) are collinear. * and see if the common point is not on a pad (i.e. if this common point can be removed). - * the ending point of pt_ref is the start point (aEndType == START) + * the ending point of aTrackRef is the start point (aEndType == START) * or the end point (aEndType != START) * flags START_ON_PAD and END_ON_PAD must be set before calling this function * if the common point can be deleted, this function @@ -604,7 +604,7 @@ bool TRACKS_CLEANER::clean_segments() * and return aCandidate (which can be deleted). * else return NULL */ -TRACK* TRACKS_CLEANER::mergeColinearSegmentIfPossible( TRACK* aTrackRef, TRACK* aCandidate, +TRACK* TRACKS_CLEANER::mergeCollinearSegmentIfPossible( TRACK* aTrackRef, TRACK* aCandidate, int aEndType ) { if( aTrackRef->m_Width != aCandidate->m_Width ) diff --git a/pcbnew/connect.cpp b/pcbnew/connect.cpp index 0639007a20..5e66f666da 100644 --- a/pcbnew/connect.cpp +++ b/pcbnew/connect.cpp @@ -105,7 +105,7 @@ void CONNECTIONS::SearchConnectionsPadsToIntersectingPads() * D_PAD::m_TracksConnected is cleared before adding items * TRACK::m_PadsConnected is not cleared */ -void CONNECTIONS::SearchTracksConnectedToPads() +void CONNECTIONS::SearchTracksConnectedToPads( bool add_to_padlist, bool add_to_tracklist) { std::vector candidates; @@ -127,8 +127,11 @@ void CONNECTIONS::SearchTracksConnectedToPads() if( pad->HitTest( cp_item->GetPoint() ) ) { - cp_item->GetTrack()->m_PadsConnected.push_back( pad ); - pad->m_TracksConnected.push_back( cp_item->GetTrack() ); + if( add_to_padlist ) + cp_item->GetTrack()->m_PadsConnected.push_back( pad ); + + if( add_to_tracklist ) + pad->m_TracksConnected.push_back( cp_item->GetTrack() ); } } } diff --git a/pcbnew/connect.h b/pcbnew/connect.h index ba0629c967..cc836eddf8 100644 --- a/pcbnew/connect.h +++ b/pcbnew/connect.h @@ -183,12 +183,16 @@ public: /** * function SearchTracksConnectedToPads * Explores the list of pads. - * Adds to m_PadsConnected member of each track the pad(s) connected to - * Adds to m_TracksConnected member of each pad the track(s) connected to + * if( add_to_padlist ) + * adds to m_PadsConnected member of each track the pad(s) connected to + * if add_to_tracklist + * adds to m_TracksConnected member of each pad the track(s) connected to * D_PAD::m_TracksConnected is cleared before adding items * TRACK::m_PadsConnected is not cleared + * @param add_to_padlist = true to fill m_PadsConnected member of each track + * @param add_to_tracklist = true to fill m_TracksConnected member of each pad */ - void SearchTracksConnectedToPads(); + void SearchTracksConnectedToPads( bool add_to_padlist = true, bool add_to_tracklist = true); /** * function CollectItemsNearTo diff --git a/pcbnew/dialogs/dialog_gendrill.cpp b/pcbnew/dialogs/dialog_gendrill.cpp index 3f0180d712..d8926d11c4 100644 --- a/pcbnew/dialogs/dialog_gendrill.cpp +++ b/pcbnew/dialogs/dialog_gendrill.cpp @@ -78,7 +78,7 @@ DIALOG_GENDRILL::DIALOG_GENDRILL( PCB_EDIT_FRAME* parent ) : int DIALOG_GENDRILL:: m_UnitDrillIsInch = true; int DIALOG_GENDRILL:: m_ZerosFormat = EXCELLON_WRITER::DECIMAL_FORMAT; bool DIALOG_GENDRILL::m_MinimalHeader = false; -bool DIALOG_GENDRILL::m_Mirror = true; +bool DIALOG_GENDRILL::m_Mirror = false; bool DIALOG_GENDRILL::m_DrillOriginIsAuxAxis = false; int DIALOG_GENDRILL:: m_PrecisionFormat = 1; bool DIALOG_GENDRILL::m_createRpt = false; diff --git a/pcbnew/drag.h b/pcbnew/drag.h index 0cff7d2a74..0af29f433f 100644 --- a/pcbnew/drag.h +++ b/pcbnew/drag.h @@ -1,8 +1,31 @@ /** * @file drag.h - * @brief Useful class and functions used to drag tracks + * @brief Useful classes and functions used to collect tracks to drag */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2004-2012 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors. + * + * 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 @@ -13,62 +36,151 @@ class wxDC; class EDA_DRAW_PANEL; class MODULE; class D_PAD; +class CONNECTIONS; -/** Helper class to handle a list of track segments to drag +/** Helper classes to handle a list of track segments to drag * and has info to undo/abort the move command - * a DRAG_SEGM manage one track segment or a via */ -class DRAG_SEGM + + /* + * a DRAG_LIST manages the list of track segments to modify + * when the pad or the module is moving + */ + +/* + * a DRAG_SEGM_PICKER manage one track segment or a via + */ +class DRAG_SEGM_PICKER { public: - TRACK* m_Segm; /* pointer to the segment a "dragger */ - D_PAD* m_Pad_Start; /* pointer to the pad origin if origin segment of pad */ - D_PAD* m_Pad_End; /* pointer to the pad end if end segment of pad */ - int m_Flag; /* indicator flags */ + TRACK* m_Track; // pointer to the parent track segment + D_PAD* m_Pad_Start; // pointer to the moving pad + // if the start point should follow this pad + // or NULL + D_PAD* m_Pad_End; // pointer to the moving pad + // if the end point should follow this pad + // or NULL + bool m_Flag; // flag used in drag vias and drag track segment functions private: - wxPoint m_StartInitialValue; - wxPoint m_EndInitialValue; // For abort: initial m_Start and m_End values for m_Segm - + double m_RotationOffset; // initial orientation of the parent module + // Used to recalculate m_PadStartOffset and m_PadEndOffset + // after a module rotation when dragging + bool m_Flipped; // initial side of the parent module + // Used to recalculate m_PadStartOffset and m_PadEndOffset + // if the module is flipped when dragging + wxPoint m_PadStartOffset; // offset between the pad and the starting point of the track + // usually 0,0, but not always + wxPoint m_PadEndOffset; // offset between the pad and the ending point of the track + // usually 0,0, but not always + wxPoint m_startInitialValue; + wxPoint m_endInitialValue; // For abort command: + // initial m_Start and m_End values for m_Track public: - DRAG_SEGM( TRACK* segm ); - ~DRAG_SEGM() {}; + DRAG_SEGM_PICKER( TRACK* aTrack ); + ~DRAG_SEGM_PICKER() {}; - void SetInitialValues() + /** + * Set auxiliary parameters relative to calucaltions needed + * to find track ends positions while dragging pads + * and when modules are rotated, flipped .. + */ + void SetAuxParameters(); + + /** + * Calculate track ends position while dragging pads + * and when modules are rotated, flipped .. + * @param aOffset = offset of module or pad position (when moving) + */ + void SetTrackEndsCoordinates(wxPoint aOffset); + + void RestoreInitialValues() { - m_Segm->m_Start = m_StartInitialValue; - m_Segm->m_End = m_EndInitialValue; + m_Track->SetStart( m_startInitialValue ); + m_Track->SetEnd( m_endInitialValue ); } }; -/* Variables */ +class DRAG_LIST +{ +public: + BOARD * m_Brd; // the main board + MODULE * m_Module; // The link to the module to move, or NULL + D_PAD * m_Pad; // The link to the pad to move, or NULL -// a list of DRAG_SEGM items used to move or drag tracks. -// Each DRAG_SEGM item points a segment to move. -extern std::vector g_DragSegmentList; + std::vector m_DragList; // The list of DRAG_SEGM_PICKER items -/* Functions */ +public: + DRAG_LIST( BOARD * aPcb ) + { + m_Brd = aPcb; + } + + /** + * Function ClearList + * clear the .m_Flags of all track segments in m_DragList + * and clear the list. + */ + void ClearList(); + + /** Build the list of track segments connected to pads of aModule + * in m_DragList + * For each selected track segment the EDIT flag is set + */ + void BuildDragListe( MODULE* aModule ); + + /** Build the list of track segments connected to aPad + * in m_DragList + * For each selected track segment the EDIT flag is set + */ + void BuildDragListe( D_PAD* aPad ); + +private: + + /** Fills m_DragList with of track segments connected to pads in aConnections + * For each selected track segment the EDIT flag is set + */ + void fillList(CONNECTIONS& aConnections); +}; + + +// Global variables: + +// a list of DRAG_SEGM_PICKER items used to move or drag tracks. +// Each DRAG_SEGM_PICKER item points a segment to move. +extern std::vector g_DragSegmentList; + +// Functions: void DrawSegmentWhileMovingFootprint( EDA_DRAW_PANEL* panel, wxDC* DC ); -void Build_Drag_Liste( EDA_DRAW_PANEL* panel, wxDC* DC, MODULE* Module ); -void Build_1_Pad_SegmentsToDrag( EDA_DRAW_PANEL* panel, wxDC* DC, D_PAD* PtPad ); -void Collect_TrackSegmentsToDrag( EDA_DRAW_PANEL* panel, wxDC* DC, - wxPoint& point, int LayerMask, int net_code ); - /** * Function EraseDragList - * clear the .m_Flags of all track segments managed by in g_DragSegmentList + * clear the .m_Flags of all track segments stored in g_DragSegmentList * and clear the list. - * In order to avoid useless memory allocation, the memory is not freed + * In order to avoid useless memory reallocation, the memory is not freed * and will be reused when creating a new list */ void EraseDragList(); -/* Add the segment"Track" to the drag list, and erase it from screen - * flag = STARTPOINT (if the point to drag is the start point of Track) - * or ENDPOINT +/* + * function used to collect track segments in drag track segment */ -void AddSegmentToDragList( EDA_DRAW_PANEL* panel, wxDC* DC, int flag, TRACK* Track ); +void Collect_TrackSegmentsToDrag( BOARD* aPcb, wxPoint& point, int LayerMask, int net_code ); + +/* Add aTrack to the drag list + * flag = STARTPOINT (if the point to drag is the start point of Track) + * or ENDPOINT (if the point to drag is the end point of Track) + */ +void AddSegmentToDragList( int flag, TRACK* aTrack ); + +/* + * Undraw the track segments in list, and set the EDIT flag + * Usually called after the track list is built, to prepare + * the redraw of the list when the mouse is moved + */ +void UndrawAndMarkSegmentsToDrag( EDA_DRAW_PANEL* aCanvas, wxDC* aDC ); + + diff --git a/pcbnew/dragsegm.cpp b/pcbnew/dragsegm.cpp index 8b6c5a71ba..44d56192f8 100644 --- a/pcbnew/dragsegm.cpp +++ b/pcbnew/dragsegm.cpp @@ -1,11 +1,36 @@ -/*********************************/ -/* functions used to drag tracks */ -/*********************************/ +/** + * @file dragsegm.cpp + * @brief Classes to find track segments connected to a pad or a module + * for drag commands + */ -/* Fichier dragsegm.cpp */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2004-2012 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors. + * + * 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 @@ -15,123 +40,291 @@ #include #include +#include -/* a list of DRAG_SEGM items used to move or drag tracks */ -std::vector g_DragSegmentList; +/* a list of DRAG_SEGM_PICKER items used to move or drag tracks */ +std::vector g_DragSegmentList; /* helper class to handle a list of track segments to drag or move */ -DRAG_SEGM::DRAG_SEGM( TRACK* segm ) +DRAG_SEGM_PICKER::DRAG_SEGM_PICKER( TRACK* aTrack ) { - m_Segm = segm; - m_StartInitialValue = m_Segm->m_Start; - m_EndInitialValue = m_Segm->m_End; - m_Pad_Start = m_Pad_End = NULL; + m_Track = aTrack; + m_startInitialValue = m_Track->m_Start; + m_endInitialValue = m_Track->m_End; + m_Pad_Start = m_Track->GetState( START_ON_PAD ) ? (D_PAD*)m_Track->start : NULL; + m_Pad_End = m_Track->GetState( END_ON_PAD ) ? (D_PAD*)m_Track->end : NULL; m_Flag = 0; + m_RotationOffset = 0.0; + m_Flipped = false; } -/* Redraw the list of segments starting in g_DragSegmentList, while moving a footprint */ +/* Set auxiliary parameters relative to calucaltions needed + * to find track ends positions while dragging pads + * and when modules are rotated, flipped .. + */ +void DRAG_SEGM_PICKER::SetAuxParameters() +{ + MODULE * module = NULL; + if( m_Pad_Start ) + { + module = (MODULE *) m_Pad_Start->GetParent(); + m_PadStartOffset = m_Track->GetStart() - m_Pad_Start->GetPosition(); + } + + if( m_Pad_End ) + { + if( module == NULL ) + module = (MODULE *) m_Pad_End->GetParent(); + m_PadEndOffset = m_Track->GetEnd() - m_Pad_End->GetPosition(); + } + + if( module ) + { + m_Flipped = module->IsFlipped(); + m_RotationOffset = module->GetOrientation(); + } +} + +/* + * Calculate track ends positions while dragging pads + * and when modules are rotated, flipped .. + * aOffset = module or pad position offset when moving the module or pad + * (the actual position is the module/pad position - offset) + */ +void DRAG_SEGM_PICKER::SetTrackEndsCoordinates(wxPoint aOffset) +{ + // the track start position is the pad position + m_PadStartOffset + // however m_PadStartOffset is known for the initial rotation/flip + // this is also true for track end position and m_PadEndOffset + // Therefore, because rotation/flipping is allowed during a drag + // and move module, we should recalculate the pad offset, + // depending on the current orientation/flip state of the module + // relative to its initial orientation. + // (although most of time, offset is 0,0) + + double curr_rot_offset = m_RotationOffset; + MODULE * module = NULL; + bool flip = false; + + if( m_Pad_Start ) + module = (MODULE *) m_Pad_Start->GetParent(); + + if( module == NULL && m_Pad_End ) + module = (MODULE *) m_Pad_End->GetParent(); + + if( module ) + { + flip = m_Flipped != module->IsFlipped(); + curr_rot_offset = module->GetOrientation() - m_RotationOffset; + if( flip ) // when flipping, module orientation is negated + curr_rot_offset = - module->GetOrientation() - m_RotationOffset; + } + + if( m_Pad_Start ) + { + wxPoint padoffset = m_PadStartOffset; + + if( curr_rot_offset != 0.0 ) + RotatePoint(&padoffset, curr_rot_offset); + + if( flip ) + NEGATE( padoffset.y ); + + m_Track->m_Start = m_Pad_Start->GetPosition() - aOffset + padoffset; + } + + if( m_Pad_End ) + { + wxPoint padoffset = m_PadEndOffset; + + if( curr_rot_offset != 0.0 ) + RotatePoint(&padoffset, curr_rot_offset); + + if( flip ) + NEGATE( padoffset.y ); + + m_Track->m_End = m_Pad_End->GetPosition() - aOffset + padoffset; + } +} + + +// A sort function needed to build ordered pads lists +extern bool sortPadsByXthenYCoord( D_PAD* const & ref, D_PAD* const & comp ); + +void DRAG_LIST::BuildDragListe( MODULE* aModule ) +{ + m_Pad = NULL; + m_Module = aModule; + + // Build connections info + CONNECTIONS connections( m_Brd ); + std::vector&padList = connections.GetPadsList(); + + for( D_PAD* pad = aModule->m_Pads; pad; pad = pad->Next() ) + padList.push_back( pad ); + + sort( padList.begin(), padList.end(), sortPadsByXthenYCoord ); + + fillList( connections ); +} + +void DRAG_LIST::BuildDragListe( D_PAD* aPad ) +{ + m_Pad = aPad; + m_Module = NULL; + + // Build connections info + CONNECTIONS connections( m_Brd ); + std::vector&padList = connections.GetPadsList(); + padList.push_back( aPad ); + + fillList( connections ); +} + +// A helper function to sort track list per tracks +bool sort_tracklist( const DRAG_SEGM_PICKER& ref, const DRAG_SEGM_PICKER& tst ) +{ + return ref.m_Track < tst.m_Track; +} +/** Fills m_DragList with track segments connected to pads in aConnections + * For each selected track segment the EDIT flag is set + */ +void DRAG_LIST::fillList(CONNECTIONS& aConnections) +{ + aConnections.BuildTracksCandidatesList( m_Brd->m_Track, NULL); + + // Build connections info tracks to pads + // Rebuild pads to track info only) + aConnections.SearchTracksConnectedToPads( false, true ); + + std::vectorpadList = aConnections.GetPadsList(); + + // clear flags and variables of selected tracks + for( unsigned ii = 0; ii < padList.size(); ii++ ) + { + D_PAD * pad = padList[ii]; + + // store track connected to the pad + for( unsigned jj = 0; jj < pad->m_TracksConnected.size(); jj++ ) + { + TRACK * track = pad->m_TracksConnected[jj]; + track->start = NULL; + track->end = NULL; + track->SetState( START_ON_PAD|END_ON_PAD|BUSY, OFF ); + } + } + + // store tracks connected to pads + for( unsigned ii = 0; ii < padList.size(); ii++ ) + { + D_PAD * pad = padList[ii]; + + // store track connected to the pad + for( unsigned jj = 0; jj < pad->m_TracksConnected.size(); jj++ ) + { + TRACK * track = pad->m_TracksConnected[jj]; + + if( pad->HitTest( track->GetStart() ) ) + { + track->start = pad; + track->SetState( START_ON_PAD, ON ); + } + + if( pad->HitTest( track->GetEnd() ) ) + { + track->end = pad; + track->SetState( END_ON_PAD, ON ); + } + DRAG_SEGM_PICKER wrapper( track ); + m_DragList.push_back( wrapper ); + } + } + + // remove duplicate in m_DragList: + // a track can be stored more than once if connected to 2 overlapping pads, or + // each track end connected to 2 moving pads + // to avoid artifact in draw function, items should be not duplicated + // However, there is not a lot of items to be removed, so there ir no optimization. + + // sort the drag list by track pointers + sort( m_DragList.begin(), m_DragList.end(), sort_tracklist ); + + // Explore the list, merge duplicates + for( int ii = 0; ii < (int)m_DragList.size()-1; ii++ ) + { + int jj = ii+1; + if( m_DragList[ii].m_Track != m_DragList[jj].m_Track ) + continue; + + // duplicate found: merge info and remove duplicate + if( m_DragList[ii].m_Pad_Start == NULL ) + m_DragList[ii].m_Pad_Start = m_DragList[jj].m_Pad_Start; + if( m_DragList[ii].m_Pad_End == NULL ) + m_DragList[ii].m_Pad_End = m_DragList[jj].m_Pad_End; + + m_DragList.erase(m_DragList.begin() + jj ); + ii--; + } + + // Initialize pad offsets and other params + for( unsigned ii = 0; ii < m_DragList.size(); ii++ ) + m_DragList[ii].SetAuxParameters(); + + // Copy the list in global list + g_DragSegmentList = m_DragList; +} + +void DRAG_LIST::ClearList() +{ + for( unsigned ii = 0; ii < m_DragList.size(); ii++ ) + m_DragList[ii].m_Track->ClearFlags(); + + m_DragList.clear(); + + m_Module = NULL; + m_Pad = NULL; +} + + +// Redraw the list of segments stored in g_DragSegmentList, while moving a footprint void DrawSegmentWhileMovingFootprint( EDA_DRAW_PANEL* panel, wxDC* DC ) { - if( g_DragSegmentList.size() == 0 ) - return; - for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) { - wxPoint pos; - - TRACK* track = g_DragSegmentList[ii].m_Segm; + TRACK* track = g_DragSegmentList[ii].m_Track; #ifndef USE_WX_OVERLAY track->Draw( panel, DC, GR_XOR ); // erase from screen at old position #endif - - D_PAD* pad = g_DragSegmentList[ii].m_Pad_Start; - - if( pad ) - { - pos = pad->GetPosition() - g_Offset_Module; - track->m_Start = pos; - } - - pad = g_DragSegmentList[ii].m_Pad_End; - - if( pad ) - { - pos = pad->GetPosition() - g_Offset_Module; - track->m_End = pos; - } - + g_DragSegmentList[ii].SetTrackEndsCoordinates( g_Offset_Module ); track->Draw( panel, DC, GR_XOR ); } } -/** Build the list of track segments connected to pads of a given module - * by populate the std::vector g_DragSegmentList - * For each selected track segment set the EDIT flag - * and redraw them in EDIT mode (sketch mode) +/** + * Function EraseDragList + * clear the .m_Flags of all track segments found in g_DragSegmentList + * and clear the list. */ -void Build_Drag_Liste( EDA_DRAW_PANEL* panel, wxDC* DC, MODULE* aModule ) +void EraseDragList() { - for( D_PAD* pad = aModule->m_Pads; pad; pad = pad->Next() ) - { - Build_1_Pad_SegmentsToDrag( panel, DC, pad ); - } + for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) + g_DragSegmentList[ii].m_Track->ClearFlags(); - return; + g_DragSegmentList.clear(); } -/** Build the list of track segments connected to a given pad - * by populate the std::vector g_DragSegmentList - * For each selected track segment set the EDIT flag - * and redraw them in EDIT mode (sketch mode) - * Net codes must be OK. - */ -void Build_1_Pad_SegmentsToDrag( EDA_DRAW_PANEL* panel, wxDC* DC, D_PAD* aPad ) -{ - BOARD* pcb = ( (PCB_BASE_FRAME*)( panel->GetParent() ) )->GetBoard(); - - int net_code = aPad->GetNet(); - - TRACK* track = pcb->m_Track->GetStartNetCode( net_code ); - - wxPoint pos = aPad->GetPosition(); - - int layerMask = aPad->GetLayerMask(); - - for( ; track; track = track->Next() ) - { - if( track->GetNet() != net_code ) - break; - - if( ( layerMask & track->ReturnMaskLayer() ) == 0 ) - continue; - - if( pos == track->m_Start ) - { - AddSegmentToDragList( panel, DC, STARTPOINT, track ); - g_DragSegmentList.back().m_Pad_Start = aPad; - } - - if( pos == track->m_End ) - { - AddSegmentToDragList( panel, DC, ENDPOINT, track ); - g_DragSegmentList.back().m_Pad_End = aPad; - } - } -} - - -/* Add the segment"Track" to the drag list, and erase it from screen +/* Add Track to the drag list, and erase it from screen * flag = STARTPOINT (if the point to drag is the start point of Track) or ENDPOINT */ -void AddSegmentToDragList( EDA_DRAW_PANEL* panel, wxDC* DC, int flag, TRACK* Track ) +void AddSegmentToDragList( int flag, TRACK* aTrack ) { - DRAG_SEGM wrapper( Track ); + DRAG_SEGM_PICKER wrapper( aTrack ); if( (flag & STARTPOINT) ) wrapper.m_Flag |= 1; @@ -139,30 +332,23 @@ void AddSegmentToDragList( EDA_DRAW_PANEL* panel, wxDC* DC, int flag, TRACK* Tra if( (flag & ENDPOINT) ) wrapper.m_Flag |= 2; - Track->Draw( panel, DC, GR_XOR ); - Track->SetState( IN_EDIT, ON ); - if( (flag & STARTPOINT) ) - Track->SetFlags( STARTPOINT ); + aTrack->SetFlags( STARTPOINT ); if( (flag & ENDPOINT) ) - Track->SetFlags( ENDPOINT ); + aTrack->SetFlags( ENDPOINT ); - Track->Draw( panel, DC, GR_XOR ); g_DragSegmentList.push_back( wrapper ); } /* Build the list of tracks connected to the ref point * Net codes must be up to date, because only tracks having the right net code are tested. - * @param aRefPos = reference point of connection + * aRefPos = reference point of connection */ -void Collect_TrackSegmentsToDrag( EDA_DRAW_PANEL* panel, wxDC* DC, - wxPoint& aRefPos, int LayerMask, int net_code ) +void Collect_TrackSegmentsToDrag( BOARD* aPcb, wxPoint& aRefPos, int LayerMask, int net_code ) { - BOARD* pcb = ( (PCB_BASE_FRAME*)( panel->GetParent() ) )->GetBoard(); - - TRACK* track = pcb->m_Track->GetStartNetCode( net_code ); + TRACK* track = aPcb->m_Track->GetStartNetCode( net_code ); for( ; track; track = track->Next() ) { @@ -187,28 +373,38 @@ void Collect_TrackSegmentsToDrag( EDA_DRAW_PANEL* panel, wxDC* DC, // and must not be entered twice. if( flag ) { - AddSegmentToDragList( panel, DC, flag, track ); + AddSegmentToDragList( flag, track ); // If a connected via is found at location aRefPos, // collect also tracks connected by this via. if( track->Type() == PCB_VIA_T ) - Collect_TrackSegmentsToDrag( panel, DC, aRefPos, track->ReturnMaskLayer(), + Collect_TrackSegmentsToDrag( aPcb, aRefPos, track->ReturnMaskLayer(), net_code ); } } } - -/** - * Function EraseDragList - * clear the .m_Flags of all track segments found in g_DragSegmentList - * and clear the list. - * the memory is not freed and will be reused when creating a new list +/* + * Undraw the track segments in list, and set the IN_EDIT flag + * Usually called after the track list is built, to prepare + * the redraw of the list when the mouse is moved */ -void EraseDragList() +void UndrawAndMarkSegmentsToDrag( EDA_DRAW_PANEL* aCanvas, wxDC* aDC ) { for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) - g_DragSegmentList[ii].m_Segm->ClearFlags(); + { + TRACK* track = g_DragSegmentList[ii].m_Track; - g_DragSegmentList.clear(); + track->Draw( aCanvas, aDC, GR_XOR ); + track->SetState( IN_EDIT, ON ); + + if( (g_DragSegmentList[ii].m_Flag & STARTPOINT) ) + track->SetFlags( STARTPOINT ); + + if( (g_DragSegmentList[ii].m_Flag & ENDPOINT) ) + track->SetFlags( ENDPOINT ); + + track->Draw( aCanvas, aDC, GR_XOR ); + } } + diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp index b6adee5749..6be48e427c 100644 --- a/pcbnew/edit.cpp +++ b/pcbnew/edit.cpp @@ -614,8 +614,6 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_POPUP_PCB_DRAG_MODULE_REQUEST: - g_Drag_Pistes_On = true; - case ID_POPUP_PCB_MOVE_MODULE_REQUEST: if( GetCurItem() == NULL ) break; @@ -625,10 +623,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) SetCurItem( GetCurItem()->GetParent() ); if( !GetCurItem() || GetCurItem()->Type() != PCB_MODULE_T ) - { - g_Drag_Pistes_On = false; break; - } module = (MODULE*) GetCurItem(); @@ -644,7 +639,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) SendMessageToEESCHEMA( module ); GetScreen()->SetCrossHairPosition( module->m_Pos ); m_canvas->MoveCursorToCrossHair(); - StartMove_Module( module, &dc ); + StartMoveModule( module, &dc, id == ID_POPUP_PCB_DRAG_MODULE_REQUEST ); break; case ID_POPUP_PCB_GET_AND_MOVE_MODULE_REQUEST: /* get module by name and move it */ @@ -665,7 +660,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) SendMessageToEESCHEMA( module ); m_canvas->MoveCursorToCrossHair(); - StartMove_Module( module, &dc ); + StartMoveModule( module, &dc, false ); break; case ID_POPUP_PCB_DELETE_MODULE: @@ -809,9 +804,8 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; } - g_Drag_Pistes_On = true; m_canvas->MoveCursorToCrossHair(); - StartMovePad( (D_PAD*) GetCurItem(), &dc ); + StartMovePad( (D_PAD*) GetCurItem(), &dc, true ); break; case ID_POPUP_PCB_MOVE_PAD_REQUEST: @@ -829,9 +823,8 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; } - g_Drag_Pistes_On = false; m_canvas->MoveCursorToCrossHair(); - StartMovePad( (D_PAD*) GetCurItem(), &dc ); + StartMovePad( (D_PAD*) GetCurItem(), &dc, false ); break; case ID_POPUP_PCB_EDIT_PAD: diff --git a/pcbnew/modedit.cpp b/pcbnew/modedit.cpp index 2dc3a7ede8..3a30a91c62 100644 --- a/pcbnew/modedit.cpp +++ b/pcbnew/modedit.cpp @@ -566,7 +566,7 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) case ID_POPUP_PCB_MOVE_PAD_REQUEST: { m_canvas->MoveCursorToCrossHair(); - StartMovePad( (D_PAD*) GetScreen()->GetCurItem(), &dc ); + StartMovePad( (D_PAD*) GetScreen()->GetCurItem(), &dc, false ); } break; diff --git a/pcbnew/modules.cpp b/pcbnew/modules.cpp index 2770048f4e..5e1fefc61b 100644 --- a/pcbnew/modules.cpp +++ b/pcbnew/modules.cpp @@ -91,9 +91,10 @@ MODULE* PCB_BASE_FRAME::GetModuleByName() } -void PCB_EDIT_FRAME::StartMove_Module( MODULE* module, wxDC* DC ) +void PCB_EDIT_FRAME::StartMoveModule( MODULE* aModule, wxDC* aDC, + bool aDragConnectedTracks ) { - if( module == NULL ) + if( aModule == NULL ) return; if( s_ModuleInitialCopy ) @@ -102,33 +103,37 @@ void PCB_EDIT_FRAME::StartMove_Module( MODULE* module, wxDC* DC ) s_PickedList.ClearItemsList(); // Should be empty, but... // Creates a copy of the current module, for abort and undo commands - s_ModuleInitialCopy = (MODULE*)module->Clone(); + s_ModuleInitialCopy = (MODULE*)aModule->Clone(); s_ModuleInitialCopy->SetParent( GetBoard() ); s_ModuleInitialCopy->ClearFlags(); - SetCurItem( module ); + SetCurItem( aModule ); GetBoard()->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK; - module->SetFlags( IS_MOVED ); + aModule->SetFlags( IS_MOVED ); /* Show ratsnest. */ if( GetBoard()->IsElementVisible( RATSNEST_VISIBLE ) ) - DrawGeneralRatsnest( DC ); + DrawGeneralRatsnest( aDC ); EraseDragList(); - if( g_Drag_Pistes_On ) + if( aDragConnectedTracks ) { - Build_Drag_Liste( m_canvas, DC, module ); + DRAG_LIST drglist( GetBoard() ); + drglist.BuildDragListe( aModule ); + ITEM_PICKER itemWrapper( NULL, UR_CHANGED ); for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) { - TRACK* segm = g_DragSegmentList[ii].m_Segm; + TRACK* segm = g_DragSegmentList[ii].m_Track; itemWrapper.SetItem( segm ); itemWrapper.SetLink( segm->Clone() ); itemWrapper.GetLink()->SetState( IN_EDIT, OFF ); s_PickedList.PushItem( itemWrapper ); } + + UndrawAndMarkSegmentsToDrag( m_canvas, aDC ); } GetBoard()->m_Status_Pcb |= DO_NOT_SHOW_GENERAL_RASTNEST; @@ -136,14 +141,14 @@ void PCB_EDIT_FRAME::StartMove_Module( MODULE* module, wxDC* DC ) m_canvas->SetAutoPanRequest( true ); // Erase the module. - if( DC ) + if( aDC ) { - module->SetFlags( DO_NOT_DRAW ); - m_canvas->RefreshDrawingRect( module->GetBoundingBox() ); - module->ClearFlags( DO_NOT_DRAW ); + aModule->SetFlags( DO_NOT_DRAW ); + m_canvas->RefreshDrawingRect( aModule->GetBoundingBox() ); + aModule->ClearFlags( DO_NOT_DRAW ); } - m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); + m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false ); } @@ -169,22 +174,13 @@ void Abort_MoveOrCopyModule( EDA_DRAW_PANEL* Panel, wxDC* DC ) */ if( module->IsMoving() ) { - if( g_Drag_Pistes_On ) - { - /* Erase on screen dragged tracks */ - for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) - { - pt_segm = g_DragSegmentList[ii].m_Segm; - pt_segm->Draw( Panel, DC, GR_XOR ); - } - } - - /* Go to old position for dragged tracks */ + /* Restore old position for dragged tracks */ for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) { - pt_segm = g_DragSegmentList[ii].m_Segm; + pt_segm = g_DragSegmentList[ii].m_Track; + pt_segm->Draw( Panel, DC, GR_XOR ); pt_segm->SetState( IN_EDIT, OFF ); - g_DragSegmentList[ii].SetInitialValues(); + g_DragSegmentList[ii].RestoreInitialValues(); pt_segm->Draw( Panel, DC, GR_OR ); } @@ -213,7 +209,6 @@ void Abort_MoveOrCopyModule( EDA_DRAW_PANEL* Panel, wxDC* DC ) module->Draw( Panel, DC, GR_OR ); } - g_Drag_Pistes_On = false; pcbframe->SetCurItem( NULL ); delete s_ModuleInitialCopy; @@ -363,7 +358,6 @@ void PCB_EDIT_FRAME::Change_Side_Module( MODULE* Module, wxDC* DC ) void PCB_BASE_FRAME::PlaceModule( MODULE* aModule, wxDC* aDC, bool aDoNotRecreateRatsnest ) { - TRACK* pt_segm; wxPoint newpos; if( aModule == 0 ) @@ -406,23 +400,19 @@ void PCB_BASE_FRAME::PlaceModule( MODULE* aModule, wxDC* aDC, bool aDoNotRecreat if( aDC ) aModule->Draw( m_canvas, aDC, GR_OR ); - if( g_DragSegmentList.size() ) + // Redraw dragged track segments, if any + for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) { - /* Redraw dragged track segments */ - for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) - { - pt_segm = g_DragSegmentList[ii].m_Segm; - pt_segm->SetState( IN_EDIT, OFF ); + TRACK * track = g_DragSegmentList[ii].m_Track; + track->SetState( IN_EDIT, OFF ); - if( aDC ) - pt_segm->Draw( m_canvas, aDC, GR_OR ); - } - - // Delete drag list - EraseDragList(); + if( aDC ) + track->Draw( m_canvas, aDC, GR_OR ); } - g_Drag_Pistes_On = false; + // Delete drag list + EraseDragList(); + m_canvas->SetMouseCapture( NULL, NULL ); if( GetBoard()->IsElementVisible( RATSNEST_VISIBLE ) && !aDoNotRecreateRatsnest ) diff --git a/pcbnew/move-drag_pads.cpp b/pcbnew/move-drag_pads.cpp index fed12ab11e..87c2aa685b 100644 --- a/pcbnew/move-drag_pads.cpp +++ b/pcbnew/move-drag_pads.cpp @@ -9,11 +9,9 @@ #include #include #include -#include #include #include #include -#include #include #include @@ -21,7 +19,6 @@ #include #include -#include static D_PAD* s_CurrentSelectedPad; @@ -44,22 +41,18 @@ static void Abort_Move_Pad( EDA_DRAW_PANEL* Panel, wxDC* DC ) pad->SetPosition( Pad_OldPos ); pad->Draw( Panel, DC, GR_XOR ); - // Pad move in progress: the restore origin. - if( g_Drag_Pistes_On ) + // Pad move in progress: restore origin of dragged tracks, if any. + for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) { - for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) - { - TRACK* Track = g_DragSegmentList[ii].m_Segm; - Track->Draw( Panel, DC, GR_XOR ); - Track->SetState( IN_EDIT, OFF ); - g_DragSegmentList[ii].SetInitialValues(); - Track->Draw( Panel, DC, GR_OR ); - } + TRACK* Track = g_DragSegmentList[ii].m_Track; + Track->Draw( Panel, DC, GR_XOR ); + Track->SetState( IN_EDIT, OFF ); + g_DragSegmentList[ii].RestoreInitialValues(); + Track->Draw( Panel, DC, GR_OR ); } EraseDragList(); s_CurrentSelectedPad = NULL; - g_Drag_Pistes_On = false; } @@ -81,209 +74,22 @@ static void Show_Pad_Move( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPo pad->SetPosition( screen->GetCrossHairPosition() ); pad->Draw( aPanel, aDC, GR_XOR ); - if( !g_Drag_Pistes_On ) - return; - for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) { - Track = g_DragSegmentList[ii].m_Segm; + Track = g_DragSegmentList[ii].m_Track; if( aErase ) Track->Draw( aPanel, aDC, GR_XOR ); - if( g_DragSegmentList[ii].m_Pad_Start ) - { - Track->m_Start = pad->GetPosition(); - } - - if( g_DragSegmentList[ii].m_Pad_End ) - { - Track->m_End = pad->GetPosition(); - } + g_DragSegmentList[ii].SetTrackEndsCoordinates( wxPoint(0, 0) ); Track->Draw( aPanel, aDC, GR_XOR ); } } -/* Load list of features for default pad selection. - */ -void PCB_BASE_FRAME::Export_Pad_Settings( D_PAD* aPad ) -{ - if( aPad == NULL ) - return; - - aPad->DisplayInfo( this ); - - D_PAD& mp = GetDesignSettings().m_Pad_Master; - - mp.SetShape( aPad->GetShape() ); - mp.SetAttribute( aPad->GetAttribute() ); - mp.SetLayerMask( aPad->GetLayerMask() ); - - mp.SetOrientation( aPad->GetOrientation() - aPad->GetParent()->GetOrientation() ); - - mp.SetSize( aPad->GetSize() ); - mp.SetDelta( aPad->GetDelta() ); - - mp.SetOffset( aPad->GetOffset() ); - mp.SetDrillSize( aPad->GetDrillSize() ); - mp.SetDrillShape( aPad->GetDrillShape() ); -} - - -/* Imports the new values of dimensions of the pad edge by aPad - * - Source: selected values of general characteristics - * - Measurements are modified - * - The position, names, and keys are not. - */ -void PCB_BASE_FRAME::Import_Pad_Settings( D_PAD* aPad, bool aDraw ) -{ - if( aDraw ) - { - aPad->SetFlags( DO_NOT_DRAW ); - m_canvas->RefreshDrawingRect( aPad->GetBoundingBox() ); - aPad->ClearFlags( DO_NOT_DRAW ); - } - - D_PAD& mp = GetDesignSettings().m_Pad_Master; - - aPad->SetShape( mp.GetShape() ); - aPad->SetLayerMask( mp.GetLayerMask() ); - aPad->SetAttribute( mp.GetAttribute() ); - aPad->SetOrientation( mp.GetOrientation() + aPad->GetParent()->GetOrientation() ); - aPad->SetSize( mp.GetSize() ); - aPad->SetDelta( wxSize( 0, 0 ) ); - aPad->SetOffset( mp.GetOffset() ); - aPad->SetDrillSize( mp.GetDrillSize() ); - aPad->SetDrillShape( mp.GetDrillShape() ); - - switch( mp.GetShape() ) - { - case PAD_TRAPEZOID: - aPad->SetDelta( mp.GetDelta() ); - break; - - case PAD_CIRCLE: - // set size.y to size.x - aPad->SetSize( wxSize( aPad->GetSize().x, aPad->GetSize().x ) ); - break; - - default: - ; - } - - switch( mp.GetAttribute() ) - { - case PAD_SMD: - case PAD_CONN: - aPad->SetDrillSize( wxSize( 0, 0 ) ); - aPad->SetOffset( wxPoint( 0, 0 ) ); - break; - default: - ; - } - - if( aDraw ) - m_canvas->RefreshDrawingRect( aPad->GetBoundingBox() ); - - aPad->GetParent()->SetLastEditTime(); -} - - -/* Add a pad on the selected module. - */ -void PCB_BASE_FRAME::AddPad( MODULE* aModule, bool draw ) -{ - // Last used pad name (pad num) - wxString lastPadName = GetDesignSettings().m_Pad_Master.GetPadName(); - - m_Pcb->m_Status_Pcb = 0; - aModule->SetLastEditTime(); - - D_PAD* pad = new D_PAD( aModule ); - - // Add the new pad to end of the module pad list. - aModule->m_Pads.PushBack( pad ); - - // Update the pad properties. - Import_Pad_Settings( pad, false ); - pad->SetNetname( wxEmptyString ); - - pad->SetPosition( GetScreen()->GetCrossHairPosition() ); - - // Set the relative pad position - // ( pad position for module orient, 0, and relative to the module position) - - wxPoint pos0 = pad->GetPosition() - aModule->GetPosition(); - RotatePoint( &pos0, -aModule->GetOrientation() ); - pad->SetPos0( pos0 ); - - // Automatically increment the current pad number. - long num = 0; - int ponder = 1; - - while( lastPadName.Len() && lastPadName.Last() >= '0' && lastPadName.Last() <= '9' ) - { - num += ( lastPadName.Last() - '0' ) * ponder; - lastPadName.RemoveLast(); - ponder *= 10; - } - - num++; // Use next number for the new pad - lastPadName << num; - pad->SetPadName( lastPadName ); - - GetDesignSettings().m_Pad_Master.SetPadName(lastPadName); - - aModule->CalculateBoundingBox(); - pad->DisplayInfo( this ); - - if( draw ) - m_canvas->RefreshDrawingRect( aModule->GetBoundingBox() ); -} - - -/** - * Function DeletePad - * Delete the pad aPad. - * Refresh the modified screen area - * Refresh modified parameters of the parent module (bounding box, last date) - * @param aPad = the pad to delete - * @param aQuery = true to promt for confirmation, false to delete silently - */ -void PCB_BASE_FRAME::DeletePad( D_PAD* aPad, bool aQuery ) -{ - MODULE* module; - - if( aPad == NULL ) - return; - - module = (MODULE*) aPad->GetParent(); - module->SetLastEditTime(); - - if( aQuery ) - { - wxString msg; - msg.Printf( _( "Delete Pad (module %s %s) " ), - GetChars( module->m_Reference->m_Text ), - GetChars( module->m_Value->m_Text ) ); - - if( !IsOK( this, msg ) ) - return; - } - - m_Pcb->m_Status_Pcb = 0; - aPad->DeleteStructure(); - m_canvas->RefreshDrawingRect( module->GetBoundingBox() ); - module->CalculateBoundingBox(); - - OnModify(); -} - - // Function to initialize the "move pad" command -void PCB_BASE_FRAME::StartMovePad( D_PAD* aPad, wxDC* DC ) +void PCB_BASE_FRAME::StartMovePad( D_PAD* aPad, wxDC* aDC, bool aDragConnectedTracks ) { if( aPad == NULL ) return; @@ -295,16 +101,20 @@ void PCB_BASE_FRAME::StartMovePad( D_PAD* aPad, wxDC* DC ) aPad->DisplayInfo( this ); m_canvas->SetMouseCapture( Show_Pad_Move, Abort_Move_Pad ); - // Draw the pad (SKETCH mode) - aPad->Draw( m_canvas, DC, GR_XOR ); + // Draw the pad, in SKETCH mode + aPad->Draw( m_canvas, aDC, GR_XOR ); aPad->SetFlags( IS_MOVED ); - aPad->Draw( m_canvas, DC, GR_XOR ); + aPad->Draw( m_canvas, aDC, GR_XOR ); + + EraseDragList(); // Build the list of track segments to drag if the command is a drag pad - if( g_Drag_Pistes_On ) - Build_1_Pad_SegmentsToDrag( m_canvas, DC, aPad ); - else - EraseDragList(); + if( aDragConnectedTracks ) + { + DRAG_LIST drglist( GetBoard() ); + drglist.BuildDragListe( aPad ); + UndrawAndMarkSegmentsToDrag( m_canvas, aDC ); + } } @@ -325,7 +135,7 @@ void PCB_BASE_FRAME::PlacePad( D_PAD* aPad, wxDC* DC ) // Save dragged track segments in undo list for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) { - Track = g_DragSegmentList[ii].m_Segm; + Track = g_DragSegmentList[ii].m_Track; // Set the old state if( g_DragSegmentList[ii].m_Pad_Start ) @@ -358,7 +168,7 @@ void PCB_BASE_FRAME::PlacePad( D_PAD* aPad, wxDC* DC ) // Redraw dragged track segments for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) { - Track = g_DragSegmentList[ii].m_Segm; + Track = g_DragSegmentList[ii].m_Track; // Set the new state if( g_DragSegmentList[ii].m_Pad_Start ) @@ -380,8 +190,7 @@ void PCB_BASE_FRAME::PlacePad( D_PAD* aPad, wxDC* DC ) RotatePoint( &dX, &dY, -module->GetOrientation() ); aPad->SetX0( dX + aPad->GetPos0().x ); - - s_CurrentSelectedPad->SetY0( dY + s_CurrentSelectedPad->GetPos0().y ); + aPad->SetY0( dY + aPad->GetPos0().y ); aPad->ClearFlags(); @@ -397,45 +206,3 @@ void PCB_BASE_FRAME::PlacePad( D_PAD* aPad, wxDC* DC ) m_canvas->SetMouseCapture( NULL, NULL ); m_Pcb->m_Status_Pcb &= ~( LISTE_RATSNEST_ITEM_OK | CONNEXION_OK ); } - - -// Rotate selected pad 90 degrees. -void PCB_BASE_FRAME::RotatePad( D_PAD* aPad, wxDC* DC ) -{ - if( aPad == NULL ) - return; - - MODULE* module = aPad->GetParent(); - - module->SetLastEditTime(); - - OnModify(); - - if( DC ) - module->Draw( m_canvas, DC, GR_XOR ); - - wxSize sz = aPad->GetSize(); - EXCHG( sz.x, sz.y ); - aPad->SetSize( sz ); - - sz = aPad->GetDrillSize(); - EXCHG( sz.x, sz.y ); - aPad->SetDrillSize( sz ); - - wxPoint pt = aPad->GetOffset(); - EXCHG( pt.x, pt.y ); - aPad->SetOffset( pt ); - - aPad->SetOffset( wxPoint( aPad->GetOffset().x, -aPad->GetOffset().y ) ); - - sz = aPad->GetDelta(); - EXCHG( sz.x, sz.y ); - sz.x = -sz.x; - aPad->SetDelta( sz ); - - module->CalculateBoundingBox(); - aPad->DisplayInfo( this ); - - if( DC ) - module->Draw( m_canvas, DC, GR_OR ); -} diff --git a/pcbnew/move_or_drag_track.cpp b/pcbnew/move_or_drag_track.cpp index 48d6a6cc18..062f2d4f73 100644 --- a/pcbnew/move_or_drag_track.cpp +++ b/pcbnew/move_or_drag_track.cpp @@ -58,8 +58,6 @@ static bool InitialiseDragParameters(); static wxPoint PosInit, s_LastPos; -static TRACK* NewTrack; /* New track or track being moved. */ -static int NbPtNewTrack; static double s_StartSegmentSlope, s_EndSegmentSlope, s_MovingSegmentSlope, s_StartSegment_Yorg, s_EndSegment_Yorg, @@ -74,89 +72,32 @@ bool s_StartSegmentPresent, s_EndSegmentPresent; static PICKED_ITEMS_LIST s_ItemsListPicker; -/** Abort function for commands drag, copy or move track +/** Abort function for drag or move track */ -static void Abort_MoveTrack( EDA_DRAW_PANEL* Panel, wxDC* DC ) +static void Abort_MoveTrack( EDA_DRAW_PANEL* aPanel, wxDC* aDC ) { - TRACK* NextS; - int ii; - BOARD * pcb = ( (PCB_EDIT_FRAME*) Panel->GetParent() )->GetBoard(); + PCB_EDIT_FRAME* frame = (PCB_EDIT_FRAME*) aPanel->GetParent(); + BOARD * pcb = frame->GetBoard(); - /* Erase the current drawings */ - wxPoint oldpos = Panel->GetScreen()->GetCrossHairPosition(); - - Panel->GetScreen()->SetCrossHairPosition( PosInit ); - - if( Panel->IsMouseCaptured() ) - Panel->CallMouseCapture( DC, wxDefaultPosition, true ); - - Panel->GetScreen()->SetCrossHairPosition( oldpos ); pcb->HighLightOFF(); - pcb->DrawHighLight( Panel, DC, pcb->GetHighLightNetCode() ); + pcb->PopHighLight(); - if( NewTrack ) - { - if( NewTrack->IsNew() ) - { - for( ii = 0; ii < NbPtNewTrack; ii++, NewTrack = NextS ) - { - if( NewTrack == NULL ) - break; - - NextS = NewTrack->Next(); - delete NewTrack; - } - } - else /* Move existing trace. */ - { - TRACK* Track = NewTrack; - int dx = s_LastPos.x - PosInit.x; - int dy = s_LastPos.y - PosInit.y; - - for( ii = 0; ii < NbPtNewTrack; ii++, Track = Track->Next() ) - { - if( Track == NULL ) - break; - - Track->m_Start.x -= dx; - Track->m_Start.y -= dy; - - Track->m_End.x -= dx; - Track->m_End.y -= dy; - - Track->ClearFlags(); - } - - DrawTraces( Panel, DC, NewTrack, NbPtNewTrack, GR_OR ); - } - - NewTrack = NULL; - } - - ( (PCB_EDIT_FRAME*) Panel->GetParent() )->SetCurItem( NULL ); + frame->SetCurItem( NULL ); + aPanel->SetMouseCapture( NULL, NULL ); /* Undo move and redraw trace segments. */ for( unsigned jj=0 ; jj < g_DragSegmentList.size(); jj++ ) { - TRACK* Track = g_DragSegmentList[jj].m_Segm; - g_DragSegmentList[jj].SetInitialValues(); - Track->SetState( IN_EDIT, OFF ); - Track->ClearFlags(); - Track->Draw( Panel, DC, GR_OR ); + TRACK* track = g_DragSegmentList[jj].m_Track; + g_DragSegmentList[jj].RestoreInitialValues(); + track->SetState( IN_EDIT, OFF ); + track->ClearFlags(); } // Clear the undo picker list: s_ItemsListPicker.ClearListAndDeleteItems(); - - pcb->PopHighLight(); - - if( pcb->IsHighLightNetON() ) - pcb->DrawHighLight( Panel, DC, pcb->GetHighLightNetCode() ); - EraseDragList(); - Panel->SetMouseCapture( NULL, NULL ); - - Panel->Refresh(); + aPanel->Refresh(); } @@ -164,9 +105,7 @@ static void Abort_MoveTrack( EDA_DRAW_PANEL* Panel, wxDC* DC ) static void Show_MoveNode( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase ) { - int ii; wxPoint moveVector; - TRACK* Track; BASE_SCREEN* screen = aPanel->GetScreen(); int track_fill_copy = DisplayOpt.DisplayPcbTrackFill; GR_DRAWMODE draw_mode = GR_XOR | GR_HIGHLIGHT; @@ -179,61 +118,42 @@ static void Show_MoveNode( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPo aErase = false; #endif - /* erase the current moved track segments from screen */ - if( aErase ) - { - if( NewTrack ) - DrawTraces( aPanel, aDC, NewTrack, NbPtNewTrack, draw_mode ); - } - - /* set the new track coordinates */ wxPoint Pos = screen->GetCrossHairPosition(); moveVector = Pos - s_LastPos; s_LastPos = Pos; - ii = NbPtNewTrack; - Track = NewTrack; - - for( ; (ii > 0) && (Track != NULL); ii--, Track = Track->Next() ) - { - if( Track->GetFlags() & STARTPOINT ) - Track->m_Start += moveVector; - - if( Track->GetFlags() & ENDPOINT ) - Track->m_End += moveVector; - } - -#ifndef USE_WX_OVERLAY - /* Redraw the current moved track segments */ - DrawTraces( aPanel, aDC, NewTrack, NbPtNewTrack, draw_mode ); -#endif + TRACK *track = NULL; for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) { - Track = g_DragSegmentList[ii].m_Segm; + if( aErase ) + track = g_DragSegmentList[ii].m_Track; if( aErase ) - Track->Draw( aPanel, aDC, draw_mode ); + track->Draw( aPanel, aDC, draw_mode ); - if( Track->GetFlags() & STARTPOINT ) - Track->m_Start += moveVector; + if( track->GetFlags() & STARTPOINT ) + track->m_Start += moveVector; - if( Track->GetFlags() & ENDPOINT ) - Track->m_End += moveVector; + if( track->GetFlags() & ENDPOINT ) + track->m_End += moveVector; - Track->Draw( aPanel, aDC, draw_mode ); + if( track->Type() == PCB_VIA_T ) + track->m_End = track->m_Start; + + track->Draw( aPanel, aDC, draw_mode ); } DisplayOpt.DisplayPcbTrackFill = track_fill_copy; // Display track length - PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) aPanel->GetParent(); - if( Track == NULL ) // can happen if g_DragSegmentList is empty - Track = NewTrack; // try to use main item - if( Track ) - Track->DisplayInfo( frame ); + if( track ) + { + PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) aPanel->GetParent(); + track->DisplayInfo( frame ); + } } @@ -298,7 +218,7 @@ static void Show_Drag_Track_Segment_With_Cte_Slope( EDA_DRAW_PANEL* aPanel, wxDC * the segment connected to its start point (if exists) */ int ii = g_DragSegmentList.size() - 1; - Track = g_DragSegmentList[ii].m_Segm; + Track = g_DragSegmentList[ii].m_Track; if( Track == NULL ) return; @@ -310,7 +230,7 @@ static void Show_Drag_Track_Segment_With_Cte_Slope( EDA_DRAW_PANEL* aPanel, wxDC if( s_EndSegmentPresent ) { // Get the segment connected to the end point - tSegmentToEnd = g_DragSegmentList[ii].m_Segm; + tSegmentToEnd = g_DragSegmentList[ii].m_Track; ii--; } @@ -318,7 +238,7 @@ static void Show_Drag_Track_Segment_With_Cte_Slope( EDA_DRAW_PANEL* aPanel, wxDC { // Get the segment connected to the start point if( ii >= 0 ) - tSegmentToStart = g_DragSegmentList[ii].m_Segm; + tSegmentToStart = g_DragSegmentList[ii].m_Track; } } @@ -531,7 +451,7 @@ bool InitialiseDragParameters() * the segment connected to its start point (if exists) */ int ii = g_DragSegmentList.size() - 1; - Track = g_DragSegmentList[ii].m_Segm; + Track = g_DragSegmentList[ii].m_Track; if( Track == NULL ) return false; @@ -541,7 +461,7 @@ bool InitialiseDragParameters() { if( s_EndSegmentPresent ) { - tSegmentToEnd = g_DragSegmentList[ii].m_Segm; // Get the segment connected to + tSegmentToEnd = g_DragSegmentList[ii].m_Track; // Get the segment connected to // the end point ii--; } @@ -549,7 +469,7 @@ bool InitialiseDragParameters() if( s_StartSegmentPresent ) { if( ii >= 0 ) - tSegmentToStart = g_DragSegmentList[ii].m_Segm; // Get the segment connected to + tSegmentToStart = g_DragSegmentList[ii].m_Track; // Get the segment connected to // the start point } } @@ -694,8 +614,6 @@ void PCB_EDIT_FRAME::StartMoveOneNodeOrSegment( TRACK* aTrack, wxDC* aDC, int aC if( !aTrack ) return; - NewTrack = NULL; - NbPtNewTrack = 0; EraseDragList(); /* Change highlighted net: the new one will be highlighted */ @@ -706,19 +624,18 @@ void PCB_EDIT_FRAME::StartMoveOneNodeOrSegment( TRACK* aTrack, wxDC* aDC, int aC PosInit = GetScreen()->GetCrossHairPosition(); - if( aTrack->Type() == PCB_VIA_T ) // For a via: always drag it + if( aTrack->Type() == PCB_VIA_T ) { aTrack->SetFlags( IS_DRAGGED | STARTPOINT | ENDPOINT ); + AddSegmentToDragList( aTrack->GetFlags(), aTrack ); if( aCommand != ID_POPUP_PCB_MOVE_TRACK_SEGMENT ) { - Collect_TrackSegmentsToDrag( m_canvas, aDC, aTrack->m_Start, + Collect_TrackSegmentsToDrag( GetBoard(), aTrack->m_Start, aTrack->ReturnMaskLayer(), aTrack->GetNet() ); } - NewTrack = aTrack; - NbPtNewTrack = 1; PosInit = aTrack->m_Start; } else @@ -730,25 +647,22 @@ void PCB_EDIT_FRAME::StartMoveOneNodeOrSegment( TRACK* aTrack, wxDC* aDC, int aC { case ID_POPUP_PCB_MOVE_TRACK_SEGMENT: // Move segment aTrack->SetFlags( IS_DRAGGED | ENDPOINT | STARTPOINT ); - AddSegmentToDragList( m_canvas, aDC, aTrack->GetFlags(), aTrack ); + AddSegmentToDragList( aTrack->GetFlags(), aTrack ); break; case ID_POPUP_PCB_DRAG_TRACK_SEGMENT: // drag a segment pos = aTrack->m_Start; - Collect_TrackSegmentsToDrag( m_canvas, aDC, pos, - aTrack->ReturnMaskLayer(), + Collect_TrackSegmentsToDrag( GetBoard(), pos, aTrack->ReturnMaskLayer(), aTrack->GetNet() ); pos = aTrack->m_End; aTrack->SetFlags( IS_DRAGGED | ENDPOINT | STARTPOINT ); - Collect_TrackSegmentsToDrag( m_canvas, aDC, pos, - aTrack->ReturnMaskLayer(), + Collect_TrackSegmentsToDrag( GetBoard(), pos, aTrack->ReturnMaskLayer(), aTrack->GetNet() ); break; case ID_POPUP_PCB_MOVE_TRACK_NODE: // Drag via or move node pos = (diag & STARTPOINT) ? aTrack->m_Start : aTrack->m_End; - Collect_TrackSegmentsToDrag( m_canvas, aDC, pos, - aTrack->ReturnMaskLayer(), + Collect_TrackSegmentsToDrag( GetBoard(), pos, aTrack->ReturnMaskLayer(), aTrack->GetNet() ); PosInit = pos; break; @@ -764,7 +678,7 @@ void PCB_EDIT_FRAME::StartMoveOneNodeOrSegment( TRACK* aTrack, wxDC* aDC, int aC for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) { - TRACK* draggedtrack = g_DragSegmentList[ii].m_Segm; + TRACK* draggedtrack = g_DragSegmentList[ii].m_Track; picker.SetItem( draggedtrack ); picker.SetLink( draggedtrack->Clone() ); s_ItemsListPicker.PushItem( picker ); @@ -781,87 +695,11 @@ void PCB_EDIT_FRAME::StartMoveOneNodeOrSegment( TRACK* aTrack, wxDC* aDC, int aC GetBoard()->DrawHighLight( m_canvas, aDC, GetBoard()->GetHighLightNetCode() ); m_canvas->CallMouseCapture( aDC, wxDefaultPosition, true ); + + UndrawAndMarkSegmentsToDrag( m_canvas, aDC ); } -#if 0 - -// @todo: This function is broken: does not handle pointers to pads for start -// and end and flags relative to these pointers -void SortTrackEndPoints( TRACK* track ) -{ - // sort the track endpoints -- should not matter in terms of drawing - // or producing the pcb -- but makes doing comparisons easier. - int dx = track->m_End.x - track->m_Start.x; - - if( dx ) - { - if( track->m_Start.x > track->m_End.x ) - { - EXCHG( track->m_Start, track->m_End ); - } - } - else - { - if( track->m_Start.y > track->m_End.y ) - { - EXCHG( track->m_Start, track->m_End ); - } - } -} - - -bool PCB_EDIT_FRAME::MergeCollinearTracks( TRACK* track, wxDC* DC, int end ) -{ - testtrack = track->GetTrace( GetBoard()->m_Track, NULL, end ); - - if( testtrack ) - { - SortTrackEndPoints( track ); - SortTrackEndPoints( testtrack ); - int dx = track->m_End.x - track->m_Start.x; - int dy = track->m_End.y - track->m_Start.y; - int tdx = testtrack->m_End.x - testtrack->m_Start.x; - int tdy = testtrack->m_End.y - testtrack->m_Start.y; - - if( ( dy * tdx == dx * tdy && dy != 0 && dx != 0 && tdy != 0 && tdx != 0 ) /* angle, same slope */ - || ( dy == 0 && tdy == 0 && dx * tdx ) /*horizontal */ - || ( dx == 0 && tdx == 0 && dy * tdy ) /*vertical */ - ) - { - if( track->m_Start == testtrack->m_Start || track->m_End == testtrack->m_Start ) - { - if( ( dx * tdx && testtrack->m_End.x > track->m_End.x ) - ||( dy * tdy && testtrack->m_End.y > track->m_End.y ) ) - { - track->m_End = testtrack->m_End; - - Delete_Segment( DC, testtrack ); - return true; - } - } - - if( track->m_Start == testtrack->m_End || track->m_End == testtrack->m_End ) - { - if( ( dx * tdx && testtrack->m_Start.x < track->m_Start.x ) - || ( dy * tdy && testtrack->m_Start.y < track->m_Start.y ) ) - { - track->m_Start = testtrack->m_Start; - - Delete_Segment( DC, testtrack ); - return true; - } - } - } - } - - return false; -} - - -#endif - - void PCB_EDIT_FRAME::Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC ) { TRACK* TrackToStartPoint = NULL; @@ -871,18 +709,8 @@ void PCB_EDIT_FRAME::Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC if( !track ) return; - -#if 0 - - // Broken functions: see comments - while( MergeCollinearTracks( track, DC, START ) ) - { - }; - - while( MergeCollinearTracks( track, DC, END ) ) - { - }; -#endif + // TODO: Use clenup functions to merge collinear segments if track + // is connected to a collinear segment. s_StartSegmentPresent = s_EndSegmentPresent = true; @@ -937,8 +765,6 @@ void PCB_EDIT_FRAME::Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC EraseDragList(); - NewTrack = NULL; - NbPtNewTrack = 0; track->SetFlags( IS_DRAGGED ); if( TrackToStartPoint ) @@ -948,7 +774,7 @@ void PCB_EDIT_FRAME::Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC if( track->m_Start != TrackToStartPoint->m_Start ) flag = ENDPOINT; - AddSegmentToDragList( m_canvas, DC, flag, TrackToStartPoint ); + AddSegmentToDragList( flag, TrackToStartPoint ); track->SetFlags( STARTPOINT ); } @@ -959,11 +785,13 @@ void PCB_EDIT_FRAME::Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC if( track->m_End != TrackToEndPoint->m_Start ) flag = ENDPOINT; - AddSegmentToDragList( m_canvas, DC, flag, TrackToEndPoint ); + AddSegmentToDragList( flag, TrackToEndPoint ); track->SetFlags( ENDPOINT ); } - AddSegmentToDragList( m_canvas, DC, track->GetFlags(), track ); + AddSegmentToDragList( track->GetFlags(), track ); + + UndrawAndMarkSegmentsToDrag( m_canvas, DC ); PosInit = GetScreen()->GetCrossHairPosition(); @@ -979,7 +807,7 @@ void PCB_EDIT_FRAME::Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) { - TRACK* draggedtrack = g_DragSegmentList[ii].m_Segm; + TRACK* draggedtrack = g_DragSegmentList[ii].m_Track; picker.SetItem( draggedtrack); picker.SetLink ( draggedtrack->Clone() ); s_ItemsListPicker.PushItem( picker ); @@ -1019,27 +847,23 @@ bool PCB_EDIT_FRAME::PlaceDraggedOrMovedTrackSegment( TRACK* Track, wxDC* DC ) /* Redraw the dragged segments */ for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) { - errdrc = m_drc->Drc( g_DragSegmentList[ii].m_Segm, GetBoard()->m_Track ); + errdrc = m_drc->Drc( g_DragSegmentList[ii].m_Track, GetBoard()->m_Track ); if( errdrc == BAD_DRC ) return false; } } - GR_DRAWMODE draw_mode = GR_OR | GR_HIGHLIGHT; - // DRC Ok: place track segments Track->ClearFlags(); Track->SetState( IN_EDIT, OFF ); - Track->Draw( m_canvas, DC, draw_mode ); /* Draw dragged tracks */ for( unsigned ii = 0; ii < g_DragSegmentList.size(); ii++ ) { - Track = g_DragSegmentList[ii].m_Segm; + Track = g_DragSegmentList[ii].m_Track; Track->SetState( IN_EDIT, OFF ); Track->ClearFlags(); - Track->Draw( m_canvas, DC, draw_mode ); /* Test the connections modified by the move * (only pad connection must be tested, track connection will be @@ -1065,21 +889,15 @@ bool PCB_EDIT_FRAME::PlaceDraggedOrMovedTrackSegment( TRACK* Track, wxDC* DC ) SaveCopyInUndoList( s_ItemsListPicker, UR_UNSPECIFIED ); s_ItemsListPicker.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items - if( GetBoard()->IsHighLightNetON() ) - HighLight( DC ); - GetBoard()->PopHighLight(); - if( GetBoard()->IsHighLightNetON() ) - GetBoard()->DrawHighLight( m_canvas, DC, GetBoard()->GetHighLightNetCode() ); - OnModify(); m_canvas->SetMouseCapture( NULL, NULL ); - m_canvas->Refresh(); - if( current_net_code > 0 ) TestNetConnection( DC, current_net_code ); + m_canvas->Refresh(); + return true; } diff --git a/pcbnew/muwave_command.cpp b/pcbnew/muwave_command.cpp index 9b312d64da..ffdf7033b3 100644 --- a/pcbnew/muwave_command.cpp +++ b/pcbnew/muwave_command.cpp @@ -101,7 +101,7 @@ void PCB_EDIT_FRAME::MuWaveCommand( wxDC* DC, const wxPoint& MousePos ) if( module ) { - StartMove_Module( module, DC ); + StartMoveModule( module, DC, false ); } m_canvas->MoveCursorToCrossHair(); diff --git a/pcbnew/onleftclick.cpp b/pcbnew/onleftclick.cpp index 65c21b087e..65cce81f0a 100644 --- a/pcbnew/onleftclick.cpp +++ b/pcbnew/onleftclick.cpp @@ -221,7 +221,7 @@ void PCB_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition ) } else { - DisplayError( this, wxT( "Internal err: Struct not PCB_TARGET_T" ) ); + DisplayError( this, wxT( "OnLeftClick err: not a PCB_TARGET_T" ) ); } break; @@ -333,7 +333,7 @@ void PCB_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition ) } else { - DisplayError( this, wxT( "Internal err: Struct not PCB_TEXT_T" ) ); + DisplayError( this, wxT( "OnLeftClick err: not a PCB_TEXT_T" ) ); } break; @@ -346,7 +346,7 @@ void PCB_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition ) SetCurItem( DrawStruct ); if( DrawStruct ) - StartMove_Module( (MODULE*) DrawStruct, aDC ); + StartMoveModule( (MODULE*) DrawStruct, aDC, false ); } else if( DrawStruct->Type() == PCB_MODULE_T ) { diff --git a/pcbnew/pad_edition_functions.cpp b/pcbnew/pad_edition_functions.cpp new file mode 100644 index 0000000000..89fb725178 --- /dev/null +++ b/pcbnew/pad_edition_functions.cpp @@ -0,0 +1,256 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2011 Wayne Stambaugh + * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * + * 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 + */ + +/** + * @file pad_change_functions.cpp + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* Exports the current pad settings to board design settings. + */ +void PCB_BASE_FRAME::Export_Pad_Settings( D_PAD* aPad ) +{ + if( aPad == NULL ) + return; + + aPad->DisplayInfo( this ); + + D_PAD& mp = GetDesignSettings().m_Pad_Master; + + mp.SetShape( aPad->GetShape() ); + mp.SetAttribute( aPad->GetAttribute() ); + mp.SetLayerMask( aPad->GetLayerMask() ); + + mp.SetOrientation( aPad->GetOrientation() - aPad->GetParent()->GetOrientation() ); + + mp.SetSize( aPad->GetSize() ); + mp.SetDelta( aPad->GetDelta() ); + + mp.SetOffset( aPad->GetOffset() ); + mp.SetDrillSize( aPad->GetDrillSize() ); + mp.SetDrillShape( aPad->GetDrillShape() ); +} + + +/* Imports the board design settings to aPad + * - The position, names, and keys are not modifed. + */ +void PCB_BASE_FRAME::Import_Pad_Settings( D_PAD* aPad, bool aDraw ) +{ + if( aDraw ) + { + aPad->SetFlags( DO_NOT_DRAW ); + m_canvas->RefreshDrawingRect( aPad->GetBoundingBox() ); + aPad->ClearFlags( DO_NOT_DRAW ); + } + + D_PAD& mp = GetDesignSettings().m_Pad_Master; + + aPad->SetShape( mp.GetShape() ); + aPad->SetLayerMask( mp.GetLayerMask() ); + aPad->SetAttribute( mp.GetAttribute() ); + aPad->SetOrientation( mp.GetOrientation() + aPad->GetParent()->GetOrientation() ); + aPad->SetSize( mp.GetSize() ); + aPad->SetDelta( wxSize( 0, 0 ) ); + aPad->SetOffset( mp.GetOffset() ); + aPad->SetDrillSize( mp.GetDrillSize() ); + aPad->SetDrillShape( mp.GetDrillShape() ); + + switch( mp.GetShape() ) + { + case PAD_TRAPEZOID: + aPad->SetDelta( mp.GetDelta() ); + break; + + case PAD_CIRCLE: + // ensure size.y == size.x + aPad->SetSize( wxSize( aPad->GetSize().x, aPad->GetSize().x ) ); + break; + + default: + ; + } + + switch( mp.GetAttribute() ) + { + case PAD_SMD: + case PAD_CONN: + aPad->SetDrillSize( wxSize( 0, 0 ) ); + aPad->SetOffset( wxPoint( 0, 0 ) ); + break; + default: + ; + } + + if( aDraw ) + m_canvas->RefreshDrawingRect( aPad->GetBoundingBox() ); + + aPad->GetParent()->SetLastEditTime(); +} + + +/* Add a new pad to aModule. + */ +void PCB_BASE_FRAME::AddPad( MODULE* aModule, bool draw ) +{ + // Last used pad name (pad num) + wxString lastPadName = GetDesignSettings().m_Pad_Master.GetPadName(); + + m_Pcb->m_Status_Pcb = 0; + aModule->SetLastEditTime(); + + D_PAD* pad = new D_PAD( aModule ); + + // Add the new pad to end of the module pad list. + aModule->m_Pads.PushBack( pad ); + + // Update the pad properties. + Import_Pad_Settings( pad, false ); + pad->SetNetname( wxEmptyString ); + + pad->SetPosition( GetScreen()->GetCrossHairPosition() ); + + // Set the relative pad position + // ( pad position for module orient, 0, and relative to the module position) + + wxPoint pos0 = pad->GetPosition() - aModule->GetPosition(); + RotatePoint( &pos0, -aModule->GetOrientation() ); + pad->SetPos0( pos0 ); + + // Automatically increment the current pad number. + long num = 0; + int ponder = 1; + + while( lastPadName.Len() && lastPadName.Last() >= '0' && lastPadName.Last() <= '9' ) + { + num += ( lastPadName.Last() - '0' ) * ponder; + lastPadName.RemoveLast(); + ponder *= 10; + } + + num++; // Use next number for the new pad + lastPadName << num; + pad->SetPadName( lastPadName ); + + GetDesignSettings().m_Pad_Master.SetPadName(lastPadName); + + aModule->CalculateBoundingBox(); + pad->DisplayInfo( this ); + + if( draw ) + m_canvas->RefreshDrawingRect( aModule->GetBoundingBox() ); +} + + +/** + * Function DeletePad + * Delete the pad aPad. + * Refresh the modified screen area + * Refresh modified parameters of the parent module (bounding box, last date) + * @param aPad = the pad to delete + * @param aQuery = true to promt for confirmation, false to delete silently + */ +void PCB_BASE_FRAME::DeletePad( D_PAD* aPad, bool aQuery ) +{ + MODULE* module; + + if( aPad == NULL ) + return; + + module = (MODULE*) aPad->GetParent(); + module->SetLastEditTime(); + + if( aQuery ) + { + wxString msg; + msg.Printf( _( "Delete Pad (module %s %s) " ), + GetChars( module->m_Reference->m_Text ), + GetChars( module->m_Value->m_Text ) ); + + if( !IsOK( this, msg ) ) + return; + } + + m_Pcb->m_Status_Pcb = 0; + aPad->DeleteStructure(); + m_canvas->RefreshDrawingRect( module->GetBoundingBox() ); + module->CalculateBoundingBox(); + + OnModify(); +} + + +// Rotate selected pad 90 degrees. +void PCB_BASE_FRAME::RotatePad( D_PAD* aPad, wxDC* DC ) +{ + if( aPad == NULL ) + return; + + MODULE* module = aPad->GetParent(); + + module->SetLastEditTime(); + + OnModify(); + + if( DC ) + module->Draw( m_canvas, DC, GR_XOR ); + + wxSize sz = aPad->GetSize(); + EXCHG( sz.x, sz.y ); + aPad->SetSize( sz ); + + sz = aPad->GetDrillSize(); + EXCHG( sz.x, sz.y ); + aPad->SetDrillSize( sz ); + + wxPoint pt = aPad->GetOffset(); + EXCHG( pt.x, pt.y ); + aPad->SetOffset( pt ); + + aPad->SetOffset( wxPoint( aPad->GetOffset().x, -aPad->GetOffset().y ) ); + + sz = aPad->GetDelta(); + EXCHG( sz.x, sz.y ); + sz.x = -sz.x; + aPad->SetDelta( sz ); + + module->CalculateBoundingBox(); + aPad->DisplayInfo( this ); + + if( DC ) + module->Draw( m_canvas, DC, GR_OR ); +} diff --git a/pcbnew/pcbnew.cpp b/pcbnew/pcbnew.cpp index 52b9817768..75270567c9 100644 --- a/pcbnew/pcbnew.cpp +++ b/pcbnew/pcbnew.cpp @@ -58,7 +58,6 @@ COLORS_DESIGN_SETTINGS g_ColorsSettings; bool Drc_On = true; bool g_AutoDeleteOldTrack = true; -bool g_Drag_Pistes_On; bool g_Show_Module_Ratsnest; bool g_Raccord_45_Auto = true; bool g_Alternate_Track_Posture = false; @@ -107,13 +106,13 @@ bool EDA_APP::OnInit() wxFileName fn; PCB_EDIT_FRAME* frame = NULL; -#ifdef KICAD_SCRIPTING - if ( !pcbnewInitPythonScripting() ) +#ifdef KICAD_SCRIPTING + if ( !pcbnewInitPythonScripting() ) { return false; } -#endif - +#endif + InitEDA_Appl( wxT( "Pcbnew" ), APP_PCBNEW_T ); if( m_Checker && m_Checker->IsAnotherRunning() ) @@ -149,10 +148,10 @@ Changing extension to .brd." ), GetChars( fn.GetFullPath() ) ); frame = new PCB_EDIT_FRAME( NULL, wxT( "Pcbnew" ), wxPoint( 0, 0 ), wxSize( 600, 400 ) ); - #ifdef KICAD_SCRIPTING + #ifdef KICAD_SCRIPTING ScriptingSetPcbEditFrame(frame); /* give the scripting helpers access to our frame */ - #endif - + #endif + frame->UpdateTitle(); SetTopWindow( frame ); @@ -224,7 +223,7 @@ int EDA_APP::OnExit() { #if KICAD_SCRIPTING_WXPYTHON pcbnewFinishPythonScripting(); #endif - return 0; + return 0; } #endif diff --git a/pcbnew/pcbnew.h b/pcbnew/pcbnew.h index 78624ab4fd..5695ff5566 100644 --- a/pcbnew/pcbnew.h +++ b/pcbnew/pcbnew.h @@ -51,7 +51,6 @@ extern wxString g_DocModulesFileName; /* variables */ extern bool Drc_On; extern bool g_AutoDeleteOldTrack; -extern bool g_Drag_Pistes_On; extern bool g_Show_Module_Ratsnest; extern bool g_Raccord_45_Auto; extern bool g_Track_45_Only_Allowed;