Merge branch 'undobuffer_refactor'

- BOARD_COMMIT class.
Wrapper around undo buffer to simplify storing changes. Also performs
all the necessary updates (ratsnest, view) once anything changes. A good
entry point to introduce an observer interface.

- Removed BOARD_ITEM::Copy(), switched to C++ copy constructors and
operator=.

- BOARD_ITEM_CONTAINER interface.
A generic interface for adding & removing items, base class for MODULE
and BOARD.

- Removed UR_MODEDIT.
Module editor now uses the same UR_* flags as the layout editor. Now,
together with BOARD_COMMIT is the way to unify undo handling code in
tools (no more ugly 'if(m_editModules) {...} else {...}').

- Common code for handling undo buffer in the layout & module editor.
board_undo_redo.cpp and modedit_undo_redo.cpp are merged to
undo_redo.cpp. A lot of redundant code removed.
This commit is contained in:
Maciej Suminski 2016-09-13 10:07:35 +02:00
commit 64f04ab3e6
112 changed files with 2698 additions and 3138 deletions

View File

@ -203,6 +203,7 @@ set( COMMON_SRCS
class_plotter.cpp class_plotter.cpp
class_undoredo_container.cpp class_undoredo_container.cpp
colors.cpp colors.cpp
commit.cpp
common.cpp common.cpp
common_plot_functions.cpp common_plot_functions.cpp
common_plotHPGL_functions.cpp common_plotHPGL_functions.cpp

View File

@ -65,13 +65,7 @@ EDA_ITEM::EDA_ITEM( KICAD_T idType )
EDA_ITEM::EDA_ITEM( const EDA_ITEM& base ) EDA_ITEM::EDA_ITEM( const EDA_ITEM& base )
{ {
initVars(); initVars();
m_StructType = base.m_StructType; *this = base;
m_Parent = base.m_Parent;
m_Flags = base.m_Flags;
// A copy of an item cannot have the same time stamp as the original item.
SetTimeStamp( GetNewTimeStamp() );
m_Status = base.m_Status;
} }
@ -82,7 +76,6 @@ void EDA_ITEM::initVars()
Pback = NULL; // Linked list: Link (previous struct) Pback = NULL; // Linked list: Link (previous struct)
m_Parent = NULL; // Linked list: Link (parent struct) m_Parent = NULL; // Linked list: Link (parent struct)
m_List = NULL; // I am not on any list yet m_List = NULL; // I am not on any list yet
m_Image = NULL; // Link to an image copy for undelete or abort command
m_Flags = 0; // flags for editions and other m_Flags = 0; // flags for editions and other
SetTimeStamp( 0 ); // Time stamp used for logical links SetTimeStamp( 0 ); // Time stamp used for logical links
m_Status = 0; m_Status = 0;
@ -224,23 +217,23 @@ bool EDA_ITEM::operator<( const EDA_ITEM& aItem ) const
return false; return false;
} }
#ifdef USE_EDA_ITEM_OP_EQ // see base_struct.h for explanations
EDA_ITEM& EDA_ITEM::operator=( const EDA_ITEM& aItem ) EDA_ITEM& EDA_ITEM::operator=( const EDA_ITEM& aItem )
{ {
if( &aItem != this ) // do not call initVars()
{
m_Image = aItem.m_Image; m_StructType = aItem.m_StructType;
m_StructType = aItem.m_StructType; m_Flags = aItem.m_Flags;
m_Parent = aItem.m_Parent; m_Status = aItem.m_Status;
m_Flags = aItem.m_Flags; m_Parent = aItem.m_Parent;
m_TimeStamp = aItem.m_TimeStamp; m_forceVisible = aItem.m_forceVisible;
m_Status = aItem.m_Status;
m_forceVisible = aItem.m_forceVisible; // A copy of an item cannot have the same time stamp as the original item.
} SetTimeStamp( GetNewTimeStamp() );
// do not copy list related fields (Pnext, Pback, m_List)
return *this; return *this;
} }
#endif
const BOX2I EDA_ITEM::ViewBBox() const const BOX2I EDA_ITEM::ViewBBox() const
{ {

View File

@ -153,10 +153,6 @@ void PICKED_ITEMS_LIST::ClearListAndDeleteItems()
case UR_LIBEDIT: /* Libedit save always a copy of the current item case UR_LIBEDIT: /* Libedit save always a copy of the current item
* So, the picker is always owner of the picked item * So, the picker is always owner of the picked item
*/ */
case UR_MODEDIT: /* Specific to the module editor (modedit creates a full
* copy of the current module when changed),
* and the picker is owner of this item
*/
delete wrapper.GetItem(); delete wrapper.GetItem();
break; break;

176
common/commit.cpp Normal file
View File

@ -0,0 +1,176 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <commit.h>
#include <base_struct.h>
COMMIT::COMMIT()
{
}
COMMIT::~COMMIT()
{
for( COMMIT_LINE& ent : m_changes )
{
if( ent.m_copy )
delete ent.m_copy;
}
}
COMMIT& COMMIT::Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType )
{
assert( aChangeType != ( CHT_MODIFY | CHT_DONE ) ); // CHT_MODIFY and CHT_DONE are not compatible
int flag = aChangeType & CHT_FLAGS;
switch( aChangeType & CHT_TYPE )
{
case CHT_ADD:
assert( m_changedItems.find( aItem ) == m_changedItems.end() );
makeEntry( aItem, CHT_ADD | flag );
return *this;
case CHT_REMOVE:
makeEntry( aItem, CHT_REMOVE | flag );
return *this;
case CHT_MODIFY:
{
EDA_ITEM* parent = parentObject( aItem );
if( m_changedItems.find( parent ) != m_changedItems.end() )
return *this; // item has been already modified once
makeEntry( parent, CHT_MODIFY | flag, parent->Clone() );
return *this;
}
default:
assert( false );
}
return *this;
}
COMMIT& COMMIT::Modified( EDA_ITEM* aItem, EDA_ITEM* aCopy )
{
EDA_ITEM* parent = parentObject( aItem );
if( m_changedItems.find( parent ) != m_changedItems.end() )
return *this; // item has been already modified once
makeEntry( parent, CHT_MODIFY, aCopy );
return *this;
}
COMMIT& COMMIT::Stage( std::vector<EDA_ITEM*>& container, CHANGE_TYPE aChangeType )
{
for( EDA_ITEM* item : container )
{
Stage( item, aChangeType );
}
return *this;
}
COMMIT& COMMIT::Stage( const PICKED_ITEMS_LIST& aItems, UNDO_REDO_T aModFlag )
{
for( unsigned int i = 0; i < aItems.GetCount(); i++ )
{
UNDO_REDO_T change_type = aItems.GetPickedItemStatus( i );
EDA_ITEM* item = aItems.GetPickedItem( i );
EDA_ITEM* copy = NULL;
if( change_type == UR_UNSPECIFIED )
change_type = aItems.m_Status;
if( change_type == UR_UNSPECIFIED )
change_type = aModFlag;
if( ( copy = aItems.GetPickedItemLink( i ) ) )
{
assert( change_type == UR_CHANGED );
// There was already a copy created, so use it
Modified( item, copy );
}
else
{
Stage( item, convert( change_type ) );
}
}
return *this;
}
void COMMIT::makeEntry( EDA_ITEM* aItem, CHANGE_TYPE aType, EDA_ITEM* aCopy )
{
// Expect an item copy if it is going to be modified
assert( !!aCopy == ( ( aType & CHT_TYPE ) == CHT_MODIFY ) );
COMMIT_LINE ent;
ent.m_item = aItem;
ent.m_type = aType;
ent.m_copy = aCopy;
m_changedItems.insert( aItem );
m_changes.push_back( ent );
}
CHANGE_TYPE COMMIT::convert( UNDO_REDO_T aType ) const
{
switch( aType )
{
case UR_NEW:
return CHT_ADD;
case UR_DELETED:
return CHT_REMOVE;
default:
assert( false );
// fall through
case UR_CHANGED:
case UR_MOVED:
case UR_MIRRORED_X:
case UR_MIRRORED_Y:
case UR_ROTATED:
case UR_ROTATED_CLOCKWISE:
case UR_FLIPPED:
return CHT_MODIFY;
}
}

View File

@ -66,23 +66,6 @@ EDA_TEXT::EDA_TEXT( const wxString& text )
} }
EDA_TEXT::EDA_TEXT( const EDA_TEXT& aText )
{
m_Pos = aText.m_Pos;
m_Size = aText.m_Size;
m_Orient = aText.m_Orient;
m_Attributs = aText.m_Attributs;
m_Mirror = aText.m_Mirror;
m_HJustify = aText.m_HJustify;
m_VJustify = aText.m_VJustify;
m_Thickness = aText.m_Thickness;
m_Italic = aText.m_Italic;
m_Bold = aText.m_Bold;
m_MultilineAllowed = aText.m_MultilineAllowed;
m_Text = aText.m_Text;
}
EDA_TEXT::~EDA_TEXT() EDA_TEXT::~EDA_TEXT()
{ {
} }

View File

@ -55,18 +55,21 @@ VIEW_GROUP::~VIEW_GROUP()
void VIEW_GROUP::Add( VIEW_ITEM* aItem ) void VIEW_GROUP::Add( VIEW_ITEM* aItem )
{ {
m_items.insert( aItem ); m_items.insert( aItem );
ViewUpdate();
} }
void VIEW_GROUP::Remove( VIEW_ITEM* aItem ) void VIEW_GROUP::Remove( VIEW_ITEM* aItem )
{ {
m_items.erase( aItem ); m_items.erase( aItem );
ViewUpdate();
} }
void VIEW_GROUP::Clear() void VIEW_GROUP::Clear()
{ {
m_items.clear(); m_items.clear();
ViewUpdate();
} }
@ -128,7 +131,8 @@ void VIEW_GROUP::FreeItems()
{ {
delete item; delete item;
} }
m_items.clear();
Clear();
} }

View File

@ -258,7 +258,5 @@ SCH_ITEM* DuplicateStruct( SCH_ITEM* aDrawStruct, bool aClone )
if( aClone ) if( aClone )
NewDrawStruct->SetTimeStamp( aDrawStruct->GetTimeStamp() ); NewDrawStruct->SetTimeStamp( aDrawStruct->GetTimeStamp() );
NewDrawStruct->SetImage( aDrawStruct );
return NewDrawStruct; return NewDrawStruct;
} }

View File

@ -102,7 +102,7 @@
/* Used if undo / redo command: /* Used if undo / redo command:
* swap data between Item and its copy, pointed by its .m_Image member * swap data between Item and its copy, pointed by its picked item link member
* swapped data is data modified by edition, so not all values are swapped * swapped data is data modified by edition, so not all values are swapped
*/ */

View File

@ -179,9 +179,6 @@ protected:
/// Flag bits for editing and other uses. /// Flag bits for editing and other uses.
STATUS_FLAGS m_Flags; STATUS_FLAGS m_Flags;
// Link to an copy of the item use to save the item's state for undo/redo feature.
EDA_ITEM* m_Image;
private: private:
void initVars(); void initVars();
@ -262,8 +259,6 @@ public:
void ClearFlags( STATUS_FLAGS aMask = EDA_ITEM_ALL_FLAGS ) { m_Flags &= ~aMask; } void ClearFlags( STATUS_FLAGS aMask = EDA_ITEM_ALL_FLAGS ) { m_Flags &= ~aMask; }
STATUS_FLAGS GetFlags() const { return m_Flags; } STATUS_FLAGS GetFlags() const { return m_Flags; }
void SetImage( EDA_ITEM* aItem ) { m_Image = aItem; }
/** /**
* Function SetForceVisible * Function SetForceVisible
* is used to set and cleag force visible flag used to force the item to be drawn * is used to set and cleag force visible flag used to force the item to be drawn
@ -482,17 +477,11 @@ public:
*/ */
static bool Sort( const EDA_ITEM* aLeft, const EDA_ITEM* aRight ) { return *aLeft < *aRight; } static bool Sort( const EDA_ITEM* aLeft, const EDA_ITEM* aRight ) { return *aLeft < *aRight; }
#if 0
/** /**
* Operator assignment * Operator assignment
* is used to assign the members of \a aItem to another object. * is used to assign the members of \a aItem to another object.
*
* @warning This is still a work in progress and not ready for prime time. Do not use
* as there is a known issue with wxString buffers.
*/ */
virtual EDA_ITEM& operator=( const EDA_ITEM& aItem ); EDA_ITEM& operator=( const EDA_ITEM& aItem );
#define USE_EDA_ITEM_OP_EQ
#endif
/// @copydoc VIEW_ITEM::ViewBBox() /// @copydoc VIEW_ITEM::ViewBBox()
virtual const BOX2I ViewBBox() const; virtual const BOX2I ViewBBox() const;

View File

@ -79,7 +79,7 @@ protected:
LAYER_ID m_Layer; LAYER_ID m_Layer;
static int getTrailingInt( wxString aStr ); static int getTrailingInt( wxString aStr );
static int getNextNumberInSequence( std::set<int> aSeq, bool aFillSequenceGaps ); static int getNextNumberInSequence( const std::set<int>& aSeq, bool aFillSequenceGaps );
public: public:
@ -88,7 +88,8 @@ public:
{ {
} }
// Do not create a copy constructor. The one generated by the compiler is adequate. // Do not create a copy constructor & operator=.
// The ones generated by the compiler are adequate.
virtual const wxPoint& GetPosition() const = 0; virtual const wxPoint& GetPosition() const = 0;

View File

@ -69,8 +69,6 @@ enum UNDO_REDO_T {
UR_ROTATED_CLOCKWISE, // Rotated item (clockwise), undo by rotating it UR_ROTATED_CLOCKWISE, // Rotated item (clockwise), undo by rotating it
UR_FLIPPED, // flipped (board items only), undo by flipping it UR_FLIPPED, // flipped (board items only), undo by flipping it
UR_WIRE_IMAGE, // Specific to Eeschema for handling wires changes. UR_WIRE_IMAGE, // Specific to Eeschema for handling wires changes.
UR_MODEDIT, // Specific to the module editor (modedit creates a full copy of
// the current module when changed)
UR_LIBEDIT, // Specific to the component editor (libedit creates a full copy UR_LIBEDIT, // Specific to the component editor (libedit creates a full copy
// of the current component when changed) // of the current component when changed)
UR_EXCHANGE_T ///< Use for changing the schematic text type where swapping UR_EXCHANGE_T ///< Use for changing the schematic text type where swapping

160
include/commit.h Normal file
View File

@ -0,0 +1,160 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __COMMIT_H
#define __COMMIT_H
#include <set>
#include <vector>
#include <class_undoredo_container.h>
class EDA_ITEM;
///> Types of changes
enum CHANGE_TYPE {
CHT_ADD = 1,
CHT_REMOVE = 2,
CHT_MODIFY = 4,
CHT_TYPE = CHT_ADD | CHT_REMOVE | CHT_MODIFY,
///> Flag to indicate the change is already applied,
///> just notify observers (not compatible with CHT_MODIFY)
CHT_DONE = 8,
CHT_FLAGS = CHT_DONE
};
template<typename T>
CHANGE_TYPE operator|( CHANGE_TYPE aTypeA, T aTypeB )
{
return CHANGE_TYPE( (int) aTypeA | (int) aTypeB );
}
template<typename T>
CHANGE_TYPE operator&( CHANGE_TYPE aTypeA, T aTypeB )
{
return CHANGE_TYPE( (int) aTypeA & (int) aTypeB );
}
/**
* Class COMMIT
*
* Represents a set of changes (additions, deletions or modifications)
* of a data model (e.g. the BOARD) class.
*
* The class can be used to propagate changes to subscribed objects (e.g. views, ratsnest),
* and automatically create undo/redo points.
*/
class COMMIT
{
public:
COMMIT();
virtual ~COMMIT();
///> Adds a new item to the model
COMMIT& Add( EDA_ITEM* aItem )
{
return Stage( aItem, CHT_ADD );
}
///> Notifies observers that aItem has been added
COMMIT& Added( EDA_ITEM* aItem )
{
return Stage( aItem, CHT_ADD | CHT_DONE );
}
///> Removes a new item from the model
COMMIT& Remove( EDA_ITEM* aItem )
{
return Stage( aItem, CHT_REMOVE );
}
///> Notifies observers that aItem has been removed
COMMIT& Removed( EDA_ITEM* aItem )
{
return Stage( aItem, CHT_REMOVE | CHT_DONE );
}
///> Modifies a given item in the model.
///> Must be called before modification is performed.
COMMIT& Modify( EDA_ITEM* aItem )
{
return Stage( aItem, CHT_MODIFY );
}
///> Creates an undo entry for an item that has been already modified. Requires a copy done
///> before the modification.
COMMIT& Modified( EDA_ITEM* aItem, EDA_ITEM* aCopy );
///> Adds a change of the item aItem of type aChangeType to the change list.
COMMIT& Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType );
COMMIT& Stage( std::vector<EDA_ITEM*>& container, CHANGE_TYPE aChangeType );
COMMIT& Stage( const PICKED_ITEMS_LIST& aItems, UNDO_REDO_T aModFlag = UR_UNSPECIFIED );
///> Executes the changes.
virtual void Push( const wxString& aMessage ) = 0;
///> Revertes the commit by restoring the modifed items state.
virtual void Revert() = 0;
bool Empty() const
{
return m_changes.empty();
}
protected:
struct COMMIT_LINE
{
///> Main item that is added/deleted/modified
EDA_ITEM* m_item;
///> Optional copy of the item
EDA_ITEM* m_copy;
///> Modification type
CHANGE_TYPE m_type;
};
// Should be called in Push() & Revert() methods
void clear()
{
m_changedItems.clear();
m_changes.clear();
}
virtual void makeEntry( EDA_ITEM* aItem, CHANGE_TYPE aType, EDA_ITEM* aCopy = NULL );
virtual EDA_ITEM* parentObject( EDA_ITEM* aItem ) const = 0;
CHANGE_TYPE convert( UNDO_REDO_T aType ) const;
std::set<EDA_ITEM*> m_changedItems;
std::vector<COMMIT_LINE> m_changes;
};
#endif

View File

@ -97,7 +97,10 @@ protected:
public: public:
EDA_TEXT( const wxString& text = wxEmptyString ); EDA_TEXT( const wxString& text = wxEmptyString );
EDA_TEXT( const EDA_TEXT& aText );
// Do not create a copy constructor & operator=.
// The ones generated by the compiler are adequate.
virtual ~EDA_TEXT(); virtual ~EDA_TEXT();
/** /**

View File

@ -43,7 +43,7 @@
#define _HE_TRIANG_H_ #define _HE_TRIANG_H_
//#define TTL_USE_NODE_ID // Each node gets it's own unique id //#define TTL_USE_NODE_ID // Each node gets it's own unique id
#define TTL_USE_NODE_FLAG // Each node gets a flag (can be set to true or false) //#define TTL_USE_NODE_FLAG // Each node gets a flag (can be set to true or false)
#include <list> #include <list>
#include <unordered_set> #include <unordered_set>
@ -106,6 +106,9 @@ protected:
/// Tag for quick connection resolution /// Tag for quick connection resolution
int m_tag; int m_tag;
/// Whether it the node can be a target for ratsnest lines
bool m_noline;
/// List of board items that share this node /// List of board items that share this node
std::unordered_set<const BOARD_CONNECTED_ITEM*> m_parents; std::unordered_set<const BOARD_CONNECTED_ITEM*> m_parents;
@ -124,7 +127,7 @@ public:
#ifdef TTL_USE_NODE_ID #ifdef TTL_USE_NODE_ID
m_id( id_count++ ), m_id( id_count++ ),
#endif #endif
m_x( aX ), m_y( aY ), m_tag( -1 ) m_x( aX ), m_y( aY ), m_tag( -1 ), m_noline( false )
{ {
m_layers.reset(); m_layers.reset();
} }
@ -156,6 +159,18 @@ public:
m_tag = aTag; m_tag = aTag;
} }
/// Decides whether this node can be a ratsnest line target
inline void SetNoLine( bool aEnable )
{
m_noline = aEnable;
}
/// Returns true if this node can be a target for ratsnest lines
inline const bool& GetNoLine() const
{
return m_noline;
}
#ifdef TTL_USE_NODE_ID #ifdef TTL_USE_NODE_ID
/// Returns the id (TTL_USE_NODE_ID must be defined) /// Returns the id (TTL_USE_NODE_ID must be defined)
inline int Id() const inline int Id() const

View File

@ -131,6 +131,7 @@ public:
inline virtual void SetLayer( int aLayer ) inline virtual void SetLayer( int aLayer )
{ {
m_layer = aLayer; m_layer = aLayer;
ViewUpdate();
} }
/** /**

View File

@ -39,6 +39,8 @@
/* Forward declarations of classes. */ /* Forward declarations of classes. */
class PCB_SCREEN; class PCB_SCREEN;
class BOARD; class BOARD;
class BOARD_COMMIT;
class BOARD_ITEM_CONTAINER;
class TEXTE_PCB; class TEXTE_PCB;
class MODULE; class MODULE;
class TRACK; class TRACK;
@ -637,64 +639,6 @@ public:
void OnSelectOptionToolbar( wxCommandEvent& event ); void OnSelectOptionToolbar( wxCommandEvent& event );
void ToolOnRightClick( wxCommandEvent& event ); void ToolOnRightClick( wxCommandEvent& event );
/**
* Function SaveCopyInUndoList.
* Creates a new entry in undo list of commands.
* add a picker to handle aItemToCopy
* @param aItemToCopy = the board item modified by the command to undo
* @param aTypeCommand = command type (see enum UNDO_REDO_T)
* @param aTransformPoint = the reference point of the transformation, for
* commands like move
*/
virtual void SaveCopyInUndoList( BOARD_ITEM* aItemToCopy,
UNDO_REDO_T aTypeCommand,
const wxPoint& aTransformPoint = wxPoint( 0, 0 ) );
/**
* Function SaveCopyInUndoList (overloaded).
* Creates a new entry in undo list of commands.
* add a list of pickers to handle a list of items
* @param aItemsList = the list of items modified by the command to undo
* @param aTypeCommand = command type (see enum UNDO_REDO_T)
* @param aTransformPoint = the reference point of the transformation, for
* commands like move
*/
virtual void SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList,
UNDO_REDO_T aTypeCommand,
const wxPoint& aTransformPoint = wxPoint( 0, 0 ) );
/**
* Function PutDataInPreviousState
* Used in undo or redo command.
* Put data pointed by List in the previous state, i.e. the state memorized by List
* @param aList = a PICKED_ITEMS_LIST pointer to the list of items to undo/redo
* @param aRedoCommand = a bool: true for redo, false for undo
* @param aRebuildRatsnet = a bool: true to rebuild ratsnest (normal use), false
* to just retrieve last state (used in abort commands that do not need to
* rebuild ratsnest)
*/
void PutDataInPreviousState( PICKED_ITEMS_LIST* aList,
bool aRedoCommand,
bool aRebuildRatsnet = true );
/**
* Function RestoreCopyFromRedoList
* Redo the last edition:
* - Save the current board in Undo list
* - Get an old version of the board from Redo list
* @return none
*/
void RestoreCopyFromRedoList( wxCommandEvent& aEvent );
/**
* Function RestoreCopyFromUndoList
* Undo the last edition:
* - Save the current board in Redo list
* - Get an old version of the board from Undo list
* @return none
*/
void RestoreCopyFromUndoList( wxCommandEvent& aEvent );
/* Block operations: */ /* Block operations: */
/** /**
@ -916,6 +860,9 @@ public:
///> @copydoc PCB_BASE_FRAME::SetBoard() ///> @copydoc PCB_BASE_FRAME::SetBoard()
void SetBoard( BOARD* aBoard ); void SetBoard( BOARD* aBoard );
///> @copydoc PCB_BASE_EDIT_FRAME::GetModel()
BOARD_ITEM_CONTAINER* GetModel() const override;
///> @copydoc PCB_BASE_FRAME::SetPageSettings() ///> @copydoc PCB_BASE_FRAME::SetPageSettings()
void SetPageSettings( const PAGE_INFO& aPageSettings ); // overload void SetPageSettings( const PAGE_INFO& aPageSettings ); // overload
@ -1142,11 +1089,9 @@ public:
* OldModule is deleted or put in undo list. * OldModule is deleted or put in undo list.
* @param aOldModule = footprint to replace * @param aOldModule = footprint to replace
* @param aNewModule = footprint to put * @param aNewModule = footprint to put
* @param aUndoPickList = the undo list used to save OldModule. If null, * @param aCommit = commit that should store the changes
* OldModule is deleted
*/ */
void Exchange_Module( MODULE* aOldModule, MODULE* aNewModule, void Exchange_Module( MODULE* aOldModule, MODULE* aNewModule, BOARD_COMMIT& aCommit );
PICKED_ITEMS_LIST* aUndoPickList );
// loading modules: see PCB_BASE_FRAME // loading modules: see PCB_BASE_FRAME

View File

@ -182,6 +182,7 @@ set( PCBNEW_AUTOROUTER_SRCS
) )
set( PCBNEW_CLASS_SRCS set( PCBNEW_CLASS_SRCS
board_commit.cpp
tool_modview.cpp tool_modview.cpp
modview_frame.cpp modview_frame.cpp
pcbframe.cpp pcbframe.cpp
@ -190,7 +191,6 @@ set( PCBNEW_CLASS_SRCS
array_creator.cpp array_creator.cpp
attribut.cpp attribut.cpp
board_items_to_polygon_shape_transform.cpp board_items_to_polygon_shape_transform.cpp
board_undo_redo.cpp
board_netlist_updater.cpp board_netlist_updater.cpp
block.cpp block.cpp
block_module_editor.cpp block_module_editor.cpp
@ -237,7 +237,6 @@ set( PCBNEW_CLASS_SRCS
modedit.cpp modedit.cpp
modedit_onclick.cpp modedit_onclick.cpp
modeditoptions.cpp modeditoptions.cpp
modedit_undo_redo.cpp
moduleframe.cpp moduleframe.cpp
modules.cpp modules.cpp
move-drag_pads.cpp move-drag_pads.cpp
@ -266,6 +265,7 @@ set( PCBNEW_CLASS_SRCS
toolbars_update_user_interface.cpp toolbars_update_user_interface.cpp
tracepcb.cpp tracepcb.cpp
tr_modif.cpp tr_modif.cpp
undo_redo.cpp
xchgmod.cpp xchgmod.cpp
zones_convert_brd_items_to_polygons_with_Boost.cpp zones_convert_brd_items_to_polygons_with_Boost.cpp
zones_convert_to_polygons_aux_functions.cpp zones_convert_to_polygons_aux_functions.cpp

View File

@ -28,7 +28,7 @@
#include "array_creator.h" #include "array_creator.h"
#include <class_undoredo_container.h> #include <board_commit.h>
#include <dialogs/dialog_create_array.h> #include <dialogs/dialog_create_array.h>
@ -41,6 +41,7 @@ void ARRAY_CREATOR::Invoke()
if( numItems == 0 ) if( numItems == 0 )
return; return;
BOARD_COMMIT commit( &m_parent );
MODULE* const module = getModule(); MODULE* const module = getModule();
const bool isModuleEditor = module != NULL; const bool isModuleEditor = module != NULL;
@ -52,77 +53,63 @@ void ARRAY_CREATOR::Invoke()
DIALOG_CREATE_ARRAY::ARRAY_OPTIONS* const array_opts = dialog.GetArrayOptions(); DIALOG_CREATE_ARRAY::ARRAY_OPTIONS* const array_opts = dialog.GetArrayOptions();
if( ret == wxID_OK && array_opts != NULL ) if( ret != wxID_OK || array_opts == NULL )
return;
for ( int i = 0; i < numItems; ++i )
{ {
PICKED_ITEMS_LIST newItemsList; BOARD_ITEM* item = getNthItemToArray( i );
if( isModuleEditor ) if( item->Type() == PCB_PAD_T && !isModuleEditor )
{ {
// modedit saves everything upfront // If it is not the module editor, then duplicate the parent module instead
m_parent.SaveCopyInUndoList( getBoard()->m_Modules, UR_MODEDIT ); item = static_cast<MODULE*>( item )->GetParent();
} }
for ( int i = 0; i < numItems; ++i ) // The first item in list is the original item. We do not modify it
for( int ptN = 1; ptN < array_opts->GetArraySize(); ptN++ )
{ {
BOARD_ITEM* item = getNthItemToArray( i ); BOARD_ITEM* new_item;
if( item->Type() == PCB_PAD_T && !isModuleEditor ) if( isModuleEditor )
{ {
// If it is not the module editor, then duplicate the parent module instead // increment pad numbers if do any renumbering
item = static_cast<MODULE*>( item )->GetParent(); // (we will number again later according to the numbering scheme if set)
new_item = module->Duplicate( item, array_opts->ShouldNumberItems() );
}
else
{
// PCB items keep the same numbering
new_item = getBoard()->Duplicate( item );
// @TODO: we should merge zones. This is a bit tricky, because
// the undo command needs saving old area, if it is merged.
} }
// The first item in list is the original item. We do not modify it if( new_item )
for( int ptN = 1; ptN < array_opts->GetArraySize(); ptN++ )
{ {
BOARD_ITEM* new_item; array_opts->TransformItem( ptN, new_item, rotPoint );
prePushAction( new_item );
commit.Add( new_item );
postPushAction( new_item );
}
if( isModuleEditor ) // attempt to renumber items if the array parameters define
// a complete numbering scheme to number by (as opposed to
// implicit numbering by incrementing the items during creation
if( new_item && array_opts->NumberingStartIsSpecified() )
{
// Renumber pads. Only new pad number renumbering has meaning,
// in the footprint editor.
if( new_item->Type() == PCB_PAD_T )
{ {
// increment pad numbers if do any renumbering const wxString padName = array_opts->GetItemNumber( ptN );
// (we will number again later according to the numbering scheme if set) static_cast<D_PAD*>( new_item )->SetPadName( padName );
new_item = module->DuplicateAndAddItem(
item, array_opts->ShouldNumberItems() );
}
else
{
// PCB items keep the same numbering
new_item = getBoard()->DuplicateAndAddItem( item );
// @TODO: we should merge zones. This is a bit tricky, because
// the undo command needs saving old area, if it is merged.
}
if( new_item )
{
array_opts->TransformItem( ptN, new_item, rotPoint );
prePushAction( new_item );
newItemsList.PushItem( new_item ); // For undo list
postPushAction( new_item );
}
// attempt to renumber items if the array parameters define
// a complete numbering scheme to number by (as opposed to
// implicit numbering by incrementing the items during creation
if( new_item && array_opts->NumberingStartIsSpecified() )
{
// Renumber pads. Only new pad number renumbering has meaning,
// in the footprint editor.
if( new_item->Type() == PCB_PAD_T )
{
const wxString padName = array_opts->GetItemNumber( ptN );
static_cast<D_PAD*>( new_item )->SetPadName( padName );
}
} }
} }
} }
if( !isModuleEditor )
{
// Add all items as a single undo point for PCB editors
m_parent.SaveCopyInUndoList( newItemsList, UR_NEW );
}
finalise();
} }
commit.Push( _( "Create an array" ) );
finalise();
} }

View File

@ -196,7 +196,7 @@ bool FOOTPRINT_EDIT_FRAME::HandleBlockEnd( wxDC* DC )
if( ret == wxID_OK ) if( ret == wxID_OK )
{ {
SaveCopyInUndoList( currentModule, UR_MODEDIT ); SaveCopyInUndoList( currentModule, UR_CHANGED );
const wxPoint blockCentre = GetScreen()->m_BlockLocate.Centre(); const wxPoint blockCentre = GetScreen()->m_BlockLocate.Centre();
MoveMarkedItemsExactly( currentModule, blockCentre, translation, rotation ); MoveMarkedItemsExactly( currentModule, blockCentre, translation, rotation );
} }
@ -213,7 +213,7 @@ bool FOOTPRINT_EDIT_FRAME::HandleBlockEnd( wxDC* DC )
itemsCount = MarkItemsInBloc( currentModule, GetScreen()->m_BlockLocate ); itemsCount = MarkItemsInBloc( currentModule, GetScreen()->m_BlockLocate );
if( itemsCount ) if( itemsCount )
SaveCopyInUndoList( currentModule, UR_MODEDIT ); SaveCopyInUndoList( currentModule, UR_CHANGED );
DeleteMarkedItems( currentModule ); DeleteMarkedItems( currentModule );
break; break;
@ -226,7 +226,7 @@ bool FOOTPRINT_EDIT_FRAME::HandleBlockEnd( wxDC* DC )
itemsCount = MarkItemsInBloc( currentModule, GetScreen()->m_BlockLocate ); itemsCount = MarkItemsInBloc( currentModule, GetScreen()->m_BlockLocate );
if( itemsCount ) if( itemsCount )
SaveCopyInUndoList( currentModule, UR_MODEDIT ); SaveCopyInUndoList( currentModule, UR_CHANGED );
RotateMarkedItems( currentModule, GetScreen()->m_BlockLocate.Centre() ); RotateMarkedItems( currentModule, GetScreen()->m_BlockLocate.Centre() );
break; break;
@ -237,7 +237,7 @@ bool FOOTPRINT_EDIT_FRAME::HandleBlockEnd( wxDC* DC )
itemsCount = MarkItemsInBloc( currentModule, GetScreen()->m_BlockLocate ); itemsCount = MarkItemsInBloc( currentModule, GetScreen()->m_BlockLocate );
if( itemsCount ) if( itemsCount )
SaveCopyInUndoList( currentModule, UR_MODEDIT ); SaveCopyInUndoList( currentModule, UR_CHANGED );
MirrorMarkedItems( currentModule, GetScreen()->m_BlockLocate.Centre() ); MirrorMarkedItems( currentModule, GetScreen()->m_BlockLocate.Centre() );
break; break;
@ -293,7 +293,7 @@ void FOOTPRINT_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
case BLOCK_MOVE: // Move case BLOCK_MOVE: // Move
case BLOCK_PRESELECT_MOVE: // Move with preselection list case BLOCK_PRESELECT_MOVE: // Move with preselection list
GetScreen()->m_BlockLocate.ClearItemsList(); GetScreen()->m_BlockLocate.ClearItemsList();
SaveCopyInUndoList( currentModule, UR_MODEDIT ); SaveCopyInUndoList( currentModule, UR_CHANGED );
MoveMarkedItems( currentModule, GetScreen()->m_BlockLocate.GetMoveVector() ); MoveMarkedItems( currentModule, GetScreen()->m_BlockLocate.GetMoveVector() );
m_canvas->Refresh( true ); m_canvas->Refresh( true );
break; break;
@ -301,7 +301,7 @@ void FOOTPRINT_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
case BLOCK_COPY: // Copy case BLOCK_COPY: // Copy
case BLOCK_COPY_AND_INCREMENT: // Copy and increment pad names case BLOCK_COPY_AND_INCREMENT: // Copy and increment pad names
GetScreen()->m_BlockLocate.ClearItemsList(); GetScreen()->m_BlockLocate.ClearItemsList();
SaveCopyInUndoList( currentModule, UR_MODEDIT ); SaveCopyInUndoList( currentModule, UR_CHANGED );
CopyMarkedItems( currentModule, GetScreen()->m_BlockLocate.GetMoveVector(), CopyMarkedItems( currentModule, GetScreen()->m_BlockLocate.GetMoveVector(),
command == BLOCK_COPY_AND_INCREMENT ); command == BLOCK_COPY_AND_INCREMENT );
break; break;
@ -313,12 +313,12 @@ void FOOTPRINT_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
case BLOCK_MIRROR_X: case BLOCK_MIRROR_X:
case BLOCK_MIRROR_Y: case BLOCK_MIRROR_Y:
case BLOCK_FLIP: // Mirror by popup menu, from block move case BLOCK_FLIP: // Mirror by popup menu, from block move
SaveCopyInUndoList( currentModule, UR_MODEDIT ); SaveCopyInUndoList( currentModule, UR_CHANGED );
MirrorMarkedItems( currentModule, GetScreen()->m_BlockLocate.Centre() ); MirrorMarkedItems( currentModule, GetScreen()->m_BlockLocate.Centre() );
break; break;
case BLOCK_ROTATE: case BLOCK_ROTATE:
SaveCopyInUndoList( currentModule, UR_MODEDIT ); SaveCopyInUndoList( currentModule, UR_CHANGED );
RotateMarkedItems( currentModule, GetScreen()->m_BlockLocate.Centre() ); RotateMarkedItems( currentModule, GetScreen()->m_BlockLocate.Centre() );
break; break;

366
pcbnew/board_commit.cpp Normal file
View File

@ -0,0 +1,366 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <class_board.h>
#include <class_module.h>
#include <wxPcbStruct.h>
#include <tool/tool_manager.h>
#include <ratsnest_data.h>
#include <view/view.h>
#include <board_commit.h>
#include <boost/bind.hpp>
#include <tools/pcb_tool.h>
BOARD_COMMIT::BOARD_COMMIT( PCB_TOOL* aTool )
{
m_toolMgr = aTool->GetManager();
m_editModules = aTool->EditingModules();
}
BOARD_COMMIT::BOARD_COMMIT( PCB_BASE_FRAME* aFrame )
{
m_toolMgr = aFrame->GetToolManager();
m_editModules = aFrame->IsType( FRAME_PCB_MODULE_EDITOR );
}
BOARD_COMMIT::~BOARD_COMMIT()
{
}
void BOARD_COMMIT::Push( const wxString& aMessage )
{
// Objects potentially interested in changes:
PICKED_ITEMS_LIST undoList;
KIGFX::VIEW* view = m_toolMgr->GetView();
BOARD* board = (BOARD*) m_toolMgr->GetModel();
PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) m_toolMgr->GetEditFrame();
RN_DATA* ratsnest = board->GetRatsnest();
std::set<EDA_ITEM*> savedModules;
if( Empty() )
return;
for( COMMIT_LINE& ent : m_changes )
{
int changeType = ent.m_type & CHT_TYPE;
int changeFlags = ent.m_type & CHT_FLAGS;
BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( ent.m_item );
// Module items need to be saved in the undo buffer before modification
if( m_editModules )
{
// Be sure that we are storing a module
if( ent.m_item->Type() != PCB_MODULE_T )
ent.m_item = ent.m_item->GetParent();
// We have not saved the module yet, so let's create an entry
if( savedModules.count( ent.m_item ) == 0 )
{
if( !ent.m_copy )
{
assert( changeType != CHT_MODIFY ); // too late to make a copy..
ent.m_copy = ent.m_item->Clone();
}
assert( ent.m_item->Type() == PCB_MODULE_T );
assert( ent.m_copy->Type() == PCB_MODULE_T );
ITEM_PICKER itemWrapper( ent.m_item, UR_CHANGED );
itemWrapper.SetLink( ent.m_copy );
undoList.PushItem( itemWrapper );
frame->SaveCopyInUndoList( undoList, UR_CHANGED );
savedModules.insert( ent.m_item );
static_cast<MODULE*>( ent.m_item )->SetLastEditTime();
}
}
switch( changeType )
{
case CHT_ADD:
{
if( !m_editModules )
{
undoList.PushItem( ITEM_PICKER( boardItem, UR_NEW ) );
if( !( changeFlags & CHT_DONE ) )
board->Add( boardItem );
//ratsnest->Add( boardItem ); // TODO currently done by BOARD::Add()
if( boardItem->Type() == PCB_MODULE_T )
{
MODULE* mod = static_cast<MODULE*>( boardItem );
mod->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) );
}
}
else
{
// modules inside modules are not supported yet
assert( boardItem->Type() != PCB_MODULE_T );
if( !( changeFlags & CHT_DONE ) )
board->m_Modules->Add( boardItem );
}
view->Add( boardItem );
break;
}
case CHT_REMOVE:
{
if( !m_editModules )
{
undoList.PushItem( ITEM_PICKER( boardItem, UR_DELETED ) );
}
switch( boardItem->Type() )
{
// Module items
case PCB_PAD_T:
case PCB_MODULE_EDGE_T:
case PCB_MODULE_TEXT_T:
{
// Do not allow footprint text removal when not editing a module
if( !m_editModules )
break;
bool remove = true;
if( boardItem->Type() == PCB_MODULE_TEXT_T )
{
TEXTE_MODULE* text = static_cast<TEXTE_MODULE*>( boardItem );
switch( text->GetType() )
{
case TEXTE_MODULE::TEXT_is_REFERENCE:
//DisplayError( frame, _( "Cannot delete component reference." ) );
remove = false;
break;
case TEXTE_MODULE::TEXT_is_VALUE:
//DisplayError( frame, _( "Cannot delete component value." ) );
remove = false;
break;
case TEXTE_MODULE::TEXT_is_DIVERS: // suppress warnings
break;
default:
assert( false );
break;
}
}
if( remove )
{
view->Remove( boardItem );
if( !( changeFlags & CHT_DONE ) )
{
MODULE* module = static_cast<MODULE*>( boardItem->GetParent() );
assert( module && module->Type() == PCB_MODULE_T );
module->Delete( boardItem );
}
board->m_Status_Pcb = 0; // it is done in the legacy view (ratsnest perhaps?)
}
break;
}
// Board items
case PCB_LINE_T: // a segment not on copper layers
case PCB_TEXT_T: // a text on a layer
case PCB_TRACE_T: // a track segment (segment on a copper layer)
case PCB_VIA_T: // a via (like track segment on a copper layer)
case PCB_DIMENSION_T: // a dimension (graphic item)
case PCB_TARGET_T: // a target (graphic item)
case PCB_MARKER_T: // a marker used to show something
case PCB_ZONE_T: // SEG_ZONE items are now deprecated
case PCB_ZONE_AREA_T:
view->Remove( boardItem );
if( !( changeFlags & CHT_DONE ) )
board->Remove( boardItem );
//ratsnest->Remove( boardItem ); // currently done by BOARD::Remove()
break;
case PCB_MODULE_T:
{
// There are no modules inside a module yet
assert( !m_editModules );
MODULE* module = static_cast<MODULE*>( boardItem );
module->ClearFlags();
module->RunOnChildren( boost::bind( &KIGFX::VIEW::Remove, view, _1 ) );
view->Remove( module );
if( !( changeFlags & CHT_DONE ) )
board->Remove( module );
// Clear flags to indicate, that the ratsnest, list of nets & pads are not valid anymore
board->m_Status_Pcb = 0;
}
break;
default: // other types do not need to (or should not) be handled
assert( false );
break;
}
break;
}
case CHT_MODIFY:
{
if( !m_editModules )
{
ITEM_PICKER itemWrapper( boardItem, UR_CHANGED );
assert( ent.m_copy );
itemWrapper.SetLink( ent.m_copy );
undoList.PushItem( itemWrapper );
}
boardItem->ViewUpdate( KIGFX::VIEW_ITEM::ALL );
ratsnest->Update( boardItem );
break;
}
default:
assert( false );
break;
}
}
if( !m_editModules )
frame->SaveCopyInUndoList( undoList, UR_UNSPECIFIED );
frame->OnModify();
ratsnest->Recalculate();
clear();
}
EDA_ITEM* BOARD_COMMIT::parentObject( EDA_ITEM* aItem ) const
{
switch( aItem->Type() )
{
case PCB_PAD_T:
case PCB_MODULE_EDGE_T:
case PCB_MODULE_TEXT_T:
return aItem->GetParent();
default:
return aItem;
}
return aItem;
}
void BOARD_COMMIT::Revert()
{
PICKED_ITEMS_LIST undoList;
KIGFX::VIEW* view = m_toolMgr->GetView();
BOARD* board = (BOARD*) m_toolMgr->GetModel();
RN_DATA* ratsnest = board->GetRatsnest();
for( auto it = m_changes.rbegin(); it != m_changes.rend(); ++it )
{
COMMIT_LINE& ent = *it;
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( ent.m_item );
BOARD_ITEM* copy = static_cast<BOARD_ITEM*>( ent.m_copy );
switch( ent.m_type )
{
case CHT_ADD:
if( item->Type() == PCB_MODULE_T )
{
MODULE* oldModule = static_cast<MODULE*>( item );
oldModule->RunOnChildren( boost::bind( &KIGFX::VIEW::Remove, view, _1 ) );
}
view->Remove( item );
ratsnest->Remove( item );
break;
case CHT_REMOVE:
if( item->Type() == PCB_MODULE_T )
{
MODULE* newModule = static_cast<MODULE*>( item );
newModule->RunOnChildren( boost::bind( &EDA_ITEM::ClearFlags, _1, SELECTED ) );
newModule->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) );
}
view->Add( item );
ratsnest->Add( item );
break;
case CHT_MODIFY:
{
if( item->Type() == PCB_MODULE_T )
{
MODULE* oldModule = static_cast<MODULE*>( item );
oldModule->RunOnChildren( boost::bind( &KIGFX::VIEW::Remove, view, _1 ) );
}
view->Remove( item );
ratsnest->Remove( item );
item->SwapData( copy );
item->ClearFlags( SELECTED );
// Update all pads/drawings/texts, as they become invalid
// for the VIEW after SwapData() called for modules
if( item->Type() == PCB_MODULE_T )
{
MODULE* newModule = static_cast<MODULE*>( item );
newModule->RunOnChildren( boost::bind( &EDA_ITEM::ClearFlags, _1, SELECTED ) );
newModule->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) );
}
view->Add( item );
ratsnest->Add( item );
delete copy;
break;
}
default:
assert( false );
break;
}
}
ratsnest->Recalculate();
clear();
}

52
pcbnew/board_commit.h Normal file
View File

@ -0,0 +1,52 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __BOARD_COMMIT_H
#define __BOARD_COMMIT_H
#include <commit.h>
class BOARD_ITEM;
class PICKED_ITEMS_LIST;
class PCB_TOOL;
class PCB_BASE_FRAME;
class TOOL_MANAGER;
class BOARD_COMMIT : public COMMIT
{
public:
BOARD_COMMIT( PCB_TOOL* aTool );
BOARD_COMMIT( PCB_BASE_FRAME* aFrame );
virtual ~BOARD_COMMIT();
virtual void Push( const wxString& aMessage );
virtual void Revert();
private:
TOOL_MANAGER* m_toolMgr;
bool m_editModules;
virtual EDA_ITEM* parentObject( EDA_ITEM* aItem ) const;
};
#endif

View File

@ -0,0 +1,73 @@
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2016 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef BOARD_ITEM_CONTAINER_H
#define BOARD_ITEM_CONTAINER_H
#include <class_board_item.h>
enum ADD_MODE { ADD_INSERT, ADD_APPEND };
/**
* @brief Abstract interface for BOARD_ITEMs capable of storing other items inside.
* @see MODULE
* @see BOARD
*/
class BOARD_ITEM_CONTAINER : public BOARD_ITEM
{
public:
BOARD_ITEM_CONTAINER( BOARD_ITEM* aParent, KICAD_T aType )
: BOARD_ITEM( aParent, aType )
{
}
virtual ~BOARD_ITEM_CONTAINER()
{
}
/**
* @brief Adds an item to the container.
* @param aItem is an item to be added.
* @param aMode decides whether the item is added in the beginning or at the end of the list.
*/
virtual void Add( BOARD_ITEM* aItem, ADD_MODE aMode = ADD_INSERT ) = 0;
/**
* @brief Removes an item from the container.
* @param aItem is an item to be removed.
*/
virtual void Remove( BOARD_ITEM* aItem ) = 0;
/**
* @brief Removes an item from the containter and deletes it.
* @param aItem is an item to be deleted.
*/
virtual void Delete( BOARD_ITEM* aItem )
{
Remove( aItem );
delete aItem;
}
};
#endif /* BOARD_ITEM_CONTAINER_H */

View File

@ -49,42 +49,28 @@
#include <wxPcbStruct.h> #include <wxPcbStruct.h>
BOARD_NETLIST_UPDATER::BOARD_NETLIST_UPDATER ( PCB_EDIT_FRAME *aFrame, BOARD *aBoard ) : BOARD_NETLIST_UPDATER::BOARD_NETLIST_UPDATER( PCB_EDIT_FRAME* aFrame, BOARD* aBoard ) :
m_frame ( aFrame ), m_commit( aFrame ),
m_frame( aFrame ),
m_board( aBoard ) m_board( aBoard )
{ {
m_reporter = &NULL_REPORTER::GetInstance(); m_reporter = &NULL_REPORTER::GetInstance();
m_undoList = new PICKED_ITEMS_LIST;
m_deleteSinglePadNets = true; m_deleteSinglePadNets = true;
m_deleteUnusedComponents = false; m_deleteUnusedComponents = false;
m_isDryRun = false; m_isDryRun = false;
m_replaceFootprints = true; m_replaceFootprints = true;
m_lookupByTimestamp = false; m_lookupByTimestamp = false;
m_warningCount = 0; m_warningCount = 0;
m_errorCount = 0; m_errorCount = 0;
} }
BOARD_NETLIST_UPDATER::~BOARD_NETLIST_UPDATER ()
BOARD_NETLIST_UPDATER::~BOARD_NETLIST_UPDATER()
{ {
delete m_undoList;
} }
void BOARD_NETLIST_UPDATER::pushUndo( BOARD_ITEM* aItem, UNDO_REDO_T aCommandType, BOARD_ITEM* aCopy )
{
ITEM_PICKER picker( aItem, aCommandType );
if( aCommandType == UR_CHANGED )
{
if( m_undoList->FindItem ( aItem ) >= 0 ) // add only once
return;
picker.SetLink( aCopy ? aCopy : aItem->Clone() );
}
m_undoList->PushItem( picker );
}
wxPoint BOARD_NETLIST_UPDATER::estimateComponentInsertionPosition() wxPoint BOARD_NETLIST_UPDATER::estimateComponentInsertionPosition()
{ {
@ -124,28 +110,24 @@ MODULE* BOARD_NETLIST_UPDATER::addNewComponent( COMPONENT* aComponent )
GetChars( aComponent->GetReference() ), GetChars( aComponent->GetReference() ),
GetChars( aComponent->GetTimeStamp() ), GetChars( aComponent->GetTimeStamp() ),
GetChars( aComponent->GetFPID().Format() ) ); GetChars( aComponent->GetFPID().Format() ) );
m_reporter->Report( msg, REPORTER::RPT_INFO ); m_reporter->Report( msg, REPORTER::RPT_INFO );
msg.Printf( _( "Add component %s, footprint: %s.\n" ), msg.Printf( _( "Add component %s, footprint: %s.\n" ),
GetChars( aComponent->GetReference() ), GetChars( aComponent->GetReference() ),
GetChars( aComponent->GetFPID().Format() ) ); GetChars( aComponent->GetFPID().Format() ) );
m_reporter->Report( msg, REPORTER::RPT_ACTION ); m_reporter->Report( msg, REPORTER::RPT_ACTION );
if( !m_isDryRun ) if( !m_isDryRun )
{ {
// Owned by NETLIST, can only copy it. // Owned by NETLIST, can only copy it.
MODULE *footprint = new MODULE( *aComponent->GetModule() ); MODULE* footprint = new MODULE( *aComponent->GetModule() );
footprint->SetParent( m_board ); footprint->SetParent( m_board );
footprint->SetPosition( estimateComponentInsertionPosition( ) ); footprint->SetPosition( estimateComponentInsertionPosition( ) );
footprint->SetTimeStamp( GetNewTimeStamp() ); footprint->SetTimeStamp( GetNewTimeStamp() );
m_board->Add( footprint, ADD_APPEND );
m_addedComponents.push_back( footprint ); m_addedComponents.push_back( footprint );
m_commit.Add( footprint );
pushUndo( footprint, UR_NEW );
return footprint; return footprint;
} }
@ -165,23 +147,22 @@ MODULE* BOARD_NETLIST_UPDATER::addNewComponent( COMPONENT* aComponent )
GetChars( aComponent->GetFPID().Format() ) ); GetChars( aComponent->GetFPID().Format() ) );
m_reporter->Report( msg, REPORTER::RPT_INFO ); m_reporter->Report( msg, REPORTER::RPT_INFO );
++m_errorCount;
m_errorCount ++;
} }
return NULL; return NULL;
} }
MODULE* BOARD_NETLIST_UPDATER::replaceComponent( NETLIST& aNetlist, MODULE *aPcbComponent, COMPONENT* aNewComponent )
MODULE* BOARD_NETLIST_UPDATER::replaceComponent( NETLIST& aNetlist, MODULE* aPcbComponent, COMPONENT* aNewComponent )
{ {
wxString msg; wxString msg;
if( !m_replaceFootprints ) if( !m_replaceFootprints )
return NULL; return NULL;
// Test if the footprint has not changed // Test if the footprint has not changed
if( aNewComponent->GetFPID().empty() || if( aNewComponent->GetFPID().empty() || aPcbComponent->GetFPID() == aNewComponent->GetFPID() )
aPcbComponent->GetFPID() == aNewComponent->GetFPID() )
return NULL; return NULL;
if( aNewComponent->GetModule() != NULL ) if( aNewComponent->GetModule() != NULL )
@ -205,7 +186,9 @@ MODULE* BOARD_NETLIST_UPDATER::replaceComponent( NETLIST& aNetlist, MODULE *aPcb
if( !m_isDryRun ) if( !m_isDryRun )
{ {
wxASSERT( aPcbComponent != NULL ); wxASSERT( aPcbComponent != NULL );
MODULE* newFootprint = new MODULE( *aNewComponent->GetModule() ); MODULE* newFootprint = new MODULE( *aNewComponent->GetModule() );
newFootprint->SetParent( m_board );
if( aNetlist.IsFindByTimeStamp() ) if( aNetlist.IsFindByTimeStamp() )
newFootprint->SetReference( aPcbComponent->GetReference() ); newFootprint->SetReference( aPcbComponent->GetReference() );
@ -213,16 +196,14 @@ MODULE* BOARD_NETLIST_UPDATER::replaceComponent( NETLIST& aNetlist, MODULE *aPcb
newFootprint->SetPath( aPcbComponent->GetPath() ); newFootprint->SetPath( aPcbComponent->GetPath() );
aPcbComponent->CopyNetlistSettings( newFootprint, false ); aPcbComponent->CopyNetlistSettings( newFootprint, false );
m_board->Remove( aPcbComponent ); m_commit.Remove( aPcbComponent );
m_board->Add( newFootprint, ADD_APPEND ); m_commit.Add( newFootprint );
pushUndo( aPcbComponent, UR_DELETED );
pushUndo( newFootprint, UR_NEW );
return newFootprint; return newFootprint;
} }
} else { }
else
{
msg.Printf( _( "Cannot change component %s footprint due to missing " msg.Printf( _( "Cannot change component %s footprint due to missing "
"footprint %s.\n" ), "footprint %s.\n" ),
GetChars( aPcbComponent->GetReference() ), GetChars( aPcbComponent->GetReference() ),
@ -238,13 +219,14 @@ MODULE* BOARD_NETLIST_UPDATER::replaceComponent( NETLIST& aNetlist, MODULE *aPcb
m_reporter->Report( msg, REPORTER::RPT_INFO ); m_reporter->Report( msg, REPORTER::RPT_INFO );
m_errorCount ++; ++m_errorCount;
} }
return NULL; return NULL;
} }
bool BOARD_NETLIST_UPDATER::updateComponentParameters( MODULE *aPcbComponent, COMPONENT* aNewComponent )
bool BOARD_NETLIST_UPDATER::updateComponentParameters( MODULE* aPcbComponent, COMPONENT* aNewComponent )
{ {
wxString msg; wxString msg;
@ -292,9 +274,10 @@ bool BOARD_NETLIST_UPDATER::updateComponentParameters( MODULE *aPcbComponent, CO
GetChars( aPcbComponent->GetPath() ), GetChars( aPcbComponent->GetPath() ),
GetChars( aPcbComponent->GetValue() ), GetChars( aPcbComponent->GetValue() ),
GetChars( aNewComponent->GetValue() ) ); GetChars( aNewComponent->GetValue() ) );
m_reporter->Report( msg, REPORTER::RPT_ACTION ); m_reporter->Report( msg, REPORTER::RPT_ACTION );
if ( !m_isDryRun ) if( !m_isDryRun )
{ {
changed = true; changed = true;
aPcbComponent->SetValue( aNewComponent->GetValue() ); aPcbComponent->SetValue( aNewComponent->GetValue() );
@ -308,9 +291,10 @@ bool BOARD_NETLIST_UPDATER::updateComponentParameters( MODULE *aPcbComponent, CO
GetChars( aPcbComponent->GetReference() ), GetChars( aPcbComponent->GetReference() ),
GetChars( aPcbComponent->GetPath() ), GetChars( aPcbComponent->GetPath() ),
GetChars( aNewComponent->GetTimeStamp() ) ); GetChars( aNewComponent->GetTimeStamp() ) );
m_reporter->Report( msg, REPORTER::RPT_INFO ); m_reporter->Report( msg, REPORTER::RPT_INFO );
if ( !m_isDryRun ) if( !m_isDryRun )
{ {
changed = true; changed = true;
aPcbComponent->SetPath( aNewComponent->GetTimeStamp() ); aPcbComponent->SetPath( aNewComponent->GetTimeStamp() );
@ -318,14 +302,15 @@ bool BOARD_NETLIST_UPDATER::updateComponentParameters( MODULE *aPcbComponent, CO
} }
if( changed ) if( changed )
pushUndo( aPcbComponent, UR_CHANGED, copy ); m_commit.Modified( aPcbComponent, copy );
else else
delete copy; delete copy;
return true; return true;
} }
bool BOARD_NETLIST_UPDATER::updateComponentPadConnections( MODULE *aPcbComponent, COMPONENT* aNewComponent )
bool BOARD_NETLIST_UPDATER::updateComponentPadConnections( MODULE* aPcbComponent, COMPONENT* aNewComponent )
{ {
wxString msg; wxString msg;
@ -333,7 +318,7 @@ bool BOARD_NETLIST_UPDATER::updateComponentPadConnections( MODULE *aPcbComponent
MODULE* copy = (MODULE*) aPcbComponent->Clone(); MODULE* copy = (MODULE*) aPcbComponent->Clone();
// At this point, the component footprint is updated. Now update the nets. // At this point, the component footprint is updated. Now update the nets.
for( D_PAD *pad = aPcbComponent->Pads(); pad; pad = pad->Next() ) for( D_PAD* pad = aPcbComponent->Pads(); pad; pad = pad->Next() )
{ {
COMPONENT_NET net = aNewComponent->GetNet( pad->GetPadName() ); COMPONENT_NET net = aNewComponent->GetNet( pad->GetPadName() );
@ -351,7 +336,6 @@ bool BOARD_NETLIST_UPDATER::updateComponentPadConnections( MODULE *aPcbComponent
GetChars( aPcbComponent->GetPath() ), GetChars( aPcbComponent->GetPath() ),
GetChars( pad->GetPadName() ) ); GetChars( pad->GetPadName() ) );
m_reporter->Report( msg, REPORTER::RPT_INFO ); m_reporter->Report( msg, REPORTER::RPT_INFO );
} }
if( !m_isDryRun ) if( !m_isDryRun )
@ -364,38 +348,46 @@ bool BOARD_NETLIST_UPDATER::updateComponentPadConnections( MODULE *aPcbComponent
{ {
if( net.GetNetName() != pad->GetNetname() ) if( net.GetNetName() != pad->GetNetname() )
{ {
NETINFO_ITEM* netinfo = m_board->FindNet( net.GetNetName() ); const wxString& netName = net.GetNetName();
NETINFO_ITEM* netinfo = m_board->FindNet( netName );
if( netinfo == NULL ) if( netinfo == nullptr )
{
// It might be a new net that has not been added to the board yet
auto netIt = m_addedNets.find( netName );
if( netIt != m_addedNets.end() )
netinfo = netIt->second;
}
if( netinfo == nullptr )
{ {
// It is a new net, we have to add it // It is a new net, we have to add it
if( !m_isDryRun ) if( !m_isDryRun )
{ {
changed = true; changed = true;
netinfo = new NETINFO_ITEM( m_board, net.GetNetName() ); netinfo = new NETINFO_ITEM( m_board, netName );
m_board->AppendNet( netinfo ); m_commit.Add( netinfo );
pushUndo( netinfo, UR_NEW ); m_addedNets[netName] = netinfo;
} }
msg.Printf( _( "Add net %s.\n" ), msg.Printf( _( "Add net %s.\n" ), GetChars( netName ) );
GetChars( net.GetNetName() ) );
m_reporter->Report( msg, REPORTER::RPT_ACTION ); m_reporter->Report( msg, REPORTER::RPT_ACTION );
} }
if( pad->GetNetname() != wxString("") ) if( !pad->GetNetname().IsEmpty() )
{ {
msg.Printf( _( "Reconnect component %s pin %s from net %s to net %s.\n"), msg.Printf( _( "Reconnect component %s pin %s from net %s to net %s.\n"),
GetChars( aPcbComponent->GetReference() ), GetChars( aPcbComponent->GetReference() ),
GetChars( pad->GetPadName() ), GetChars( pad->GetPadName() ),
GetChars( pad->GetNetname() ), GetChars( pad->GetNetname() ),
GetChars( net.GetNetName() ) ); GetChars( netName ) );
} else { } else {
msg.Printf( _( "Connect component %s pin %s to net %s.\n"), msg.Printf( _( "Connect component %s pin %s to net %s.\n"),
GetChars( aPcbComponent->GetReference() ), GetChars( aPcbComponent->GetReference() ),
GetChars( pad->GetPadName() ), GetChars( pad->GetPadName() ),
GetChars( net.GetNetName() ) ); GetChars( netName ) );
} }
m_reporter->Report( msg, REPORTER::RPT_ACTION ); m_reporter->Report( msg, REPORTER::RPT_ACTION );
@ -406,27 +398,27 @@ bool BOARD_NETLIST_UPDATER::updateComponentPadConnections( MODULE *aPcbComponent
GetChars( aPcbComponent->GetPath() ), GetChars( aPcbComponent->GetPath() ),
GetChars( pad->GetPadName() ), GetChars( pad->GetPadName() ),
GetChars( pad->GetNetname() ), GetChars( pad->GetNetname() ),
GetChars( net.GetNetName() ) ); GetChars( netName ) );
m_reporter->Report( msg, REPORTER::RPT_INFO ); m_reporter->Report( msg, REPORTER::RPT_INFO );
if ( !m_isDryRun ) if( !m_isDryRun )
{ {
changed = true; changed = true;
pad->SetNetCode( netinfo->GetNet() ); pad->SetNet( netinfo );
} }
} }
} }
} }
if( changed ) if( changed )
pushUndo( aPcbComponent, UR_CHANGED, copy ); m_commit.Modified( aPcbComponent, copy );
else else
delete copy; delete copy;
return true; return true;
} }
bool BOARD_NETLIST_UPDATER::deleteUnusedComponents( NETLIST& aNetlist ) bool BOARD_NETLIST_UPDATER::deleteUnusedComponents( NETLIST& aNetlist )
{ {
wxString msg; wxString msg;
@ -437,9 +429,6 @@ bool BOARD_NETLIST_UPDATER::deleteUnusedComponents( NETLIST& aNetlist )
{ {
nextModule = module->Next(); nextModule = module->Next();
if( module->IsLocked() )
continue;
if( m_lookupByTimestamp ) if( m_lookupByTimestamp )
component = aNetlist.GetComponentByTimeStamp( module->GetPath() ); component = aNetlist.GetComponentByTimeStamp( module->GetPath() );
else else
@ -447,6 +436,14 @@ bool BOARD_NETLIST_UPDATER::deleteUnusedComponents( NETLIST& aNetlist )
if( component == NULL ) if( component == NULL )
{ {
if( module->IsLocked() )
{
msg.Printf( _( "Component %s is locked, skipping removal.\n" ),
GetChars( module->GetReference() ) );
m_reporter->Report( msg, REPORTER::RPT_INFO );
continue;
}
msg.Printf( _( "Remove component %s." ), msg.Printf( _( "Remove component %s." ),
GetChars( module->GetReference() ) ); GetChars( module->GetReference() ) );
m_reporter->Report( msg, REPORTER::RPT_ACTION ); m_reporter->Report( msg, REPORTER::RPT_ACTION );
@ -457,16 +454,14 @@ bool BOARD_NETLIST_UPDATER::deleteUnusedComponents( NETLIST& aNetlist )
m_reporter->Report( msg, REPORTER::RPT_INFO ); m_reporter->Report( msg, REPORTER::RPT_INFO );
if( !m_isDryRun ) if( !m_isDryRun )
{ m_commit.Remove( module );
pushUndo( module, UR_DELETED );
m_board->Remove( module );
}
} }
} }
return true; return true;
} }
bool BOARD_NETLIST_UPDATER::deleteSinglePadNets() bool BOARD_NETLIST_UPDATER::deleteSinglePadNets()
{ {
int count = 0; int count = 0;
@ -520,7 +515,6 @@ bool BOARD_NETLIST_UPDATER::deleteSinglePadNets()
{ {
msg.Printf( _( "Remove single pad net %s." ), msg.Printf( _( "Remove single pad net %s." ),
GetChars( previouspad->GetNetname() ) ); GetChars( previouspad->GetNetname() ) );
m_reporter->Report( msg, REPORTER::RPT_ACTION ); m_reporter->Report( msg, REPORTER::RPT_ACTION );
msg.Printf( _( "Remove single pad net \"%s\" on \"%s\" pad '%s'\n" ), msg.Printf( _( "Remove single pad net \"%s\" on \"%s\" pad '%s'\n" ),
@ -529,7 +523,6 @@ bool BOARD_NETLIST_UPDATER::deleteSinglePadNets()
GetChars( previouspad->GetPadName() ) ); GetChars( previouspad->GetPadName() ) );
m_reporter->Report( msg, REPORTER::RPT_ACTION ); m_reporter->Report( msg, REPORTER::RPT_ACTION );
//pushUndo( previouspad, UR_CHANGED );
previouspad->SetNetCode( NETINFO_LIST::UNCONNECTED ); previouspad->SetNetCode( NETINFO_LIST::UNCONNECTED );
} }
} }
@ -547,13 +540,12 @@ bool BOARD_NETLIST_UPDATER::deleteSinglePadNets()
// Examine last pad // Examine last pad
if( pad && count == 1 ) if( pad && count == 1 )
{
//pushUndo( pad, UR_CHANGED );
pad->SetNetCode( NETINFO_LIST::UNCONNECTED ); pad->SetNetCode( NETINFO_LIST::UNCONNECTED );
}
return true; return true;
} }
bool BOARD_NETLIST_UPDATER::testConnectivity( NETLIST& aNetlist ) bool BOARD_NETLIST_UPDATER::testConnectivity( NETLIST& aNetlist )
{ {
// Last step: Some tests: // Last step: Some tests:
@ -592,7 +584,7 @@ bool BOARD_NETLIST_UPDATER::testConnectivity( NETLIST& aNetlist )
GetChars( padname ), GetChars( padname ),
GetChars( footprint->GetFPID().Format() ) ); GetChars( footprint->GetFPID().Format() ) );
m_reporter->Report( msg, REPORTER::RPT_ERROR ); m_reporter->Report( msg, REPORTER::RPT_ERROR );
m_errorCount ++; ++m_errorCount;
} }
} }
@ -611,13 +603,14 @@ bool BOARD_NETLIST_UPDATER::testConnectivity( NETLIST& aNetlist )
msg.Printf( _( "Copper zone (net name %s): net has no pads connected." ), msg.Printf( _( "Copper zone (net name %s): net has no pads connected." ),
GetChars( zone->GetNet()->GetNetname() ) ); GetChars( zone->GetNet()->GetNetname() ) );
m_reporter->Report( msg, REPORTER::RPT_WARNING ); m_reporter->Report( msg, REPORTER::RPT_WARNING );
m_warningCount ++; ++m_warningCount;
} }
} }
return true; return true;
} }
bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist ) bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
{ {
wxString msg; wxString msg;
@ -630,17 +623,15 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
m_board->SetStatus( 0 ); m_board->SetStatus( 0 );
} }
for( int i = 0; i < (int) aNetlist.GetCount(); i++ ) for( int i = 0; i < (int) aNetlist.GetCount(); i++ )
{ {
COMPONENT* component = aNetlist.GetComponent( i ); COMPONENT* component = aNetlist.GetComponent( i );
MODULE *footprint = NULL; MODULE* footprint = NULL;
msg.Printf( _( "Processing component \"%s:%s:%s\".\n" ), msg.Printf( _( "Processing component \"%s:%s:%s\".\n" ),
GetChars( component->GetReference() ), GetChars( component->GetReference() ),
GetChars( component->GetTimeStamp() ), GetChars( component->GetTimeStamp() ),
GetChars( component->GetFPID().Format() ) ); GetChars( component->GetFPID().Format() ) );
m_reporter->Report( msg, REPORTER::RPT_INFO ); m_reporter->Report( msg, REPORTER::RPT_INFO );
if( aNetlist.IsFindByTimeStamp() ) if( aNetlist.IsFindByTimeStamp() )
@ -650,8 +641,9 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
if( footprint ) // An existing footprint. if( footprint ) // An existing footprint.
{ {
MODULE *newFootprint = replaceComponent ( aNetlist, footprint, component ); MODULE* newFootprint = replaceComponent( aNetlist, footprint, component );
if ( newFootprint )
if( newFootprint )
footprint = newFootprint; footprint = newFootprint;
} }
else else
@ -666,9 +658,6 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
} }
} }
//aNetlist.GetDeleteExtraFootprints() //aNetlist.GetDeleteExtraFootprints()
if( m_deleteUnusedComponents ) if( m_deleteUnusedComponents )
@ -677,47 +666,40 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
if( m_deleteSinglePadNets ) if( m_deleteSinglePadNets )
deleteSinglePadNets(); deleteSinglePadNets();
if ( !m_isDryRun ) if( !m_isDryRun )
{ {
m_frame->SaveCopyInUndoList( *m_undoList, UR_UNSPECIFIED, wxPoint(0, 0) ); m_commit.Push( _( "Update netlist" ) );
m_frame->OnModify(); m_frame->Compile_Ratsnest( NULL, false );
m_frame->Compile_Ratsnest( NULL, true );
m_board->GetRatsnest()->ProcessBoard(); m_board->GetRatsnest()->ProcessBoard();
testConnectivity( aNetlist ); testConnectivity( aNetlist );
} }
// Update the ratsnest // Update the ratsnest
m_reporter->Report( wxT( "" ), REPORTER::RPT_ACTION );
m_reporter->Report( wxT( "" ), REPORTER::RPT_ACTION );
m_reporter->Report( wxT(""), REPORTER::RPT_ACTION ); msg.Printf( _( "Total warnings: %d, errors: %d." ), m_warningCount, m_errorCount );
m_reporter->Report( wxT(""), REPORTER::RPT_ACTION );
msg.Printf( _( "Total warnings: %d, errors: %d." ),
m_warningCount, m_errorCount );
m_reporter->Report( msg, REPORTER::RPT_ACTION ); m_reporter->Report( msg, REPORTER::RPT_ACTION );
if( m_errorCount )
if ( m_errorCount )
{ {
m_reporter->Report( _( "Errors occured during the netlist update. Unless you "
m_reporter->Report( _("Errors occured during the netlist update. Unless you " "fix them, your board will not be consistent with the schematics." ),
"fix them, your board will not be consistent with the schematics." ),
REPORTER::RPT_ERROR ); REPORTER::RPT_ERROR );
return false; return false;
} else { }
m_reporter->Report( _("Netlist update successful!" ), else
REPORTER::RPT_ACTION ); {
m_reporter->Report( _( "Netlist update successful!" ), REPORTER::RPT_ACTION );
} }
return true; return true;
} }
bool BOARD_NETLIST_UPDATER::UpdateNetlist( const wxString& aNetlistFileName, bool BOARD_NETLIST_UPDATER::UpdateNetlist( const wxString& aNetlistFileName,
const wxString& aCmpFileName ) const wxString& aCmpFileName )
{ {
return false; return false;
} }

View File

@ -39,10 +39,9 @@ class REPORTER;
class NETLIST; class NETLIST;
class COMPONENT; class COMPONENT;
class MODULE; class MODULE;
class PICKED_ITEMS_LIST;
class PCB_EDIT_FRAME; class PCB_EDIT_FRAME;
#include <class_undoredo_container.h> #include <board_commit.h>
/** /**
* Class BOARD_NETLIST_UPDATER * Class BOARD_NETLIST_UPDATER
@ -72,94 +71,89 @@ class PCB_EDIT_FRAME;
class BOARD_NETLIST_UPDATER class BOARD_NETLIST_UPDATER
{ {
public: public:
BOARD_NETLIST_UPDATER( PCB_EDIT_FRAME* aFrame, BOARD* aBoard );
~BOARD_NETLIST_UPDATER();
BOARD_NETLIST_UPDATER( PCB_EDIT_FRAME *aFrame, BOARD *aBoard ); /**
~BOARD_NETLIST_UPDATER(); * Function UpdateNetlist()
*
* Updates the board's components according to the new netlist.
* See BOARD_NETLIST_UPDATER class description for the details of the process.
* @param aNetlist the new netlist
* @return true if process was completed successfully
*/
bool UpdateNetlist( NETLIST& aNetlist );
/** // @todo: implement and move NETLIST::ReadPcbNetlist here
* Function UpdateNetlist() bool UpdateNetlist( const wxString& aNetlistFileName, const wxString& aCmpFileName );
*
* Updates the board's components according to the new netlist.
* See BOARD_NETLIST_UPDATER class description for the details of the process.
* @param aNetlist the new netlist
* @return true if process was completed successfully
*/
bool UpdateNetlist( NETLIST& aNetlist );
// @todo: implement and move NETLIST::ReadPcbNetlist here ///> Sets the reporter object
bool UpdateNetlist( const wxString& aNetlistFileName, void SetReporter( REPORTER* aReporter )
const wxString& aCmpFileName ); {
m_reporter = aReporter;
}
///> Enables "delete single pad nets" option
void SetDeleteSinglePadNets( bool aEnabled )
{
m_deleteSinglePadNets = aEnabled;
}
///> Sets the reporter object ///> Enables dry run mode (just report, no changes to PCB)
void SetReporter ( REPORTER *aReporter ) void SetIsDryRun( bool aEnabled )
{ {
m_reporter = aReporter; m_isDryRun = aEnabled;
} }
///> Enables "delete single pad nets" option ///> Enables replacing footprints with new ones
void SetDeleteSinglePadNets( bool aEnabled ) void SetReplaceFootprints( bool aEnabled )
{ {
m_deleteSinglePadNets = aEnabled; m_replaceFootprints = aEnabled;
} }
///> Enables dry run mode (just report, no changes to PCB) ///> Enables removing unused components
void SetIsDryRun ( bool aEnabled ) void SetDeleteUnusedComponents( bool aEnabled )
{ {
m_isDryRun = aEnabled; m_deleteUnusedComponents = aEnabled;
} }
///> Enables replacing footprints with new ones ///> Enables component lookup by timestamp instead of reference
void SetReplaceFootprints ( bool aEnabled ) void SetLookupByTimestamp( bool aEnabled )
{ {
m_replaceFootprints = aEnabled; m_lookupByTimestamp = aEnabled;
} }
///> Enables removing unused components std::vector<MODULE*> GetAddedComponents() const
void SetDeleteUnusedComponents ( bool aEnabled ) {
{ return m_addedComponents;
m_deleteUnusedComponents = aEnabled; }
}
///> Enables component lookup by timestamp instead of reference
void SetLookupByTimestamp ( bool aEnabled )
{
m_lookupByTimestamp = aEnabled;
}
std::vector<MODULE*> GetAddedComponents() const
{
return m_addedComponents;
}
private: private:
wxPoint estimateComponentInsertionPosition();
MODULE* addNewComponent( COMPONENT* aComponent );
MODULE* replaceComponent( NETLIST& aNetlist, MODULE* aPcbComponent, COMPONENT* aNewComponent );
bool updateComponentParameters( MODULE* aPcbComponent, COMPONENT* aNewComponent );
bool updateComponentPadConnections( MODULE* aPcbComponent, COMPONENT* aNewComponent );
bool deleteUnusedComponents( NETLIST& aNetlist );
bool deleteSinglePadNets();
bool testConnectivity( NETLIST& aNetlist );
void pushUndo( BOARD_ITEM* aItem, UNDO_REDO_T aCommandType, BOARD_ITEM* aCopy = NULL ); BOARD_COMMIT m_commit;
PCB_EDIT_FRAME* m_frame;
BOARD* m_board;
REPORTER* m_reporter;
wxPoint estimateComponentInsertionPosition(); std::vector<MODULE*> m_addedComponents;
MODULE* addNewComponent( COMPONENT* aComponent ); std::map<wxString, NETINFO_ITEM*> m_addedNets;
MODULE* replaceComponent( NETLIST& aNetlist, MODULE *aPcbComponent, COMPONENT* aNewComponent );
bool updateComponentParameters( MODULE *aPcbComponent, COMPONENT* aNewComponent );
bool updateComponentPadConnections( MODULE *aPcbComponent, COMPONENT* aNewComponent );
bool deleteUnusedComponents( NETLIST& aNetlist );
bool deleteSinglePadNets();
bool testConnectivity( NETLIST& aNetlist );
PICKED_ITEMS_LIST *m_undoList; bool m_deleteSinglePadNets;
PCB_EDIT_FRAME *m_frame; bool m_deleteUnusedComponents;
BOARD *m_board; bool m_isDryRun;
REPORTER *m_reporter; bool m_replaceFootprints;
bool m_lookupByTimestamp;
std::vector<MODULE*> m_addedComponents; int m_warningCount;
int m_errorCount;
bool m_deleteSinglePadNets;
bool m_deleteUnusedComponents;
bool m_isDryRun;
bool m_replaceFootprints;
bool m_lookupByTimestamp;
int m_warningCount;
int m_errorCount;
}; };
#endif #endif

View File

@ -67,7 +67,7 @@ wxPoint BOARD_ITEM::ZeroOffset( 0, 0 );
BOARD::BOARD() : BOARD::BOARD() :
BOARD_ITEM( (BOARD_ITEM*) NULL, PCB_T ), BOARD_ITEM_CONTAINER( (BOARD_ITEM*) NULL, PCB_T ),
m_NetInfo( this ), m_NetInfo( this ),
m_paper( PAGE_INFO::A4 ) m_paper( PAGE_INFO::A4 )
{ {
@ -858,7 +858,7 @@ bool BOARD::IsModuleLayerVisible( LAYER_ID layer )
} }
void BOARD::Add( BOARD_ITEM* aBoardItem, int aControl ) void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
{ {
if( aBoardItem == NULL ) if( aBoardItem == NULL )
{ {
@ -869,24 +869,22 @@ void BOARD::Add( BOARD_ITEM* aBoardItem, int aControl )
switch( aBoardItem->Type() ) switch( aBoardItem->Type() )
{ {
case PCB_NETINFO_T: case PCB_NETINFO_T:
aBoardItem->SetParent( this );
m_NetInfo.AppendNet( (NETINFO_ITEM*) aBoardItem ); m_NetInfo.AppendNet( (NETINFO_ITEM*) aBoardItem );
break;
// this one uses a vector // this one uses a vector
case PCB_MARKER_T: case PCB_MARKER_T:
aBoardItem->SetParent( this );
m_markers.push_back( (MARKER_PCB*) aBoardItem ); m_markers.push_back( (MARKER_PCB*) aBoardItem );
break; break;
// this one uses a vector // this one uses a vector
case PCB_ZONE_AREA_T: case PCB_ZONE_AREA_T:
aBoardItem->SetParent( this );
m_ZoneDescriptorList.push_back( (ZONE_CONTAINER*) aBoardItem ); m_ZoneDescriptorList.push_back( (ZONE_CONTAINER*) aBoardItem );
break; break;
case PCB_TRACE_T: case PCB_TRACE_T:
case PCB_VIA_T: case PCB_VIA_T:
if( aControl & ADD_APPEND ) if( aMode == ADD_APPEND )
{ {
m_Track.PushBack( (TRACK*) aBoardItem ); m_Track.PushBack( (TRACK*) aBoardItem );
} }
@ -897,44 +895,36 @@ void BOARD::Add( BOARD_ITEM* aBoardItem, int aControl )
m_Track.Insert( (TRACK*) aBoardItem, insertAid ); m_Track.Insert( (TRACK*) aBoardItem, insertAid );
} }
aBoardItem->SetParent( this );
break; break;
case PCB_ZONE_T: case PCB_ZONE_T:
if( aControl & ADD_APPEND ) if( aMode == ADD_APPEND )
m_Zone.PushBack( (SEGZONE*) aBoardItem ); m_Zone.PushBack( (SEGZONE*) aBoardItem );
else else
m_Zone.PushFront( (SEGZONE*) aBoardItem ); m_Zone.PushFront( (SEGZONE*) aBoardItem );
aBoardItem->SetParent( this );
break; break;
case PCB_MODULE_T: case PCB_MODULE_T:
if( aControl & ADD_APPEND ) if( aMode == ADD_APPEND )
m_Modules.PushBack( (MODULE*) aBoardItem ); m_Modules.PushBack( (MODULE*) aBoardItem );
else else
m_Modules.PushFront( (MODULE*) aBoardItem ); m_Modules.PushFront( (MODULE*) aBoardItem );
aBoardItem->SetParent( this );
// Because the list of pads has changed, reset the status // Because the list of pads has changed, reset the status
// This indicate the list of pad and nets must be recalculated before use // This indicate the list of pad and nets must be recalculated before use
m_Status_Pcb = 0; m_Status_Pcb = 0;
break; break;
case PCB_MODULE_EDGE_T:
assert( false ); // TODO Orson: I am just checking if it is supposed to be here
case PCB_DIMENSION_T: case PCB_DIMENSION_T:
case PCB_LINE_T: case PCB_LINE_T:
case PCB_TEXT_T: case PCB_TEXT_T:
case PCB_TARGET_T: case PCB_TARGET_T:
if( aControl & ADD_APPEND ) if( aMode == ADD_APPEND )
m_Drawings.PushBack( aBoardItem ); m_Drawings.PushBack( aBoardItem );
else else
m_Drawings.PushFront( aBoardItem ); m_Drawings.PushFront( aBoardItem );
aBoardItem->SetParent( this );
break; break;
// other types may use linked list // other types may use linked list
@ -944,15 +934,17 @@ void BOARD::Add( BOARD_ITEM* aBoardItem, int aControl )
msg.Printf( wxT( "BOARD::Add() needs work: BOARD_ITEM type (%d) not handled" ), msg.Printf( wxT( "BOARD::Add() needs work: BOARD_ITEM type (%d) not handled" ),
aBoardItem->Type() ); aBoardItem->Type() );
wxFAIL_MSG( msg ); wxFAIL_MSG( msg );
return;
} }
break; break;
} }
aBoardItem->SetParent( this );
m_ratsnest->Add( aBoardItem ); m_ratsnest->Add( aBoardItem );
} }
BOARD_ITEM* BOARD::Remove( BOARD_ITEM* aBoardItem ) void BOARD::Remove( BOARD_ITEM* aBoardItem )
{ {
// find these calls and fix them! Don't send me no stinking' NULL. // find these calls and fix them! Don't send me no stinking' NULL.
wxASSERT( aBoardItem ); wxASSERT( aBoardItem );
@ -965,6 +957,7 @@ BOARD_ITEM* BOARD::Remove( BOARD_ITEM* aBoardItem )
m_NetInfo.RemoveNet( item ); m_NetInfo.RemoveNet( item );
break; break;
} }
case PCB_MARKER_T: case PCB_MARKER_T:
// find the item in the vector, then remove it // find the item in the vector, then remove it
@ -1007,7 +1000,6 @@ BOARD_ITEM* BOARD::Remove( BOARD_ITEM* aBoardItem )
case PCB_DIMENSION_T: case PCB_DIMENSION_T:
case PCB_LINE_T: case PCB_LINE_T:
case PCB_TEXT_T: case PCB_TEXT_T:
case PCB_MODULE_EDGE_T:
case PCB_TARGET_T: case PCB_TARGET_T:
m_Drawings.Remove( aBoardItem ); m_Drawings.Remove( aBoardItem );
break; break;
@ -1018,8 +1010,6 @@ BOARD_ITEM* BOARD::Remove( BOARD_ITEM* aBoardItem )
} }
m_ratsnest->Remove( aBoardItem ); m_ratsnest->Remove( aBoardItem );
return aBoardItem;
} }
@ -2605,7 +2595,7 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets,
{ {
// It is a new net, we have to add it // It is a new net, we have to add it
netinfo = new NETINFO_ITEM( this, net.GetNetName() ); netinfo = new NETINFO_ITEM( this, net.GetNetName() );
m_NetInfo.AppendNet( netinfo ); Add( netinfo );
} }
pad->SetNetCode( netinfo->GetNet() ); pad->SetNetCode( netinfo->GetNet() );
@ -2781,18 +2771,14 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets,
} }
BOARD_ITEM* BOARD::DuplicateAndAddItem( const BOARD_ITEM* aItem ) BOARD_ITEM* BOARD::Duplicate( const BOARD_ITEM* aItem,
bool aAddToBoard )
{ {
BOARD_ITEM* new_item = NULL; BOARD_ITEM* new_item = NULL;
switch( aItem->Type() ) switch( aItem->Type() )
{ {
case PCB_MODULE_T: case PCB_MODULE_T:
{
MODULE* new_module = new MODULE( *static_cast<const MODULE*>( aItem ) );
new_item = new_module;
break;
}
case PCB_TEXT_T: case PCB_TEXT_T:
case PCB_LINE_T: case PCB_LINE_T:
case PCB_TRACE_T: case PCB_TRACE_T:
@ -2809,7 +2795,7 @@ BOARD_ITEM* BOARD::DuplicateAndAddItem( const BOARD_ITEM* aItem )
break; break;
} }
if( new_item ) if( new_item && aAddToBoard )
Add( new_item ); Add( new_item );
return new_item; return new_item;

View File

@ -42,6 +42,7 @@
#include <class_title_block.h> #include <class_title_block.h>
#include <class_zone_settings.h> #include <class_zone_settings.h>
#include <pcb_plot_params.h> #include <pcb_plot_params.h>
#include <board_item_container.h>
class PCB_BASE_FRAME; class PCB_BASE_FRAME;
@ -162,7 +163,7 @@ DECL_VEC_FOR_SWIG(TRACKS, TRACK*)
* Class BOARD * Class BOARD
* holds information pertinent to a Pcbnew printed circuit board. * holds information pertinent to a Pcbnew printed circuit board.
*/ */
class BOARD : public BOARD_ITEM class BOARD : public BOARD_ITEM_CONTAINER
{ {
friend class PCB_EDIT_FRAME; friend class PCB_EDIT_FRAME;
@ -212,6 +213,20 @@ private:
*/ */
void chainMarkedSegments( wxPoint aPosition, const LSET& aLayerSet, TRACKS* aList ); void chainMarkedSegments( wxPoint aPosition, const LSET& aLayerSet, TRACKS* aList );
// The default copy constructor & operator= are inadequate,
// either write one or do not use it at all
BOARD( const BOARD& aOther ) :
BOARD_ITEM_CONTAINER( aOther ), m_NetInfo( this )
{
assert( false );
}
BOARD& operator=( const BOARD& aOther )
{
assert( false );
return *this; // just to mute warning
}
public: public:
static inline bool ClassOf( const EDA_ITEM* aItem ) static inline bool ClassOf( const EDA_ITEM* aItem )
{ {
@ -257,46 +272,13 @@ public:
void SetFileFormatVersionAtLoad( int aVersion ) { m_fileFormatVersionAtLoad = aVersion; } void SetFileFormatVersionAtLoad( int aVersion ) { m_fileFormatVersionAtLoad = aVersion; }
int GetFileFormatVersionAtLoad() const { return m_fileFormatVersionAtLoad; } int GetFileFormatVersionAtLoad() const { return m_fileFormatVersionAtLoad; }
/** ///> @copydoc BOARD_ITEM_CONTAINER::Add()
* Function Add void Add( BOARD_ITEM* aItem, ADD_MODE aMode = ADD_INSERT ) override;
* adds the given item to this BOARD and takes ownership of its memory.
* @param aBoardItem The item to add to this board.
* @param aControl An int which can vary how the item is added.
*/
void Add( BOARD_ITEM* aBoardItem, int aControl = 0 );
#define ADD_APPEND 1 ///< aControl flag for Add( aControl ), appends not inserts ///> @copydoc BOARD_ITEM_CONTAINER::Remove()
void Remove( BOARD_ITEM* aBoardItem ) override;
/** BOARD_ITEM* Duplicate( const BOARD_ITEM* aItem, bool aAddToBoard = false );
* Function Delete
* removes the given single item from this BOARD and deletes its memory.
* @param aBoardItem The item to remove from this board and delete
*/
void Delete( BOARD_ITEM* aBoardItem )
{
// developers should run DEBUG versions and fix such calls with NULL
wxASSERT( aBoardItem );
if( aBoardItem )
delete Remove( aBoardItem );
}
/**
* Function Remove
* removes \a aBoardItem from this BOARD and returns it to caller without deleting it.
* @param aBoardItem The item to remove from this board.
* @return BOARD_ITEM* \a aBoardItem which was passed in.
*/
BOARD_ITEM* Remove( BOARD_ITEM* aBoardItem );
/**
* Function DuplicateAndAddItem
* duplicates an item, and add it to the board list.
* @param aItem The item to duplicate.
* @return BOARD_ITEM* \a the new item which was added.
*/
BOARD_ITEM* DuplicateAndAddItem( const BOARD_ITEM* aItem );
/** /**
* Function GetRatsnest() * Function GetRatsnest()
@ -802,16 +784,6 @@ public:
*/ */
NETINFO_ITEM* FindNet( const wxString& aNetname ) const; NETINFO_ITEM* FindNet( const wxString& aNetname ) const;
/**
* Function AppendNet
* adds a new net description item to the current board.
* @param aNewNet is the new description item.
*/
void AppendNet( NETINFO_ITEM* aNewNet )
{
m_NetInfo.AppendNet( aNewNet );
}
NETINFO_LIST& GetNetInfo() NETINFO_LIST& GetNetInfo()
{ {
return m_NetInfo; return m_NetInfo;

View File

@ -34,6 +34,8 @@
#include <class_board.h> #include <class_board.h>
#include <class_board_item.h> #include <class_board_item.h>
#include <ratsnest_data.cpp>
BOARD_CONNECTED_ITEM::BOARD_CONNECTED_ITEM( BOARD_ITEM* aParent, KICAD_T idtype ) : BOARD_CONNECTED_ITEM::BOARD_CONNECTED_ITEM( BOARD_ITEM* aParent, KICAD_T idtype ) :
BOARD_ITEM( aParent, idtype ), m_netinfo( &NETINFO_LIST::ORPHANED_ITEM ), BOARD_ITEM( aParent, idtype ), m_netinfo( &NETINFO_LIST::ORPHANED_ITEM ),
m_Subnet( 0 ), m_ZoneSubnet( 0 ) m_Subnet( 0 ), m_ZoneSubnet( 0 )
@ -41,13 +43,6 @@ BOARD_CONNECTED_ITEM::BOARD_CONNECTED_ITEM( BOARD_ITEM* aParent, KICAD_T idtype
} }
BOARD_CONNECTED_ITEM::BOARD_CONNECTED_ITEM( const BOARD_CONNECTED_ITEM& aItem ) :
BOARD_ITEM( aItem ), m_netinfo( aItem.m_netinfo ), m_Subnet( aItem.m_Subnet ),
m_ZoneSubnet( aItem.m_ZoneSubnet )
{
}
bool BOARD_CONNECTED_ITEM::SetNetCode( int aNetCode, bool aNoAssert ) bool BOARD_CONNECTED_ITEM::SetNetCode( int aNetCode, bool aNoAssert )
{ {
// if aNetCode < 0 ( typically NETINFO_LIST::FORCE_ORPHANED ) // if aNetCode < 0 ( typically NETINFO_LIST::FORCE_ORPHANED )
@ -55,6 +50,11 @@ bool BOARD_CONNECTED_ITEM::SetNetCode( int aNetCode, bool aNoAssert )
// set the m_netinfo to the dummy NETINFO_LIST::ORPHANED // set the m_netinfo to the dummy NETINFO_LIST::ORPHANED
BOARD* board = GetBoard(); BOARD* board = GetBoard();
RN_DATA* ratsnest = board ? board->GetRatsnest() : NULL;
bool addRatsnest = false;
if( ratsnest )
addRatsnest = ratsnest->Remove( this );
if( ( aNetCode >= 0 ) && board ) if( ( aNetCode >= 0 ) && board )
m_netinfo = board->FindNet( aNetCode ); m_netinfo = board->FindNet( aNetCode );
@ -64,6 +64,10 @@ bool BOARD_CONNECTED_ITEM::SetNetCode( int aNetCode, bool aNoAssert )
if( !aNoAssert ) if( !aNoAssert )
assert( m_netinfo ); assert( m_netinfo );
// Add only if it was previously added to the ratsnest
if( addRatsnest )
ratsnest->Add( this );
return ( m_netinfo != NULL ); return ( m_netinfo != NULL );
} }

View File

@ -56,7 +56,8 @@ public:
BOARD_CONNECTED_ITEM( BOARD_ITEM* aParent, KICAD_T idtype ); BOARD_CONNECTED_ITEM( BOARD_ITEM* aParent, KICAD_T idtype );
BOARD_CONNECTED_ITEM( const BOARD_CONNECTED_ITEM& aItem ); // Do not create a copy constructor & operator=.
// The ones generated by the compiler are adequate.
static inline bool ClassOf( const EDA_ITEM* aItem ) static inline bool ClassOf( const EDA_ITEM* aItem )
{ {
@ -91,6 +92,16 @@ public:
return m_netinfo; return m_netinfo;
} }
/**
* Function SetNet
* Sets a NET_INFO object for the item.
*/
void SetNet( NETINFO_ITEM* aNetInfo )
{
assert( aNetInfo->GetBoard() == GetBoard() );
m_netinfo = aNetInfo;
}
/** /**
* Function GetNetCode * Function GetNetCode
* @return int - the net code. * @return int - the net code.

View File

@ -219,8 +219,12 @@ int BOARD_ITEM::getTrailingInt( wxString aStr )
return number; return number;
} }
int BOARD_ITEM::getNextNumberInSequence( std::set<int> aSeq, bool aFillSequenceGaps)
int BOARD_ITEM::getNextNumberInSequence( const std::set<int>& aSeq, bool aFillSequenceGaps)
{ {
if( aSeq.empty() )
return 1;
// By default go to the end of the sequence // By default go to the end of the sequence
int candidate = *aSeq.rbegin(); int candidate = *aSeq.rbegin();
@ -230,16 +234,16 @@ int BOARD_ITEM::getNextNumberInSequence( std::set<int> aSeq, bool aFillSequenceG
// start at the beginning // start at the beginning
candidate = *aSeq.begin(); candidate = *aSeq.begin();
for( std::set<int>::iterator it = aSeq.begin(), for( auto it : aSeq )
itEnd = aSeq.end(); it != itEnd; ++it )
{ {
if( *it - candidate > 1 ) if( it - candidate > 1 )
break; break;
candidate = *it; candidate = it;
} }
} }
candidate++; ++candidate;
return candidate; return candidate;
} }

View File

@ -89,30 +89,6 @@ void DIMENSION::SetLayer( LAYER_ID aLayer )
} }
void DIMENSION::Copy( DIMENSION* source )
{
m_Value = source->m_Value;
SetLayer( source->GetLayer() );
m_Width = source->m_Width;
m_Shape = source->m_Shape;
m_Height = source->m_Height;
m_Unit = source->m_Unit;
SetTimeStamp( GetNewTimeStamp() );
m_Text.Copy( &source->m_Text );
m_crossBarO = source->m_crossBarO;
m_crossBarF = source->m_crossBarF;
m_featureLineGO = source->m_featureLineGO;
m_featureLineGF = source->m_featureLineGF;
m_featureLineDO = source->m_featureLineDO;
m_featureLineDF = source->m_featureLineDF;
m_arrowD1F = source->m_arrowD1F;
m_arrowD2F = source->m_arrowD2F;
m_arrowG1F = source->m_arrowG1F;
m_arrowG2F = source->m_arrowG2F;
}
void DIMENSION::Move( const wxPoint& offset ) void DIMENSION::Move( const wxPoint& offset )
{ {
m_Text.SetTextPosition( m_Text.GetTextPosition() + offset ); m_Text.SetTextPosition( m_Text.GetTextPosition() + offset );

View File

@ -78,7 +78,8 @@ public:
DIMENSION( BOARD_ITEM* aParent ); DIMENSION( BOARD_ITEM* aParent );
// Do not create a copy constructor. The one generated by the compiler is adequate. // Do not create a copy constructor & operator=.
// The ones generated by the compiler are adequate.
~DIMENSION(); ~DIMENSION();
@ -182,8 +183,6 @@ public:
TEXTE_PCB& Text() { return m_Text; } TEXTE_PCB& Text() { return m_Text; }
TEXTE_PCB& Text() const { return *(const_cast<TEXTE_PCB*> (&m_Text)); } TEXTE_PCB& Text() const { return *(const_cast<TEXTE_PCB*> (&m_Text)); }
void Copy( DIMENSION* source );
void Draw( EDA_DRAW_PANEL* panel, wxDC* DC, void Draw( EDA_DRAW_PANEL* panel, wxDC* DC,
GR_DRAWMODE aColorMode, const wxPoint& offset = ZeroOffset ); GR_DRAWMODE aColorMode, const wxPoint& offset = ZeroOffset );

View File

@ -64,34 +64,6 @@ DRAWSEGMENT::~DRAWSEGMENT()
} }
const DRAWSEGMENT& DRAWSEGMENT::operator = ( const DRAWSEGMENT& rhs )
{
// skip the linked list stuff, and parent
m_Type = rhs.m_Type;
m_Layer = rhs.m_Layer;
m_Width = rhs.m_Width;
m_Start = rhs.m_Start;
m_End = rhs.m_End;
m_Shape = rhs.m_Shape;
m_Angle = rhs.m_Angle;
m_TimeStamp = rhs.m_TimeStamp;
m_BezierC1 = rhs.m_BezierC1;
m_BezierC2 = rhs.m_BezierC1;
m_BezierPoints = rhs.m_BezierPoints;
return *this;
}
void DRAWSEGMENT::Copy( DRAWSEGMENT* source )
{
if( source == NULL ) // who would do this?
return;
*this = *source; // operator = ()
}
void DRAWSEGMENT::Rotate( const wxPoint& aRotCentre, double aAngle ) void DRAWSEGMENT::Rotate( const wxPoint& aRotCentre, double aAngle )
{ {
switch( m_Shape ) switch( m_Shape )

View File

@ -65,13 +65,11 @@ protected:
public: public:
DRAWSEGMENT( BOARD_ITEM* aParent = NULL, KICAD_T idtype = PCB_LINE_T ); DRAWSEGMENT( BOARD_ITEM* aParent = NULL, KICAD_T idtype = PCB_LINE_T );
// Do not create a copy constructor. The one generated by the compiler is adequate. // Do not create a copy constructor & operator=.
// The ones generated by the compiler are adequate.
~DRAWSEGMENT(); ~DRAWSEGMENT();
/// skip the linked list stuff, and parent
const DRAWSEGMENT& operator = ( const DRAWSEGMENT& rhs );
static inline bool ClassOf( const EDA_ITEM* aItem ) static inline bool ClassOf( const EDA_ITEM* aItem )
{ {
return aItem && PCB_LINE_T == aItem->Type(); return aItem && PCB_LINE_T == aItem->Type();
@ -181,8 +179,6 @@ public:
m_PolyPoints = aPoints; m_PolyPoints = aPoints;
} }
void Copy( DRAWSEGMENT* source );
void Draw( EDA_DRAW_PANEL* panel, wxDC* DC, void Draw( EDA_DRAW_PANEL* panel, wxDC* DC,
GR_DRAWMODE aDrawMode, const wxPoint& aOffset = ZeroOffset ); GR_DRAWMODE aDrawMode, const wxPoint& aOffset = ZeroOffset );

View File

@ -65,30 +65,6 @@ EDGE_MODULE::~EDGE_MODULE()
} }
const EDGE_MODULE& EDGE_MODULE::operator = ( const EDGE_MODULE& rhs )
{
if( &rhs == this )
return *this;
DRAWSEGMENT::operator=( rhs );
m_Start0 = rhs.m_Start0;
m_End0 = rhs.m_End0;
m_PolyPoints = rhs.m_PolyPoints; // std::vector copy
return *this;
}
void EDGE_MODULE::Copy( EDGE_MODULE* source )
{
if( source == NULL )
return;
*this = *source;
}
void EDGE_MODULE::SetLocalCoord() void EDGE_MODULE::SetLocalCoord()
{ {
MODULE* module = (MODULE*) m_Parent; MODULE* module = (MODULE*) m_Parent;

View File

@ -46,21 +46,16 @@ class EDGE_MODULE : public DRAWSEGMENT
public: public:
EDGE_MODULE( MODULE* parent, STROKE_T aShape = S_SEGMENT ); EDGE_MODULE( MODULE* parent, STROKE_T aShape = S_SEGMENT );
// Do not create a copy constructor. The one generated by the compiler is adequate. // Do not create a copy constructor & operator=.
// EDGE_MODULE( const EDGE_MODULE& ); // The ones generated by the compiler are adequate.
~EDGE_MODULE(); ~EDGE_MODULE();
/// skip the linked list stuff, and parent
const EDGE_MODULE& operator = ( const EDGE_MODULE& rhs );
static inline bool ClassOf( const EDA_ITEM* aItem ) static inline bool ClassOf( const EDA_ITEM* aItem )
{ {
return aItem && PCB_MODULE_EDGE_T == aItem->Type(); return aItem && PCB_MODULE_EDGE_T == aItem->Type();
} }
void Copy( EDGE_MODULE* source ); // copy structure
/** /**
* Move an edge of the footprint. * Move an edge of the footprint.
* This is a footprint shape modification. * This is a footprint shape modification.

View File

@ -69,16 +69,6 @@ PCB_TARGET::~PCB_TARGET()
{ {
} }
void PCB_TARGET::Copy( PCB_TARGET* source )
{
m_Layer = source->m_Layer;
m_Width = source->m_Width;
m_Pos = source->m_Pos;
m_Shape = source->m_Shape;
m_Size = source->m_Size;
SetTimeStamp( GetNewTimeStamp() );
}
/* Draw PCB_TARGET object: 2 segments + 1 circle /* Draw PCB_TARGET object: 2 segments + 1 circle
* The circle radius is half the radius of the target * The circle radius is half the radius of the target

View File

@ -54,6 +54,9 @@ public:
PCB_TARGET( BOARD_ITEM* aParent, int aShape, LAYER_ID aLayer, PCB_TARGET( BOARD_ITEM* aParent, int aShape, LAYER_ID aLayer,
const wxPoint& aPos, int aSize, int aWidth ); const wxPoint& aPos, int aSize, int aWidth );
// Do not create a copy constructor & operator=.
// The ones generated by the compiler are adequate.
~PCB_TARGET(); ~PCB_TARGET();
void SetPosition( const wxPoint& aPos ) { m_Pos = aPos; } // override void SetPosition( const wxPoint& aPos ) { m_Pos = aPos; } // override
@ -77,8 +80,6 @@ public:
void Flip( const wxPoint& aCentre ); void Flip( const wxPoint& aCentre );
void Copy( PCB_TARGET* source );
void Draw( EDA_DRAW_PANEL* panel, wxDC* DC, void Draw( EDA_DRAW_PANEL* panel, wxDC* DC,
GR_DRAWMODE aDrawMode, const wxPoint& offset = ZeroOffset ); GR_DRAWMODE aDrawMode, const wxPoint& offset = ZeroOffset );

View File

@ -50,7 +50,7 @@
MODULE::MODULE( BOARD* parent ) : MODULE::MODULE( BOARD* parent ) :
BOARD_ITEM( (BOARD_ITEM*) parent, PCB_MODULE_T ), BOARD_ITEM_CONTAINER( (BOARD_ITEM*) parent, PCB_MODULE_T ),
m_initial_comments( 0 ) m_initial_comments( 0 )
{ {
m_Attributs = MOD_DEFAULT; m_Attributs = MOD_DEFAULT;
@ -79,11 +79,10 @@ MODULE::MODULE( BOARD* parent ) :
MODULE::MODULE( const MODULE& aModule ) : MODULE::MODULE( const MODULE& aModule ) :
BOARD_ITEM( aModule ) BOARD_ITEM_CONTAINER( aModule )
{ {
m_Pos = aModule.m_Pos; m_Pos = aModule.m_Pos;
m_fpid = aModule.m_fpid; m_fpid = aModule.m_fpid;
m_Layer = aModule.m_Layer;
m_Attributs = aModule.m_Attributs; m_Attributs = aModule.m_Attributs;
m_ModuleStatus = aModule.m_ModuleStatus; m_ModuleStatus = aModule.m_ModuleStatus;
m_Orient = aModule.m_Orient; m_Orient = aModule.m_Orient;
@ -105,35 +104,27 @@ MODULE::MODULE( const MODULE& aModule ) :
// Copy reference and value. // Copy reference and value.
m_Reference = new TEXTE_MODULE( *aModule.m_Reference ); m_Reference = new TEXTE_MODULE( *aModule.m_Reference );
m_Reference->SetParent( this ); m_Reference->SetParent( this );
m_Value = new TEXTE_MODULE( *aModule.m_Value ); m_Value = new TEXTE_MODULE( *aModule.m_Value );
m_Value->SetParent( this ); m_Value->SetParent( this );
// Copy auxiliary data: Pads // Copy auxiliary data: Pads
for( D_PAD* pad = aModule.m_Pads; pad; pad = pad->Next() ) for( D_PAD* pad = aModule.m_Pads; pad; pad = pad->Next() )
{ {
D_PAD* newpad = new D_PAD( *pad ); Add( new D_PAD( *pad ) );
assert( newpad->GetNet() == pad->GetNet() );
newpad->SetParent( this );
m_Pads.PushBack( newpad );
} }
// Copy auxiliary data: Drawings // Copy auxiliary data: Drawings
for( BOARD_ITEM* item = aModule.m_Drawings; item; item = item->Next() ) for( BOARD_ITEM* item = aModule.m_Drawings; item; item = item->Next() )
{ {
BOARD_ITEM* newItem;
switch( item->Type() ) switch( item->Type() )
{ {
case PCB_MODULE_TEXT_T: case PCB_MODULE_TEXT_T:
case PCB_MODULE_EDGE_T: case PCB_MODULE_EDGE_T:
newItem = static_cast<BOARD_ITEM*>( item->Clone() ); Add( static_cast<BOARD_ITEM*>( item->Clone() ) );
newItem->SetParent( this );
m_Drawings.PushBack( newItem );
break; break;
default: default:
wxLogMessage( wxT( "MODULE::Copy() Internal Err: unknown type" ) ); wxLogMessage( wxT( "Class MODULE copy constructor internal error: unknown type" ) );
break; break;
} }
} }
@ -161,13 +152,76 @@ MODULE::~MODULE()
delete m_initial_comments; delete m_initial_comments;
} }
/**
* Function ClearAllNets MODULE& MODULE::operator=( const MODULE& aOther )
* Clear (i.e. force the ORPHANED dummy net info) the net info which {
* depends on a given board for all pads of the footprint. BOARD_ITEM::operator=( aOther );
* This is needed when a footprint is copied between the fp editor and
* the board editor for instance, because net info become fully broken m_Pos = aOther.m_Pos;
*/ m_fpid = aOther.m_fpid;
m_Attributs = aOther.m_Attributs;
m_ModuleStatus = aOther.m_ModuleStatus;
m_Orient = aOther.m_Orient;
m_BoundaryBox = aOther.m_BoundaryBox;
m_CntRot90 = aOther.m_CntRot90;
m_CntRot180 = aOther.m_CntRot180;
m_LastEditTime = aOther.m_LastEditTime;
m_Link = aOther.m_Link;
m_Path = aOther.m_Path; //is this correct behavior?
m_LocalClearance = aOther.m_LocalClearance;
m_LocalSolderMaskMargin = aOther.m_LocalSolderMaskMargin;
m_LocalSolderPasteMargin = aOther.m_LocalSolderPasteMargin;
m_LocalSolderPasteMarginRatio = aOther.m_LocalSolderPasteMarginRatio;
m_ZoneConnection = aOther.m_ZoneConnection;
m_ThermalWidth = aOther.m_ThermalWidth;
m_ThermalGap = aOther.m_ThermalGap;
// Copy reference and value
*m_Reference = *aOther.m_Reference;
m_Reference->SetParent( this );
*m_Value = *aOther.m_Value;
m_Value->SetParent( this );
// Copy auxiliary data: Pads
m_Pads.DeleteAll();
for( D_PAD* pad = aOther.m_Pads; pad; pad = pad->Next() )
{
Add( new D_PAD( *pad ) );
}
// Copy auxiliary data: Drawings
m_Drawings.DeleteAll();
for( BOARD_ITEM* item = aOther.m_Drawings; item; item = item->Next() )
{
switch( item->Type() )
{
case PCB_MODULE_TEXT_T:
case PCB_MODULE_EDGE_T:
Add( static_cast<BOARD_ITEM*>( item->Clone() ) );
break;
default:
wxLogMessage( wxT( "MODULE::operator=() internal error: unknown type" ) );
break;
}
}
// Copy auxiliary data: 3D_Drawings info
m_3D_Drawings.clear();
m_3D_Drawings = aOther.m_3D_Drawings;
m_Doc = aOther.m_Doc;
m_KeyWord = aOther.m_KeyWord;
// Ensure auxiliary data is up to date
CalculateBoundingBox();
return *this;
}
void MODULE::ClearAllNets() void MODULE::ClearAllNets()
{ {
// Force the ORPHANED dummy net info for all pads. // Force the ORPHANED dummy net info for all pads.
@ -177,10 +231,6 @@ void MODULE::ClearAllNets()
} }
/* Draw the anchor cross (vertical)
* Must be done after the pads, because drawing the hole will erase overwrite
* every thing already drawn.
*/
void MODULE::DrawAncre( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& offset, void MODULE::DrawAncre( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& offset,
int dim_ancre, GR_DRAWMODE draw_mode ) int dim_ancre, GR_DRAWMODE draw_mode )
{ {
@ -195,86 +245,7 @@ void MODULE::DrawAncre( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& offset,
} }
void MODULE::Copy( MODULE* aModule ) void MODULE::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
{
m_Pos = aModule->m_Pos;
m_Layer = aModule->m_Layer;
m_fpid = aModule->m_fpid;
m_Attributs = aModule->m_Attributs;
m_ModuleStatus = aModule->m_ModuleStatus;
m_Orient = aModule->m_Orient;
m_BoundaryBox = aModule->m_BoundaryBox;
m_CntRot90 = aModule->m_CntRot90;
m_CntRot180 = aModule->m_CntRot180;
m_LastEditTime = aModule->m_LastEditTime;
m_Link = aModule->m_Link;
m_Path = aModule->m_Path; //is this correct behavior?
SetTimeStamp( GetNewTimeStamp() );
m_LocalClearance = aModule->m_LocalClearance;
m_LocalSolderMaskMargin = aModule->m_LocalSolderMaskMargin;
m_LocalSolderPasteMargin = aModule->m_LocalSolderPasteMargin;
m_LocalSolderPasteMarginRatio = aModule->m_LocalSolderPasteMarginRatio;
m_ZoneConnection = aModule->m_ZoneConnection;
m_ThermalWidth = aModule->m_ThermalWidth;
m_ThermalGap = aModule->m_ThermalGap;
// Copy reference and value.
m_Reference->Copy( aModule->m_Reference );
m_Value->Copy( aModule->m_Value );
// Copy auxiliary data: Pads
m_Pads.DeleteAll();
for( D_PAD* pad = aModule->m_Pads; pad; pad = pad->Next() )
{
D_PAD* newpad = new D_PAD( this );
newpad->Copy( pad );
m_Pads.PushBack( newpad );
}
// Copy auxiliary data: Drawings
m_Drawings.DeleteAll();
for( BOARD_ITEM* item = aModule->m_Drawings; item; item = item->Next() )
{
switch( item->Type() )
{
case PCB_MODULE_TEXT_T:
{
TEXTE_MODULE* textm = new TEXTE_MODULE( this );
textm->Copy( static_cast<TEXTE_MODULE*>( item ) );
m_Drawings.PushBack( textm );
break;
}
case PCB_MODULE_EDGE_T:
{
EDGE_MODULE * edge;
edge = new EDGE_MODULE( this );
edge->Copy( (EDGE_MODULE*) item );
m_Drawings.PushBack( edge );
break;
}
default:
wxLogMessage( wxT( "MODULE::Copy() Internal Err: unknown type" ) );
break;
}
}
// Copy auxiliary data: 3D_Drawings info
m_3D_Drawings.clear();
m_3D_Drawings = aModule->m_3D_Drawings;
m_Doc = aModule->m_Doc;
m_KeyWord = aModule->m_KeyWord;
// Ensure auxiliary data is up to date
CalculateBoundingBox();
}
void MODULE::Add( BOARD_ITEM* aBoardItem, bool doAppend )
{ {
switch( aBoardItem->Type() ) switch( aBoardItem->Type() )
{ {
@ -285,14 +256,14 @@ void MODULE::Add( BOARD_ITEM* aBoardItem, bool doAppend )
// no break // no break
case PCB_MODULE_EDGE_T: case PCB_MODULE_EDGE_T:
if( doAppend ) if( aMode == ADD_APPEND )
m_Drawings.PushBack( aBoardItem ); m_Drawings.PushBack( aBoardItem );
else else
m_Drawings.PushFront( aBoardItem ); m_Drawings.PushFront( aBoardItem );
break; break;
case PCB_PAD_T: case PCB_PAD_T:
if( doAppend ) if( aMode == ADD_APPEND )
m_Pads.PushBack( static_cast<D_PAD*>( aBoardItem ) ); m_Pads.PushBack( static_cast<D_PAD*>( aBoardItem ) );
else else
m_Pads.PushFront( static_cast<D_PAD*>( aBoardItem ) ); m_Pads.PushFront( static_cast<D_PAD*>( aBoardItem ) );
@ -310,10 +281,32 @@ void MODULE::Add( BOARD_ITEM* aBoardItem, bool doAppend )
} }
aBoardItem->SetParent( this ); aBoardItem->SetParent( this );
SetLastEditTime();
// Update relative coordinates, it can be done only after there is a parent object assigned
switch( aBoardItem->Type() )
{
case PCB_MODULE_TEXT_T:
static_cast<TEXTE_MODULE*>( aBoardItem )->SetLocalCoord();
break;
case PCB_MODULE_EDGE_T:
static_cast<EDGE_MODULE*>( aBoardItem )->SetLocalCoord();
break;
case PCB_PAD_T:
static_cast<D_PAD*>( aBoardItem )->SetLocalCoord();
break;
default:
// Huh? It should have been filtered out by the previous switch
assert(false);
break;
}
} }
BOARD_ITEM* MODULE::Remove( BOARD_ITEM* aBoardItem ) void MODULE::Remove( BOARD_ITEM* aBoardItem )
{ {
switch( aBoardItem->Type() ) switch( aBoardItem->Type() )
{ {
@ -324,10 +317,12 @@ BOARD_ITEM* MODULE::Remove( BOARD_ITEM* aBoardItem )
// no break // no break
case PCB_MODULE_EDGE_T: case PCB_MODULE_EDGE_T:
return m_Drawings.Remove( aBoardItem ); m_Drawings.Remove( aBoardItem );
break;
case PCB_PAD_T: case PCB_PAD_T:
return m_Pads.Remove( static_cast<D_PAD*>( aBoardItem ) ); m_Pads.Remove( static_cast<D_PAD*>( aBoardItem ) );
break;
default: default:
{ {
@ -337,8 +332,6 @@ BOARD_ITEM* MODULE::Remove( BOARD_ITEM* aBoardItem )
wxFAIL_MSG( msg ); wxFAIL_MSG( msg );
} }
} }
return NULL;
} }
@ -516,9 +509,6 @@ const EDA_RECT MODULE::GetBoundingBox() const
} }
/* Virtual function, from EDA_ITEM.
* display module info on MsgPanel
*/
void MODULE::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) void MODULE::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList )
{ {
int nbpad; int nbpad;
@ -902,11 +892,6 @@ const BOX2I MODULE::ViewBBox() const
} }
/* Test for validity of the name in a library of the footprint
* ( no spaces, dir separators ... )
* return true if the given name is valid
* static function
*/
bool MODULE::IsLibNameValid( const wxString & aName ) bool MODULE::IsLibNameValid( const wxString & aName )
{ {
const wxChar * invalids = StringLibNameInvalidChars( false ); const wxChar * invalids = StringLibNameInvalidChars( false );
@ -918,13 +903,6 @@ bool MODULE::IsLibNameValid( const wxString & aName )
} }
/* Test for validity of the name of a footprint to be used in a footprint library
* ( no spaces, dir separators ... )
* param bool aUserReadable = false to get the list of invalid chars
* true to get a readable form (i.e ' ' = 'space' '\t'= 'tab')
* return a constant string giving the list of invalid chars in lib name
* static function
*/
const wxChar* MODULE::StringLibNameInvalidChars( bool aUserReadable ) const wxChar* MODULE::StringLibNameInvalidChars( bool aUserReadable )
{ {
static const wxChar invalidChars[] = wxT("%$\t \"\\/"); static const wxChar invalidChars[] = wxT("%$\t \"\\/");
@ -1132,8 +1110,9 @@ void MODULE::SetOrientation( double newangle )
CalculateBoundingBox(); CalculateBoundingBox();
} }
BOARD_ITEM* MODULE::DuplicateAndAddItem( const BOARD_ITEM* aItem, BOARD_ITEM* MODULE::Duplicate( const BOARD_ITEM* aItem,
bool aIncrementPadNumbers ) bool aIncrementPadNumbers,
bool aAddToModule )
{ {
BOARD_ITEM* new_item = NULL; BOARD_ITEM* new_item = NULL;
D_PAD* new_pad = NULL; D_PAD* new_pad = NULL;
@ -1144,7 +1123,9 @@ BOARD_ITEM* MODULE::DuplicateAndAddItem( const BOARD_ITEM* aItem,
{ {
new_pad = new D_PAD( *static_cast<const D_PAD*>( aItem ) ); new_pad = new D_PAD( *static_cast<const D_PAD*>( aItem ) );
Pads().PushBack( new_pad ); if( aAddToModule )
Pads().PushBack( new_pad );
new_item = new_pad; new_item = new_pad;
break; break;
} }
@ -1159,7 +1140,9 @@ BOARD_ITEM* MODULE::DuplicateAndAddItem( const BOARD_ITEM* aItem,
{ {
TEXTE_MODULE* new_text = new TEXTE_MODULE( *old_text ); TEXTE_MODULE* new_text = new TEXTE_MODULE( *old_text );
GraphicalItems().PushBack( new_text ); if( aAddToModule )
GraphicalItems().PushBack( new_text );
new_item = new_text; new_item = new_text;
} }
break; break;
@ -1170,7 +1153,9 @@ BOARD_ITEM* MODULE::DuplicateAndAddItem( const BOARD_ITEM* aItem,
EDGE_MODULE* new_edge = new EDGE_MODULE( EDGE_MODULE* new_edge = new EDGE_MODULE(
*static_cast<const EDGE_MODULE*>(aItem) ); *static_cast<const EDGE_MODULE*>(aItem) );
GraphicalItems().PushBack( new_edge ); if( aAddToModule )
GraphicalItems().PushBack( new_edge );
new_item = new_edge; new_item = new_edge;
break; break;
} }

View File

@ -36,6 +36,7 @@
#include <dlist.h> #include <dlist.h>
#include <layers_id_colors_and_visibility.h> // ALL_LAYERS definition. #include <layers_id_colors_and_visibility.h> // ALL_LAYERS definition.
#include <class_board_item.h> #include <class_board_item.h>
#include <board_item_container.h>
#include <fpid.h> #include <fpid.h>
#include <class_text_mod.h> #include <class_text_mod.h>
@ -75,7 +76,7 @@ enum MODULE_ATTR_T
}; };
class MODULE : public BOARD_ITEM class MODULE : public BOARD_ITEM_CONTAINER
{ {
public: public:
MODULE( BOARD* parent ); MODULE( BOARD* parent );
@ -84,6 +85,8 @@ public:
~MODULE(); ~MODULE();
MODULE& operator=( const MODULE& aOther );
static inline bool ClassOf( const EDA_ITEM* aItem ) static inline bool ClassOf( const EDA_ITEM* aItem )
{ {
return PCB_MODULE_T == aItem->Type(); return PCB_MODULE_T == aItem->Type();
@ -92,37 +95,11 @@ public:
MODULE* Next() const { return static_cast<MODULE*>( Pnext ); } MODULE* Next() const { return static_cast<MODULE*>( Pnext ); }
MODULE* Back() const { return static_cast<MODULE*>( Pback ); } MODULE* Back() const { return static_cast<MODULE*>( Pback ); }
void Copy( MODULE* Module ); // Copy structure ///> @copydoc BOARD_ITEM_CONTAINER::Add()
void Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode = ADD_INSERT ) override;
/** ///> @copydoc BOARD_ITEM_CONTAINER::Remove()
* Function Add void Remove( BOARD_ITEM* aBoardItem ) override;
* adds the given item to this MODULE and takes ownership of its memory.
* @param aBoardItem The item to add to this board.
* @param doAppend If true, then append, else insert.
*/
void Add( BOARD_ITEM* aBoardItem, bool doAppend = true );
/**
* Function Delete
* removes the given single item from this MODULE and deletes its memory.
* @param aBoardItem The item to remove from this module and delete
*/
void Delete( BOARD_ITEM* aBoardItem )
{
// developers should run DEBUG versions and fix such calls with NULL
wxASSERT( aBoardItem );
if( aBoardItem )
delete Remove( aBoardItem );
}
/**
* Function Remove
* removes \a aBoardItem from this MODULE and returns it to caller without deleting it.
* @param aBoardItem The item to remove from this module.
* @return BOARD_ITEM* \a aBoardItem which was passed in.
*/
BOARD_ITEM* Remove( BOARD_ITEM* aBoardItem );
/** /**
* Function ClearAllNets * Function ClearAllNets
@ -404,9 +381,16 @@ public:
void DrawEdgesOnly( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& offset, void DrawEdgesOnly( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& offset,
GR_DRAWMODE draw_mode ); GR_DRAWMODE draw_mode );
/**
* Function DrawAncre
* Draw the anchor cross (vertical)
* Must be done after the pads, because drawing the hole will erase overwrite
* every thing already drawn.
*/
void DrawAncre( EDA_DRAW_PANEL* panel, wxDC* DC, void DrawAncre( EDA_DRAW_PANEL* panel, wxDC* DC,
const wxPoint& offset, int dim_ancre, GR_DRAWMODE draw_mode ); const wxPoint& offset, int dim_ancre, GR_DRAWMODE draw_mode );
///> @copydoc EDA_ITEM::GetMsgPanelInfo
void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ); void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList );
bool HitTest( const wxPoint& aPosition ) const; bool HitTest( const wxPoint& aPosition ) const;
@ -536,12 +520,13 @@ public:
void SetPlacementCost90( int aCost ) { m_CntRot90 = aCost; } void SetPlacementCost90( int aCost ) { m_CntRot90 = aCost; }
/** /**
* Function DuplicateAndAddItem * Function Duplicate
* Duplicate a given item within the module * Duplicate a given item within the module, without adding to the board
* @return the new item, or NULL if the item could not be duplicated * @return the new item, or NULL if the item could not be duplicated
*/ */
BOARD_ITEM* DuplicateAndAddItem( const BOARD_ITEM* item, BOARD_ITEM* Duplicate( const BOARD_ITEM* aItem,
bool aIncrementPadNumbers ); bool aIncrementPadNumbers,
bool aAddToModule = false );
/** /**
* Function Add3DModel * Function Add3DModel

View File

@ -423,41 +423,6 @@ bool D_PAD::IncrementPadName( bool aSkipUnconnectable, bool aFillSequenceGaps )
} }
void D_PAD::Copy( D_PAD* source )
{
if( source == NULL )
return;
m_Pos = source->m_Pos;
m_layerMask = source->m_layerMask;
m_NumPadName = source->m_NumPadName;
m_netinfo = source->m_netinfo;
m_Drill = source->m_Drill;
m_drillShape = source->m_drillShape;
m_Offset = source->m_Offset;
m_Size = source->m_Size;
m_DeltaSize = source->m_DeltaSize;
m_Pos0 = source->m_Pos0;
m_boundingRadius = source->m_boundingRadius;
m_padShape = source->m_padShape;
m_Attribute = source->m_Attribute;
m_Orient = source->m_Orient;
m_LengthPadToDie = source->m_LengthPadToDie;
m_LocalClearance = source->m_LocalClearance;
m_LocalSolderMaskMargin = source->m_LocalSolderMaskMargin;
m_LocalSolderPasteMargin = source->m_LocalSolderPasteMargin;
m_LocalSolderPasteMarginRatio = source->m_LocalSolderPasteMarginRatio;
m_ZoneConnection = source->m_ZoneConnection;
m_ThermalWidth = source->m_ThermalWidth;
m_ThermalGap = source->m_ThermalGap;
m_padRoundRectRadiusScale = source->m_padRoundRectRadiusScale;
SetSubRatsnest( 0 );
SetSubNet( 0 );
}
void D_PAD::CopyNetlistSettings( D_PAD* aPad, bool aCopyLocalSettings ) void D_PAD::CopyNetlistSettings( D_PAD* aPad, bool aCopyLocalSettings )
{ {
// Don't do anything foolish like trying to copy to yourself. // Don't do anything foolish like trying to copy to yourself.

View File

@ -82,8 +82,8 @@ public:
public: public:
D_PAD( MODULE* parent ); D_PAD( MODULE* parent );
// Do not create a copy constructor. The one generated by the compiler is adequate. // Do not create a copy constructor & operator=.
// D_PAD( const D_PAD& o ); // The ones generated by the compiler are adequate.
/* Default layers used for pads, according to the pad type. /* Default layers used for pads, according to the pad type.
* this is default values only, they can be changed for a given pad * this is default values only, they can be changed for a given pad
@ -99,8 +99,6 @@ public:
return aItem && PCB_PAD_T == aItem->Type(); return aItem && PCB_PAD_T == aItem->Type();
} }
void Copy( D_PAD* source );
D_PAD* Next() const { return static_cast<D_PAD*>( Pnext ); } D_PAD* Next() const { return static_cast<D_PAD*>( Pnext ); }
MODULE* GetParent() const { return (MODULE*) m_Parent; } MODULE* GetParent() const { return (MODULE*) m_Parent; }

View File

@ -60,27 +60,6 @@ TEXTE_PCB:: ~TEXTE_PCB()
} }
void TEXTE_PCB::Copy( TEXTE_PCB* source )
{
m_Parent = source->m_Parent;
Pback = Pnext = NULL;
m_Mirror = source->m_Mirror;
m_Size = source->m_Size;
m_Orient = source->m_Orient;
m_Pos = source->m_Pos;
m_Layer = source->m_Layer;
m_Thickness = source->m_Thickness;
m_Attributs = source->m_Attributs;
m_Italic = source->m_Italic;
m_Bold = source->m_Bold;
m_HJustify = source->m_HJustify;
m_VJustify = source->m_VJustify;
m_MultilineAllowed = source->m_MultilineAllowed;
m_Text = source->m_Text;
}
void TEXTE_PCB::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, void TEXTE_PCB::Draw( EDA_DRAW_PANEL* panel, wxDC* DC,
GR_DRAWMODE DrawMode, const wxPoint& offset ) GR_DRAWMODE DrawMode, const wxPoint& offset )
{ {

View File

@ -45,7 +45,8 @@ class TEXTE_PCB : public BOARD_ITEM, public EDA_TEXT
public: public:
TEXTE_PCB( BOARD_ITEM* parent ); TEXTE_PCB( BOARD_ITEM* parent );
// Do not create a copy constructor. The one generated by the compiler is adequate. // Do not create a copy constructor & operator=.
// The ones generated by the compiler are adequate.
~TEXTE_PCB(); ~TEXTE_PCB();
@ -73,9 +74,6 @@ public:
void Flip( const wxPoint& aCentre ); void Flip( const wxPoint& aCentre );
/* duplicate structure */
void Copy( TEXTE_PCB* source );
void Draw( EDA_DRAW_PANEL* panel, wxDC* DC, void Draw( EDA_DRAW_PANEL* panel, wxDC* DC,
GR_DRAWMODE aDrawMode, const wxPoint& offset = ZeroOffset ); GR_DRAWMODE aDrawMode, const wxPoint& offset = ZeroOffset );

View File

@ -124,27 +124,6 @@ void TEXTE_MODULE::Move( const wxPoint& aMoveVector )
} }
void TEXTE_MODULE::Copy( TEXTE_MODULE* source )
{
if( source == NULL )
return;
m_Pos = source->m_Pos;
SetLayer( source->GetLayer() );
m_Mirror = source->m_Mirror;
m_NoShow = source->m_NoShow;
m_Type = source->m_Type;
m_Orient = source->m_Orient;
m_Pos0 = source->m_Pos0;
m_Size = source->m_Size;
m_Thickness = source->m_Thickness;
m_Italic = source->m_Italic;
m_Bold = source->m_Bold;
m_Text = source->m_Text;
}
int TEXTE_MODULE::GetLength() const int TEXTE_MODULE::GetLength() const
{ {
return m_Text.Len(); return m_Text.Len();

View File

@ -64,7 +64,8 @@ public:
TEXTE_MODULE( MODULE* parent, TEXT_TYPE text_type = TEXT_is_DIVERS ); TEXTE_MODULE( MODULE* parent, TEXT_TYPE text_type = TEXT_is_DIVERS );
// Do not create a copy constructor. The one generated by the compiler is adequate. // Do not create a copy constructor & operator=.
// The ones generated by the compiler are adequate.
~TEXTE_MODULE(); ~TEXTE_MODULE();
@ -112,8 +113,6 @@ public:
void SetPos0( const wxPoint& aPos ) { m_Pos0 = aPos; SetDrawCoord(); } void SetPos0( const wxPoint& aPos ) { m_Pos0 = aPos; SetDrawCoord(); }
const wxPoint& GetPos0() const { return m_Pos0; } const wxPoint& GetPos0() const { return m_Pos0; }
void Copy( TEXTE_MODULE* source ); // copy structure
int GetLength() const; // text length int GetLength() const; // text length
/** /**

View File

@ -105,6 +105,32 @@ ZONE_CONTAINER::ZONE_CONTAINER( const ZONE_CONTAINER& aZone ) :
} }
ZONE_CONTAINER& ZONE_CONTAINER::operator=( const ZONE_CONTAINER& aOther )
{
BOARD_CONNECTED_ITEM::operator=( aOther );
m_Poly->RemoveAllContours();
m_Poly->Copy( aOther.m_Poly ); // copy outlines
m_CornerSelection = -1; // for corner moving, corner index to drag or -1 if no selection
m_ZoneClearance = aOther.m_ZoneClearance; // clearance value
m_ZoneMinThickness = aOther.m_ZoneMinThickness;
m_FillMode = aOther.m_FillMode; // filling mode (segments/polygons)
m_ArcToSegmentsCount = aOther.m_ArcToSegmentsCount;
m_PadConnection = aOther.m_PadConnection;
m_ThermalReliefGap = aOther.m_ThermalReliefGap;
m_ThermalReliefCopperBridge = aOther.m_ThermalReliefCopperBridge;
m_Poly->SetHatchStyle( aOther.m_Poly->GetHatchStyle() );
m_Poly->SetHatchPitch( aOther.m_Poly->GetHatchPitch() );
m_Poly->m_HatchLines = aOther.m_Poly->m_HatchLines; // copy vector <CSegment>
m_FilledPolysList.RemoveAllContours();
m_FilledPolysList.Append( aOther.m_FilledPolysList );
m_FillSegmList.clear();
m_FillSegmList = aOther.m_FillSegmList;
return *this;
}
ZONE_CONTAINER::~ZONE_CONTAINER() ZONE_CONTAINER::~ZONE_CONTAINER()
{ {
delete m_Poly; delete m_Poly;
@ -751,33 +777,6 @@ void ZONE_CONTAINER::Mirror( const wxPoint& mirror_ref )
} }
void ZONE_CONTAINER::Copy( ZONE_CONTAINER* src )
{
m_Parent = src->m_Parent;
m_Layer = src->m_Layer;
SetNetCode( src->GetNetCode() );
SetTimeStamp( src->m_TimeStamp );
m_Poly->RemoveAllContours();
m_Poly->Copy( src->m_Poly ); // copy outlines
m_CornerSelection = -1; // For corner moving, corner index to drag,
// or -1 if no selection
m_ZoneClearance = src->m_ZoneClearance; // clearance value
m_ZoneMinThickness = src->m_ZoneMinThickness;
m_FillMode = src->m_FillMode; // Filling mode (segments/polygons)
m_ArcToSegmentsCount = src->m_ArcToSegmentsCount;
m_PadConnection = src->m_PadConnection;
m_ThermalReliefGap = src->m_ThermalReliefGap;
m_ThermalReliefCopperBridge = src->m_ThermalReliefCopperBridge;
m_Poly->SetHatchStyle( src->m_Poly->GetHatchStyle() );
m_Poly->SetHatchPitch( src->m_Poly->GetHatchPitch() );
m_Poly->m_HatchLines = src->m_Poly->m_HatchLines; // Copy vector <CSegment>
m_FilledPolysList.RemoveAllContours();
m_FilledPolysList.Append( src->m_FilledPolysList );
m_FillSegmList.clear();
m_FillSegmList = src->m_FillSegmList;
}
ZoneConnection ZONE_CONTAINER::GetPadConnection( D_PAD* aPad ) const ZoneConnection ZONE_CONTAINER::GetPadConnection( D_PAD* aPad ) const
{ {
if( aPad == NULL || aPad->GetZoneConnection() == PAD_ZONE_CONN_INHERITED ) if( aPad == NULL || aPad->GetZoneConnection() == PAD_ZONE_CONN_INHERITED )

View File

@ -82,6 +82,7 @@ public:
ZONE_CONTAINER( BOARD* parent ); ZONE_CONTAINER( BOARD* parent );
ZONE_CONTAINER( const ZONE_CONTAINER& aZone ); ZONE_CONTAINER( const ZONE_CONTAINER& aZone );
ZONE_CONTAINER& operator=( const ZONE_CONTAINER &aOther );
~ZONE_CONTAINER(); ~ZONE_CONTAINER();
@ -104,13 +105,6 @@ public:
*/ */
unsigned GetPriority() const { return m_priority; } unsigned GetPriority() const { return m_priority; }
/**
* Function copy
* copy useful data from the source.
* flags and linked list pointers are NOT copied
*/
void Copy( ZONE_CONTAINER* src );
void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ); void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList );
/** /**

View File

@ -942,6 +942,10 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode()
} }
} }
/// @todo LEGACY tracks might have changed their nets, so we need to refresh labels in GAL
for( TRACK* track = m_Pcb->m_Track; track; track = track->Next() )
track->ViewUpdate();
// Sort the track list by net codes: // Sort the track list by net codes:
RebuildTrackChain( m_Pcb ); RebuildTrackChain( m_Pcb );
} }

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Mar 9 2016) // C++ code generated with wxFormBuilder (version Jun 21 2016)
// http://www.wxformbuilder.org/ // http://www.wxformbuilder.org/
// //
// PLEASE DO "NOT" EDIT THIS FILE! // PLEASE DO "NOT" EDIT THIS FILE!
@ -290,19 +290,19 @@ DIALOG_CREATE_ARRAY_BASE::DIALOG_CREATE_ARRAY_BASE( wxWindow* parent, wxWindowID
// Connect Events // Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_CREATE_ARRAY_BASE::OnClose ) ); this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_CREATE_ARRAY_BASE::OnClose ) );
m_entryNx->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryNx->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryNy->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryNy->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryDx->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryDx->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryDy->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryDy->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryOffsetX->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryOffsetX->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryOffsetY->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryOffsetY->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryStagger->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryStagger->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_rbGridStartNumberingOpt->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_rbGridStartNumberingOpt->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_radioBoxGridNumberingScheme->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_radioBoxGridNumberingScheme->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryCentreX->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryCentreX->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryCentreY->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryCentreY->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryCircAngle->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryCircAngle->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryCircCount->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryCircCount->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_rbCircStartNumberingOpt->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_rbCircStartNumberingOpt->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_stdButtonsOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnOkClick ), NULL, this ); m_stdButtonsOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnOkClick ), NULL, this );
} }
@ -311,19 +311,19 @@ DIALOG_CREATE_ARRAY_BASE::~DIALOG_CREATE_ARRAY_BASE()
{ {
// Disconnect Events // Disconnect Events
this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_CREATE_ARRAY_BASE::OnClose ) ); this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_CREATE_ARRAY_BASE::OnClose ) );
m_entryNx->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryNx->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryNy->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryNy->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryDx->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryDx->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryDy->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryDy->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryOffsetX->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryOffsetX->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryOffsetY->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryOffsetY->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryStagger->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryStagger->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_rbGridStartNumberingOpt->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_rbGridStartNumberingOpt->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_radioBoxGridNumberingScheme->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_radioBoxGridNumberingScheme->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryCentreX->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryCentreX->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryCentreY->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryCentreY->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryCircAngle->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryCircAngle->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_entryCircCount->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_entryCircCount->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_rbCircStartNumberingOpt->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this ); m_rbCircStartNumberingOpt->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnParameterChanged ), NULL, this );
m_stdButtonsOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnOkClick ), NULL, this ); m_stdButtonsOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_CREATE_ARRAY_BASE::OnOkClick ), NULL, this );

View File

@ -446,8 +446,8 @@
<event name="OnRightUp"></event> <event name="OnRightUp"></event>
<event name="OnSetFocus"></event> <event name="OnSetFocus"></event>
<event name="OnSize"></event> <event name="OnSize"></event>
<event name="OnText"></event> <event name="OnText">OnParameterChanged</event>
<event name="OnTextEnter">OnParameterChanged</event> <event name="OnTextEnter"></event>
<event name="OnTextMaxLen"></event> <event name="OnTextMaxLen"></event>
<event name="OnTextURL"></event> <event name="OnTextURL"></event>
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
@ -626,8 +626,8 @@
<event name="OnRightUp"></event> <event name="OnRightUp"></event>
<event name="OnSetFocus"></event> <event name="OnSetFocus"></event>
<event name="OnSize"></event> <event name="OnSize"></event>
<event name="OnText"></event> <event name="OnText">OnParameterChanged</event>
<event name="OnTextEnter">OnParameterChanged</event> <event name="OnTextEnter"></event>
<event name="OnTextMaxLen"></event> <event name="OnTextMaxLen"></event>
<event name="OnTextURL"></event> <event name="OnTextURL"></event>
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
@ -806,8 +806,8 @@
<event name="OnRightUp"></event> <event name="OnRightUp"></event>
<event name="OnSetFocus"></event> <event name="OnSetFocus"></event>
<event name="OnSize"></event> <event name="OnSize"></event>
<event name="OnText"></event> <event name="OnText">OnParameterChanged</event>
<event name="OnTextEnter">OnParameterChanged</event> <event name="OnTextEnter"></event>
<event name="OnTextMaxLen"></event> <event name="OnTextMaxLen"></event>
<event name="OnTextURL"></event> <event name="OnTextURL"></event>
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
@ -1072,8 +1072,8 @@
<event name="OnRightUp"></event> <event name="OnRightUp"></event>
<event name="OnSetFocus"></event> <event name="OnSetFocus"></event>
<event name="OnSize"></event> <event name="OnSize"></event>
<event name="OnText"></event> <event name="OnText">OnParameterChanged</event>
<event name="OnTextEnter">OnParameterChanged</event> <event name="OnTextEnter"></event>
<event name="OnTextMaxLen"></event> <event name="OnTextMaxLen"></event>
<event name="OnTextURL"></event> <event name="OnTextURL"></event>
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
@ -1338,8 +1338,8 @@
<event name="OnRightUp"></event> <event name="OnRightUp"></event>
<event name="OnSetFocus"></event> <event name="OnSetFocus"></event>
<event name="OnSize"></event> <event name="OnSize"></event>
<event name="OnText"></event> <event name="OnText">OnParameterChanged</event>
<event name="OnTextEnter">OnParameterChanged</event> <event name="OnTextEnter"></event>
<event name="OnTextMaxLen"></event> <event name="OnTextMaxLen"></event>
<event name="OnTextURL"></event> <event name="OnTextURL"></event>
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
@ -1604,8 +1604,8 @@
<event name="OnRightUp"></event> <event name="OnRightUp"></event>
<event name="OnSetFocus"></event> <event name="OnSetFocus"></event>
<event name="OnSize"></event> <event name="OnSize"></event>
<event name="OnText"></event> <event name="OnText">OnParameterChanged</event>
<event name="OnTextEnter">OnParameterChanged</event> <event name="OnTextEnter"></event>
<event name="OnTextMaxLen"></event> <event name="OnTextMaxLen"></event>
<event name="OnTextURL"></event> <event name="OnTextURL"></event>
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
@ -1870,8 +1870,8 @@
<event name="OnRightUp"></event> <event name="OnRightUp"></event>
<event name="OnSetFocus"></event> <event name="OnSetFocus"></event>
<event name="OnSize"></event> <event name="OnSize"></event>
<event name="OnText"></event> <event name="OnText">OnParameterChanged</event>
<event name="OnTextEnter">OnParameterChanged</event> <event name="OnTextEnter"></event>
<event name="OnTextMaxLen"></event> <event name="OnTextMaxLen"></event>
<event name="OnTextURL"></event> <event name="OnTextURL"></event>
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
@ -3937,8 +3937,8 @@
<event name="OnRightUp"></event> <event name="OnRightUp"></event>
<event name="OnSetFocus"></event> <event name="OnSetFocus"></event>
<event name="OnSize"></event> <event name="OnSize"></event>
<event name="OnText"></event> <event name="OnText">OnParameterChanged</event>
<event name="OnTextEnter">OnParameterChanged</event> <event name="OnTextEnter"></event>
<event name="OnTextMaxLen"></event> <event name="OnTextMaxLen"></event>
<event name="OnTextURL"></event> <event name="OnTextURL"></event>
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
@ -4203,8 +4203,8 @@
<event name="OnRightUp"></event> <event name="OnRightUp"></event>
<event name="OnSetFocus"></event> <event name="OnSetFocus"></event>
<event name="OnSize"></event> <event name="OnSize"></event>
<event name="OnText"></event> <event name="OnText">OnParameterChanged</event>
<event name="OnTextEnter">OnParameterChanged</event> <event name="OnTextEnter"></event>
<event name="OnTextMaxLen"></event> <event name="OnTextMaxLen"></event>
<event name="OnTextURL"></event> <event name="OnTextURL"></event>
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
@ -4399,6 +4399,7 @@
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="name">m_circPadNumberingSizer</property> <property name="name">m_circPadNumberingSizer</property>
<property name="orient">wxVERTICAL</property> <property name="orient">wxVERTICAL</property>
<property name="parent">1</property>
<property name="permission">protected</property> <property name="permission">protected</property>
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Mar 9 2016) // C++ code generated with wxFormBuilder (version Jun 21 2016)
// http://www.wxformbuilder.org/ // http://www.wxformbuilder.org/
// //
// PLEASE DO "NOT" EDIT THIS FILE! // PLEASE DO "NOT" EDIT THIS FILE!

View File

@ -41,6 +41,7 @@
#include <wxPcbStruct.h> #include <wxPcbStruct.h>
#include <base_units.h> #include <base_units.h>
#include <project.h> #include <project.h>
#include <board_commit.h>
#include <class_module.h> #include <class_module.h>
#include <class_text_mod.h> #include <class_text_mod.h>
@ -325,10 +326,10 @@ void DIALOG_MODULE_BOARD_EDITOR::InitModeditProperties()
} }
m_ReferenceCopy = new TEXTE_MODULE( NULL ); m_ReferenceCopy = new TEXTE_MODULE( m_CurrentModule->Reference() );
m_ValueCopy = new TEXTE_MODULE( NULL ); m_ReferenceCopy->SetParent( m_CurrentModule );
m_ReferenceCopy->Copy( &m_CurrentModule->Reference() ); m_ValueCopy = new TEXTE_MODULE( m_CurrentModule->Value() );
m_ValueCopy->Copy( &m_CurrentModule->Value() ); m_ValueCopy->SetParent( m_CurrentModule );
m_ReferenceCtrl->SetValue( m_ReferenceCopy->GetText() ); m_ReferenceCtrl->SetValue( m_ReferenceCopy->GetText() );
m_ValueCtrl->SetValue( m_ValueCopy->GetText() ); m_ValueCtrl->SetValue( m_ValueCopy->GetText() );
@ -610,6 +611,9 @@ bool DIALOG_MODULE_BOARD_EDITOR::TransferDataFromWindow()
wxPoint modpos; wxPoint modpos;
wxString msg; wxString msg;
BOARD_COMMIT commit( m_Parent );
commit.Modify( m_CurrentModule );
if( !Validate() || !DIALOG_MODULE_BOARD_EDITOR_BASE::TransferDataFromWindow() || if( !Validate() || !DIALOG_MODULE_BOARD_EDITOR_BASE::TransferDataFromWindow() ||
!m_PanelProperties->TransferDataFromWindow() ) !m_PanelProperties->TransferDataFromWindow() )
{ {
@ -623,10 +627,6 @@ bool DIALOG_MODULE_BOARD_EDITOR::TransferDataFromWindow()
return false; return false;
} }
if( m_CurrentModule->GetFlags() == 0 ) // this is a simple edition, we
// must create an undo entry
m_Parent->SaveCopyInUndoList( m_CurrentModule, UR_CHANGED );
if( m_DC ) if( m_DC )
{ {
m_Parent->GetCanvas()->CrossHairOff( m_DC ); m_Parent->GetCanvas()->CrossHairOff( m_DC );
@ -634,8 +634,10 @@ bool DIALOG_MODULE_BOARD_EDITOR::TransferDataFromWindow()
} }
// Init Fields (should be first, because they can be moved or/and flipped later): // Init Fields (should be first, because they can be moved or/and flipped later):
m_CurrentModule->Reference().Copy( m_ReferenceCopy ); TEXTE_MODULE& reference = m_CurrentModule->Reference();
m_CurrentModule->Value().Copy( m_ValueCopy ); reference = *m_ReferenceCopy;
TEXTE_MODULE& value = m_CurrentModule->Value();
value = *m_ValueCopy;
// Initialize masks clearances // Initialize masks clearances
m_CurrentModule->SetLocalClearance( ValueFromTextCtrl( *m_NetClearanceValueCtrl ) ); m_CurrentModule->SetLocalClearance( ValueFromTextCtrl( *m_NetClearanceValueCtrl ) );
@ -739,7 +741,9 @@ bool DIALOG_MODULE_BOARD_EDITOR::TransferDataFromWindow()
m_CurrentModule->CalculateBoundingBox(); m_CurrentModule->CalculateBoundingBox();
m_Parent->OnModify(); // This is a simple edition, we must create an undo entry
if( m_CurrentModule->GetFlags() == 0 )
commit.Push( _( "Modify module properties" ) );
SetReturnCode( PRM_EDITOR_EDIT_OK ); SetReturnCode( PRM_EDITOR_EDIT_OK );

View File

@ -43,6 +43,7 @@
#include <macros.h> #include <macros.h>
#include <validators.h> #include <validators.h>
#include <kicad_string.h> #include <kicad_string.h>
#include <board_commit.h>
#include <class_module.h> #include <class_module.h>
#include <class_text_mod.h> #include <class_text_mod.h>
@ -165,10 +166,10 @@ void DIALOG_MODULE_MODULE_EDITOR::initModeditProperties()
m_DocCtrl->SetValue( m_currentModule->GetDescription() ); m_DocCtrl->SetValue( m_currentModule->GetDescription() );
m_KeywordCtrl->SetValue( m_currentModule->GetKeywords() ); m_KeywordCtrl->SetValue( m_currentModule->GetKeywords() );
m_referenceCopy = new TEXTE_MODULE( NULL ); m_referenceCopy = new TEXTE_MODULE( m_currentModule->Reference() );
m_valueCopy = new TEXTE_MODULE( NULL ); m_referenceCopy->SetParent( m_currentModule );
m_referenceCopy->Copy( &m_currentModule->Reference() ); m_valueCopy = new TEXTE_MODULE( m_currentModule->Value() );
m_valueCopy->Copy( &m_currentModule->Value() ); m_valueCopy->SetParent( m_currentModule );
m_ReferenceCtrl->SetValue( m_referenceCopy->GetText() ); m_ReferenceCtrl->SetValue( m_referenceCopy->GetText() );
m_ValueCtrl->SetValue( m_valueCopy->GetText() ); m_ValueCtrl->SetValue( m_valueCopy->GetText() );
m_FootprintNameCtrl->SetValue( m_currentModule->GetFPID().Format() ); m_FootprintNameCtrl->SetValue( m_currentModule->GetFPID().Format() );
@ -440,6 +441,7 @@ void DIALOG_MODULE_MODULE_EDITOR::OnCancelClick( wxCommandEvent& event )
void DIALOG_MODULE_MODULE_EDITOR::OnOkClick( wxCommandEvent& event ) void DIALOG_MODULE_MODULE_EDITOR::OnOkClick( wxCommandEvent& event )
{ {
BOARD_COMMIT commit( m_parent );
wxString msg; wxString msg;
// First, test for invalid chars in module name // First, test for invalid chars in module name
@ -465,7 +467,8 @@ void DIALOG_MODULE_MODULE_EDITOR::OnOkClick( wxCommandEvent& event )
return; return;
} }
m_parent->SaveCopyInUndoList( m_currentModule, UR_MODEDIT ); commit.Modify( m_currentModule );
m_currentModule->SetLocked( m_AutoPlaceCtrl->GetSelection() == 1 ); m_currentModule->SetLocked( m_AutoPlaceCtrl->GetSelection() == 1 );
switch( m_AttributsCtrl->GetSelection() ) switch( m_AttributsCtrl->GetSelection() )
@ -493,8 +496,10 @@ void DIALOG_MODULE_MODULE_EDITOR::OnOkClick( wxCommandEvent& event )
m_currentModule->SetFPID( FPID( footprintName ) ); m_currentModule->SetFPID( FPID( footprintName ) );
// Init Fields: // Init Fields:
m_currentModule->Reference().Copy( m_referenceCopy ); TEXTE_MODULE& reference = m_currentModule->Reference();
m_currentModule->Value().Copy( m_valueCopy ); reference = *m_referenceCopy;
TEXTE_MODULE& value = m_currentModule->Value();
value = *m_valueCopy;
// Initialize masks clearances // Initialize masks clearances
m_currentModule->SetLocalClearance( ValueFromTextCtrl( *m_NetClearanceValueCtrl ) ); m_currentModule->SetLocalClearance( ValueFromTextCtrl( *m_NetClearanceValueCtrl ) );
@ -520,7 +525,7 @@ void DIALOG_MODULE_MODULE_EDITOR::OnOkClick( wxCommandEvent& event )
m_currentModule->CalculateBoundingBox(); m_currentModule->CalculateBoundingBox();
m_parent->OnModify(); commit.Push( _( "Modify module properties" ) );
EndModal( 1 ); EndModal( 1 );
} }

View File

@ -41,6 +41,7 @@
#include <wxBasePcbFrame.h> #include <wxBasePcbFrame.h>
#include <base_units.h> #include <base_units.h>
#include <wx/numformatter.h> #include <wx/numformatter.h>
#include <board_commit.h>
#include <class_module.h> #include <class_module.h>
#include <class_text_mod.h> #include <class_text_mod.h>
@ -207,11 +208,13 @@ bool DialogEditModuleText::TransferDataToWindow()
bool DialogEditModuleText::TransferDataFromWindow() bool DialogEditModuleText::TransferDataFromWindow()
{ {
BOARD_COMMIT commit( m_parent );
if( !Validate() || !DialogEditModuleText_base::TransferDataFromWindow() ) if( !Validate() || !DialogEditModuleText_base::TransferDataFromWindow() )
return false; return false;
if( m_module ) if( m_module )
m_parent->SaveCopyInUndoList( m_module, UR_CHANGED ); commit.Modify( m_currentText );
#ifndef USE_WX_OVERLAY #ifndef USE_WX_OVERLAY
if( m_dc ) //Erase old text on screen if( m_dc ) //Erase old text on screen
@ -325,7 +328,7 @@ bool DialogEditModuleText::TransferDataFromWindow()
m_parent->Refresh(); m_parent->Refresh();
#endif #endif
m_parent->OnModify(); commit.Push( _( "Modify module text" ) );
if( m_module ) if( m_module )
m_module->SetLastEditTime(); m_module->SetLastEditTime();

View File

@ -30,6 +30,7 @@ using namespace std::placeholders;
#include <pcbnew.h> #include <pcbnew.h>
#include <wxPcbStruct.h> #include <wxPcbStruct.h>
#include <ratsnest_data.h> #include <ratsnest_data.h>
#include <board_commit.h>
#include <class_board.h> #include <class_board.h>
#include <class_module.h> #include <class_module.h>
@ -108,11 +109,9 @@ void DIALOG_GLOBAL_DELETION::AcceptPcbDelete()
return; return;
BOARD* pcb = m_Parent->GetBoard(); BOARD* pcb = m_Parent->GetBoard();
PICKED_ITEMS_LIST pickersList; BOARD_COMMIT commit( m_Parent );
ITEM_PICKER itemPicker( NULL, UR_DELETED );
BOARD_ITEM* item; BOARD_ITEM* item;
BOARD_ITEM* nextitem; BOARD_ITEM* nextitem;
RN_DATA* ratsnest = pcb->GetRatsnest();
LSET layers_filter = LSET().set(); LSET layers_filter = LSET().set();
@ -128,11 +127,7 @@ void DIALOG_GLOBAL_DELETION::AcceptPcbDelete()
{ {
if( delAll || layers_filter[item->GetLayer()] ) if( delAll || layers_filter[item->GetLayer()] )
{ {
itemPicker.SetItem( item ); commit.Remove( item );
pickersList.PushItem( itemPicker );
pcb->Remove( item );
item->ViewRelease();
ratsnest->Remove( item );
gen_rastnest = true; gen_rastnest = true;
} }
else else
@ -160,13 +155,9 @@ void DIALOG_GLOBAL_DELETION::AcceptPcbDelete()
{ {
nextitem = item->Next(); nextitem = item->Next();
if( delAll || if( delAll || ( item->Type() == PCB_LINE_T && masque_layer[item->GetLayer()] ) )
( item->Type() == PCB_LINE_T && masque_layer[item->GetLayer()] ) )
{ {
itemPicker.SetItem( item ); commit.Remove( item );
pickersList.PushItem( itemPicker );
item->ViewRelease();
item->UnLink();
} }
} }
} }
@ -179,13 +170,9 @@ void DIALOG_GLOBAL_DELETION::AcceptPcbDelete()
{ {
nextitem = item->Next(); nextitem = item->Next();
if( delAll || if( delAll || ( item->Type() == PCB_TEXT_T && del_text_layers[item->GetLayer()] ) )
( item->Type() == PCB_TEXT_T && del_text_layers[item->GetLayer()] ) )
{ {
itemPicker.SetItem( item ); commit.Remove( item );
pickersList.PushItem( itemPicker );
item->ViewRelease();
item->UnLink();
} }
} }
} }
@ -205,13 +192,7 @@ void DIALOG_GLOBAL_DELETION::AcceptPcbDelete()
if( del_fp ) if( del_fp )
{ {
itemPicker.SetItem( item ); commit.Remove( item );
pickersList.PushItem( itemPicker );
static_cast<MODULE*>( item )->RunOnChildren(
std::bind( &KIGFX::VIEW_ITEM::ViewRelease, _1 ) );
ratsnest->Remove( item );
item->ViewRelease();
item->UnLink();
gen_rastnest = true; gen_rastnest = true;
} }
} }
@ -249,17 +230,12 @@ void DIALOG_GLOBAL_DELETION::AcceptPcbDelete()
continue; continue;
} }
itemPicker.SetItem( track ); commit.Remove( track );
pickersList.PushItem( itemPicker );
track->ViewRelease();
ratsnest->Remove( track );
track->UnLink();
gen_rastnest = true; gen_rastnest = true;
} }
} }
if( pickersList.GetCount() ) commit.Push( wxT( "Global delete" ) );
m_Parent->SaveCopyInUndoList( pickersList, UR_DELETED );
if( m_DelMarkers->GetValue() ) if( m_DelMarkers->GetValue() )
pcb->DeleteMARKERs(); pcb->DeleteMARKERs();
@ -268,9 +244,7 @@ void DIALOG_GLOBAL_DELETION::AcceptPcbDelete()
m_Parent->Compile_Ratsnest( NULL, true ); m_Parent->Compile_Ratsnest( NULL, true );
// There is a chance that some of tracks have changed their nets, so rebuild ratsnest from scratch // There is a chance that some of tracks have changed their nets, so rebuild ratsnest from scratch
if( m_Parent->IsGalCanvasActive() ) // TODO necessary? if not, remove rn_data.h header as well
pcb->GetRatsnest()->ProcessBoard(); //if( m_Parent->IsGalCanvasActive() )
//pcb->GetRatsnest()->ProcessBoard();
m_Parent->GetCanvas()->Refresh();
m_Parent->OnModify();
} }

View File

@ -34,6 +34,7 @@
#include <base_units.h> #include <base_units.h>
#include <kicad_string.h> #include <kicad_string.h>
#include <macros.h> #include <macros.h>
#include <board_commit.h>
#include <pcbnew.h> #include <pcbnew.h>
#include <wxPcbStruct.h> #include <wxPcbStruct.h>
@ -134,35 +135,21 @@ void DIALOG_GLOBAL_MODULES_FIELDS_EDITION::OnOKClick( wxCommandEvent& event )
void PCB_EDIT_FRAME::OnResetModuleTextSizes( wxCommandEvent& event ) void PCB_EDIT_FRAME::OnResetModuleTextSizes( wxCommandEvent& event )
{ {
DIALOG_GLOBAL_MODULES_FIELDS_EDITION dlg(this); DIALOG_GLOBAL_MODULES_FIELDS_EDITION dlg( this );
dlg.ShowModal(); dlg.ShowModal();
if( IsGalCanvasActive() )
{
for( MODULE* module = GetBoard()->m_Modules; module; module = module->Next() )
{
module->Value().ViewUpdate();
module->Reference().ViewUpdate();
}
}
m_canvas->Refresh();
} }
void PCB_BASE_FRAME::ResetModuleTextSizes( const wxString & aFilter, bool aRef, void PCB_BASE_FRAME::ResetModuleTextSizes( const wxString & aFilter, bool aRef,
bool aValue, bool aOthers ) bool aValue, bool aOthers )
{ {
MODULE* module; BOARD_COMMIT commit( this );
BOARD_ITEM* boardItem;
ITEM_PICKER itemWrapper( NULL, UR_CHANGED ); int modTextWidth = GetDesignSettings().m_ModuleTextWidth;
PICKED_ITEMS_LIST undoItemList; const wxSize& modTextSize = GetDesignSettings().m_ModuleTextSize;
unsigned int ii;
// Prepare undo list // Prepare undo list
for( module = GetBoard()->m_Modules; module; module = module->Next() ) for( MODULE* module = GetBoard()->m_Modules; module; module = module->Next() )
{ {
itemWrapper.SetItem( module );
if( ! aFilter.IsEmpty() ) if( ! aFilter.IsEmpty() )
{ {
if( ! WildCompareString( aFilter, FROM_UTF8( module->GetFPID().Format().c_str() ), if( ! WildCompareString( aFilter, FROM_UTF8( module->GetFPID().Format().c_str() ),
@ -173,81 +160,50 @@ void PCB_BASE_FRAME::ResetModuleTextSizes( const wxString & aFilter, bool aRef,
if( aRef ) if( aRef )
{ {
TEXTE_MODULE *item = &module->Reference(); TEXTE_MODULE* item = &module->Reference();
if( item->GetSize() != GetDesignSettings().m_ModuleTextSize || if( item->GetSize() != GetDesignSettings().m_ModuleTextSize ||
item->GetThickness() != GetDesignSettings().m_ModuleTextWidth ) item->GetThickness() != GetDesignSettings().m_ModuleTextWidth )
{ {
undoItemList.PushItem( itemWrapper ); commit.Modify( item );
item->SetThickness( modTextWidth );
item->SetSize( modTextSize );
} }
} }
if( aValue ) if( aValue )
{ {
TEXTE_MODULE *item = &module->Value(); TEXTE_MODULE* item = &module->Value();
if( item->GetSize() != GetDesignSettings().m_ModuleTextSize || if( item->GetSize() != GetDesignSettings().m_ModuleTextSize ||
item->GetThickness() != GetDesignSettings().m_ModuleTextWidth ) item->GetThickness() != GetDesignSettings().m_ModuleTextWidth )
{ {
undoItemList.PushItem( itemWrapper ); commit.Modify( item );
item->SetThickness( modTextWidth );
item->SetSize( modTextSize );
} }
} }
if( aOthers ) if( aOthers )
{ {
// Go through all other module text fields // Go through all other module text fields
for( boardItem = module->GraphicalItems(); boardItem; boardItem = boardItem->Next() ) for( BOARD_ITEM* boardItem = module->GraphicalItems(); boardItem; boardItem = boardItem->Next() )
{ {
if( boardItem->Type() == PCB_MODULE_TEXT_T ) if( boardItem->Type() == PCB_MODULE_TEXT_T )
{ {
TEXTE_MODULE *item = static_cast<TEXTE_MODULE*>( boardItem ); TEXTE_MODULE* item = static_cast<TEXTE_MODULE*>( boardItem );
if( item->GetSize() != GetDesignSettings().m_ModuleTextSize if( item->GetSize() != GetDesignSettings().m_ModuleTextSize
|| item->GetThickness() != GetDesignSettings().m_ModuleTextWidth ) || item->GetThickness() != GetDesignSettings().m_ModuleTextWidth )
{ {
undoItemList.PushItem( itemWrapper ); commit.Modify( item );
item->SetThickness( modTextWidth );
item->SetSize( modTextSize );
} }
} }
} }
} }
} }
// Exit if there's nothing to do commit.Push( wxT( "Reset module text size" ) );
if( !undoItemList.GetCount() )
return;
SaveCopyInUndoList( undoItemList, UR_CHANGED );
// Apply changes to modules in the undo list
for( ii = 0; ii < undoItemList.GetCount(); ii++ )
{
module = (MODULE*) undoItemList.GetPickedItem( ii );
if( aRef )
{
module->Reference().SetThickness( GetDesignSettings().m_ModuleTextWidth );
module->Reference().SetSize( GetDesignSettings().m_ModuleTextSize );
}
if( aValue )
{
module->Value().SetThickness( GetDesignSettings().m_ModuleTextWidth );
module->Value().SetSize( GetDesignSettings().m_ModuleTextSize );
}
if( aOthers )
{
for( boardItem = module->GraphicalItems(); boardItem; boardItem = boardItem->Next() )
{
if( boardItem->Type() == PCB_MODULE_TEXT_T )
{
TEXTE_MODULE *item = static_cast<TEXTE_MODULE*>( boardItem );
item->SetThickness( GetDesignSettings().m_ModuleTextWidth );
item->SetSize( GetDesignSettings().m_ModuleTextSize );
}
}
}
}
OnModify();
} }

View File

@ -44,6 +44,7 @@
#include <class_board_design_settings.h> #include <class_board_design_settings.h>
#include <base_units.h> #include <base_units.h>
#include <wx/valnum.h> #include <wx/valnum.h>
#include <board_commit.h>
#include <class_board.h> #include <class_board.h>
#include <class_drawsegment.h> #include <class_drawsegment.h>
@ -227,7 +228,8 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::TransferDataFromWindow()
if( !DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::TransferDataFromWindow() ) if( !DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::TransferDataFromWindow() )
return false; return false;
m_parent->SaveCopyInUndoList( m_item, UR_CHANGED ); BOARD_COMMIT commit( m_parent );
commit.Modify( m_item );
wxString msg; wxString msg;
@ -264,7 +266,7 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::TransferDataFromWindow()
m_item->SetAngle( m_AngleValue * 10.0 ); m_item->SetAngle( m_AngleValue * 10.0 );
} }
m_parent->OnModify(); commit.Push( _( "Modify drawing properties" ) );
if( m_DC ) if( m_DC )
m_item->Draw( m_parent->GetCanvas(), m_DC, GR_OR ); m_item->Draw( m_parent->GetCanvas(), m_DC, GR_OR );

View File

@ -43,6 +43,7 @@
#include <module_editor_frame.h> #include <module_editor_frame.h>
#include <base_units.h> #include <base_units.h>
#include <wx/valnum.h> #include <wx/valnum.h>
#include <board_commit.h>
#include <class_board.h> #include <class_board.h>
#include <class_module.h> #include <class_module.h>
@ -212,6 +213,9 @@ void DIALOG_MODEDIT_FP_BODY_ITEM_PROPERTIES::OnLayerChoice( wxCommandEvent& even
bool DIALOG_MODEDIT_FP_BODY_ITEM_PROPERTIES::TransferDataFromWindow() bool DIALOG_MODEDIT_FP_BODY_ITEM_PROPERTIES::TransferDataFromWindow()
{ {
BOARD_COMMIT commit( m_parent );
commit.Modify( m_module );
if( !DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::TransferDataFromWindow() ) if( !DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::TransferDataFromWindow() )
return false; return false;
@ -223,14 +227,10 @@ bool DIALOG_MODEDIT_FP_BODY_ITEM_PROPERTIES::TransferDataFromWindow()
* confirmation is requested */ * confirmation is requested */
if( !IsOK( NULL, if( !IsOK( NULL,
_( "The graphic item will be on a copper layer. This is very dangerous. Are you sure?" ) ) ) _( "The graphic item will be on a copper layer. This is very dangerous. Are you sure?" ) ) )
return false;; return false;
} }
m_parent->SaveCopyInUndoList( m_module, UR_MODEDIT );
m_module->SetLastEditTime();
wxString msg; wxString msg;
wxPoint coord; wxPoint coord;
msg = m_Center_StartXCtrl->GetValue(); msg = m_Center_StartXCtrl->GetValue();
@ -262,7 +262,8 @@ bool DIALOG_MODEDIT_FP_BODY_ITEM_PROPERTIES::TransferDataFromWindow()
m_item->SetAngle( m_AngleValue * 10.0 ); m_item->SetAngle( m_AngleValue * 10.0 );
} }
m_parent->OnModify(); commit.Push( _( "Modify module graphic item" ) );
m_parent->SetMsgPanel( m_item ); m_parent->SetMsgPanel( m_item );
return true; return true;

View File

@ -38,6 +38,7 @@
#include <wxBasePcbFrame.h> #include <wxBasePcbFrame.h>
#include <pcbcommon.h> #include <pcbcommon.h>
#include <base_units.h> #include <base_units.h>
#include <board_commit.h>
#include <class_board.h> #include <class_board.h>
#include <class_module.h> #include <class_module.h>
@ -117,9 +118,9 @@ DIALOG_PAD_PROPERTIES::DIALOG_PAD_PROPERTIES( PCB_BASE_FRAME* aParent, D_PAD* aP
m_dummyPad = new D_PAD( (MODULE*) NULL ); m_dummyPad = new D_PAD( (MODULE*) NULL );
if( aPad ) if( aPad )
m_dummyPad->Copy( aPad ); *m_dummyPad = *aPad;
else // We are editing a "master" pad, i.e. a template to create new pads else // We are editing a "master" pad, i.e. a template to create new pads
m_dummyPad->Copy( m_padMaster ); *m_dummyPad = *m_padMaster;
// Show the X and Y axis. It is usefull because pad shape can have an offset // Show the X and Y axis. It is usefull because pad shape can have an offset
// or be a complex shape. // or be a complex shape.
@ -921,6 +922,8 @@ bool DIALOG_PAD_PROPERTIES::TransferDataToWindow()
bool DIALOG_PAD_PROPERTIES::TransferDataFromWindow() bool DIALOG_PAD_PROPERTIES::TransferDataFromWindow()
{ {
BOARD_COMMIT commit( m_parent );
if( !wxDialog::TransferDataFromWindow() ) if( !wxDialog::TransferDataFromWindow() )
return false; return false;
@ -940,114 +943,116 @@ bool DIALOG_PAD_PROPERTIES::TransferDataFromWindow()
// m_padMaster is a pattern: ensure there is no net for this pad: // m_padMaster is a pattern: ensure there is no net for this pad:
m_padMaster->SetNetCode( NETINFO_LIST::UNCONNECTED ); m_padMaster->SetNetCode( NETINFO_LIST::UNCONNECTED );
if( m_currentPad ) // Set current Pad parameters if( !m_currentPad ) // Set current Pad parameters
return false;
commit.Modify( m_currentPad );
wxSize size;
MODULE* footprint = m_currentPad->GetParent();
footprint->SetLastEditTime();
// redraw the area where the pad was, without pad (delete pad on screen)
m_currentPad->SetFlags( DO_NOT_DRAW );
m_parent->GetCanvas()->RefreshDrawingRect( m_currentPad->GetBoundingBox() );
m_currentPad->ClearFlags( DO_NOT_DRAW );
// Update values
m_currentPad->SetShape( m_padMaster->GetShape() );
m_currentPad->SetAttribute( m_padMaster->GetAttribute() );
if( m_currentPad->GetPosition() != m_padMaster->GetPosition() )
{ {
wxSize size; m_currentPad->SetPosition( m_padMaster->GetPosition() );
MODULE* footprint = m_currentPad->GetParent(); rastnestIsChanged = true;
m_parent->SaveCopyInUndoList( footprint, UR_CHANGED );
footprint->SetLastEditTime();
// redraw the area where the pad was, without pad (delete pad on screen)
m_currentPad->SetFlags( DO_NOT_DRAW );
m_parent->GetCanvas()->RefreshDrawingRect( m_currentPad->GetBoundingBox() );
m_currentPad->ClearFlags( DO_NOT_DRAW );
// Update values
m_currentPad->SetShape( m_padMaster->GetShape() );
m_currentPad->SetAttribute( m_padMaster->GetAttribute() );
if( m_currentPad->GetPosition() != m_padMaster->GetPosition() )
{
m_currentPad->SetPosition( m_padMaster->GetPosition() );
rastnestIsChanged = true;
}
// compute the pos 0 value, i.e. pad position for footprint with orientation = 0
// i.e. relative to footprint origin (footprint position)
wxPoint pt = m_currentPad->GetPosition() - footprint->GetPosition();
RotatePoint( &pt, -footprint->GetOrientation() );
m_currentPad->SetPos0( pt );
m_currentPad->SetOrientation( m_padMaster->GetOrientation() * isign
+ footprint->GetOrientation() );
m_currentPad->SetSize( m_padMaster->GetSize() );
size = m_padMaster->GetDelta();
size.y *= isign;
m_currentPad->SetDelta( size );
m_currentPad->SetDrillSize( m_padMaster->GetDrillSize() );
m_currentPad->SetDrillShape( m_padMaster->GetDrillShape() );
wxPoint offset = m_padMaster->GetOffset();
offset.y *= isign;
m_currentPad->SetOffset( offset );
m_currentPad->SetPadToDieLength( m_padMaster->GetPadToDieLength() );
if( m_currentPad->GetLayerSet() != m_padMaster->GetLayerSet() )
{
rastnestIsChanged = true;
m_currentPad->SetLayerSet( m_padMaster->GetLayerSet() );
}
if( m_isFlipped )
{
m_currentPad->SetLayerSet( FlipLayerMask( m_currentPad->GetLayerSet() ) );
}
m_currentPad->SetPadName( m_padMaster->GetPadName() );
wxString padNetname;
// For PAD_ATTRIB_HOLE_NOT_PLATED, ensure there is no net name selected
if( m_padMaster->GetAttribute() != PAD_ATTRIB_HOLE_NOT_PLATED )
padNetname = m_PadNetNameCtrl->GetValue();
if( m_currentPad->GetNetname() != padNetname )
{
const NETINFO_ITEM* netinfo = m_board->FindNet( padNetname );
if( !padNetname.IsEmpty() && netinfo == NULL )
{
DisplayError( NULL, _( "Unknown netname, netname not changed" ) );
}
else if( netinfo )
{
rastnestIsChanged = true;
m_currentPad->SetNetCode( netinfo->GetNet() );
}
}
m_currentPad->SetLocalClearance( m_padMaster->GetLocalClearance() );
m_currentPad->SetLocalSolderMaskMargin( m_padMaster->GetLocalSolderMaskMargin() );
m_currentPad->SetLocalSolderPasteMargin( m_padMaster->GetLocalSolderPasteMargin() );
m_currentPad->SetLocalSolderPasteMarginRatio( m_padMaster->GetLocalSolderPasteMarginRatio() );
m_currentPad->SetZoneConnection( m_padMaster->GetZoneConnection() );
m_currentPad->SetThermalWidth( m_padMaster->GetThermalWidth() );
m_currentPad->SetThermalGap( m_padMaster->GetThermalGap() );
m_currentPad->SetRoundRectRadiusRatio( m_padMaster->GetRoundRectRadiusRatio() );
// rounded rect pads with radius ratio = 0 are in fact rect pads.
// So set the right shape (and perhaps issues with a radius = 0)
if( m_currentPad->GetShape() == PAD_SHAPE_ROUNDRECT &&
m_currentPad->GetRoundRectRadiusRatio() == 0.0 )
{
m_currentPad->SetShape( PAD_SHAPE_RECT );
}
footprint->CalculateBoundingBox();
m_parent->SetMsgPanel( m_currentPad );
// redraw the area where the pad was
m_parent->GetCanvas()->RefreshDrawingRect( m_currentPad->GetBoundingBox() );
m_parent->OnModify();
} }
// compute the pos 0 value, i.e. pad position for footprint with orientation = 0
// i.e. relative to footprint origin (footprint position)
wxPoint pt = m_currentPad->GetPosition() - footprint->GetPosition();
RotatePoint( &pt, -footprint->GetOrientation() );
m_currentPad->SetPos0( pt );
m_currentPad->SetOrientation( m_padMaster->GetOrientation() * isign
+ footprint->GetOrientation() );
m_currentPad->SetSize( m_padMaster->GetSize() );
size = m_padMaster->GetDelta();
size.y *= isign;
m_currentPad->SetDelta( size );
m_currentPad->SetDrillSize( m_padMaster->GetDrillSize() );
m_currentPad->SetDrillShape( m_padMaster->GetDrillShape() );
wxPoint offset = m_padMaster->GetOffset();
offset.y *= isign;
m_currentPad->SetOffset( offset );
m_currentPad->SetPadToDieLength( m_padMaster->GetPadToDieLength() );
if( m_currentPad->GetLayerSet() != m_padMaster->GetLayerSet() )
{
rastnestIsChanged = true;
m_currentPad->SetLayerSet( m_padMaster->GetLayerSet() );
}
if( m_isFlipped )
{
m_currentPad->SetLayerSet( FlipLayerMask( m_currentPad->GetLayerSet() ) );
}
m_currentPad->SetPadName( m_padMaster->GetPadName() );
wxString padNetname;
// For PAD_ATTRIB_HOLE_NOT_PLATED, ensure there is no net name selected
if( m_padMaster->GetAttribute() != PAD_ATTRIB_HOLE_NOT_PLATED )
padNetname = m_PadNetNameCtrl->GetValue();
if( m_currentPad->GetNetname() != padNetname )
{
const NETINFO_ITEM* netinfo = m_board->FindNet( padNetname );
if( !padNetname.IsEmpty() && netinfo == NULL )
{
DisplayError( NULL, _( "Unknown netname, netname not changed" ) );
}
else if( netinfo )
{
rastnestIsChanged = true;
m_currentPad->SetNetCode( netinfo->GetNet() );
}
}
m_currentPad->SetLocalClearance( m_padMaster->GetLocalClearance() );
m_currentPad->SetLocalSolderMaskMargin( m_padMaster->GetLocalSolderMaskMargin() );
m_currentPad->SetLocalSolderPasteMargin( m_padMaster->GetLocalSolderPasteMargin() );
m_currentPad->SetLocalSolderPasteMarginRatio( m_padMaster->GetLocalSolderPasteMarginRatio() );
m_currentPad->SetZoneConnection( m_padMaster->GetZoneConnection() );
m_currentPad->SetThermalWidth( m_padMaster->GetThermalWidth() );
m_currentPad->SetThermalGap( m_padMaster->GetThermalGap() );
m_currentPad->SetRoundRectRadiusRatio( m_padMaster->GetRoundRectRadiusRatio() );
// rounded rect pads with radius ratio = 0 are in fact rect pads.
// So set the right shape (and perhaps issues with a radius = 0)
if( m_currentPad->GetShape() == PAD_SHAPE_ROUNDRECT &&
m_currentPad->GetRoundRectRadiusRatio() == 0.0 )
{
m_currentPad->SetShape( PAD_SHAPE_RECT );
}
footprint->CalculateBoundingBox();
m_parent->SetMsgPanel( m_currentPad );
// redraw the area where the pad was
m_parent->GetCanvas()->RefreshDrawingRect( m_currentPad->GetBoundingBox() );
commit.Push( _( "Modify pad" ) );
if( rastnestIsChanged ) // The net ratsnest must be recalculated if( rastnestIsChanged ) // The net ratsnest must be recalculated
m_board->m_Status_Pcb = 0; m_board->m_Status_Pcb = 0;

View File

@ -43,6 +43,7 @@
#include <wx/wx.h> #include <wx/wx.h>
#include <dialog_pcb_text_properties_base.h> #include <dialog_pcb_text_properties_base.h>
#include <class_pcb_layer_box_selector.h> #include <class_pcb_layer_box_selector.h>
#include <board_commit.h>
class PCB_EDIT_FRAME; class PCB_EDIT_FRAME;
@ -188,10 +189,12 @@ bool DIALOG_PCB_TEXT_PROPERTIES::TransferDataToWindow()
bool DIALOG_PCB_TEXT_PROPERTIES::TransferDataFromWindow() bool DIALOG_PCB_TEXT_PROPERTIES::TransferDataFromWindow()
{ {
if( !DIALOG_PCB_TEXT_PROPERTIES_BASE::TransferDataFromWindow() ) if( !DIALOG_PCB_TEXT_PROPERTIES_BASE::TransferDataFromWindow() )
return false; return false;
BOARD_COMMIT commit( m_Parent );
commit.Modify( m_SelectedPCBText );
// Test for acceptable layer. // Test for acceptable layer.
// Incorrect layer can happen for old boards, // Incorrect layer can happen for old boards,
// having texts on edge cut layer for instance // having texts on edge cut layer for instance
@ -206,8 +209,7 @@ bool DIALOG_PCB_TEXT_PROPERTIES::TransferDataFromWindow()
// If no other command in progress, prepare undo command // If no other command in progress, prepare undo command
// (for a command in progress, will be made later, at the completion of command) // (for a command in progress, will be made later, at the completion of command)
if( m_SelectedPCBText->GetFlags() == 0 ) bool pushCommit = ( m_SelectedPCBText->GetFlags() == 0 );
m_Parent->SaveCopyInUndoList( m_SelectedPCBText, UR_CHANGED );
/* set flag in edit to force undo/redo/abort proper operation, /* set flag in edit to force undo/redo/abort proper operation,
* and avoid new calls to SaveCopyInUndoList for the same text * and avoid new calls to SaveCopyInUndoList for the same text
@ -303,9 +305,11 @@ bool DIALOG_PCB_TEXT_PROPERTIES::TransferDataFromWindow()
m_SelectedPCBText->Draw( m_Parent->GetCanvas(), m_DC, GR_OR ); m_SelectedPCBText->Draw( m_Parent->GetCanvas(), m_DC, GR_OR );
} }
#else #else
m_parent->Refresh(); m_Parent->Refresh();
#endif #endif
m_Parent->OnModify();
if( pushCommit )
commit.Push( _( "Change text properties" ) );
return true; return true;
} }

View File

@ -29,6 +29,8 @@
#include <wxPcbStruct.h> #include <wxPcbStruct.h>
#include <confirm.h> #include <confirm.h>
#include <board_commit.h>
DIALOG_TRACK_VIA_PROPERTIES::DIALOG_TRACK_VIA_PROPERTIES( PCB_BASE_FRAME* aParent, const SELECTION& aItems ) : DIALOG_TRACK_VIA_PROPERTIES::DIALOG_TRACK_VIA_PROPERTIES( PCB_BASE_FRAME* aParent, const SELECTION& aItems ) :
DIALOG_TRACK_VIA_PROPERTIES_BASE( aParent ), m_items( aItems ), DIALOG_TRACK_VIA_PROPERTIES_BASE( aParent ), m_items( aItems ),
m_trackStartX( aParent, m_TrackStartXCtrl, m_TrackStartXUnit ), m_trackStartX( aParent, m_TrackStartXCtrl, m_TrackStartXUnit ),
@ -202,7 +204,7 @@ DIALOG_TRACK_VIA_PROPERTIES::DIALOG_TRACK_VIA_PROPERTIES( PCB_BASE_FRAME* aParen
} }
bool DIALOG_TRACK_VIA_PROPERTIES::Apply() bool DIALOG_TRACK_VIA_PROPERTIES::Apply( COMMIT& aCommit )
{ {
if( !check() ) if( !check() )
return false; return false;
@ -214,6 +216,7 @@ bool DIALOG_TRACK_VIA_PROPERTIES::Apply()
for( int i = 0; i < m_items.Size(); ++i ) for( int i = 0; i < m_items.Size(); ++i )
{ {
BOARD_ITEM* item = m_items.Item<BOARD_ITEM>( i ); BOARD_ITEM* item = m_items.Item<BOARD_ITEM>( i );
aCommit.Modify( item );
switch( item->Type() ) switch( item->Type() )
{ {

View File

@ -28,6 +28,8 @@
#include <layers_id_colors_and_visibility.h> #include <layers_id_colors_and_visibility.h>
struct SELECTION; struct SELECTION;
class COMMIT;
class PCB_BASE_FRAME; class PCB_BASE_FRAME;
class DIALOG_TRACK_VIA_PROPERTIES : public DIALOG_TRACK_VIA_PROPERTIES_BASE class DIALOG_TRACK_VIA_PROPERTIES : public DIALOG_TRACK_VIA_PROPERTIES_BASE
@ -36,7 +38,7 @@ public:
DIALOG_TRACK_VIA_PROPERTIES( PCB_BASE_FRAME* aParent, const SELECTION& aItems ); DIALOG_TRACK_VIA_PROPERTIES( PCB_BASE_FRAME* aParent, const SELECTION& aItems );
///> Applies values from the dialog to the selected items. ///> Applies values from the dialog to the selected items.
bool Apply(); bool Apply( COMMIT& aCommit );
private: private:
void onClose( wxCloseEvent& aEvent ); void onClose( wxCloseEvent& aEvent );

View File

@ -19,35 +19,29 @@ DIALOG_UPDATE_PCB::DIALOG_UPDATE_PCB( PCB_EDIT_FRAME* aParent, NETLIST *aNetlist
m_netlist (aNetlist) m_netlist (aNetlist)
{ {
m_messagePanel->SetLabel( _("Changes to be applied:") ); m_messagePanel->SetLabel( _("Changes to be applied:") );
m_messagePanel->SetLazyUpdate ( true ); m_messagePanel->SetLazyUpdate( true );
m_netlist->SortByReference(); m_netlist->SortByReference();
m_btnPerformUpdate->SetFocus(); m_btnPerformUpdate->SetFocus();
m_messagePanel->SetVisibleSeverities( REPORTER::RPT_WARNING | REPORTER::RPT_ERROR | REPORTER::RPT_ACTION ); m_messagePanel->SetVisibleSeverities( REPORTER::RPT_WARNING | REPORTER::RPT_ERROR | REPORTER::RPT_ACTION );
} }
DIALOG_UPDATE_PCB::~DIALOG_UPDATE_PCB() DIALOG_UPDATE_PCB::~DIALOG_UPDATE_PCB()
{ {
} }
void DIALOG_UPDATE_PCB::PerformUpdate( bool aDryRun ) void DIALOG_UPDATE_PCB::PerformUpdate( bool aDryRun )
{ {
m_messagePanel->Clear(); m_messagePanel->Clear();
REPORTER &reporter = m_messagePanel->Reporter(); REPORTER& reporter = m_messagePanel->Reporter();
KIGFX::VIEW* view = m_frame->GetGalCanvas()->GetView(); TOOL_MANAGER* toolManager = m_frame->GetToolManager();
TOOL_MANAGER *toolManager = m_frame->GetToolManager(); BOARD* board = m_frame->GetBoard();
BOARD *board = m_frame->GetBoard();
if( !aDryRun ) if( !aDryRun )
{ {
// Remove old modules
for( MODULE* module = board->m_Modules; module; module = module->Next() )
{
module->RunOnChildren( std::bind( &KIGFX::VIEW::Remove, view, _1 ) );
view->Remove( module );
}
// Clear selection, just in case a selected item has to be removed // Clear selection, just in case a selected item has to be removed
toolManager->RunAction( COMMON_ACTIONS::selectionClear, true ); toolManager->RunAction( COMMON_ACTIONS::selectionClear, true );
@ -57,7 +51,8 @@ void DIALOG_UPDATE_PCB::PerformUpdate( bool aDryRun )
m_netlist->SetFindByTimeStamp( m_matchByTimestamp->GetValue() ); m_netlist->SetFindByTimeStamp( m_matchByTimestamp->GetValue() );
m_netlist->SetReplaceFootprints( true ); m_netlist->SetReplaceFootprints( true );
try { try
{
m_frame->LoadFootprints( *m_netlist, &reporter ); m_frame->LoadFootprints( *m_netlist, &reporter );
} }
catch( IO_ERROR &error ) catch( IO_ERROR &error )
@ -70,14 +65,12 @@ void DIALOG_UPDATE_PCB::PerformUpdate( bool aDryRun )
} }
BOARD_NETLIST_UPDATER updater( m_frame, m_frame->GetBoard() ); BOARD_NETLIST_UPDATER updater( m_frame, m_frame->GetBoard() );
updater.SetReporter ( &reporter ); updater.SetReporter ( &reporter );
updater.SetIsDryRun( aDryRun); updater.SetIsDryRun( aDryRun);
updater.SetLookupByTimestamp( m_matchByTimestamp->GetValue() ); updater.SetLookupByTimestamp( m_matchByTimestamp->GetValue() );
updater.SetDeleteUnusedComponents ( true ); updater.SetDeleteUnusedComponents ( true );
updater.SetReplaceFootprints( true ); updater.SetReplaceFootprints( true );
updater.SetDeleteSinglePadNets ( false ); updater.SetDeleteSinglePadNets( false );
updater.UpdateNetlist( *m_netlist ); updater.UpdateNetlist( *m_netlist );
m_messagePanel->Flush(); m_messagePanel->Flush();
@ -85,30 +78,14 @@ void DIALOG_UPDATE_PCB::PerformUpdate( bool aDryRun )
if( aDryRun ) if( aDryRun )
return; return;
std::vector<MODULE*> newFootprints = updater.GetAddedComponents();
m_frame->OnModify();
m_frame->SetCurItem( NULL ); m_frame->SetCurItem( NULL );
// Reload modules
for( MODULE* module = board->m_Modules; module; module = module->Next() )
{
module->RunOnChildren( std::bind( &KIGFX::VIEW::Add, view, _1 ) );
view->Add( module );
module->ViewUpdate();
}
// Rebuild the board connectivity:
if( m_frame->IsGalCanvasActive() )
board->GetRatsnest()->ProcessBoard();
m_frame->Compile_Ratsnest( NULL, true );
m_frame->SetMsgPanel( board ); m_frame->SetMsgPanel( board );
if( m_frame->IsGalCanvasActive() ) if( m_frame->IsGalCanvasActive() )
{ {
std::vector<MODULE*> newFootprints = updater.GetAddedComponents();
// Place the new modules
m_frame->SpreadFootprints( &newFootprints, false, false, m_frame->GetCrossHairPosition() ); m_frame->SpreadFootprints( &newFootprints, false, false, m_frame->GetCrossHairPosition() );
if( !newFootprints.empty() ) if( !newFootprints.empty() )
@ -117,30 +94,33 @@ void DIALOG_UPDATE_PCB::PerformUpdate( bool aDryRun )
{ {
toolManager->RunAction( COMMON_ACTIONS::selectItem, true, footprint ); toolManager->RunAction( COMMON_ACTIONS::selectItem, true, footprint );
} }
toolManager->InvokeTool( "pcbnew.InteractiveEdit" ); toolManager->InvokeTool( "pcbnew.InteractiveEdit" );
} }
} }
m_btnPerformUpdate->Enable( false ); m_btnPerformUpdate->Enable( false );
m_btnPerformUpdate->SetLabel( _( "Update complete" ) ); m_btnPerformUpdate->SetLabel( _( "Update complete" ) );
m_btnCancel->SetLabel ( _("Close") ); m_btnCancel->SetLabel( _( "Close" ) );
m_btnCancel->SetFocus(); m_btnCancel->SetFocus();
} }
void DIALOG_UPDATE_PCB::OnMatchChange( wxCommandEvent& event ) void DIALOG_UPDATE_PCB::OnMatchChange( wxCommandEvent& event )
{ {
PerformUpdate( true ); PerformUpdate( true );
} }
void DIALOG_UPDATE_PCB::OnCancelClick( wxCommandEvent& event ) void DIALOG_UPDATE_PCB::OnCancelClick( wxCommandEvent& event )
{ {
EndModal( wxID_CANCEL ); EndModal( wxID_CANCEL );
} }
void DIALOG_UPDATE_PCB::OnUpdateClick( wxCommandEvent& event ) void DIALOG_UPDATE_PCB::OnUpdateClick( wxCommandEvent& event )
{ {
m_messagePanel->SetLabel( _("Changes applied to the PCB:") ); m_messagePanel->SetLabel( _( "Changes applied to the PCB:" ) );
PerformUpdate( false ); PerformUpdate( false );
m_btnCancel->SetFocus( ); m_btnCancel->SetFocus();
} }

View File

@ -37,6 +37,7 @@
#include <dialog_helpers.h> #include <dialog_helpers.h>
#include <macros.h> #include <macros.h>
#include <base_units.h> #include <base_units.h>
#include <board_commit.h>
#include <class_board.h> #include <class_board.h>
#include <class_pcb_text.h> #include <class_pcb_text.h>
@ -161,6 +162,8 @@ DIALOG_DIMENSION_EDITOR::DIALOG_DIMENSION_EDITOR( PCB_EDIT_FRAME* aParent,
void DIALOG_DIMENSION_EDITOR::OnOKClick( wxCommandEvent& event ) void DIALOG_DIMENSION_EDITOR::OnOKClick( wxCommandEvent& event )
{ {
BOARD_COMMIT commit( m_parent );
LAYER_ID newlayer = ToLAYER_ID( m_SelLayerBox->GetLayerSelection() ); LAYER_ID newlayer = ToLAYER_ID( m_SelLayerBox->GetLayerSelection() );
if( !m_parent->GetBoard()->IsLayerEnabled( newlayer ) ) if( !m_parent->GetBoard()->IsLayerEnabled( newlayer ) )
@ -177,7 +180,7 @@ void DIALOG_DIMENSION_EDITOR::OnOKClick( wxCommandEvent& event )
} }
#endif #endif
m_parent->SaveCopyInUndoList(m_currentDimension, UR_CHANGED); commit.Modify( m_currentDimension );
if( m_Name->GetValue() != wxEmptyString ) if( m_Name->GetValue() != wxEmptyString )
{ {
@ -228,7 +231,7 @@ void DIALOG_DIMENSION_EDITOR::OnOKClick( wxCommandEvent& event )
m_parent->Refresh(); m_parent->Refresh();
#endif #endif
m_parent->OnModify(); commit.Push( _( "Modifed dimensions properties" ) );
event.Skip(); // ends returning wxID_OK (default behavior) event.Skip(); // ends returning wxID_OK (default behavior)
} }

View File

@ -2622,7 +2622,7 @@ void EAGLE_PLUGIN::loadSignals( CPTREE& aSignals )
const string& nname = net->second.get<string>( "<xmlattr>.name" ); const string& nname = net->second.get<string>( "<xmlattr>.name" );
wxString netName = FROM_UTF8( nname.c_str() ); wxString netName = FROM_UTF8( nname.c_str() );
m_board->AppendNet( new NETINFO_ITEM( m_board, netName, netCode ) ); m_board->Add( new NETINFO_ITEM( m_board, netName, netCode ) );
m_xpath->Value( nname.c_str() ); m_xpath->Value( nname.c_str() );

View File

@ -163,7 +163,7 @@ void FOOTPRINT_EDIT_FRAME::Edit_Edge_Width( EDGE_MODULE* aEdge )
{ {
MODULE* module = GetBoard()->m_Modules; MODULE* module = GetBoard()->m_Modules;
SaveCopyInUndoList( module, UR_MODEDIT ); SaveCopyInUndoList( module, UR_CHANGED );
if( aEdge == NULL ) if( aEdge == NULL )
{ {
@ -225,7 +225,7 @@ void FOOTPRINT_EDIT_FRAME::Edit_Edge_Layer( EDGE_MODULE* aEdge )
if( aEdge && (aEdge->GetLayer() != new_layer) ) if( aEdge && (aEdge->GetLayer() != new_layer) )
{ {
if( ! modified ) // save only once if( ! modified ) // save only once
SaveCopyInUndoList( module, UR_MODEDIT ); SaveCopyInUndoList( module, UR_CHANGED );
aEdge->SetLayer( new_layer ); aEdge->SetLayer( new_layer );
modified = true; modified = true;
} }
@ -233,7 +233,7 @@ void FOOTPRINT_EDIT_FRAME::Edit_Edge_Layer( EDGE_MODULE* aEdge )
} }
else if( aEdge->GetLayer() != new_layer ) else if( aEdge->GetLayer() != new_layer )
{ {
SaveCopyInUndoList( module, UR_MODEDIT ); SaveCopyInUndoList( module, UR_CHANGED );
aEdge->SetLayer( new_layer ); aEdge->SetLayer( new_layer );
modified = true; modified = true;
} }
@ -330,7 +330,7 @@ EDGE_MODULE* FOOTPRINT_EDIT_FRAME::Begin_Edge_Module( EDGE_MODULE* aEdge,
if( aEdge == NULL ) // Start a new edge item if( aEdge == NULL ) // Start a new edge item
{ {
SaveCopyInUndoList( module, UR_MODEDIT ); SaveCopyInUndoList( module, UR_CHANGED );
aEdge = new EDGE_MODULE( module ); aEdge = new EDGE_MODULE( module );
MoveVector.x = MoveVector.y = 0; MoveVector.x = MoveVector.y = 0;

View File

@ -136,7 +136,7 @@ void PCB_EDIT_FRAME::StartMoveTextePcb( TEXTE_PCB* aTextePcb, wxDC* aDC, bool aE
// if it is an existing item: prepare a copy to undo/abort command // if it is an existing item: prepare a copy to undo/abort command
if( !aTextePcb->IsNew() ) if( !aTextePcb->IsNew() )
s_TextCopy.Copy( aTextePcb ); s_TextCopy = *aTextePcb;
aTextePcb->SetFlags( IS_MOVED ); aTextePcb->SetFlags( IS_MOVED );
SetMsgPanel( aTextePcb ); SetMsgPanel( aTextePcb );
@ -192,7 +192,7 @@ TEXTE_PCB* PCB_EDIT_FRAME::CreateTextePcb( wxDC* aDC, TEXTE_PCB* aText )
if( aText ) if( aText )
{ {
textePcb->Copy( aText ); *textePcb = *aText;
GetBoard()->Add( textePcb ); GetBoard()->Add( textePcb );
textePcb->SetFlags( IS_NEW ); textePcb->SetFlags( IS_NEW );
if( aDC ) if( aDC )

View File

@ -243,7 +243,7 @@ void PCB_BASE_FRAME::PlaceTexteModule( TEXTE_MODULE* Text, wxDC* DC )
if( IsType( FRAME_PCB ) ) if( IsType( FRAME_PCB ) )
SaveCopyInUndoList( Module, UR_CHANGED ); SaveCopyInUndoList( Module, UR_CHANGED );
else else
SaveCopyInUndoList( Module, UR_MODEDIT ); SaveCopyInUndoList( Module, UR_CHANGED );
Text->SetOrientation( tmp ); Text->SetOrientation( tmp );

View File

@ -245,7 +245,7 @@ bool InvokeDXFDialogModuleImport( PCB_BASE_FRAME* aCaller, MODULE* aModule )
{ {
const std::list<BOARD_ITEM*>& list = dlg.GetImportedItems(); const std::list<BOARD_ITEM*>& list = dlg.GetImportedItems();
aCaller->SaveCopyInUndoList( aModule, UR_MODEDIT ); aCaller->SaveCopyInUndoList( aModule, UR_CHANGED );
aCaller->OnModify(); aCaller->OnModify();
std::list<BOARD_ITEM*>::const_iterator it, itEnd; std::list<BOARD_ITEM*>::const_iterator it, itEnd;
@ -264,7 +264,6 @@ bool InvokeDXFDialogModuleImport( PCB_BASE_FRAME* aCaller, MODULE* aModule )
converted = new EDGE_MODULE( aModule ); converted = new EDGE_MODULE( aModule );
*static_cast<DRAWSEGMENT*>( converted ) = *static_cast<DRAWSEGMENT*>( item ); *static_cast<DRAWSEGMENT*>( converted ) = *static_cast<DRAWSEGMENT*>( item );
aModule->Add( converted ); aModule->Add( converted );
static_cast<EDGE_MODULE*>( converted )->SetLocalCoord();
delete item; delete item;
break; break;
} }
@ -274,7 +273,6 @@ bool InvokeDXFDialogModuleImport( PCB_BASE_FRAME* aCaller, MODULE* aModule )
converted = new TEXTE_MODULE( aModule ); converted = new TEXTE_MODULE( aModule );
*static_cast<TEXTE_PCB*>( converted ) = *static_cast<TEXTE_PCB*>( item ); *static_cast<TEXTE_PCB*>( converted ) = *static_cast<TEXTE_PCB*>( item );
aModule->Add( converted ); aModule->Add( converted );
static_cast<TEXTE_MODULE*>( converted )->SetLocalCoord();
delete item; delete item;
break; break;
} }

View File

@ -2080,7 +2080,7 @@ void LEGACY_PLUGIN::loadNETINFO_ITEM()
// if it is not the net 0, or if the net 0 does not exists. // if it is not the net 0, or if the net 0 does not exists.
if( net && ( net->GetNet() > 0 || m_board->FindNet( 0 ) == NULL ) ) if( net && ( net->GetNet() > 0 || m_board->FindNet( 0 ) == NULL ) )
{ {
m_board->AppendNet( net ); m_board->Add( net );
// Be sure we have room to store the net in m_netCodes // Be sure we have room to store the net in m_netCodes
if( (int)m_netCodes.size() <= netCode ) if( (int)m_netCodes.size() <= netCode )

View File

@ -40,6 +40,7 @@
#include <macros.h> #include <macros.h>
#include <invoke_pcb_dialog.h> #include <invoke_pcb_dialog.h>
#include <class_pcb_layer_widget.h> #include <class_pcb_layer_widget.h>
#include <board_commit.h>
#include <class_board.h> #include <class_board.h>
#include <class_module.h> #include <class_module.h>
@ -436,66 +437,42 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
} }
m_toolManager->RunAction( COMMON_ACTIONS::selectionClear, true ); m_toolManager->RunAction( COMMON_ACTIONS::selectionClear, true );
pcbframe->GetToolManager()->RunAction( COMMON_ACTIONS::selectionClear, true );
BOARD_COMMIT commit( pcbframe );
// Create the "new" module // Create the "new" module
MODULE* newmodule = new MODULE( *module_in_edit ); MODULE* newmodule = new MODULE( *module_in_edit );
newmodule->SetParent( mainpcb ); newmodule->SetParent( mainpcb );
newmodule->SetLink( 0 ); newmodule->SetLink( 0 );
// Put the footprint in the main pcb linked list.
mainpcb->Add( newmodule );
if( source_module ) // this is an update command if( source_module ) // this is an update command
{ {
// In the main board, // In the main board,
// the new module replace the old module (pos, orient, ref, value // the new module replace the old module (pos, orient, ref, value
// and connexions are kept) // and connexions are kept)
// and the source_module (old module) is deleted // and the source_module (old module) is deleted
PICKED_ITEMS_LIST pickList; pcbframe->Exchange_Module( source_module, newmodule, commit );
if( pcbframe->IsGalCanvasActive() )
{
KIGFX::VIEW* view = pcbframe->GetGalCanvas()->GetView();
source_module->RunOnChildren( std::bind( &KIGFX::VIEW::Remove, view,
std::placeholders::_1 ) );
view->Remove( source_module );
}
pcbframe->Exchange_Module( source_module, newmodule, &pickList );
newmodule->SetTimeStamp( module_in_edit->GetLink() ); newmodule->SetTimeStamp( module_in_edit->GetLink() );
commit.Push( wxT( "Update module" ) );
if( pickList.GetCount() )
pcbframe->SaveCopyInUndoList( pickList, UR_UNSPECIFIED );
} }
else // This is an insert command else // This is an insert command
{ {
wxPoint cursor_pos = pcbframe->GetCrossHairPosition(); wxPoint cursor_pos = pcbframe->GetCrossHairPosition();
commit.Add( newmodule );
pcbframe->SetCrossHairPosition( wxPoint( 0, 0 ) ); pcbframe->SetCrossHairPosition( wxPoint( 0, 0 ) );
pcbframe->PlaceModule( newmodule, NULL ); pcbframe->PlaceModule( newmodule, NULL );
newmodule->SetPosition( wxPoint( 0, 0 ) ); newmodule->SetPosition( wxPoint( 0, 0 ) );
pcbframe->SetCrossHairPosition( cursor_pos ); pcbframe->SetCrossHairPosition( cursor_pos );
newmodule->SetTimeStamp( GetNewTimeStamp() ); newmodule->SetTimeStamp( GetNewTimeStamp() );
pcbframe->SaveCopyInUndoList( newmodule, UR_NEW ); commit.Push( wxT( "Insert module" ) );
} }
newmodule->ClearFlags(); newmodule->ClearFlags();
GetScreen()->ClrModify(); GetScreen()->ClrModify();
pcbframe->SetCurItem( NULL ); pcbframe->SetCurItem( NULL );
// @todo LEGACY should be unnecessary
mainpcb->m_Status_Pcb = 0; mainpcb->m_Status_Pcb = 0;
if( pcbframe->IsGalCanvasActive() )
{
RN_DATA* ratsnest = pcbframe->GetBoard()->GetRatsnest();
ratsnest->Update( newmodule );
ratsnest->Recalculate();
KIGFX::VIEW* view = pcbframe->GetGalCanvas()->GetView();
newmodule->RunOnChildren( std::bind( &KIGFX::VIEW::Add, view,
std::placeholders::_1 ) );
view->Add( newmodule );
pcbframe->GetGalCanvas()->ForceRefresh();
}
} }
break; break;
@ -651,7 +628,7 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
break; break;
case ID_POPUP_PCB_DELETE_PAD: case ID_POPUP_PCB_DELETE_PAD:
SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); SaveCopyInUndoList( GetBoard()->m_Modules, UR_CHANGED );
DeletePad( (D_PAD*) GetScreen()->GetCurItem(), false ); DeletePad( (D_PAD*) GetScreen()->GetCurItem(), false );
SetCurItem( NULL ); SetCurItem( NULL );
m_canvas->MoveCursorToCrossHair(); m_canvas->MoveCursorToCrossHair();
@ -674,13 +651,13 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
break; break;
case ID_POPUP_PCB_IMPORT_PAD_SETTINGS: case ID_POPUP_PCB_IMPORT_PAD_SETTINGS:
SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); SaveCopyInUndoList( GetBoard()->m_Modules, UR_CHANGED );
m_canvas->MoveCursorToCrossHair(); m_canvas->MoveCursorToCrossHair();
Import_Pad_Settings( (D_PAD*) GetScreen()->GetCurItem(), true ); Import_Pad_Settings( (D_PAD*) GetScreen()->GetCurItem(), true );
break; break;
case ID_POPUP_PCB_GLOBAL_IMPORT_PAD_SETTINGS: case ID_POPUP_PCB_GLOBAL_IMPORT_PAD_SETTINGS:
SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); SaveCopyInUndoList( GetBoard()->m_Modules, UR_CHANGED );
// Calls the global change dialog: // Calls the global change dialog:
DlgGlobalChange_PadSettings( (D_PAD*) GetScreen()->GetCurItem() ); DlgGlobalChange_PadSettings( (D_PAD*) GetScreen()->GetCurItem() );
m_canvas->MoveCursorToCrossHair(); m_canvas->MoveCursorToCrossHair();
@ -707,7 +684,7 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
break; break;
case ID_POPUP_PCB_DELETE_TEXTMODULE: case ID_POPUP_PCB_DELETE_TEXTMODULE:
SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); SaveCopyInUndoList( GetBoard()->m_Modules, UR_CHANGED );
DeleteTextModule( static_cast<TEXTE_MODULE*>( GetScreen()->GetCurItem() ) ); DeleteTextModule( static_cast<TEXTE_MODULE*>( GetScreen()->GetCurItem() ) );
SetCurItem( NULL ); SetCurItem( NULL );
m_canvas->MoveCursorToCrossHair(); m_canvas->MoveCursorToCrossHair();
@ -765,7 +742,7 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
break; break;
case ID_POPUP_PCB_DELETE_EDGE: case ID_POPUP_PCB_DELETE_EDGE:
SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); SaveCopyInUndoList( GetBoard()->m_Modules, UR_CHANGED );
m_canvas->MoveCursorToCrossHair(); m_canvas->MoveCursorToCrossHair();
RemoveStruct( GetScreen()->GetCurItem() ); RemoveStruct( GetScreen()->GetCurItem() );
SetCurItem( NULL ); SetCurItem( NULL );
@ -774,7 +751,7 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
case ID_MODEDIT_MODULE_ROTATE: case ID_MODEDIT_MODULE_ROTATE:
case ID_MODEDIT_MODULE_MIRROR: case ID_MODEDIT_MODULE_MIRROR:
case ID_MODEDIT_MODULE_MOVE_EXACT: case ID_MODEDIT_MODULE_MOVE_EXACT:
SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); SaveCopyInUndoList( GetBoard()->m_Modules, UR_CHANGED );
Transform( (MODULE*) GetScreen()->GetCurItem(), id ); Transform( (MODULE*) GetScreen()->GetCurItem(), id );
m_canvas->Refresh(); m_canvas->Refresh();
break; break;
@ -870,7 +847,7 @@ void FOOTPRINT_EDIT_FRAME::moveExact()
if( ret == wxID_OK ) if( ret == wxID_OK )
{ {
SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); SaveCopyInUndoList( GetBoard()->m_Modules, UR_CHANGED );
BOARD_ITEM* item = GetScreen()->GetCurItem(); BOARD_ITEM* item = GetScreen()->GetCurItem();

View File

@ -61,7 +61,7 @@ void FOOTPRINT_EDIT_FRAME::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
break; break;
case PCB_MODULE_EDGE_T: case PCB_MODULE_EDGE_T:
SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); SaveCopyInUndoList( GetBoard()->m_Modules, UR_CHANGED );
Place_EdgeMod( static_cast<EDGE_MODULE*>( item ) ); Place_EdgeMod( static_cast<EDGE_MODULE*>( item ) );
break; break;
@ -147,7 +147,7 @@ void FOOTPRINT_EDIT_FRAME::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
if( item && item->Type() != PCB_MODULE_T ) // Cannot delete the module itself if( item && item->Type() != PCB_MODULE_T ) // Cannot delete the module itself
{ {
SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); SaveCopyInUndoList( GetBoard()->m_Modules, UR_CHANGED );
RemoveStruct( item ); RemoveStruct( item );
SetCurItem( NULL ); SetCurItem( NULL );
} }
@ -162,7 +162,7 @@ void FOOTPRINT_EDIT_FRAME::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
|| (module->GetFlags() != 0) ) || (module->GetFlags() != 0) )
break; break;
SaveCopyInUndoList( module, UR_MODEDIT ); SaveCopyInUndoList( module, UR_CHANGED );
// set the new relative internal local coordinates of footprint items // set the new relative internal local coordinates of footprint items
wxPoint moveVector = module->GetPosition() - GetCrossHairPosition(); wxPoint moveVector = module->GetPosition() - GetCrossHairPosition();
@ -187,14 +187,14 @@ void FOOTPRINT_EDIT_FRAME::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
if( GetBoard()->m_Modules == NULL ) if( GetBoard()->m_Modules == NULL )
break; break;
SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); SaveCopyInUndoList( GetBoard()->m_Modules, UR_CHANGED );
CreateTextModule( GetBoard()->m_Modules, DC ); CreateTextModule( GetBoard()->m_Modules, DC );
break; break;
case ID_MODEDIT_PAD_TOOL: case ID_MODEDIT_PAD_TOOL:
if( GetBoard()->m_Modules ) if( GetBoard()->m_Modules )
{ {
SaveCopyInUndoList( GetBoard()->m_Modules, UR_MODEDIT ); SaveCopyInUndoList( GetBoard()->m_Modules, UR_CHANGED );
AddPad( GetBoard()->m_Modules, true ); AddPad( GetBoard()->m_Modules, true );
} }

View File

@ -1,176 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2007-2014 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2012 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
*/
#include <functional>
using namespace std::placeholders;
#include <fctsys.h>
#include <class_drawpanel.h>
#include <class_draw_panel_gal.h>
#include <tool/tool_manager.h>
#include <wxPcbStruct.h>
#include <class_board.h>
#include <class_module.h>
#include <pcbnew.h>
#include <protos.h>
#include <module_editor_frame.h>
void FOOTPRINT_EDIT_FRAME::SaveCopyInUndoList( BOARD_ITEM* aItem,
UNDO_REDO_T aTypeCommand,
const wxPoint& aTransformPoint )
{
EDA_ITEM* item;
MODULE* CopyItem;
PICKED_ITEMS_LIST* lastcmd;
CopyItem = new MODULE( *( (MODULE*) aItem ) );
CopyItem->SetParent( GetBoard() );
lastcmd = new PICKED_ITEMS_LIST();
ITEM_PICKER wrapper( CopyItem, UR_MODEDIT );
lastcmd->PushItem( wrapper );
GetScreen()->PushCommandToUndoList( lastcmd );
/* Clear current flags (which can be temporary set by a current edit command) */
for( item = CopyItem->GraphicalItems(); item != NULL; item = item->Next() )
item->ClearFlags();
for( D_PAD* pad = CopyItem->Pads(); pad; pad = pad->Next() )
pad->ClearFlags();
CopyItem->Reference().ClearFlags();
CopyItem->Value().ClearFlags();
/* Clear redo list, because after new save there is no redo to do */
GetScreen()->ClearUndoORRedoList( GetScreen()->m_RedoList );
}
void FOOTPRINT_EDIT_FRAME::SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList,
UNDO_REDO_T aTypeCommand,
const wxPoint& aTransformPoint )
{
assert( aItemsList.GetPickedItem( 0 )->GetParent()->Type() == PCB_MODULE_T );
MODULE* owner = static_cast<MODULE*>( aItemsList.GetPickedItem( 0 )->GetParent() );
#ifndef NDEBUG
// All items should have the same parent (MODULE) to make undo/redo entry valid
for( unsigned int i = 0; i < aItemsList.GetCount(); ++i )
assert( aItemsList.GetPickedItem( i )->GetParent() == owner );
#endif /* not NDEBUG */
SaveCopyInUndoList( owner, aTypeCommand, aTransformPoint );
}
void FOOTPRINT_EDIT_FRAME::RestoreCopyFromRedoList( wxCommandEvent& aEvent )
{
if( GetScreen()->GetRedoCommandCount() <= 0 )
return;
// Inform tools that undo command was issued
TOOL_EVENT event( TC_MESSAGE, TA_UNDO_REDO, AS_GLOBAL );
m_toolManager->ProcessEvent( event );
// Save current module state in undo list
PICKED_ITEMS_LIST* lastcmd = new PICKED_ITEMS_LIST();
MODULE* module = GetBoard()->m_Modules.PopFront();
ITEM_PICKER wrapper( module, UR_MODEDIT );
KIGFX::VIEW* view = GetGalCanvas()->GetView();
lastcmd->PushItem( wrapper );
GetScreen()->PushCommandToUndoList( lastcmd );
view->Remove( module );
module->RunOnChildren( std::bind( &KIGFX::VIEW::Remove, view, _1 ) );
// Retrieve last module state from undo list
lastcmd = GetScreen()->PopCommandFromRedoList();
wrapper = lastcmd->PopItem();
module = (MODULE*) wrapper.GetItem();
delete lastcmd;
if( module )
{
GetBoard()->Add( module );
GetGalCanvas()->GetView()->Add( module );
module->RunOnChildren( std::bind( &KIGFX::VIEW::Add, view, _1 ) );
module->ViewUpdate();
}
SetCurItem( NULL );
OnModify();
m_canvas->Refresh();
}
void FOOTPRINT_EDIT_FRAME::RestoreCopyFromUndoList( wxCommandEvent& aEvent )
{
if( UndoRedoBlocked() )
return;
if( GetScreen()->GetUndoCommandCount() <= 0 )
return;
// Inform tools that undo command was issued
TOOL_EVENT event( TC_MESSAGE, TA_UNDO_REDO, AS_GLOBAL );
m_toolManager->ProcessEvent( event );
if( UndoRedoBlocked() )
return;
// Save current module state in redo list
PICKED_ITEMS_LIST* lastcmd = new PICKED_ITEMS_LIST();
MODULE* module = GetBoard()->m_Modules.PopFront();
ITEM_PICKER wrapper( module, UR_MODEDIT );
KIGFX::VIEW* view = GetGalCanvas()->GetView();
lastcmd->PushItem( wrapper );
GetScreen()->PushCommandToRedoList( lastcmd );
view->Remove( module );
module->RunOnChildren( std::bind( &KIGFX::VIEW::Remove, view, _1 ) );
// Retrieve last module state from undo list
lastcmd = GetScreen()->PopCommandFromUndoList();
wrapper = lastcmd->PopItem();
module = (MODULE*) wrapper.GetItem();
delete lastcmd;
if( module )
{
GetBoard()->Add( module, ADD_APPEND );
view->Add( module );
module->RunOnChildren( std::bind( &KIGFX::VIEW::Add, view, _1 ) );
module->ViewUpdate();
}
SetCurItem( NULL );
OnModify();
m_canvas->Refresh();
}

View File

@ -54,6 +54,9 @@ public:
*/ */
static const wxChar* GetFootprintEditorFrameName(); static const wxChar* GetFootprintEditorFrameName();
///> @copydoc PCB_BASE_FRAME::GetModel()
BOARD_ITEM_CONTAINER* GetModel() const override;
BOARD_DESIGN_SETTINGS& GetDesignSettings() const; // overload PCB_BASE_FRAME, get parent's BOARD_DESIGN_SETTINGS& GetDesignSettings() const; // overload PCB_BASE_FRAME, get parent's
void SetDesignSettings( const BOARD_DESIGN_SETTINGS& aSettings ); // overload void SetDesignSettings( const BOARD_DESIGN_SETTINGS& aSettings ); // overload
@ -267,50 +270,6 @@ public:
BOARD_ITEM* ModeditLocateAndDisplay( int aHotKeyCode = 0 ); BOARD_ITEM* ModeditLocateAndDisplay( int aHotKeyCode = 0 );
/* Undo and redo functions */
/**
* Function SaveCopyInUndoList.
* Creates a new entry in undo list of commands.
* add a picker to handle aItemToCopy
* @param aItem = the board item modified by the command to undo
* @param aTypeCommand = command type (see enum UNDO_REDO_T)
* @param aTransformPoint = the reference point of the transformation, for
* commands like move
*/
virtual void SaveCopyInUndoList( BOARD_ITEM* aItem,
UNDO_REDO_T aTypeCommand,
const wxPoint& aTransformPoint = wxPoint( 0, 0 ) );
/**
* Function SaveCopyInUndoList (overloaded).
* Creates a new entry in undo list of commands.
* add a list of pickers to handle a list of items
* @param aItemsList = the list of items modified by the command to undo
* @param aTypeCommand = command type (see enum UNDO_REDO_T)
* @param aTransformPoint = the reference point of the transformation, for
* commands like move
*/
virtual void SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList,
UNDO_REDO_T aTypeCommand,
const wxPoint& aTransformPoint = wxPoint( 0, 0 ) );
/**
* Function RestoreCopyFromUndoList
* performs an undo operation on the last edition:
* - Place the current edited library component in Redo list
* - Get old version of the current edited library component
*/
void RestoreCopyFromUndoList( wxCommandEvent& aEvent );
/**
* Function RestoreCopyFromRedoList
* performs a redo operation on the the last edition:
* - Place the current edited library component in undo list
* - Get old version of the current edited library component
*/
void RestoreCopyFromRedoList( wxCommandEvent& aEvent );
/// Return the current library nickname. /// Return the current library nickname.
const wxString GetCurrentLib() const; const wxString GetCurrentLib() const;

View File

@ -350,6 +350,12 @@ FOOTPRINT_EDIT_FRAME::~FOOTPRINT_EDIT_FRAME()
} }
BOARD_ITEM_CONTAINER* FOOTPRINT_EDIT_FRAME::GetModel() const
{
return GetBoard()->m_Modules;
}
const wxString FOOTPRINT_EDIT_FRAME::getLibPath() const wxString FOOTPRINT_EDIT_FRAME::getLibPath()
{ {
try try
@ -948,13 +954,12 @@ void FOOTPRINT_EDIT_FRAME::setupTools()
m_toolManager->RegisterTool( new PLACEMENT_TOOL ); m_toolManager->RegisterTool( new PLACEMENT_TOOL );
m_toolManager->RegisterTool( new PICKER_TOOL ); m_toolManager->RegisterTool( new PICKER_TOOL );
m_toolManager->GetTool<SELECTION_TOOL>()->EditModules( true ); m_toolManager->GetTool<SELECTION_TOOL>()->SetEditModules( true );
m_toolManager->GetTool<EDIT_TOOL>()->EditModules( true ); m_toolManager->GetTool<EDIT_TOOL>()->SetEditModules( true );
m_toolManager->GetTool<DRAWING_TOOL>()->EditModules( true ); m_toolManager->GetTool<DRAWING_TOOL>()->SetEditModules( true );
m_toolManager->ResetTools( TOOL_BASE::RUN ); m_toolManager->ResetTools( TOOL_BASE::RUN );
m_toolManager->InvokeTool( "pcbnew.InteractiveSelection" ); m_toolManager->InvokeTool( "pcbnew.InteractiveSelection" );
} }

View File

@ -52,7 +52,7 @@ void PCB_BASE_FRAME::Export_Pad_Settings( D_PAD* aPad )
D_PAD& mp = GetDesignSettings().m_Pad_Master; D_PAD& mp = GetDesignSettings().m_Pad_Master;
// Copy all settings. Some of them are not used, but they break anything // Copy all settings. Some of them are not used, but they break anything
mp.Copy( aPad ); mp = *aPad;
// The pad orientation, for historical reasons is the // The pad orientation, for historical reasons is the
// pad rotation + parent rotation. // pad rotation + parent rotation.
// store only the pad rotation. // store only the pad rotation.

View File

@ -925,7 +925,7 @@ void PCB::AddToBoard()
{ {
net = m_pcbNetlist[i]; net = m_pcbNetlist[i];
m_board->AppendNet( new NETINFO_ITEM( m_board, net->m_name, net->m_netCode ) ); m_board->Add( new NETINFO_ITEM( m_board, net->m_name, net->m_netCode ) );
} }
for( i = 0; i < (int) m_pcbComponents.GetCount(); i++ ) for( i = 0; i < (int) m_pcbComponents.GetCount(); i++ )

View File

@ -278,7 +278,7 @@ void PCB_PAD::AddToModule( MODULE* aModule, int aRotation, bool aEncapsulatedPad
{ {
// It is a new net // It is a new net
netinfo = new NETINFO_ITEM( m_board, m_net ); netinfo = new NETINFO_ITEM( m_board, m_net );
m_board->AppendNet( netinfo ); m_board->Add( netinfo );
} }
pad->SetNetCode( netinfo->GetNet() ); pad->SetNetCode( netinfo->GetNet() );

View File

@ -27,6 +27,8 @@
#include <wxBasePcbFrame.h> #include <wxBasePcbFrame.h>
class BOARD_ITEM_CONTAINER;
/** /**
* Common, abstract interface for edit frames. * Common, abstract interface for edit frames.
*/ */
@ -42,6 +44,12 @@ public:
virtual ~PCB_BASE_EDIT_FRAME() {}; virtual ~PCB_BASE_EDIT_FRAME() {};
/**
* Function GetModel()
* returns the primary data model.
*/
virtual BOARD_ITEM_CONTAINER* GetModel() const = 0;
/** /**
* Function CreateNewLibrary * Function CreateNewLibrary
* prompts user for a library path, then creates a new footprint library at that * prompts user for a library path, then creates a new footprint library at that
@ -61,26 +69,62 @@ public:
*/ */
virtual void OnEditItemRequest( wxDC* aDC, BOARD_ITEM* aItem ) = 0; virtual void OnEditItemRequest( wxDC* aDC, BOARD_ITEM* aItem ) = 0;
// Undo buffer handling
/**
* Function SaveCopyInUndoList
* Creates a new entry in undo list of commands.
* add a picker to handle aItemToCopy
* @param aItemToCopy = the board item modified by the command to undo
* @param aTypeCommand = command type (see enum UNDO_REDO_T)
* @param aTransformPoint = the reference point of the transformation, for
* commands like move
*/
void SaveCopyInUndoList( BOARD_ITEM* aItemToCopy, UNDO_REDO_T aTypeCommand,
const wxPoint& aTransformPoint = wxPoint( 0, 0 ) ) override;
/**
* Function SaveCopyInUndoList
* Creates a new entry in undo list of commands.
* add a list of pickers to handle a list of items
* @param aItemsList = the list of items modified by the command to undo
* @param aTypeCommand = command type (see enum UNDO_REDO_T)
* @param aTransformPoint = the reference point of the transformation,
* for commands like move
*/
void SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList, UNDO_REDO_T aTypeCommand,
const wxPoint& aTransformPoint = wxPoint( 0, 0 ) ) override;
/** /**
* Function RestoreCopyFromRedoList * Function RestoreCopyFromRedoList
* Redo the last edition: * Redo the last edition:
* - Save the current data in Undo list * - Save the current board in Undo list
* - Get an old version of the data from Redo list * - Get an old version of the board from Redo list
* @return none
*/ */
virtual void RestoreCopyFromRedoList( wxCommandEvent& aEvent ) = 0; void RestoreCopyFromRedoList( wxCommandEvent& aEvent );
/** /**
* Function RestoreCopyFromUndoList * Function RestoreCopyFromUndoList
* Undo the last edition: * Undo the last edition:
* - Save the current board in Redo list * - Save the current board in Redo list
* - Get an old version of the data from Undo list * - Get an old version of the board from Undo list
* @return none
*/ */
virtual void RestoreCopyFromUndoList( wxCommandEvent& aEvent ) = 0; void RestoreCopyFromUndoList( wxCommandEvent& aEvent );
int GetRotationAngle() const { return m_rotationAngle; } /**
void SetRotationAngle( int aRotationAngle ); * Function PutDataInPreviousState
* Used in undo or redo command.
bool PostCommandMenuEvent( int evt_type ); * Put data pointed by List in the previous state, i.e. the state memorized by List
* @param aList = a PICKED_ITEMS_LIST pointer to the list of items to undo/redo
* @param aRedoCommand = a bool: true for redo, false for undo
* @param aRebuildRatsnet = a bool: true to rebuild ratsnest (normal use), false
* to just retrieve last state (used in abort commands that do not need to
* rebuild ratsnest)
*/
void PutDataInPreviousState( PICKED_ITEMS_LIST* aList,
bool aRedoCommand,
bool aRebuildRatsnet = true );
/** /**
* Function UndoRedoBlocked * Function UndoRedoBlocked
@ -100,6 +144,20 @@ public:
m_undoRedoBlocked = aBlock; m_undoRedoBlocked = aBlock;
} }
/**
* Function GetRotationAngle()
* Returns the angle used for rotate operations.
*/
int GetRotationAngle() const { return m_rotationAngle; }
/**
* Function SetRotationAngle()
* Sets the angle used for rotate operations.
*/
void SetRotationAngle( int aRotationAngle );
bool PostCommandMenuEvent( int evt_type );
///> @copydoc EDA_DRAW_FRAME::UseGalCanvas() ///> @copydoc EDA_DRAW_FRAME::UseGalCanvas()
void UseGalCanvas( bool aEnable ); void UseGalCanvas( bool aEnable );

View File

@ -1242,10 +1242,10 @@ void PCB_PARSER::parseNETINFO_ITEM() throw( IO_ERROR, PARSE_ERROR )
// net 0 should be already in list, so store this net // net 0 should be already in list, so store this net
// if it is not the net 0, or if the net 0 does not exists. // if it is not the net 0, or if the net 0 does not exists.
// (TODO: a better test.) // (TODO: a better test.)
if( netCode > 0 || m_board->FindNet( 0 ) == NULL ) if( netCode > NETINFO_LIST::UNCONNECTED || !m_board->FindNet( NETINFO_LIST::UNCONNECTED ) )
{ {
NETINFO_ITEM* net = new NETINFO_ITEM( m_board, name, netCode ); NETINFO_ITEM* net = new NETINFO_ITEM( m_board, name, netCode );
m_board->AppendNet( net ); m_board->Add( net );
// Store the new code mapping // Store the new code mapping
pushValueIntoMap( netCode, net->GetNet() ); pushValueIntoMap( netCode, net->GetNet() );
@ -2988,7 +2988,7 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER() throw( IO_ERROR, PARSE_ERROR )
{ {
int newnetcode = m_board->GetNetCount(); int newnetcode = m_board->GetNetCount();
net = new NETINFO_ITEM( m_board, netnameFromfile, newnetcode ); net = new NETINFO_ITEM( m_board, netnameFromfile, newnetcode );
m_board->AppendNet( net ); m_board->Add( net );
// Store the new code mapping // Store the new code mapping
pushValueIntoMap( newnetcode, net->GetNet() ); pushValueIntoMap( newnetcode, net->GetNet() );

View File

@ -196,8 +196,8 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME )
EVT_TOOL( wxID_CUT, PCB_EDIT_FRAME::Process_Special_Functions ) EVT_TOOL( wxID_CUT, PCB_EDIT_FRAME::Process_Special_Functions )
EVT_TOOL( wxID_COPY, PCB_EDIT_FRAME::Process_Special_Functions ) EVT_TOOL( wxID_COPY, PCB_EDIT_FRAME::Process_Special_Functions )
EVT_TOOL( wxID_PASTE, PCB_EDIT_FRAME::Process_Special_Functions ) EVT_TOOL( wxID_PASTE, PCB_EDIT_FRAME::Process_Special_Functions )
EVT_TOOL( wxID_UNDO, PCB_EDIT_FRAME::RestoreCopyFromUndoList ) EVT_TOOL( wxID_UNDO, PCB_BASE_EDIT_FRAME::RestoreCopyFromUndoList )
EVT_TOOL( wxID_REDO, PCB_EDIT_FRAME::RestoreCopyFromRedoList ) EVT_TOOL( wxID_REDO, PCB_BASE_EDIT_FRAME::RestoreCopyFromRedoList )
EVT_TOOL( wxID_PRINT, PCB_EDIT_FRAME::ToPrinter ) EVT_TOOL( wxID_PRINT, PCB_EDIT_FRAME::ToPrinter )
EVT_TOOL( ID_GEN_PLOT_SVG, PCB_EDIT_FRAME::SVG_Print ) EVT_TOOL( ID_GEN_PLOT_SVG, PCB_EDIT_FRAME::SVG_Print )
EVT_TOOL( ID_GEN_PLOT, PCB_EDIT_FRAME::Process_Special_Functions ) EVT_TOOL( ID_GEN_PLOT, PCB_EDIT_FRAME::Process_Special_Functions )
@ -481,7 +481,7 @@ void PCB_EDIT_FRAME::SetBoard( BOARD* aBoard )
if( IsGalCanvasActive() ) if( IsGalCanvasActive() )
{ {
aBoard->GetRatsnest()->Recalculate(); aBoard->GetRatsnest()->ProcessBoard();
// reload the worksheet // reload the worksheet
SetPageSettings( aBoard->GetPageSettings() ); SetPageSettings( aBoard->GetPageSettings() );
@ -489,6 +489,12 @@ void PCB_EDIT_FRAME::SetBoard( BOARD* aBoard )
} }
BOARD_ITEM_CONTAINER* PCB_EDIT_FRAME::GetModel() const
{
return m_Pcb;
}
void PCB_EDIT_FRAME::SetPageSettings( const PAGE_INFO& aPageSettings ) void PCB_EDIT_FRAME::SetPageSettings( const PAGE_INFO& aPageSettings )
{ {
PCB_BASE_FRAME::SetPageSettings( aPageSettings ); PCB_BASE_FRAME::SetPageSettings( aPageSettings );
@ -667,17 +673,8 @@ void PCB_EDIT_FRAME::Show3D_Frame( wxCommandEvent& event )
void PCB_EDIT_FRAME::UseGalCanvas( bool aEnable ) void PCB_EDIT_FRAME::UseGalCanvas( bool aEnable )
{ {
if( aEnable ) if( !aEnable )
{
BOARD* board = GetBoard();
if( board )
board->GetRatsnest()->ProcessBoard();
}
else
{
Compile_Ratsnest( NULL, true ); Compile_Ratsnest( NULL, true );
}
PCB_BASE_EDIT_FRAME::UseGalCanvas( aEnable ); PCB_BASE_EDIT_FRAME::UseGalCanvas( aEnable );

View File

@ -215,11 +215,11 @@ void RN_NET::validateEdge( RN_EDGE_MST_PTR& aEdge )
// If any of nodes belonging to the edge has the flag set, // If any of nodes belonging to the edge has the flag set,
// change it to the closest node that has flag cleared // change it to the closest node that has flag cleared
if( source->GetFlag() ) if( source->GetNoLine() )
{ {
valid = false; valid = false;
std::list<RN_NODE_PTR> closest = GetClosestNodes( source, LINE_TARGET() );
std::list<RN_NODE_PTR> closest = GetClosestNodes( source, WITHOUT_FLAG() );
for( RN_NODE_PTR& node : closest ) for( RN_NODE_PTR& node : closest )
{ {
if( node && node != target ) if( node && node != target )
@ -230,11 +230,11 @@ void RN_NET::validateEdge( RN_EDGE_MST_PTR& aEdge )
} }
} }
if( target->GetFlag() ) if( target->GetNoLine() )
{ {
valid = false; valid = false;
std::list<RN_NODE_PTR> closest = GetClosestNodes( target, LINE_TARGET() );
std::list<RN_NODE_PTR> closest = GetClosestNodes( target, WITHOUT_FLAG() );
for( RN_NODE_PTR& node : closest ) for( RN_NODE_PTR& node : closest )
{ {
if( node && node != source ) if( node && node != source )
@ -398,7 +398,7 @@ RN_POLY::RN_POLY( const SHAPE_POLY_SET* aParent,
// Mark it as not appropriate as a destination of ratsnest edges // Mark it as not appropriate as a destination of ratsnest edges
// (edges coming out from a polygon vertex look weird) // (edges coming out from a polygon vertex look weird)
m_node->SetFlag( true ); m_node->SetNoLine( true );
} }
@ -761,7 +761,7 @@ void RN_NET::GetAllItems( std::list<BOARD_CONNECTED_ITEM*>& aOutput, RN_ITEM_TYP
void RN_NET::ClearSimple() void RN_NET::ClearSimple()
{ {
for( const RN_NODE_PTR& node : m_blockedNodes ) for( const RN_NODE_PTR& node : m_blockedNodes )
node->SetFlag( false ); node->SetNoLine( false );
m_blockedNodes.clear(); m_blockedNodes.clear();
m_simpleNodes.clear(); m_simpleNodes.clear();
@ -1033,22 +1033,25 @@ void RN_NET::processPads()
} }
void RN_DATA::Add( const BOARD_ITEM* aItem ) bool RN_DATA::Add( const BOARD_ITEM* aItem )
{ {
int net; int net;
if( aItem->IsConnected() ) if( aItem->IsConnected() )
{ {
net = static_cast<const BOARD_CONNECTED_ITEM*>( aItem )->GetNetCode(); net = static_cast<const BOARD_CONNECTED_ITEM*>( aItem )->GetNetCode();
if( net < 1 ) // do not process unconnected items
return;
if( net >= (int) m_nets.size() ) // Autoresize if( net < 1 ) // do not process unconnected items
return false;
// Autoresize is necessary e.g. for module editor
if( net >= (int) m_nets.size() )
m_nets.resize( net + 1 ); m_nets.resize( net + 1 );
} }
else if( aItem->Type() == PCB_MODULE_T ) else if( aItem->Type() == PCB_MODULE_T )
{ {
const MODULE* module = static_cast<const MODULE*>( aItem ); const MODULE* module = static_cast<const MODULE*>( aItem );
for( const D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() ) for( const D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() )
{ {
net = pad->GetNetCode(); net = pad->GetNetCode();
@ -1056,16 +1059,24 @@ void RN_DATA::Add( const BOARD_ITEM* aItem )
if( net < 1 ) // do not process unconnected items if( net < 1 ) // do not process unconnected items
continue; continue;
if( net >= (int) m_nets.size() ) // Autoresize // Autoresize is necessary e.g. for module editor
if( net >= (int) m_nets.size() )
m_nets.resize( net + 1 ); m_nets.resize( net + 1 );
m_nets[net].AddItem( pad ); m_nets[net].AddItem( pad );
} }
return; return true;
}
else if( aItem->Type() == PCB_NETINFO_T )
{
int netCount = m_board->GetNetCount();
if( (unsigned) netCount > m_nets.size() )
m_nets.resize( netCount );
return true;
} }
else
return;
switch( aItem->Type() ) switch( aItem->Type() )
{ {
@ -1086,12 +1097,15 @@ void RN_DATA::Add( const BOARD_ITEM* aItem )
break; break;
default: default:
return false;
break; break;
} }
return true;
} }
void RN_DATA::Remove( const BOARD_ITEM* aItem ) bool RN_DATA::Remove( const BOARD_ITEM* aItem )
{ {
int net; int net;
@ -1100,21 +1114,19 @@ void RN_DATA::Remove( const BOARD_ITEM* aItem )
net = static_cast<const BOARD_CONNECTED_ITEM*>( aItem )->GetNetCode(); net = static_cast<const BOARD_CONNECTED_ITEM*>( aItem )->GetNetCode();
if( net < 1 ) // do not process unconnected items if( net < 1 ) // do not process unconnected items
return; return false;
#ifdef NDEBUG // Autoresize is necessary e.g. for module editor
if( net >= (int) m_nets.size() ) // Autoresize if( net >= (int) m_nets.size() )
{ {
m_nets.resize( net + 1 ); m_nets.resize( net + 1 );
return false; // if it was resized, then surely the item had not been added before
return; // if it was resized, then surely the item had not been added before
} }
#endif
assert( net < (int) m_nets.size() );
} }
else if( aItem->Type() == PCB_MODULE_T ) else if( aItem->Type() == PCB_MODULE_T )
{ {
const MODULE* module = static_cast<const MODULE*>( aItem ); const MODULE* module = static_cast<const MODULE*>( aItem );
for( const D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() ) for( const D_PAD* pad = module->Pads().GetFirst(); pad; pad = pad->Next() )
{ {
net = pad->GetNetCode(); net = pad->GetNetCode();
@ -1122,23 +1134,22 @@ void RN_DATA::Remove( const BOARD_ITEM* aItem )
if( net < 1 ) // do not process unconnected items if( net < 1 ) // do not process unconnected items
continue; continue;
#ifdef NDEBUG // Autoresize is necessary e.g. for module editor
if( net >= (int) m_nets.size() ) // Autoresize if( net >= (int) m_nets.size() )
{ {
m_nets.resize( net + 1 ); m_nets.resize( net + 1 );
return false; // if it was resized, then surely the item had not been added before
return; // if it was resized, then surely the item had not been added before
} }
#endif
assert( net < (int) m_nets.size() );
m_nets[net].RemoveItem( pad ); m_nets[net].RemoveItem( pad );
} }
return; return true;
} }
else else
return; {
return false;
}
switch( aItem->Type() ) switch( aItem->Type() )
{ {
@ -1159,15 +1170,24 @@ void RN_DATA::Remove( const BOARD_ITEM* aItem )
break; break;
default: default:
return false;
break; break;
} }
return true;
} }
void RN_DATA::Update( const BOARD_ITEM* aItem ) bool RN_DATA::Update( const BOARD_ITEM* aItem )
{ {
Remove( aItem ); if( Remove( aItem ) )
Add( aItem ); {
bool res = Add( aItem );
assert( res );
return true;
}
return false;
} }
@ -1227,9 +1247,6 @@ void RN_DATA::Recalculate( int aNet )
{ {
unsigned int netCount = m_board->GetNetCount(); unsigned int netCount = m_board->GetNetCount();
if( netCount > m_nets.size() )
m_nets.resize( netCount );
if( aNet < 0 && netCount > 1 ) // Recompute everything if( aNet < 0 && netCount > 1 ) // Recompute everything
{ {
#ifdef PROFILE #ifdef PROFILE

View File

@ -92,19 +92,19 @@ struct RN_NODE_FILTER : public std::unary_function<const RN_NODE_PTR&, bool>
RN_NODE_AND_FILTER operator&&( const RN_NODE_FILTER& aFilter1, const RN_NODE_FILTER& aFilter2 ); RN_NODE_AND_FILTER operator&&( const RN_NODE_FILTER& aFilter1, const RN_NODE_FILTER& aFilter2 );
RN_NODE_OR_FILTER operator||( const RN_NODE_FILTER& aFilter1, const RN_NODE_FILTER& aFilter2 ); RN_NODE_OR_FILTER operator||( const RN_NODE_FILTER& aFilter1, const RN_NODE_FILTER& aFilter2 );
///> Filters out nodes that have the flag set. ///> Filters out nodes that cannot be a ratsnest line target
struct WITHOUT_FLAG : public RN_NODE_FILTER struct LINE_TARGET : public RN_NODE_FILTER
{ {
bool operator()( const RN_NODE_PTR& aNode ) const bool operator()( const RN_NODE_PTR& aNode ) const
{ {
return !aNode->GetFlag(); return !aNode->GetNoLine();
} }
}; };
///> Filters out nodes with a specific tag ///> Filters out nodes with a specific tag
struct DIFFERENT_TAG : public RN_NODE_FILTER struct DIFF_TAG : public RN_NODE_FILTER
{ {
DIFFERENT_TAG( int aTag ) : DIFF_TAG( int aTag ) :
m_tag( aTag ) m_tag( aTag )
{} {}
@ -515,7 +515,7 @@ public:
inline void AddBlockedNode( RN_NODE_PTR& aNode ) inline void AddBlockedNode( RN_NODE_PTR& aNode )
{ {
m_blockedNodes.insert( aNode ); m_blockedNodes.insert( aNode );
aNode->SetFlag( true ); aNode->SetNoLine( true );
} }
/** /**
@ -647,22 +647,26 @@ public:
* Function Add() * Function Add()
* Adds an item to the ratsnest data. * Adds an item to the ratsnest data.
* @param aItem is an item to be added. * @param aItem is an item to be added.
* @return True if operation succeeded.
*/ */
void Add( const BOARD_ITEM* aItem ); bool Add( const BOARD_ITEM* aItem );
/** /**
* Function Remove() * Function Remove()
* Removes an item from the ratsnest data. * Removes an item from the ratsnest data.
* @param aItem is an item to be updated. * @param aItem is an item to be updated.
* @return True if operation succeeded.
*/ */
void Remove( const BOARD_ITEM* aItem ); bool Remove( const BOARD_ITEM* aItem );
/** /**
* Function Update() * Function Update()
* Updates the ratsnest data for an item. * Updates the ratsnest data for an item.
* @param aItem is an item to be updated. * @param aItem is an item to be updated.
* @return True if operation succeeded. The item will not be updated if it was not previously
* added to the ratsnest.
*/ */
void Update( const BOARD_ITEM* aItem ); bool Update( const BOARD_ITEM* aItem );
/** /**
* Function AddSimple() * Function AddSimple()

View File

@ -79,7 +79,7 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const
if( node->GetRefCount() > 1 ) if( node->GetRefCount() > 1 )
continue; continue;
RN_NODE_PTR dest = net.GetClosestNode( node, WITHOUT_FLAG() ); RN_NODE_PTR dest = net.GetClosestNode( node, LINE_TARGET() );
if( dest ) if( dest )
{ {

View File

@ -229,8 +229,6 @@ void LENGTH_TUNER_TOOL::performTuning()
} }
m_router->StopRouting(); m_router->StopRouting();
m_frame->OnModify();
highlightNet( false ); highlightNet( false );
} }

View File

@ -24,6 +24,7 @@
#include <class_board_connected_item.h> #include <class_board_connected_item.h>
#include <class_module.h> #include <class_module.h>
#include <class_track.h> #include <class_track.h>
#include <board_commit.h>
#include <ratsnest_data.h> #include <ratsnest_data.h>
#include <layers_id_colors_and_visibility.h> #include <layers_id_colors_and_visibility.h>
#include <geometry/convex_hull.h> #include <geometry/convex_hull.h>
@ -154,7 +155,7 @@ int PNS_PCBNEW_RULE_RESOLVER::Clearance( const PNS::ITEM* aA, const PNS::ITEM* a
int net_b = aB->Net(); int net_b = aB->Net();
int cl_b = ( net_b >= 0 ? m_clearanceCache[net_b].clearance : m_defaultClearance ); int cl_b = ( net_b >= 0 ? m_clearanceCache[net_b].clearance : m_defaultClearance );
bool linesOnly = aA->OfKind( PNS::ITEM::SEGMENT_T | PNS::ITEM::LINE_T ) bool linesOnly = aA->OfKind( PNS::ITEM::SEGMENT_T | PNS::ITEM::LINE_T )
&& aB->OfKind( PNS::ITEM::SEGMENT_T | PNS::ITEM::LINE_T ); && aB->OfKind( PNS::ITEM::SEGMENT_T | PNS::ITEM::LINE_T );
if( linesOnly && net_a >= 0 && net_b >= 0 && m_clearanceCache[net_a].coupledNet == net_b ) if( linesOnly && net_a >= 0 && net_b >= 0 && m_clearanceCache[net_a].coupledNet == net_b )
@ -413,11 +414,13 @@ PNS_KICAD_IFACE::PNS_KICAD_IFACE()
m_world = nullptr; m_world = nullptr;
m_router = nullptr; m_router = nullptr;
m_debugDecorator = nullptr; m_debugDecorator = nullptr;
m_commit = nullptr;
} }
PNS_KICAD_IFACE::~PNS_KICAD_IFACE() PNS_KICAD_IFACE::~PNS_KICAD_IFACE()
{ {
delete m_commit;
delete m_ruleResolver; delete m_ruleResolver;
delete m_debugDecorator; delete m_debugDecorator;
@ -738,12 +741,11 @@ void PNS_KICAD_IFACE::SyncWorld( PNS::NODE *aWorld )
for( TRACK* t = m_board->m_Track; t; t = t->Next() ) for( TRACK* t = m_board->m_Track; t; t = t->Next() )
{ {
KICAD_T type = t->Type(); KICAD_T type = t->Type();
PNS::ITEM* item = NULL;
if( type == PCB_TRACE_T ) { if( type == PCB_TRACE_T ) {
std::unique_ptr< PNS::SEGMENT > segment = syncTrack( t ); std::unique_ptr< PNS::SEGMENT > segment = syncTrack( t );
if( segment ) { if( segment ) {
aWorld->Add( std::move( segment ) ); aWorld->Add( std::move( segment ) );
} }
} else if( type == PCB_VIA_T ) { } else if( type == PCB_VIA_T ) {
std::unique_ptr< PNS::VIA > via = syncVia( static_cast<VIA*>( t ) ); std::unique_ptr< PNS::VIA > via = syncVia( static_cast<VIA*>( t ) );
@ -821,9 +823,8 @@ void PNS_KICAD_IFACE::RemoveItem( PNS::ITEM* aItem )
if( parent ) if( parent )
{ {
m_view->Remove( parent ); assert( m_commit );
m_board->Remove( parent ); m_commit->Remove( parent );
m_undoBuffer.PushItem( ITEM_PICKER( parent, UR_DELETED ) );
} }
} }
@ -871,20 +872,16 @@ void PNS_KICAD_IFACE::AddItem( PNS::ITEM* aItem )
{ {
aItem->SetParent( newBI ); aItem->SetParent( newBI );
newBI->ClearFlags(); newBI->ClearFlags();
m_view->Add( newBI );
m_board->Add( newBI ); assert( m_commit );
m_undoBuffer.PushItem( ITEM_PICKER( newBI, UR_NEW ) ); m_commit->Add( newBI );
newBI->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
} }
} }
void PNS_KICAD_IFACE::Commit() void PNS_KICAD_IFACE::Commit()
{ {
m_board->GetRatsnest()->Recalculate(); m_commit->Push( wxT( "Added a track" ) );
m_frame->SaveCopyInUndoList( m_undoBuffer, UR_UNSPECIFIED );
m_undoBuffer.ClearItemsList();
m_frame->OnModify();
} }
@ -909,6 +906,7 @@ void PNS_KICAD_IFACE::SetView( KIGFX::VIEW *aView )
m_debugDecorator->SetView( m_view ); m_debugDecorator->SetView( m_view );
} }
void PNS_KICAD_IFACE::UpdateNet( int aNetCode ) void PNS_KICAD_IFACE::UpdateNet( int aNetCode )
{ {
wxLogTrace( "PNS", "Update-net %d", aNetCode ); wxLogTrace( "PNS", "Update-net %d", aNetCode );
@ -924,7 +922,11 @@ void PNS_KICAD_IFACE::SetRouter( PNS::ROUTER* aRouter )
m_router = aRouter; m_router = aRouter;
} }
void PNS_KICAD_IFACE::SetHostFrame( PCB_EDIT_FRAME *aFrame )
void PNS_KICAD_IFACE::SetHostFrame( PCB_EDIT_FRAME* aFrame )
{ {
m_frame = aFrame; m_frame = aFrame;
delete m_commit;
m_commit = new BOARD_COMMIT( aFrame );
} }

View File

@ -30,6 +30,7 @@ class PNS_PCBNEW_RULE_RESOLVER;
class PNS_PCBNEW_DEBUG_DECORATOR; class PNS_PCBNEW_DEBUG_DECORATOR;
class BOARD; class BOARD;
class BOARD_COMMIT;
namespace KIGFX namespace KIGFX
{ {
class VIEW; class VIEW;
@ -75,6 +76,7 @@ private:
BOARD* m_board; BOARD* m_board;
PICKED_ITEMS_LIST m_undoBuffer; PICKED_ITEMS_LIST m_undoBuffer;
PCB_EDIT_FRAME* m_frame; PCB_EDIT_FRAME* m_frame;
BOARD_COMMIT* m_commit;
}; };
#endif #endif

View File

@ -277,8 +277,8 @@ void ROUTER::updateView( NODE* aNode, ITEM_SET& aCurrent )
for ( auto item : added ) for ( auto item : added )
m_iface->DisplayItem( item ); m_iface->DisplayItem( item );
for ( auto item : removed ) for( auto item : removed )
m_iface->HideItem ( item ); m_iface->HideItem( item );
} }

View File

@ -144,7 +144,7 @@ public:
void SwitchLayer( int layer ); void SwitchLayer( int layer );
void ToggleViaPlacement(); void ToggleViaPlacement();
void SetOrthoMode ( bool aEnable ); void SetOrthoMode( bool aEnable );
int GetCurrentLayer() const; int GetCurrentLayer() const;
const std::vector<int> GetCurrentNets() const; const std::vector<int> GetCurrentNets() const;
@ -211,8 +211,7 @@ public:
ITEM* QueryItemByParent( const BOARD_ITEM* aItem ) const; ITEM* QueryItemByParent( const BOARD_ITEM* aItem ) const;
void SetFailureReason( const wxString& aReason ) { m_failureReason = aReason; }
void SetFailureReason ( const wxString& aReason ) { m_failureReason = aReason; }
const wxString& FailureReason() const { return m_failureReason; } const wxString& FailureReason() const { return m_failureReason; }
PLACEMENT_ALGO* Placer() { return m_placer.get(); } PLACEMENT_ALGO* Placer() { return m_placer.get(); }
@ -270,7 +269,6 @@ private:
bool m_violation; bool m_violation;
ROUTING_SETTINGS m_settings; ROUTING_SETTINGS m_settings;
///> Stores list of modified items in the current operation
SIZES_SETTINGS m_sizes; SIZES_SETTINGS m_sizes;
ROUTER_MODE m_mode; ROUTER_MODE m_mode;

View File

@ -105,7 +105,6 @@ void TOOL_BASE::Reset( RESET_REASON aReason )
m_board = getModel<BOARD>(); m_board = getModel<BOARD>();
m_iface = new PNS_KICAD_IFACE; m_iface = new PNS_KICAD_IFACE;
m_iface->SetBoard( m_board ); m_iface->SetBoard( m_board );
m_iface->SetView( getView() ); m_iface->SetView( getView() );
m_iface->SetHostFrame( m_frame ); m_iface->SetHostFrame( m_frame );

View File

@ -23,10 +23,12 @@
#ifndef __PNS_TOOL_BASE_H #ifndef __PNS_TOOL_BASE_H
#define __PNS_TOOL_BASE_H #define __PNS_TOOL_BASE_H
#include <memory>
#include <import_export.h> #include <import_export.h>
#include <math/vector2d.h> #include <math/vector2d.h>
#include <tool/tool_interactive.h> #include <tools/pcb_tool.h>
#include <board_commit.h>
#include <msgpanel.h> #include <msgpanel.h>

View File

@ -120,7 +120,6 @@ void ROUTER_PREVIEW_ITEM::Update( const PNS::ITEM* aItem )
m_color = COLOR4D( 0, 1, 0, 1 ); m_color = COLOR4D( 0, 1, 0, 1 );
ViewSetVisible( true ); ViewSetVisible( true );
ViewUpdate( GEOMETRY | APPEARANCE );
} }
@ -276,7 +275,6 @@ void ROUTER_PREVIEW_ITEM::Line( const SHAPE_LINE_CHAIN& aLine, int aWidth, int a
m_shape = aLine.Clone(); m_shape = aLine.Clone();
ViewSetVisible( true ); ViewSetVisible( true );
ViewUpdate( GEOMETRY | APPEARANCE );
} }

View File

@ -534,8 +534,6 @@ bool ROUTER_TOOL::finishInteractive()
{ {
m_router->StopRouting(); m_router->StopRouting();
m_frame->OnModify();
m_ctls->SetAutoPan( false ); m_ctls->SetAutoPan( false );
m_ctls->ForceCursorPosition( false ); m_ctls->ForceCursorPosition( false );
highlightNet( false ); highlightNet( false );
@ -740,7 +738,6 @@ int ROUTER_TOOL::mainLoop( PNS::ROUTER_MODE aMode )
void ROUTER_TOOL::performDragging() void ROUTER_TOOL::performDragging()
{ {
PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME>();
VIEW_CONTROLS* ctls = getViewControls(); VIEW_CONTROLS* ctls = getViewControls();
if( m_startItem && m_startItem->IsLocked() ) if( m_startItem && m_startItem->IsLocked() )
@ -759,8 +756,6 @@ void ROUTER_TOOL::performDragging()
ctls->SetAutoPan( true ); ctls->SetAutoPan( true );
bool modified = false;
while( OPT_TOOL_EVENT evt = Wait() ) while( OPT_TOOL_EVENT evt = Wait() )
{ {
ctls->ForceCursorPosition( false ); ctls->ForceCursorPosition( false );
@ -775,10 +770,7 @@ void ROUTER_TOOL::performDragging()
else if( evt->IsClick( BUT_LEFT ) ) else if( evt->IsClick( BUT_LEFT ) )
{ {
if( m_router->FixRoute( m_endSnapPoint, m_endItem ) ) if( m_router->FixRoute( m_endSnapPoint, m_endItem ) )
{
modified = true;
break; break;
}
} }
handleCommonEvents( *evt ); handleCommonEvents( *evt );
@ -787,9 +779,6 @@ void ROUTER_TOOL::performDragging()
if( m_router->RoutingInProgress() ) if( m_router->RoutingInProgress() )
m_router->StopRouting(); m_router->StopRouting();
if( modified )
frame->OnModify();
m_startItem = NULL; m_startItem = NULL;
ctls->SetAutoPan( false ); ctls->SetAutoPan( false );
@ -829,8 +818,6 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
ctls->SetAutoPan( true ); ctls->SetAutoPan( true );
frame->UndoRedoBlock( true ); frame->UndoRedoBlock( true );
bool modified = false;
while( OPT_TOOL_EVENT evt = Wait() ) while( OPT_TOOL_EVENT evt = Wait() )
{ {
p0 = ctls->GetCursorPosition(); p0 = ctls->GetCursorPosition();
@ -845,7 +832,7 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
} }
else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) )
{ {
modified = m_router->FixRoute( p0, NULL ); m_router->FixRoute( p0, NULL );
break; break;
} }
} }
@ -853,9 +840,6 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent )
if( m_router->RoutingInProgress() ) if( m_router->RoutingInProgress() )
m_router->StopRouting(); m_router->StopRouting();
if( modified )
frame->OnModify();
ctls->SetAutoPan( false ); ctls->SetAutoPan( false );
ctls->ShowCursor( false ); ctls->ShowCursor( false );
frame->UndoRedoBlock( false ); frame->UndoRedoBlock( false );

View File

@ -34,6 +34,7 @@
#include <dialog_helpers.h> #include <dialog_helpers.h>
#include <base_units.h> #include <base_units.h>
#include <gr_basic.h> #include <gr_basic.h>
#include <board_commit.h>
#include <class_board.h> #include <class_board.h>
#include <class_mire.h> #include <class_mire.h>
@ -128,12 +129,14 @@ void TARGET_PROPERTIES_DIALOG_EDITOR::OnCancelClick( wxCommandEvent& event )
*/ */
void TARGET_PROPERTIES_DIALOG_EDITOR::OnOkClick( wxCommandEvent& event ) void TARGET_PROPERTIES_DIALOG_EDITOR::OnOkClick( wxCommandEvent& event )
{ {
BOARD_COMMIT commit( m_Parent );
commit.Modify( m_Target );
if( m_DC ) if( m_DC )
m_Target->Draw( m_Parent->GetCanvas(), m_DC, GR_XOR ); m_Target->Draw( m_Parent->GetCanvas(), m_DC, GR_XOR );
// Save old item in undo list, if is is not currently edited (will be later if so) // Save old item in undo list, if is is not currently edited (will be later if so)
if( m_Target->GetFlags() == 0 ) bool pushCommit = ( m_Target->GetFlags() == 0 );
m_Parent->SaveCopyInUndoList( m_Target, UR_CHANGED );
if( m_Target->GetFlags() != 0 ) // other edition in progress (MOVE, NEW ..) if( m_Target->GetFlags() != 0 ) // other edition in progress (MOVE, NEW ..)
m_Target->SetFlags( IN_EDIT ); // set flag in edit to force m_Target->SetFlags( IN_EDIT ); // set flag in edit to force
@ -150,7 +153,9 @@ void TARGET_PROPERTIES_DIALOG_EDITOR::OnOkClick( wxCommandEvent& event )
if( m_DC ) if( m_DC )
m_Target->Draw( m_Parent->GetCanvas(), m_DC, ( m_Target->IsMoving() ) ? GR_XOR : GR_OR ); m_Target->Draw( m_Parent->GetCanvas(), m_DC, ( m_Target->IsMoving() ) ? GR_XOR : GR_OR );
m_Parent->OnModify(); if( pushCommit )
commit.Push( _( "Modified alignment target" ) );
EndModal( 1 ); EndModal( 1 );
} }

View File

@ -138,6 +138,10 @@ TOOL_ACTION COMMON_ACTIONS::properties( "pcbnew.InteractiveEdit.properties",
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_EDIT_ITEM ), AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_EDIT_ITEM ),
_( "Properties..." ), _( "Displays item properties dialog" ), editor_xpm ); _( "Properties..." ), _( "Displays item properties dialog" ), editor_xpm );
TOOL_ACTION COMMON_ACTIONS::editModifiedSelection( "pcbnew.InteractiveEdit.ModifiedSelection",
AS_GLOBAL, 0,
"", "" );
// Drawing tool actions // Drawing tool actions
TOOL_ACTION COMMON_ACTIONS::drawLine( "pcbnew.InteractiveDrawing.line", TOOL_ACTION COMMON_ACTIONS::drawLine( "pcbnew.InteractiveDrawing.line",
@ -564,10 +568,6 @@ TOOL_ACTION COMMON_ACTIONS::routerInlineDrag( "pcbnew.InteractiveRouter.InlineDr
"", "" ); "", "" );
// Point editor // Point editor
TOOL_ACTION COMMON_ACTIONS::pointEditorUpdate( "pcbnew.PointEditor.update",
AS_GLOBAL, 0,
"", "" ); // No description, it is not supposed to be shown anywhere
TOOL_ACTION COMMON_ACTIONS::pointEditorAddCorner( "pcbnew.PointEditor.addCorner", TOOL_ACTION COMMON_ACTIONS::pointEditorAddCorner( "pcbnew.PointEditor.addCorner",
AS_GLOBAL, 0, AS_GLOBAL, 0,
_( "Create corner" ), _( "Create corner" ), add_corner_xpm ); _( "Create corner" ), _( "Create corner" ), add_corner_xpm );

View File

@ -79,6 +79,9 @@ public:
/// Activation of the edit tool /// Activation of the edit tool
static TOOL_ACTION properties; static TOOL_ACTION properties;
/// Modified selection notification
static TOOL_ACTION editModifiedSelection;
/// Activation of the exact move tool /// Activation of the exact move tool
static TOOL_ACTION moveExact; static TOOL_ACTION moveExact;
@ -161,9 +164,6 @@ public:
static TOOL_ACTION routerInlineDrag; static TOOL_ACTION routerInlineDrag;
// Point Editor // Point Editor
/// Update edit points
static TOOL_ACTION pointEditorUpdate;
/// Break outline (insert additional points to an edge) /// Break outline (insert additional points to an edge)
static TOOL_ACTION pointEditorAddCorner; static TOOL_ACTION pointEditorAddCorner;

View File

@ -40,6 +40,7 @@
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
#include <router/direction.h> #include <router/direction.h>
#include <ratsnest_data.h> #include <ratsnest_data.h>
#include <board_commit.h>
#include <class_board.h> #include <class_board.h>
#include <class_edge_mod.h> #include <class_edge_mod.h>
@ -49,8 +50,8 @@
#include <class_module.h> #include <class_module.h>
DRAWING_TOOL::DRAWING_TOOL() : DRAWING_TOOL::DRAWING_TOOL() :
TOOL_INTERACTIVE( "pcbnew.InteractiveDrawing" ), m_view( NULL ), PCB_TOOL( "pcbnew.InteractiveDrawing" ), m_view( NULL ),
m_controls( NULL ), m_board( NULL ), m_frame( NULL ), m_editModules( false ), m_lineWidth( 1 ) m_controls( NULL ), m_board( NULL ), m_frame( NULL ), m_lineWidth( 1 )
{ {
} }
@ -66,61 +67,34 @@ void DRAWING_TOOL::Reset( RESET_REASON aReason )
m_view = getView(); m_view = getView();
m_controls = getViewControls(); m_controls = getViewControls();
m_board = getModel<BOARD>(); m_board = getModel<BOARD>();
m_frame = getEditFrame<PCB_EDIT_FRAME>(); m_frame = getEditFrame<PCB_BASE_EDIT_FRAME>();
} }
int DRAWING_TOOL::DrawLine( const TOOL_EVENT& aEvent ) int DRAWING_TOOL::DrawLine( const TOOL_EVENT& aEvent )
{ {
BOARD_ITEM_CONTAINER* parent = m_frame->GetModel();
DRAWSEGMENT* line = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT;
boost::optional<VECTOR2D> startingPoint; boost::optional<VECTOR2D> startingPoint;
BOARD_COMMIT commit( m_frame );
if( m_editModules ) m_frame->SetToolID( m_editModules ? ID_MODEDIT_LINE_TOOL : ID_PCB_ADD_LINE_BUTT,
wxCURSOR_PENCIL, _( "Add graphic line" ) );
while( drawSegment( S_SEGMENT, line, startingPoint ) )
{ {
m_frame->SetToolID( ID_MODEDIT_LINE_TOOL, wxCURSOR_PENCIL, _( "Add graphic line" ) ); if( line )
EDGE_MODULE* line = new EDGE_MODULE( m_board->m_Modules );
while( drawSegment( S_SEGMENT, reinterpret_cast<DRAWSEGMENT*&>( line ), startingPoint ) )
{ {
if( line ) commit.Add( line );
{ commit.Push( _( "Draw a line segment" ) );
m_frame->OnModify(); startingPoint = line->GetEnd();
m_frame->SaveCopyInUndoList( m_board->m_Modules, UR_MODEDIT );
line->SetParent( m_board->m_Modules );
line->SetLocalCoord();
m_board->m_Modules->GraphicalItems().PushFront( line );
startingPoint = line->GetEnd();
}
else
{
startingPoint = boost::none;
}
line = new EDGE_MODULE( m_board->m_Modules );
} }
} else
else // !m_editModules case
{
m_frame->SetToolID( ID_PCB_ADD_LINE_BUTT, wxCURSOR_PENCIL, _( "Add graphic line" ) );
DRAWSEGMENT* line = new DRAWSEGMENT;
while( drawSegment( S_SEGMENT, line, startingPoint ) )
{ {
if( line ) startingPoint = boost::none;
{
m_board->Add( line );
m_frame->OnModify();
m_frame->SaveCopyInUndoList( line, UR_NEW );
startingPoint = line->GetEnd();
}
else
{
startingPoint = boost::none;
}
line = new DRAWSEGMENT;
} }
line = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT;
} }
m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
@ -131,43 +105,22 @@ int DRAWING_TOOL::DrawLine( const TOOL_EVENT& aEvent )
int DRAWING_TOOL::DrawCircle( const TOOL_EVENT& aEvent ) int DRAWING_TOOL::DrawCircle( const TOOL_EVENT& aEvent )
{ {
if( m_editModules ) BOARD_ITEM_CONTAINER* parent = m_frame->GetModel();
DRAWSEGMENT* circle = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT;
BOARD_COMMIT commit( m_frame );
m_frame->SetToolID( m_editModules ? ID_MODEDIT_CIRCLE_TOOL : ID_PCB_CIRCLE_BUTT,
wxCURSOR_PENCIL, _( "Add graphic circle" ) );
while( drawSegment( S_CIRCLE, circle ) )
{ {
m_frame->SetToolID( ID_MODEDIT_CIRCLE_TOOL, wxCURSOR_PENCIL, _( "Add graphic circle" ) ); if( circle )
EDGE_MODULE* circle = new EDGE_MODULE( m_board->m_Modules );
while( drawSegment( S_CIRCLE, reinterpret_cast<DRAWSEGMENT*&>( circle ) ) )
{ {
if( circle ) commit.Add( circle );
{ commit.Push( _( "Draw a circle" ) );
m_frame->OnModify();
m_frame->SaveCopyInUndoList( m_board->m_Modules, UR_MODEDIT );
circle->SetParent( m_board->m_Modules );
circle->SetLocalCoord();
m_board->m_Modules->GraphicalItems().PushFront( circle );
}
circle = new EDGE_MODULE( m_board->m_Modules );
} }
}
else // !m_editModules case
{
m_frame->SetToolID( ID_PCB_CIRCLE_BUTT, wxCURSOR_PENCIL, _( "Add graphic circle" ) );
DRAWSEGMENT* circle = new DRAWSEGMENT; circle = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT;
while( drawSegment( S_CIRCLE, circle ) )
{
if( circle )
{
m_board->Add( circle );
m_frame->OnModify();
m_frame->SaveCopyInUndoList( circle, UR_NEW );
}
circle = new DRAWSEGMENT;
}
} }
m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
@ -178,43 +131,22 @@ int DRAWING_TOOL::DrawCircle( const TOOL_EVENT& aEvent )
int DRAWING_TOOL::DrawArc( const TOOL_EVENT& aEvent ) int DRAWING_TOOL::DrawArc( const TOOL_EVENT& aEvent )
{ {
if( m_editModules ) BOARD_ITEM_CONTAINER* parent = m_frame->GetModel();
DRAWSEGMENT* arc = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT;
BOARD_COMMIT commit( m_frame );
m_frame->SetToolID( m_editModules ? ID_MODEDIT_ARC_TOOL : ID_PCB_ARC_BUTT,
wxCURSOR_PENCIL, _( "Add graphic arc" ) );
while( drawArc( arc ) )
{ {
m_frame->SetToolID( ID_MODEDIT_ARC_TOOL, wxCURSOR_PENCIL, _( "Add graphic arc" ) ); if( arc )
EDGE_MODULE* arc = new EDGE_MODULE( m_board->m_Modules );
while( drawArc( reinterpret_cast<DRAWSEGMENT*&>( arc ) ) )
{ {
if( arc ) commit.Add( arc );
{ commit.Push( _( "Draw an arc" ) );
m_frame->OnModify();
m_frame->SaveCopyInUndoList( m_board->m_Modules, UR_MODEDIT );
arc->SetParent( m_board->m_Modules );
arc->SetLocalCoord();
m_board->m_Modules->GraphicalItems().PushFront( arc );
}
arc = new EDGE_MODULE( m_board->m_Modules );
} }
}
else // !m_editModules case
{
m_frame->SetToolID( ID_PCB_ARC_BUTT, wxCURSOR_PENCIL, _( "Add graphic arc" ) );
DRAWSEGMENT* arc = new DRAWSEGMENT; arc = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT;
while( drawArc( arc ) )
{
if( arc )
{
m_board->Add( arc );
m_frame->OnModify();
m_frame->SaveCopyInUndoList( arc, UR_NEW );
}
arc = new DRAWSEGMENT;
}
} }
m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
@ -225,22 +157,167 @@ int DRAWING_TOOL::DrawArc( const TOOL_EVENT& aEvent )
int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent ) int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
{ {
if( m_editModules ) BOARD_ITEM* text = NULL;
return placeTextModule(); const BOARD_DESIGN_SETTINGS& dsnSettings = m_frame->GetDesignSettings();
else BOARD_COMMIT commit( m_frame );
return placeTextPcb();
// Add a VIEW_GROUP that serves as a preview for the new item
KIGFX::VIEW_GROUP preview( m_view );
m_view->Add( &preview );
m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true );
m_controls->ShowCursor( true );
m_controls->SetSnapping( true );
// do not capture or auto-pan until we start placing some text
Activate();
m_frame->SetToolID( m_editModules ? ID_MODEDIT_TEXT_TOOL : ID_PCB_ADD_TEXT_BUTT,
wxCURSOR_PENCIL, _( "Add text" ) );
// Main loop: keep receiving events
while( OPT_TOOL_EVENT evt = Wait() )
{
VECTOR2I cursorPos = m_controls->GetCursorPosition();
if( evt->IsCancel() || evt->IsActivate() )
{
if( text )
{
// Delete the old text and have another try
delete text;
text = NULL;
preview.Clear();
m_controls->SetAutoPan( false );
m_controls->CaptureCursor( false );
m_controls->ShowCursor( true );
}
else
break;
if( evt->IsActivate() ) // now finish unconditionally
break;
}
else if( text && evt->Category() == TC_COMMAND )
{
if( evt->IsAction( &COMMON_ACTIONS::rotate ) )
{
text->Rotate( text->GetPosition(), m_frame->GetRotationAngle() );
preview.ViewUpdate();
}
// TODO rotate CCW
else if( evt->IsAction( &COMMON_ACTIONS::flip ) )
{
text->Flip( text->GetPosition() );
preview.ViewUpdate();
}
}
else if( evt->IsClick( BUT_LEFT ) )
{
if( !text )
{
// Init the new item attributes
if( m_editModules )
{
TEXTE_MODULE* textMod = new TEXTE_MODULE( (MODULE*) m_frame->GetModel() );
textMod->SetLayer( m_frame->GetActiveLayer() );
textMod->SetSize( dsnSettings.m_ModuleTextSize );
textMod->SetThickness( dsnSettings.m_ModuleTextWidth );
textMod->SetTextPosition( wxPoint( cursorPos.x, cursorPos.y ) );
DialogEditModuleText textDialog( m_frame, textMod, NULL );
bool placing = textDialog.ShowModal() && ( textMod->GetText().Length() > 0 );
if( !placing )
text = textMod;
else
delete textMod;
}
else
{
TEXTE_PCB* textPcb = new TEXTE_PCB( m_frame->GetModel() );
// TODO we have to set IS_NEW, otherwise InstallTextPCB.. creates an undo entry :| LEGACY_CLEANUP
textPcb->SetFlags( IS_NEW );
LAYER_ID layer = m_frame->GetActiveLayer();
textPcb->SetLayer( layer );
// Set the mirrored option for layers on the BACK side of the board
if( IsBackLayer( layer ) )
textPcb->SetMirrored( true );
textPcb->SetSize( dsnSettings.m_PcbTextSize );
textPcb->SetThickness( dsnSettings.m_PcbTextWidth );
textPcb->SetTextPosition( wxPoint( cursorPos.x, cursorPos.y ) );
getEditFrame<PCB_EDIT_FRAME>()->InstallTextPCBOptionsFrame( textPcb, NULL );
if( textPcb->GetText().IsEmpty() )
delete textPcb;
else
text = textPcb;
}
if( text == NULL )
continue;
m_controls->CaptureCursor( true );
m_controls->SetAutoPan( true );
//m_controls->ShowCursor( false );
preview.Add( text );
}
else
{
//assert( text->GetText().Length() > 0 );
//assert( text->GetSize().x > 0 && text->GetSize().y > 0 );
text->ClearFlags();
preview.Remove( text );
commit.Add( text );
commit.Push( _( "Place a text" ) );
m_controls->CaptureCursor( false );
m_controls->SetAutoPan( false );
m_controls->ShowCursor( true );
text = NULL;
}
}
else if( text && evt->IsMotion() )
{
text->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) );
// Show a preview of the item
preview.ViewUpdate();
}
}
m_controls->ShowCursor( false );
m_controls->SetSnapping( false );
m_controls->SetAutoPan( false );
m_controls->CaptureCursor( false );
m_view->Remove( &preview );
m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
return 0;
} }
int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent ) int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
{ {
DIMENSION* dimension = NULL; DIMENSION* dimension = NULL;
BOARD_COMMIT commit( m_frame );
int maxThickness; int maxThickness;
// if one day it is possible to draw dimensions in the footprint editor,
// then hereby I'm letting you know that this tool does not handle UR_MODEDIT undo yet
assert( !m_editModules );
// Add a VIEW_GROUP that serves as a preview for the new item // Add a VIEW_GROUP that serves as a preview for the new item
KIGFX::VIEW_GROUP preview( m_view ); KIGFX::VIEW_GROUP preview( m_view );
m_view->Add( &preview ); m_view->Add( &preview );
@ -271,7 +348,6 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
if( step != SET_ORIGIN ) // start from the beginning if( step != SET_ORIGIN ) // start from the beginning
{ {
preview.Clear(); preview.Clear();
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
delete dimension; delete dimension;
step = SET_ORIGIN; step = SET_ORIGIN;
@ -355,14 +431,11 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
assert( dimension->GetOrigin() != dimension->GetEnd() ); assert( dimension->GetOrigin() != dimension->GetEnd() );
assert( dimension->GetWidth() > 0 ); assert( dimension->GetWidth() > 0 );
m_view->Add( dimension );
m_board->Add( dimension );
//dimension->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
m_frame->OnModify();
m_frame->SaveCopyInUndoList( dimension, UR_NEW );
preview.Remove( dimension ); preview.Remove( dimension );
commit.Add( dimension );
commit.Push( _( "Draw a dimension" ) );
} }
} }
break; break;
@ -435,7 +508,7 @@ int DRAWING_TOOL::DrawKeepout( const TOOL_EVENT& aEvent )
int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent ) int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
{ {
if( m_editModules && !m_board->m_Modules ) if( !m_frame->GetModel() )
return 0; return 0;
DIALOG_DXF_IMPORT dlg( m_frame ); DIALOG_DXF_IMPORT dlg( m_frame );
@ -451,6 +524,7 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
// Add a VIEW_GROUP that serves as a preview for the new item // Add a VIEW_GROUP that serves as a preview for the new item
KIGFX::VIEW_GROUP preview( m_view ); KIGFX::VIEW_GROUP preview( m_view );
BOARD_COMMIT commit( m_frame );
// Build the undo list & add items to the current view // Build the undo list & add items to the current view
for( auto it = list.begin(), itEnd = list.end(); it != itEnd; ++it ) for( auto it = list.begin(), itEnd = list.end(); it != itEnd; ++it )
@ -488,6 +562,7 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
else if( evt->Category() == TC_COMMAND ) else if( evt->Category() == TC_COMMAND )
{ {
// TODO it should be handled by EDIT_TOOL, so add items and select?
if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) if( evt->IsAction( &COMMON_ACTIONS::rotate ) )
{ {
for( KIGFX::VIEW_GROUP::const_iter it = preview.Begin(), end = preview.End(); it != end; ++it ) for( KIGFX::VIEW_GROUP::const_iter it = preview.Begin(), end = preview.End(); it != end; ++it )
@ -513,33 +588,32 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
else if( evt->IsClick( BUT_LEFT ) ) else if( evt->IsClick( BUT_LEFT ) )
{ {
// Place the drawing // Place the drawing
if( m_editModules ) PICKED_ITEMS_LIST picklist;
BOARD_ITEM_CONTAINER* parent = m_frame->GetModel();
for( KIGFX::VIEW_GROUP::const_iter it = preview.Begin(); it != preview.End(); ++it )
{ {
assert( m_board->m_Modules ); BOARD_ITEM* item = static_cast<BOARD_ITEM*>( *it );
m_frame->SaveCopyInUndoList( m_board->m_Modules, UR_MODEDIT );
m_board->m_Modules->SetLastEditTime();
for( KIGFX::VIEW_GROUP::const_iter it = preview.Begin(), end = preview.End(); it != end; ++it ) if( m_editModules )
{ {
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( *it );
BOARD_ITEM* converted = NULL;
// Modules use different types for the same things, // Modules use different types for the same things,
// so we need to convert imported items to appropriate classes. // so we need to convert imported items to appropriate classes.
BOARD_ITEM* converted = NULL;
switch( item->Type() ) switch( item->Type() )
{ {
case PCB_TEXT_T: case PCB_TEXT_T:
converted = new TEXTE_MODULE( m_board->m_Modules ); converted = new TEXTE_MODULE( (MODULE*) parent );
// Copy coordinates, layer, etc. // Copy coordinates, layer, etc.
*static_cast<TEXTE_PCB*>( converted ) = *static_cast<TEXTE_PCB*>( item ); *static_cast<BOARD_ITEM*>( converted ) = *static_cast<BOARD_ITEM*>( item );
static_cast<TEXTE_MODULE*>( converted )->SetLocalCoord();
break; break;
case PCB_LINE_T: case PCB_LINE_T:
converted = new EDGE_MODULE( m_board->m_Modules ); converted = new EDGE_MODULE( (MODULE*) parent );
// Copy coordinates, layer, etc. // Copy coordinates, layer, etc.
*static_cast<DRAWSEGMENT*>( converted ) = *static_cast<DRAWSEGMENT*>( item ); *static_cast<DRAWSEGMENT*>( converted ) = *static_cast<DRAWSEGMENT*>( item );
static_cast<EDGE_MODULE*>( converted )->SetLocalCoord();
break; break;
default: default:
@ -548,33 +622,13 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
} }
delete item; delete item;
item = converted;
if( converted )
{
m_board->m_Modules->Add( converted );
m_view->Add( converted );
}
}
}
else // !m_editModules case
{
PICKED_ITEMS_LIST picklist;
for( KIGFX::VIEW_GROUP::const_iter it = preview.Begin(), end = preview.End(); it != end; ++it )
{
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( *it );
m_board->Add( item );
ITEM_PICKER itemWrapper( item, UR_NEW );
picklist.PushItem( itemWrapper );
m_view->Add( item );
} }
m_frame->SaveCopyInUndoList( picklist, UR_NEW ); commit.Add( item );
} }
m_frame->OnModify(); commit.Push( _( "Place a DXF drawing" ) );
break; break;
} }
} }
@ -608,15 +662,16 @@ int DRAWING_TOOL::SetAnchor( const TOOL_EVENT& aEvent )
{ {
if( evt->IsClick( BUT_LEFT ) ) if( evt->IsClick( BUT_LEFT ) )
{ {
m_frame->SaveCopyInUndoList( m_board->m_Modules, UR_MODEDIT ); MODULE* module = (MODULE*) m_frame->GetModel();
m_board->m_Modules->SetLastEditTime(); BOARD_COMMIT commit( m_frame );
commit.Modify( module );
// set the new relative internal local coordinates of footprint items // set the new relative internal local coordinates of footprint items
VECTOR2I cursorPos = m_controls->GetCursorPosition(); VECTOR2I cursorPos = m_controls->GetCursorPosition();
wxPoint moveVector = m_board->m_Modules->GetPosition() - wxPoint( cursorPos.x, cursorPos.y ); wxPoint moveVector = module->GetPosition() - wxPoint( cursorPos.x, cursorPos.y );
m_board->m_Modules->MoveAnchorPosition( moveVector ); module->MoveAnchorPosition( moveVector );
m_board->m_Modules->ViewUpdate(); commit.Push( _( "Move the footprint reference anchor" ) );
// Usually, we do not need to change twice the anchor position, // Usually, we do not need to change twice the anchor position,
// so deselect the active tool // so deselect the active tool
@ -751,51 +806,25 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
( evt->IsDblClick( BUT_LEFT ) && aShape == S_SEGMENT ) ) ( evt->IsDblClick( BUT_LEFT ) && aShape == S_SEGMENT ) )
// User has clicked twice in the same spot // User has clicked twice in the same spot
{ // a clear sign that the current drawing is finished { // a clear sign that the current drawing is finished
// Now we have to add the helper line as well
if( direction45 ) if( direction45 )
{ {
// Now we have to add the helper line as well BOARD_ITEM_CONTAINER* parent = m_frame->GetModel();
if( m_editModules ) DRAWSEGMENT* l = m_editModules ? new EDGE_MODULE( (MODULE*) parent )
{ : new DRAWSEGMENT;
EDGE_MODULE* l = new EDGE_MODULE( m_board->m_Modules );
// Copy coordinates, layer, etc. // Copy coordinates, layer, etc.
*static_cast<DRAWSEGMENT*>( l ) = line45; *static_cast<DRAWSEGMENT*>( l ) = line45;
l->SetEnd( aGraphic->GetStart() ); l->SetEnd( aGraphic->GetStart() );
l->SetLocalCoord();
m_frame->SaveCopyInUndoList( m_board->m_Modules, UR_MODEDIT ); BOARD_COMMIT commit( m_frame );
m_board->m_Modules->SetLastEditTime(); commit.Add( l );
m_board->m_Modules->GraphicalItems().PushFront( l ); commit.Push( _( "Draw a line" ) );
m_view->Add( l );
l->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
}
else
{
DRAWSEGMENT* l = static_cast<DRAWSEGMENT*>( line45.Clone() );
l->SetEnd( aGraphic->GetStart() );
m_frame->SaveCopyInUndoList( l, UR_NEW );
m_board->Add( l );
m_view->Add( l );
l->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
}
m_frame->OnModify();
} }
delete aGraphic; delete aGraphic;
aGraphic = NULL; aGraphic = NULL;
} }
else
{
assert( aGraphic->GetLength() > 0 );
assert( aGraphic->GetWidth() > 0 );
m_view->Add( aGraphic );
aGraphic->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
}
preview.Clear(); preview.Clear();
break; break;
@ -882,7 +911,6 @@ bool DRAWING_TOOL::drawArc( DRAWSEGMENT*& aGraphic )
if( evt->IsCancel() || evt->IsActivate() ) if( evt->IsCancel() || evt->IsActivate() )
{ {
preview.Clear(); preview.Clear();
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
delete aGraphic; delete aGraphic;
aGraphic = NULL; aGraphic = NULL;
break; break;
@ -1031,10 +1059,7 @@ int DRAWING_TOOL::drawZone( bool aKeepout )
ZONE_CONTAINER* zone = NULL; ZONE_CONTAINER* zone = NULL;
DRAWSEGMENT line45; DRAWSEGMENT line45;
DRAWSEGMENT* helperLine = NULL; // we will need more than one helper line DRAWSEGMENT* helperLine = NULL; // we will need more than one helper line
BOARD_COMMIT commit( m_frame );
// if one day it is possible to draw zones in the footprint editor,
// then hereby I'm letting you know that this tool does not handle UR_MODEDIT undo yet
assert( !m_editModules );
// Add a VIEW_GROUP that serves as a preview for the new item // Add a VIEW_GROUP that serves as a preview for the new item
KIGFX::VIEW_GROUP preview( m_view ); KIGFX::VIEW_GROUP preview( m_view );
@ -1118,17 +1143,11 @@ int DRAWING_TOOL::drawZone( bool aKeepout )
zone->Outline()->CloseLastContour(); zone->Outline()->CloseLastContour();
zone->Outline()->RemoveNullSegments(); zone->Outline()->RemoveNullSegments();
m_board->Add( zone );
m_view->Add( zone );
if( !aKeepout ) if( !aKeepout )
static_cast<PCB_EDIT_FRAME*>( m_frame )->Fill_Zone( zone ); static_cast<PCB_EDIT_FRAME*>( m_frame )->Fill_Zone( zone );
zone->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); commit.Add( zone );
m_board->GetRatsnest()->Update( zone ); commit.Push( _( "Draw a zone" ) );
m_frame->OnModify();
m_frame->SaveCopyInUndoList( zone, UR_NEW );
zone = NULL; zone = NULL;
} }
@ -1246,248 +1265,6 @@ int DRAWING_TOOL::drawZone( bool aKeepout )
} }
int DRAWING_TOOL::placeTextModule()
{
TEXTE_MODULE* text = new TEXTE_MODULE( NULL );
const BOARD_DESIGN_SETTINGS& dsnSettings = m_frame->GetDesignSettings();
assert( m_editModules );
// Add a VIEW_GROUP that serves as a preview for the new item
KIGFX::VIEW_GROUP preview( m_view );
m_view->Add( &preview );
m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true );
m_controls->ShowCursor( true );
m_controls->SetSnapping( true );
// do not capture or auto-pan until we start placing some text
Activate();
m_frame->SetToolID( ID_MODEDIT_TEXT_TOOL, wxCURSOR_PENCIL, _( "Add text" ) );
bool placing = false;
// Main loop: keep receiving events
while( OPT_TOOL_EVENT evt = Wait() )
{
VECTOR2I cursorPos = m_controls->GetCursorPosition();
if( evt->IsCancel() || evt->IsActivate() )
{
preview.Clear();
preview.ViewUpdate();
m_controls->SetAutoPan( false );
m_controls->CaptureCursor( false );
m_controls->ShowCursor( true );
if( !placing || evt->IsActivate() )
{
delete text;
break;
}
else
{
placing = false; // start from the beginning
}
}
else if( text && evt->Category() == TC_COMMAND )
{
if( evt->IsAction( &COMMON_ACTIONS::rotate ) )
{
text->Rotate( text->GetPosition(), m_frame->GetRotationAngle() );
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
}
else if( evt->IsAction( &COMMON_ACTIONS::flip ) )
{
text->Flip( text->GetPosition() );
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
}
}
else if( evt->IsClick( BUT_LEFT ) )
{
if( !placing )
{
text->SetSize( dsnSettings.m_ModuleTextSize );
text->SetThickness( dsnSettings.m_ModuleTextWidth );
text->SetTextPosition( wxPoint( cursorPos.x, cursorPos.y ) );
DialogEditModuleText textDialog( m_frame, text, NULL );
placing = textDialog.ShowModal() && ( text->GetText().Length() > 0 );
if( !placing )
continue;
m_controls->CaptureCursor( true );
m_controls->SetAutoPan( true );
m_controls->ShowCursor( false );
text->SetParent( m_board->m_Modules ); // it has to set after the settings dialog
// otherwise the dialog stores it in undo buffer
preview.Add( text );
}
else
{
assert( text->GetText().Length() > 0 );
assert( text->GetSize().x > 0 && text->GetSize().y > 0 );
text->SetLocalCoord();
text->ClearFlags();
// Module has to be saved before any modification is made
m_frame->SaveCopyInUndoList( m_board->m_Modules, UR_MODEDIT );
m_board->m_Modules->SetLastEditTime();
m_board->m_Modules->GraphicalItems().PushFront( text );
m_view->Add( text );
text->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
m_frame->OnModify();
preview.Remove( text );
m_controls->CaptureCursor( false );
m_controls->SetAutoPan( false );
m_controls->ShowCursor( true );
text = new TEXTE_MODULE( NULL );
placing = false;
}
}
else if( text && evt->IsMotion() )
{
text->SetTextPosition( wxPoint( cursorPos.x, cursorPos.y ) );
// Show a preview of the item
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
}
}
m_controls->ShowCursor( false );
m_controls->SetSnapping( false );
m_controls->SetAutoPan( false );
m_controls->CaptureCursor( false );
m_view->Remove( &preview );
m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
return 0;
}
int DRAWING_TOOL::placeTextPcb()
{
TEXTE_PCB* text = NULL;
assert( !m_editModules );
// Add a VIEW_GROUP that serves as a preview for the new item
KIGFX::VIEW_GROUP preview( m_view );
m_view->Add( &preview );
m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true );
m_controls->ShowCursor( true );
m_controls->SetSnapping( true );
// do not capture or auto-pan until we start placing some text
Activate();
m_frame->SetToolID( ID_PCB_ADD_TEXT_BUTT, wxCURSOR_PENCIL, _( "Add text" ) );
// Main loop: keep receiving events
while( OPT_TOOL_EVENT evt = Wait() )
{
VECTOR2I cursorPos = m_controls->GetCursorPosition();
if( evt->IsCancel() || evt->IsActivate() )
{
if( text )
{
// Delete the old text and have another try
m_board->Delete( text ); // it was already added by CreateTextPcb()
text = NULL;
preview.Clear();
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
m_controls->SetAutoPan( false );
m_controls->CaptureCursor( false );
m_controls->ShowCursor( true );
}
else
break;
if( evt->IsActivate() ) // now finish unconditionally
break;
}
else if( text && evt->Category() == TC_COMMAND )
{
if( evt->IsAction( &COMMON_ACTIONS::rotate ) )
{
text->Rotate( text->GetPosition(), m_frame->GetRotationAngle() );
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
}
else if( evt->IsAction( &COMMON_ACTIONS::flip ) )
{
text->Flip( text->GetPosition() );
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
}
}
else if( evt->IsClick( BUT_LEFT ) )
{
if( !text )
{
// Init the new item attributes
text = static_cast<PCB_EDIT_FRAME*>( m_frame )->CreateTextePcb( NULL );
if( text == NULL )
continue;
m_controls->CaptureCursor( true );
m_controls->SetAutoPan( true );
preview.Add( text );
}
else
{
assert( text->GetText().Length() > 0 );
assert( text->GetSize().x > 0 && text->GetSize().y > 0 );
text->ClearFlags();
m_view->Add( text );
// m_board->Add( text ); // it is already added by CreateTextePcb()
text->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
m_frame->OnModify();
m_frame->SaveCopyInUndoList( text, UR_NEW );
preview.Remove( text );
m_controls->CaptureCursor( false );
m_controls->SetAutoPan( false );
text = NULL;
}
}
else if( text && evt->IsMotion() )
{
text->SetTextPosition( wxPoint( cursorPos.x, cursorPos.y ) );
// Show a preview of the item
preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
}
}
m_controls->ShowCursor( false );
m_controls->SetSnapping( false );
m_controls->SetAutoPan( false );
m_controls->CaptureCursor( false );
m_view->Remove( &preview );
m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString );
return 0;
}
void DRAWING_TOOL::make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper ) const void DRAWING_TOOL::make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper ) const
{ {
VECTOR2I cursorPos = m_controls->GetCursorPosition(); VECTOR2I cursorPos = m_controls->GetCursorPosition();

View File

@ -25,7 +25,7 @@
#ifndef __DRAWING_TOOL_H #ifndef __DRAWING_TOOL_H
#define __DRAWING_TOOL_H #define __DRAWING_TOOL_H
#include <tool/tool_interactive.h> #include <tools/pcb_tool.h>
#include <boost/optional.hpp> #include <boost/optional.hpp>
namespace KIGFX namespace KIGFX
@ -34,7 +34,7 @@ namespace KIGFX
class VIEW_CONTROLS; class VIEW_CONTROLS;
} }
class BOARD; class BOARD;
class PCB_EDIT_FRAME; class PCB_BASE_EDIT_FRAME;
class DRAWSEGMENT; class DRAWSEGMENT;
/** /**
@ -43,7 +43,7 @@ class DRAWSEGMENT;
* Tool responsible for drawing graphical elements like lines, arcs, circles, etc. * Tool responsible for drawing graphical elements like lines, arcs, circles, etc.
*/ */
class DRAWING_TOOL : public TOOL_INTERACTIVE class DRAWING_TOOL : public PCB_TOOL
{ {
public: public:
DRAWING_TOOL(); DRAWING_TOOL();
@ -121,17 +121,6 @@ public:
*/ */
int SetAnchor( const TOOL_EVENT& aEvent ); int SetAnchor( const TOOL_EVENT& aEvent );
/**
* Function EditModules()
* Toggles edit module mode. When enabled, one may select parts of modules individually
* (graphics, pads, etc.), so they can be modified.
* @param aEnabled decides if the mode should be enabled.
*/
void EditModules( bool aEnabled )
{
m_editModules = aEnabled;
}
///> Sets up handlers for various events. ///> Sets up handlers for various events.
void SetTransitions(); void SetTransitions();
@ -156,20 +145,6 @@ private:
///> @param aKeepout decides if the drawn polygon is a zone or a keepout area. ///> @param aKeepout decides if the drawn polygon is a zone or a keepout area.
int drawZone( bool aKeepout ); int drawZone( bool aKeepout );
/**
* Function placeTextModule()
* Displays a dialog that allows to input text and its settings and then lets the user decide
* where to place the text in module .
*/
int placeTextModule();
/**
* Function placeTextPcb()
* Displays a dialog that allows to input text and its settings and then lets the user decide
* where to place the text in board editor.
*/
int placeTextPcb();
/** /**
* Function make45DegLine() * Function make45DegLine()
* Forces a DRAWSEGMENT to be drawn at multiple of 45 degrees. The origin stays the same, * Forces a DRAWSEGMENT to be drawn at multiple of 45 degrees. The origin stays the same,
@ -185,10 +160,7 @@ private:
KIGFX::VIEW* m_view; KIGFX::VIEW* m_view;
KIGFX::VIEW_CONTROLS* m_controls; KIGFX::VIEW_CONTROLS* m_controls;
BOARD* m_board; BOARD* m_board;
PCB_EDIT_FRAME* m_frame; PCB_BASE_EDIT_FRAME* m_frame;
/// Edit module mode flag
bool m_editModules;
/// Stores the current line width for multisegment drawing. /// Stores the current line width for multisegment drawing.
unsigned int m_lineWidth; unsigned int m_lineWidth;

View File

@ -56,10 +56,11 @@ using namespace std::placeholders;
#include <dialogs/dialog_move_exact.h> #include <dialogs/dialog_move_exact.h>
#include <dialogs/dialog_track_via_properties.h> #include <dialogs/dialog_track_via_properties.h>
#include <board_commit.h>
EDIT_TOOL::EDIT_TOOL() : EDIT_TOOL::EDIT_TOOL() :
TOOL_INTERACTIVE( "pcbnew.InteractiveEdit" ), m_selectionTool( NULL ), PCB_TOOL( "pcbnew.InteractiveEdit" ), m_selectionTool( NULL ),
m_dragging( false ), m_editModules( false ), m_undoInhibit( 0 ), m_dragging( false ), m_updateFlag( KIGFX::VIEW_ITEM::NONE )
m_updateFlag( KIGFX::VIEW_ITEM::NONE )
{ {
} }
@ -68,6 +69,9 @@ void EDIT_TOOL::Reset( RESET_REASON aReason )
{ {
m_dragging = false; m_dragging = false;
m_updateFlag = KIGFX::VIEW_ITEM::NONE; m_updateFlag = KIGFX::VIEW_ITEM::NONE;
if( aReason != RUN )
m_commit.reset( new BOARD_COMMIT( this ) );
} }
@ -111,9 +115,6 @@ bool EDIT_TOOL::invokeInlineRouter()
TRACK* track = uniqueSelected<TRACK>(); TRACK* track = uniqueSelected<TRACK>();
VIA* via = uniqueSelected<VIA>(); VIA* via = uniqueSelected<VIA>();
if( isUndoInhibited() )
return false;
if( track || via ) if( track || via )
{ {
ROUTER_TOOL* theRouter = static_cast<ROUTER_TOOL*>( m_toolMgr->FindTool( "pcbnew.InteractiveRouter" ) ); ROUTER_TOOL* theRouter = static_cast<ROUTER_TOOL*>( m_toolMgr->FindTool( "pcbnew.InteractiveRouter" ) );
@ -143,7 +144,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
// Be sure that there is at least one item that we can modify. If nothing was selected before, // Be sure that there is at least one item that we can modify. If nothing was selected before,
// try looking for the stuff under mouse cursor (i.e. Kicad old-style hover selection) // try looking for the stuff under mouse cursor (i.e. Kicad old-style hover selection)
if( !hoverSelection( selection ) ) if( !hoverSelection() )
return 0; return 0;
Activate(); Activate();
@ -215,11 +216,10 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
lockOverride = true; lockOverride = true;
// Save items, so changes can be undone // Save items, so changes can be undone
if( !isUndoInhibited() ) selection.ForAll<BOARD_ITEM>( [&](BOARD_ITEM* item)
{ {
editFrame->OnModify(); m_commit->Modify( item );
editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); } );
}
m_cursor = controls->GetCursorPosition(); m_cursor = controls->GetCursorPosition();
@ -244,17 +244,18 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
controls->SetAutoPan( true ); controls->SetAutoPan( true );
m_dragging = true; m_dragging = true;
incUndoInhibit();
} }
} }
selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate, true ); m_toolMgr->RunAction( COMMON_ACTIONS::editModifiedSelection, true );
} }
// Dispatch TOOL_ACTIONs // Dispatch TOOL_ACTIONs
else if( evt->Category() == TC_COMMAND ) else if( evt->Category() == TC_COMMAND )
{ {
wxPoint modPoint = getModificationPoint( selection );
if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) if( evt->IsAction( &COMMON_ACTIONS::rotate ) )
{ {
Rotate( aEvent ); Rotate( aEvent );
@ -302,6 +303,14 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
//MoveExact( aEvent ); //MoveExact( aEvent );
break; // exit the loop - we move exactly, so we have finished moving break; // exit the loop - we move exactly, so we have finished moving
} }
if( m_dragging )
{
// Update dragging offset (distance between cursor and the first dragged item)
m_offset = selection.Item<BOARD_ITEM>( 0 )->GetPosition() - modPoint;
selection.group->ViewUpdate( KIGFX::VIEW_ITEM::ALL );
updateRatsnest( true );
}
} }
else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) )
@ -313,31 +322,17 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
} }
} while( ( evt = Wait() ) ); //Should be assignment not equality test } while( ( evt = Wait() ) ); //Should be assignment not equality test
if( m_dragging )
decUndoInhibit();
m_dragging = false; m_dragging = false;
m_offset.x = 0; m_offset.x = 0;
m_offset.y = 0; m_offset.y = 0;
if( restore ) if( unselect || restore )
{
// Modifications have to be rollbacked, so restore the previous state of items
wxCommandEvent dummy;
editFrame->RestoreCopyFromUndoList( dummy );
}
else
{
// Changes are applied, so update the items
selection.group->ItemsViewUpdate( m_updateFlag );
}
if( unselect )
m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true );
RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); if( restore )
ratsnest->ClearSimple(); m_commit->Revert();
ratsnest->Recalculate(); else
m_commit->Push( _( "Drag" ) );
controls->ShowCursor( false ); controls->ShowCursor( false );
controls->SetAutoPan( false ); controls->SetAutoPan( false );
@ -354,7 +349,7 @@ int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent )
// Shall the selection be cleared at the end? // Shall the selection be cleared at the end?
bool unselect = selection.Empty(); bool unselect = selection.Empty();
if( !hoverSelection( selection, false ) ) if( !hoverSelection( false ) )
return 0; return 0;
// Tracks & vias are treated in a special way: // Tracks & vias are treated in a special way:
@ -364,17 +359,8 @@ int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent )
if( dlg.ShowModal() ) if( dlg.ShowModal() )
{ {
RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest(); dlg.Apply( *m_commit );
m_commit->Push( _( "Edit track/via properties" ) );
editFrame->OnModify();
editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED );
dlg.Apply();
selection.ForAll<KIGFX::VIEW_ITEM>( std::bind( &KIGFX::VIEW_ITEM::ViewUpdate,
std::placeholders::_1, KIGFX::VIEW_ITEM::ALL ) );
selection.ForAll<BOARD_ITEM>( std::bind( &RN_DATA::Update, ratsnest,
std::placeholders::_1 ) );
ratsnest->Recalculate();
} }
} }
else if( selection.Size() == 1 ) // Properties are displayed when there is only one item selected else if( selection.Size() == 1 ) // Properties are displayed when there is only one item selected
@ -382,34 +368,18 @@ int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent )
// Display properties dialog // Display properties dialog
BOARD_ITEM* item = selection.Item<BOARD_ITEM>( 0 ); BOARD_ITEM* item = selection.Item<BOARD_ITEM>( 0 );
// Store the head of the undo list to compare if anything has changed
std::vector<PICKED_ITEMS_LIST*>& undoList = editFrame->GetScreen()->m_UndoList.m_CommandsList;
// Some of properties dialogs alter pointers, so we should deselect them // Some of properties dialogs alter pointers, so we should deselect them
m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true );
// Store flags, so they can be restored later
STATUS_FLAGS flags = item->GetFlags(); STATUS_FLAGS flags = item->GetFlags();
item->ClearFlags(); item->ClearFlags();
// It is necessary to determine if anything has changed, so store the current undo save point // Do not handle undo buffer, it is done by the properties dialogs @todo LEGACY
PICKED_ITEMS_LIST* undoSavePoint = undoList.empty() ? NULL : undoList.back();
// Display properties dialog provided by the legacy canvas frame // Display properties dialog provided by the legacy canvas frame
editFrame->OnEditItemRequest( NULL, item ); editFrame->OnEditItemRequest( NULL, item );
if( !undoList.empty() && undoList.back() != undoSavePoint ) // Undo buffer has changed m_toolMgr->RunAction( COMMON_ACTIONS::editModifiedSelection, true );
{
// Process changes stored after undoSavePoint
processUndoBuffer( undoSavePoint );
// Update the modified item
item->ViewUpdate();
RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest();
ratsnest->Recalculate();
// TODO OBSERVER! I miss you so much..
m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate, true );
}
item->SetFlags( flags ); item->SetFlags( flags );
} }
@ -428,43 +398,26 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
// Shall the selection be cleared at the end? // Shall the selection be cleared at the end?
bool unselect = selection.Empty(); bool unselect = selection.Empty();
if( !hoverSelection( selection ) || m_selectionTool->CheckLock() == SELECTION_LOCKED ) if( !hoverSelection() || m_selectionTool->CheckLock() == SELECTION_LOCKED )
return 0; return 0;
wxPoint rotatePoint = getModificationPoint( selection ); wxPoint rotatePoint = getModificationPoint( selection );
// If it is being dragged, then it is already saved with UR_CHANGED flag
if( !isUndoInhibited() )
{
editFrame->OnModify();
editFrame->SaveCopyInUndoList( selection.items, UR_ROTATED, rotatePoint );
}
for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) for( unsigned int i = 0; i < selection.items.GetCount(); ++i )
{ {
BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i ); BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i );
m_commit->Modify( item );
item->Rotate( rotatePoint, editFrame->GetRotationAngle() ); item->Rotate( rotatePoint, editFrame->GetRotationAngle() );
if( !m_dragging )
item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
} }
updateRatsnest( m_dragging ); if( !m_dragging )
m_commit->Push( _( "Rotate" ) );
// Update dragging offset (distance between cursor and the first dragged item)
m_offset = static_cast<BOARD_ITEM*>( selection.items.GetPickedItem( 0 ) )->GetPosition() -
rotatePoint;
if( m_dragging )
selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
else
getModel<BOARD>()->GetRatsnest()->Recalculate();
if( unselect ) if( unselect )
m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true );
m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate, true ); // TODO selectionModified
m_toolMgr->RunAction( COMMON_ACTIONS::editModifiedSelection, true );
return 0; return 0;
} }
@ -473,47 +426,29 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent ) int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent )
{ {
const SELECTION& selection = m_selectionTool->GetSelection(); const SELECTION& selection = m_selectionTool->GetSelection();
PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>();
// Shall the selection be cleared at the end? // Shall the selection be cleared at the end?
bool unselect = selection.Empty(); bool unselect = selection.Empty();
if( !hoverSelection( selection ) || m_selectionTool->CheckLock() == SELECTION_LOCKED ) if( !hoverSelection() || m_selectionTool->CheckLock() == SELECTION_LOCKED )
return 0; return 0;
wxPoint flipPoint = getModificationPoint( selection ); wxPoint flipPoint = getModificationPoint( selection );
if( !isUndoInhibited() ) // If it is being dragged, then it is already saved with UR_CHANGED flag
{
editFrame->OnModify();
editFrame->SaveCopyInUndoList( selection.items, UR_FLIPPED, flipPoint );
}
for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) for( unsigned int i = 0; i < selection.items.GetCount(); ++i )
{ {
BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i ); BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i );
m_commit->Modify( item );
item->Flip( flipPoint ); item->Flip( flipPoint );
if( !m_dragging )
item->ViewUpdate( KIGFX::VIEW_ITEM::LAYERS );
} }
updateRatsnest( m_dragging ); if( !m_dragging )
m_commit->Push( _( "Flip" ) );
// Update dragging offset (distance between cursor and the first dragged item)
m_offset = static_cast<BOARD_ITEM*>( selection.items.GetPickedItem( 0 ) )->GetPosition() -
flipPoint;
if( m_dragging )
selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
else
getModel<BOARD>()->GetRatsnest()->Recalculate();
if( unselect ) if( unselect )
m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true );
m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate, true ); m_toolMgr->RunAction( COMMON_ACTIONS::editModifiedSelection, true );
return 0; return 0;
} }
@ -521,126 +456,27 @@ int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent )
int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent ) int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent )
{ {
const SELECTION& selection = m_selectionTool->GetSelection(); if( !hoverSelection() || m_selectionTool->CheckLock() == SELECTION_LOCKED )
if( !hoverSelection( selection ) || m_selectionTool->CheckLock() == SELECTION_LOCKED )
return 0; return 0;
// Get a copy of the selected items set // Get a copy instead of a reference, as we are going to clear current selection
PICKED_ITEMS_LIST selectedItems = selection.items; SELECTION selection = m_selectionTool->GetSelection();
PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>();
// As we are about to remove items, they have to be removed from the selection first // As we are about to remove items, they have to be removed from the selection first
m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true );
// Save them for( unsigned int i = 0; i < selection.items.GetCount(); ++i )
for( unsigned int i = 0; i < selectedItems.GetCount(); ++i ) {
selectedItems.SetPickedItemStatus( UR_DELETED, i ); BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i );
m_commit->Remove( item );
}
editFrame->OnModify(); m_commit->Push( _( "Delete" ) );
editFrame->SaveCopyInUndoList( selectedItems, UR_DELETED );
// And now remove
for( unsigned int i = 0; i < selectedItems.GetCount(); ++i )
remove( static_cast<BOARD_ITEM*>( selectedItems.GetPickedItem( i ) ) );
getModel<BOARD>()->GetRatsnest()->Recalculate();
return 0; return 0;
} }
void EDIT_TOOL::remove( BOARD_ITEM* aItem )
{
BOARD* board = getModel<BOARD>();
switch( aItem->Type() )
{
case PCB_MODULE_T:
{
MODULE* module = static_cast<MODULE*>( aItem );
module->ClearFlags();
module->RunOnChildren( std::bind( &KIGFX::VIEW::Remove, getView(), std::placeholders::_1 ) );
// Module itself is deleted after the switch scope is finished
// list of pads is rebuild by BOARD::BuildListOfNets()
// Clear flags to indicate, that the ratsnest, list of nets & pads are not valid anymore
board->m_Status_Pcb = 0;
}
break;
// Default removal procedure
case PCB_MODULE_TEXT_T:
{
TEXTE_MODULE* text = static_cast<TEXTE_MODULE*>( aItem );
switch( text->GetType() )
{
case TEXTE_MODULE::TEXT_is_REFERENCE:
DisplayError( getEditFrame<PCB_BASE_FRAME>(), _( "Cannot delete component reference." ) );
return;
case TEXTE_MODULE::TEXT_is_VALUE:
DisplayError( getEditFrame<PCB_BASE_FRAME>(), _( "Cannot delete component value." ) );
return;
case TEXTE_MODULE::TEXT_is_DIVERS: // suppress warnings
break;
}
if( m_editModules )
{
MODULE* module = static_cast<MODULE*>( aItem->GetParent() );
module->SetLastEditTime();
board->m_Status_Pcb = 0; // it is done in the legacy view
aItem->DeleteStructure();
}
return;
}
case PCB_PAD_T:
case PCB_MODULE_EDGE_T:
{
MODULE* module = static_cast<MODULE*>( aItem->GetParent() );
module->SetLastEditTime();
board->m_Status_Pcb = 0; // it is done in the legacy view
if( !m_editModules )
{
getView()->Remove( aItem );
board->Remove( aItem );
}
aItem->DeleteStructure();
return;
}
case PCB_LINE_T: // a segment not on copper layers
case PCB_TEXT_T: // a text on a layer
case PCB_TRACE_T: // a track segment (segment on a copper layer)
case PCB_VIA_T: // a via (like track segment on a copper layer)
case PCB_DIMENSION_T: // a dimension (graphic item)
case PCB_TARGET_T: // a target (graphic item)
case PCB_MARKER_T: // a marker used to show something
case PCB_ZONE_T: // SEG_ZONE items are now deprecated
case PCB_ZONE_AREA_T:
break;
default: // other types do not need to (or should not) be handled
assert( false );
return;
}
getView()->Remove( aItem );
board->Remove( aItem );
}
int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent ) int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent )
{ {
const SELECTION& selection = m_selectionTool->GetSelection(); const SELECTION& selection = m_selectionTool->GetSelection();
@ -648,7 +484,7 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent )
// Shall the selection be cleared at the end? // Shall the selection be cleared at the end?
bool unselect = selection.Empty(); bool unselect = selection.Empty();
if( !hoverSelection( selection ) || m_selectionTool->CheckLock() == SELECTION_LOCKED ) if( !hoverSelection() || m_selectionTool->CheckLock() == SELECTION_LOCKED )
return 0; return 0;
wxPoint translation; wxPoint translation;
@ -661,13 +497,6 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent )
if( ret == wxID_OK ) if( ret == wxID_OK )
{ {
if( !isUndoInhibited() )
{
editFrame->OnModify();
// Record an action of move and rotate
editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED );
}
VECTOR2I rp = selection.GetCenter(); VECTOR2I rp = selection.GetCenter();
wxPoint rotPoint( rp.x, rp.y ); wxPoint rotPoint( rp.x, rp.y );
@ -675,6 +504,7 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent )
{ {
BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i ); BOARD_ITEM* item = selection.Item<BOARD_ITEM>( i );
m_commit->Modify( item );
item->Move( translation ); item->Move( translation );
item->Rotate( rotPoint, rotation ); item->Rotate( rotPoint, rotation );
@ -682,17 +512,12 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent )
item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
} }
updateRatsnest( m_dragging ); m_commit->Push( _( "Move exact" ) );
if( m_dragging )
selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
else
getModel<BOARD>()->GetRatsnest()->Recalculate();
if( unselect ) if( unselect )
m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true );
m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate, true ); m_toolMgr->RunAction( COMMON_ACTIONS::editModifiedSelection, true );
} }
return 0; return 0;
@ -710,21 +535,11 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
const SELECTION& selection = selTool->GetSelection(); const SELECTION& selection = selTool->GetSelection();
// Be sure that there is at least one item that we can modify // Be sure that there is at least one item that we can modify
if( !hoverSelection( selection ) ) if( !hoverSelection() )
return 0; return 0;
// we have a selection to work on now, so start the tool process // we have a selection to work on now, so start the tool process
PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>();
editFrame->OnModify();
// prevent other tools making undo points while the duplicate is going on
// so that if you cancel, you don't get a duplicate object hiding over
// the original
incUndoInhibit();
if( m_editModules )
editFrame->SaveCopyInUndoList( editFrame->GetBoard()->m_Modules, UR_MODEDIT );
std::vector<BOARD_ITEM*> old_items; std::vector<BOARD_ITEM*> old_items;
@ -748,7 +563,7 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
BOARD_ITEM* new_item = NULL; BOARD_ITEM* new_item = NULL;
if( m_editModules ) if( m_editModules )
new_item = editFrame->GetBoard()->m_Modules->DuplicateAndAddItem( item, increment ); new_item = editFrame->GetBoard()->m_Modules->Duplicate( item, increment );
else else
{ {
#if 0 #if 0
@ -757,18 +572,12 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
// so zones are not duplicated // so zones are not duplicated
if( item->Type() != PCB_ZONE_AREA_T ) if( item->Type() != PCB_ZONE_AREA_T )
#endif #endif
new_item = editFrame->GetBoard()->DuplicateAndAddItem( item ); new_item = editFrame->GetBoard()->Duplicate( item );
} }
if( new_item ) if( new_item )
{ {
if( new_item->Type() == PCB_MODULE_T ) m_commit->Add( new_item );
{
static_cast<MODULE*>( new_item )->RunOnChildren( std::bind( &KIGFX::VIEW::Add,
getView(), std::placeholders::_1 ) );
}
editFrame->GetGalCanvas()->GetView()->Add( new_item );
// Select the new item, so we can pick it up // Select the new item, so we can pick it up
m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, new_item ); m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, new_item );
@ -776,22 +585,17 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
} }
// record the new items as added // record the new items as added
if( !m_editModules && !selection.Empty() ) if( !selection.Empty() )
{ {
editFrame->SaveCopyInUndoList( selection.items, UR_NEW );
editFrame->DisplayToolMsg( wxString::Format( _( "Duplicated %d item(s)" ), editFrame->DisplayToolMsg( wxString::Format( _( "Duplicated %d item(s)" ),
(int) old_items.size() ) ); (int) old_items.size() ) );
// If items were duplicated, pick them up // If items were duplicated, pick them up
// this works well for "dropping" copies around // this works well for "dropping" copies around and pushes the commit
TOOL_EVENT evt = COMMON_ACTIONS::editActivate.MakeEvent(); TOOL_EVENT evt = COMMON_ACTIONS::editActivate.MakeEvent();
Main( evt ); Main( evt );
} }
// and re-enable undos
decUndoInhibit();
return 0; return 0;
}; };
@ -801,11 +605,9 @@ class GAL_ARRAY_CREATOR: public ARRAY_CREATOR
public: public:
GAL_ARRAY_CREATOR( PCB_BASE_FRAME& editFrame, bool editModules, GAL_ARRAY_CREATOR( PCB_BASE_FRAME& editFrame, bool editModules,
RN_DATA* ratsnest,
const SELECTION& selection ): const SELECTION& selection ):
ARRAY_CREATOR( editFrame ), ARRAY_CREATOR( editFrame ),
m_editModules( editModules ), m_editModules( editModules ),
m_ratsnest( ratsnest ),
m_selection( selection ) m_selection( selection )
{} {}
@ -848,24 +650,13 @@ private:
void postPushAction( BOARD_ITEM* new_item ) //override void postPushAction( BOARD_ITEM* new_item ) //override
{ {
KIGFX::VIEW* view = m_parent.GetToolManager()->GetView();
if( new_item->Type() == PCB_MODULE_T)
{
static_cast<MODULE*>(new_item)->RunOnChildren(
std::bind(&KIGFX::VIEW::Add, view, std::placeholders::_1));
}
m_parent.GetGalCanvas()->GetView()->Add( new_item );
m_ratsnest->Update( new_item );
} }
void finalise() // override void finalise() // override
{ {
m_ratsnest->Recalculate();
} }
bool m_editModules; bool m_editModules;
RN_DATA* m_ratsnest;
const SELECTION& m_selection; const SELECTION& m_selection;
}; };
@ -877,18 +668,12 @@ int EDIT_TOOL::CreateArray( const TOOL_EVENT& aEvent )
const SELECTION& selection = selTool->GetSelection(); const SELECTION& selection = selTool->GetSelection();
// pick up items under the cursor if needed // pick up items under the cursor if needed
if( !hoverSelection( selection ) ) if( !hoverSelection() )
return 0; return 0;
// we have a selection to work on now, so start the tool process // we have a selection to work on now, so start the tool process
PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>(); PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>();
editFrame->OnModify(); GAL_ARRAY_CREATOR array_creator( *editFrame, m_editModules, selection );
GAL_ARRAY_CREATOR array_creator( *editFrame, m_editModules,
getModel<BOARD>()->GetRatsnest(),
selection );
array_creator.Invoke(); array_creator.Invoke();
return 0; return 0;
@ -947,9 +732,11 @@ wxPoint EDIT_TOOL::getModificationPoint( const SELECTION& aSelection )
} }
bool EDIT_TOOL::hoverSelection( const SELECTION& aSelection, bool aSanitize ) bool EDIT_TOOL::hoverSelection( bool aSanitize )
{ {
if( aSelection.Empty() ) // Try to find an item that could be modified const SELECTION& selection = m_selectionTool->GetSelection();
if( selection.Empty() ) // Try to find an item that could be modified
{ {
m_toolMgr->RunAction( COMMON_ACTIONS::selectionCursor, true ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionCursor, true );
@ -963,79 +750,10 @@ bool EDIT_TOOL::hoverSelection( const SELECTION& aSelection, bool aSanitize )
if( aSanitize ) if( aSanitize )
m_selectionTool->SanitizeSelection(); m_selectionTool->SanitizeSelection();
if( aSelection.Empty() ) // TODO is it necessary? if( selection.Empty() ) // TODO is it necessary?
m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true );
return !aSelection.Empty(); return !selection.Empty();
}
void EDIT_TOOL::processUndoBuffer( const PICKED_ITEMS_LIST* aLastChange )
{
PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
const std::vector<PICKED_ITEMS_LIST*>& undoList = editFrame->GetScreen()->m_UndoList.m_CommandsList;
bool process = false;
for( const PICKED_ITEMS_LIST* list : undoList )
{
if( process )
processPickedList( list );
else if( list == aLastChange )
process = true; // Start processing starting with the next undo save point
}
// If we could not find the requested save point in the current undo list
// then the undo list must have been completely altered, so process everything
if( !process )
{
for( const PICKED_ITEMS_LIST* list : undoList )
processPickedList( list );
}
}
void EDIT_TOOL::processPickedList( const PICKED_ITEMS_LIST* aList )
{
KIGFX::VIEW* view = getView();
RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest();
for( unsigned int i = 0; i < aList->GetCount(); ++i )
{
UNDO_REDO_T operation = aList->GetPickedItemStatus( i );
BOARD_ITEM* updItem = static_cast<BOARD_ITEM*>( aList->GetPickedItem( i ) );
switch( operation )
{
case UR_CHANGED:
ratsnest->Update( updItem );
// fall through
case UR_MODEDIT:
updItem->ViewUpdate( KIGFX::VIEW_ITEM::ALL );
break;
case UR_DELETED:
if( updItem->Type() == PCB_MODULE_T )
static_cast<MODULE*>( updItem )->RunOnChildren( std::bind( &KIGFX::VIEW::Remove,
view, std::placeholders::_1 ) );
view->Remove( updItem );
//ratsnest->Remove( updItem ); // this is done in BOARD::Remove
break;
case UR_NEW:
if( updItem->Type() == PCB_MODULE_T )
static_cast<MODULE*>( updItem )->RunOnChildren( std::bind( &KIGFX::VIEW::Add,
view, std::placeholders::_1 ) );
view->Add( updItem );
//ratsnest->Add( updItem ); // this is done in BOARD::Add
break;
default:
assert( false ); // Not handled
break;
}
}
} }
@ -1044,7 +762,7 @@ int EDIT_TOOL::editFootprintInFpEditor( const TOOL_EVENT& aEvent )
const SELECTION& selection = m_selectionTool->GetSelection(); const SELECTION& selection = m_selectionTool->GetSelection();
bool unselect = selection.Empty(); bool unselect = selection.Empty();
if( !hoverSelection( selection ) ) if( !hoverSelection() )
return 0; return 0;
MODULE* mod = uniqueSelected<MODULE>(); MODULE* mod = uniqueSelected<MODULE>();
@ -1054,7 +772,7 @@ int EDIT_TOOL::editFootprintInFpEditor( const TOOL_EVENT& aEvent )
PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>(); PCB_BASE_EDIT_FRAME* editFrame = getEditFrame<PCB_BASE_EDIT_FRAME>();
editFrame-> SetCurItem( mod ); editFrame->SetCurItem( mod );
if( editFrame->GetCurItem()->GetTimeStamp() == 0 ) // Module Editor needs a non null timestamp if( editFrame->GetCurItem()->GetTimeStamp() == 0 ) // Module Editor needs a non null timestamp
{ {

View File

@ -27,9 +27,10 @@
#define __EDIT_TOOL_H #define __EDIT_TOOL_H
#include <math/vector2d.h> #include <math/vector2d.h>
#include <tool/tool_interactive.h> #include <tools/pcb_tool.h>
#include <view/view_group.h> #include <view/view_group.h>
class BOARD_COMMIT;
class BOARD_ITEM; class BOARD_ITEM;
class SELECTION_TOOL; class SELECTION_TOOL;
@ -45,7 +46,7 @@ class VIEW_GROUP;
* using the pcbnew.InteractiveSelection tool. * using the pcbnew.InteractiveSelection tool.
*/ */
class EDIT_TOOL : public TOOL_INTERACTIVE class EDIT_TOOL : public PCB_TOOL
{ {
public: public:
EDIT_TOOL(); EDIT_TOOL();
@ -114,17 +115,6 @@ public:
*/ */
int CreateArray( const TOOL_EVENT& aEvent ); int CreateArray( const TOOL_EVENT& aEvent );
/**
* Function EditModules()
*
* Toggles edit module mode. When enabled, one may select parts of modules individually
* (graphics, pads, etc.), so they can be modified.
* @param aEnabled decides if the mode should be enabled.
*/
void EditModules( bool aEnabled )
{
m_editModules = aEnabled;
}
///> Sets up handlers for various events. ///> Sets up handlers for various events.
void SetTransitions(); void SetTransitions();
@ -143,15 +133,6 @@ private:
///> of edit reference point). ///> of edit reference point).
VECTOR2I m_cursor; VECTOR2I m_cursor;
/// Edit module mode flag
bool m_editModules;
/// Counter of undo inhibitions. When zero, undo is not inhibited.
int m_undoInhibit;
///> Removes and frees a single BOARD_ITEM.
void remove( BOARD_ITEM* aItem );
///> The required update flag for modified items ///> The required update flag for modified items
KIGFX::VIEW_ITEM::VIEW_UPDATE_FLAGS m_updateFlag; KIGFX::VIEW_ITEM::VIEW_UPDATE_FLAGS m_updateFlag;
@ -172,49 +153,8 @@ private:
wxPoint getModificationPoint( const SELECTION& aSelection ); wxPoint getModificationPoint( const SELECTION& aSelection );
///> If there are no items currently selected, it tries to choose the item that is under ///> If there are no items currently selected, it tries to choose the item that is under
///> the cursor or displays a disambiguation menu if there are multpile items. ///> the cursor or displays a disambiguation menu if there are multiple items.
bool hoverSelection( const SELECTION& aSelection, bool aSanitize = true ); bool hoverSelection( bool aSanitize = true );
///> Processes the current undo buffer since the last change. If the last change does not occur
///> in the current buffer, then the whole list is processed.
void processUndoBuffer( const PICKED_ITEMS_LIST* aLastChange );
///> Updates items stored in the list.
void processPickedList( const PICKED_ITEMS_LIST* aList );
/**
* Increments the undo inhibit counter. This will indicate that tools
* should not create an undo point, as another tool is doing it already,
* and considers that its operation is atomic, even if it calls another one
* (for example a duplicate calls a move).
*/
inline void incUndoInhibit()
{
m_undoInhibit++;
}
/**
* Decrements the inhibit counter. An assert is raised if the counter drops
* below zero.
*/
inline void decUndoInhibit()
{
m_undoInhibit--;
wxASSERT_MSG( m_undoInhibit >= 0, wxT( "Undo inhibit count decremented past zero" ) );
}
/**
* Report if the tool manager has been told at least once that undo
* points should not be created. This can be ignored if the undo point
* is still required.
*
* @return true if undo are inhibited
*/
inline bool isUndoInhibited() const
{
return m_undoInhibit > 0;
}
int editFootprintInFpEditor( const TOOL_EVENT& aEvent ); int editFootprintInFpEditor( const TOOL_EVENT& aEvent );
@ -230,6 +170,8 @@ private:
BOARD_ITEM* item = selection.Item<BOARD_ITEM>( 0 ); BOARD_ITEM* item = selection.Item<BOARD_ITEM>( 0 );
return dyn_cast<T*>( item ); return dyn_cast<T*>( item );
} }
std::unique_ptr<BOARD_COMMIT> m_commit;
}; };
#endif #endif

Some files were not shown because too many files have changed in this diff Show More