KiCad PCB EDA Suite
Loading...
Searching...
No Matches
load_select_footprint.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2018 Jean-Pierre Charras, [email protected]
5 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22#include <functional>
23using namespace std::placeholders;
24
25#include <board.h>
26#include <footprint.h>
27#include <confirm.h>
29#include <eda_list_dialog.h>
35#include <pcb_io/pcb_io_mgr.h>
36#include <string_utils.h>
37#include <kiway.h>
38#include <lib_id.h>
39#include <macros.h>
41#include <pcb_edit_frame.h>
42#include <pcbnew_settings.h>
44#include <drc/drc_item.h>
45#include <view/view_controls.h>
47#include <widgets/lib_tree.h>
50#include <project_pcb.h>
51#include <locale_io.h>
52
53
54static wxArrayString s_FootprintHistoryList;
55static unsigned s_FootprintHistoryMaxCount = 8;
56
57static void AddFootprintToHistory( const wxString& aName )
58{
59 // Remove duplicates
60 for( int ii = s_FootprintHistoryList.GetCount() - 1; ii >= 0; --ii )
61 {
62 if( s_FootprintHistoryList[ ii ] == aName )
63 s_FootprintHistoryList.RemoveAt((size_t) ii );
64 }
65
66 // Add the new name at the beginning of the history list
67 s_FootprintHistoryList.Insert( aName, 0 );
68
69 // Remove extra names
71 s_FootprintHistoryList.RemoveAt( s_FootprintHistoryList.GetCount() - 1 );
72}
73
74
75#include <bitmaps.h>
77{
78 bool is_last_fp_from_brd = IsCurrentFPFromBoard();
79
80 FOOTPRINT* newFootprint = nullptr;
82
83 if( frame == nullptr ) // happens if no board editor opened
84 return false;
85
86 if( aFootprint == nullptr )
87 {
88 if( !frame->GetBoard() || !frame->GetBoard()->GetFirstFootprint() )
89 return false;
90
91 aFootprint = SelectFootprintFromBoard( frame->GetBoard() );
92 }
93
94 if( aFootprint == nullptr )
95 return false;
96
97 // Ensure we do not have the pad editor open (that is apseudo modal dlg).
98 // LoadFootprintFromBoard() can be called from the board editor, and we must ensure
99 // no footprint item is currently in edit
100 if( wxWindow::FindWindowByName( PAD_PROPERTIES_DLG_NAME ) )
101 wxWindow::FindWindowByName( PAD_PROPERTIES_DLG_NAME )->Close();
102
103 // Open the placed footprint as a session-only instance tab over its own fp-holder board instead
104 // of replacing the working document; re-editing the same footprint focuses the existing tab.
105 wxCHECK( m_tabsPanel, false );
106
107 const wxString instanceKey =
109 const bool createdNewTab = m_tabsPanel->FindTab( instanceKey ) < 0;
110
112
113 if( !ctx )
114 return false;
115
116 newFootprint = ctx->GetBoard()->GetFirstFootprint();
117
118 // A board-sourced footprint follows the board, not the library, so do not watch a lib file.
119 setFPWatcher( nullptr );
120
121 // Show a scaled placement in its library (unscaled) frame in the editor. The board scale is
122 // re-applied on save via ExchangeFootprint. Only a freshly opened tab needs this reset.
123 if( createdNewTab )
124 newFootprint->SetTransformScale( 1.0, 1.0 );
125
126 Zoom_Automatique( false );
127
128 m_adapter->SetPreselectNode( newFootprint->GetFPID(), 0 );
129
130 // A re-focused instance tab keeps its live edit history; only a freshly opened tab starts clean.
131 if( createdNewTab )
132 {
134 GetScreen()->SetContentModified( false );
135 }
136
137 // Update the save items if needed.
138 if( !is_last_fp_from_brd )
139 {
142
143 if( IsLibraryTreeShown() )
145 }
146
147 Update3DView( true, true );
148 UpdateView();
149 GetCanvas()->Refresh();
150 m_treePane->GetLibTree()->RefreshLibTree(); // update any previously-highlighted items
151
152 return true;
153}
154
155
157{
158 wxString footprintName = aPreselect.Format().wx_str();
159 LIB_ID fpid;
160 FOOTPRINT* footprint = nullptr;
161
162 static wxString lastComponentName;
163
164 if( KIWAY_PLAYER* frame = Kiway().Player( FRAME_FOOTPRINT_CHOOSER, true, this ) )
165 {
166 if( frame->ShowModal( &footprintName, this ) )
167 fpid.Parse( UTF8( footprintName ) );
168
169 frame->Destroy();
170 }
171
172 if( !fpid.IsValid() )
173 return nullptr;
174
175 footprint = LoadFootprint( fpid );
176
177 if( footprint )
178 {
179 lastComponentName = footprintName;
180 AddFootprintToHistory( footprintName );
181 }
182
183 return footprint;
184}
185
186
188{
189 // When loading a footprint from a library in the footprint editor
190 // the items UUIDs must be keep and not reinitialized
191 bool keepUUID = IsType( FRAME_FOOTPRINT_EDITOR );
192
193 return LoadFootprintFromProject( m_pcb, aFootprintId, keepUUID );
194}
195
196
198{
199 static wxString oldName; // Save name of last footprint selected.
200
201 wxString fpname;
202 wxString msg;
203 wxArrayString listnames;
204
205 for( FOOTPRINT* footprint : aPcb->Footprints() )
206 listnames.Add( footprint->GetReference() );
207
208 msg.Printf( _( "Footprints [%u items]" ), (unsigned) listnames.GetCount() );
209
210 wxArrayString headers;
211
212 headers.Add( _( "Footprint" ) );
213
214 std::vector<wxArrayString> itemsToDisplay;
215
216 // Conversion from wxArrayString to vector of ArrayString
217 for( unsigned i = 0; i < listnames.GetCount(); i++ )
218 {
219 wxArrayString item;
220
221 item.Add( listnames[i] );
222 itemsToDisplay.push_back( item );
223 }
224
225 EDA_LIST_DIALOG dlg( this, msg, headers, itemsToDisplay, wxEmptyString );
226
227 if( dlg.ShowModal() == wxID_OK )
228 fpname = dlg.GetTextSelection();
229 else
230 return nullptr;
231
232 oldName = fpname;
233
234 for( FOOTPRINT* fp : aPcb->Footprints() )
235 {
236 if( fpname == fp->GetReference() )
237 return fp;
238 }
239
240 return nullptr;
241}
242
243
244bool FOOTPRINT_EDIT_FRAME::SaveLibraryAs( const wxString& aLibraryPath )
245{
246 const wxString& curLibPath = aLibraryPath;
247 wxString dstLibPath = CreateNewLibrary( _( "Save Footprint Library As" ), aLibraryPath );
248
249 if( !dstLibPath )
250 return false; // user aborted in CreateNewLibrary()
251
252 wxBusyCursor dummy;
253 wxString msg;
254
255 LOCALE_IO toggle_locale;
258
259 if( dstType == PCB_IO_MGR::FILE_TYPE_NONE )
260 dstType = PCB_IO_MGR::KICAD_SEXP;
261
262 try
263 {
266
267 if( !cur )
268 {
269 msg = wxString::Format( _( "Unable to find a reader for '%s'." ), curLibPath );
270 DisplayError( this, msg );
271 return false;
272 }
273
274 if( !dst )
275 {
276 msg = wxString::Format( _( "Unable to find a writer for '%s'." ), dstLibPath );
277 DisplayError( this, msg );
278 return false;
279 }
280
281 wxArrayString footprints;
282
283 cur->FootprintEnumerate( footprints, curLibPath, false );
284
285 for( const wxString& fp : footprints )
286 {
287 const FOOTPRINT* footprint = cur->GetEnumeratedFootprint( curLibPath, fp );
288 dst->FootprintSave( dstLibPath, footprint );
289
290 msg = wxString::Format( _( "Footprint '%s' saved." ), fp );
291 SetStatusText( msg );
292 }
293 }
294 catch( const IO_ERROR& ioe )
295 {
296 DisplayErrorMessage( this, _( "Error saving footprint library" ), ioe.What() );
297 return false;
298 }
299
300 msg = wxString::Format( _( "Footprint library '%s' saved as '%s'." ),
301 curLibPath,
302 dstLibPath );
303
304 DisplayInfoMessage( this, msg );
305
306 SetStatusText( wxEmptyString );
307 return true;
308}
309
310
311static FOOTPRINT* s_FootprintInitialCopy = nullptr; // Copy of footprint for abort/undo command
312
313static PICKED_ITEMS_LIST s_PickedList; // A pick-list to save initial footprint
314 // and dragged tracks
315
316void PCB_BASE_FRAME::PlaceFootprint( FOOTPRINT* aFootprint, bool aRecreateRatsnest, std::optional<VECTOR2I> aPosition )
317{
318 if( aFootprint == nullptr )
319 return;
320
321 OnModify();
322
323 if( aFootprint->IsNew() )
324 {
326 }
327 else if( aFootprint->IsMoving() )
328 {
329 ITEM_PICKER picker( nullptr, aFootprint, UNDO_REDO::CHANGED );
331 s_PickedList.PushItem( picker );
332 s_FootprintInitialCopy = nullptr; // the picker is now owner of s_ModuleInitialCopy.
333 }
334
335 if( s_PickedList.GetCount() )
336 {
338
339 // Clear list, but DO NOT delete items, because they are owned by the saved undo
340 // list and they therefore in use
341 s_PickedList.ClearItemsList();
342 }
343
344 if( aPosition.has_value() )
345 aFootprint->SetPosition( aPosition.value() );
346 else
347 aFootprint->SetPosition( GetCanvas()->GetViewControls()->GetCursorPosition() );
348
349 aFootprint->ClearFlags();
350
352 s_FootprintInitialCopy = nullptr;
353
354 if( aRecreateRatsnest )
355 m_pcb->GetConnectivity()->Update( aFootprint );
356
357 if( aRecreateRatsnest )
358 m_pcb->CompileRatsnest();
359
360 SetMsgPanel( aFootprint );
361}
362
void SetContentModified(bool aModified=true)
Definition base_screen.h:55
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:372
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition board.h:587
const FOOTPRINTS & Footprints() const
Definition board.h:420
int ShowModal() override
virtual void ClearUndoRedoList()
Clear the undo and redo list using ClearUndoORRedoList()
bool IsType(FRAME_T aType) const
void ReCreateMenuBar()
Recreate the menu bar.
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
virtual void ReCreateHToolbar()
virtual void Zoom_Automatique(bool aWarpPointer)
Redraw the screen with best zoom level and the best centering that shows all the page or the board.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
const KIID m_Uuid
Definition eda_item.h:531
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition eda_item.h:154
bool IsMoving() const
Definition eda_item.h:130
bool IsNew() const
Definition eda_item.h:129
A dialog which shows:
wxString GetTextSelection(int aColumn=0)
Return the selected text from aColumn in the wxListCtrl in the dialog.
One open footprint tab owning its fp-holder board, lent to the frame by raw pointer while active.
BOARD * GetBoard() const
The fp-holder board owned by this context.
static wxString MakeInstanceTabKey(const KIID &aSourceUuid)
De-duplication key for a placed board footprint, in a namespace disjoint from library keys.
bool SaveLibraryAs(const wxString &aLibraryPath)
Save a library to a new name and/or library type.
EDITOR_TABS_PANEL * m_tabsPanel
FOOTPRINT_EDITOR_TAB_CONTEXT * findOrCreateFootprintInstanceTab(FOOTPRINT *aBoardFootprint)
Find or create the instance tab for a placed board footprint and make it the active tab.
FOOTPRINT * SelectFootprintFromBoard(BOARD *aPcb)
Display the list of footprints currently existing on the BOARD.
wxObjectDataPtr< LIB_TREE_MODEL_ADAPTER > m_adapter
bool IsLibraryTreeShown() const override
FOOTPRINT_TREE_PANE * m_treePane
bool LoadFootprintFromBoard(FOOTPRINT *aFootprint)
Load a footprint from the main board into the Footprint Editor.
void SetPosition(const VECTOR2I &aPos) override
const LIB_ID & GetFPID() const
Definition footprint.h:441
void SetTransformScale(double aScaleX, double aScaleY)
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
void SetLink(EDA_ITEM *aItem)
KIWAY_PLAYER(KIWAY *aKiway, wxWindow *aParent, FRAME_T aFrameType, const wxString &aTitle, const wxPoint &aPos, const wxSize &aSize, long aStyle, const wxString &aFrameName, const EDA_IU_SCALE &aIuScale)
virtual KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=nullptr)
Return the KIWAY_PLAYER* given a FRAME_T.
Definition kiway.cpp:398
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:45
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition lib_id.cpp:48
bool IsValid() const
Check if this LID_ID is valid.
Definition lib_id.h:168
UTF8 Format() const
Definition lib_id.cpp:115
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:37
wxString CreateNewLibrary(const wxString &aDialogTitle, const wxString &aInitialPath=wxEmptyString)
If a library name is given, creates a new footprint library in the project folder with the given name...
void setFPWatcher(FOOTPRINT *aFootprint)
Create or removes a watcher on the specified footprint.
void OnModify() override
Must be called after a change in order to set the "modify" flag and update other data structures and ...
virtual void SaveCopyInUndoList(EDA_ITEM *aItemToCopy, UNDO_REDO aTypeCommand)
Create a new entry in undo list of commands.
FOOTPRINT * SelectFootprintFromLibrary(LIB_ID aPreselect=LIB_ID())
Open a dialog to select a footprint.
FOOTPRINT * LoadFootprint(const LIB_ID &aFootprintId)
Attempt to load aFootprintId from the footprint library table.
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
BOARD * GetBoard() const
void PlaceFootprint(FOOTPRINT *aFootprint, bool aRecreateRatsnest=true, std::optional< VECTOR2I > aPosition=std::nullopt)
Place aFootprint at the current cursor position (or provided one) and updates footprint coordinates w...
virtual void Update3DView(bool aMarkDirty, bool aRefresh, const wxString *aTitle=nullptr)
Update the 3D view, if the viewer is opened by this frame.
The main frame for Pcbnew.
PCB_FILE_T
The set of file types that the PCB_IO_MGR knows about, and for which there has been a plugin written,...
Definition pcb_io_mgr.h:52
@ KICAD_SEXP
S-expression Pcbnew file format.
Definition pcb_io_mgr.h:54
static PCB_IO * FindPlugin(PCB_FILE_T aFileType)
Return a #PLUGIN which the caller can use to import, export, save, or load design documents.
static PCB_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath, int aCtl=0)
Return a plugin type given a footprint library's libPath.
A holder to handle information on schematic or board items.
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
Definition utf8.h:67
wxString wx_str() const
Definition utf8.cpp:41
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:245
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:217
void DisplayError(wxWindow *aParent, const wxString &aText)
Display an error or warning message box with aMessage.
Definition confirm.cpp:192
This file is part of the common library.
#define PAD_PROPERTIES_DLG_NAME
DIALOG_PAD_PROPERTIES, derived from DIALOG_PAD_PROPERTIES_BASE, created by wxFormBuilder.
#define _(s)
static wxArrayString s_FootprintHistoryList
static unsigned s_FootprintHistoryMaxCount
static void AddFootprintToHistory(const wxString &aName)
@ FRAME_PCB_EDITOR
Definition frame_type.h:38
@ FRAME_FOOTPRINT_CHOOSER
Definition frame_type.h:40
@ FRAME_FOOTPRINT_EDITOR
Definition frame_type.h:39
std::unique_ptr< T > IO_RELEASER
Helper to hold and release an IO_BASE object when exceptions are thrown.
Definition io_mgr.h:33
static PICKED_ITEMS_LIST s_PickedList
static FOOTPRINT * s_FootprintInitialCopy
static void AddFootprintToHistory(const wxString &aName)
This file contains miscellaneous commonly used macros and functions.
FOOTPRINT * LoadFootprintFromProject(BOARD *aBoard, const LIB_ID &aFootprintId, bool aKeepUuid)
Load a footprint from the project library table and apply board default settings.
KIWAY Kiway(KFCTL_STANDALONE)
std::vector< FAB_LAYER_COLOR > dummy