KiCad PCB EDA Suite
getpart.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) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2008-2017 Wayne Stambaugh <stambaughw@verizon.net>
6  * Copyright (C) 2004-2017 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, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
31 #include <algorithm>
32 #include <fctsys.h>
33 #include <pgm_base.h>
34 #include <kiway.h>
35 #include <gr_basic.h>
36 #include <class_drawpanel.h>
37 #include <confirm.h>
38 #include <schframe.h>
39 #include <kicad_device_context.h>
40 #include <msgpanel.h>
41 
42 #include <general.h>
43 #include <class_library.h>
44 #include <sch_component.h>
45 #include <libeditframe.h>
46 #include <viewlib_frame.h>
47 #include <eeschema_id.h>
48 
50 #include <cmp_tree_model_adapter.h>
51 #include <dialog_get_component.h>
52 
53 
55  const SCHLIB_FILTER* aFilter,
56  LIB_ALIAS* aPreselectedAlias,
57  int aUnit, int aConvert )
58 {
59  // Close any open non-modal Lib browser, and open a new one, in "modal" mode:
60  LIB_VIEW_FRAME* viewlibFrame = (LIB_VIEW_FRAME*) Kiway().Player( FRAME_SCH_VIEWER, false );
61 
62  if( viewlibFrame )
63  viewlibFrame->Destroy();
64 
65  viewlibFrame = (LIB_VIEW_FRAME*) Kiway().Player( FRAME_SCH_VIEWER_MODAL, true, this );
66 
67  if( aFilter )
68  viewlibFrame->SetFilter( aFilter );
69 
70  if( aPreselectedAlias )
71  {
72  viewlibFrame->SetSelectedLibrary( aPreselectedAlias->GetLibraryName() );
73  viewlibFrame->SetSelectedComponent( aPreselectedAlias->GetName() );
74  }
75 
76  viewlibFrame->SetUnitAndConvert( aUnit, aConvert );
77 
78  viewlibFrame->Refresh();
79 
81 
82  if( viewlibFrame->ShowModal( &sel.Name, this ) )
83  {
84  sel.Unit = viewlibFrame->GetUnit();
85  sel.Convert = viewlibFrame->GetConvert();
86  }
87 
88  viewlibFrame->Destroy();
89 
90  return sel;
91 }
92 
93 
95  const SCHLIB_FILTER* aFilter,
96  std::vector<COMPONENT_SELECTION>& aHistoryList,
97  bool aUseLibBrowser,
98  int aUnit,
99  int aConvert,
100  const wxString& aHighlight,
101  bool aAllowFields )
102 {
103  wxString dialogTitle;
104  PART_LIBS* libs = Prj().SchLibs();
105 
106  auto adapter( CMP_TREE_MODEL_ADAPTER::Create( libs ) );
107  bool loaded = false;
108 
109  if( aFilter )
110  {
111  const wxArrayString& liblist = aFilter->GetAllowedLibList();
112 
113  for( unsigned ii = 0; ii < liblist.GetCount(); ii++ )
114  {
115  PART_LIB* currLibrary = libs->FindLibrary( liblist[ii] );
116 
117  if( currLibrary )
118  {
119  loaded = true;
120  adapter->AddLibrary( *currLibrary );
121  }
122  }
123 
124  if( aFilter->GetFilterPowerParts() )
125  adapter->SetFilter( CMP_TREE_MODEL_ADAPTER::CMP_FILTER_POWER );
126 
127  }
128 
129 
130  if( !aHistoryList.empty() )
131  {
132  wxArrayString history_list;
133 
134  for( auto const& i : aHistoryList )
135  history_list.push_back( i.Name );
136 
137  adapter->AddAliasList( "-- " + _( "History" ) + " --", history_list, NULL );
138  adapter->SetPreselectNode( aHistoryList[0].Name, aHistoryList[0].Unit );
139  }
140 
141  if( !loaded )
142  {
143  for( PART_LIB& lib : *libs )
144  {
145  adapter->AddLibrary( lib );
146  }
147  }
148 
149  if( !aHighlight.IsEmpty() )
150  adapter->SetPreselectNode( aHighlight, /* aUnit */ 0 );
151 
152  dialogTitle.Printf( _( "Choose Component (%d items loaded)" ),
153  adapter->GetComponentsCount() );
154  DIALOG_CHOOSE_COMPONENT dlg( this, dialogTitle, adapter, aConvert, aAllowFields );
155 
156  if( dlg.ShowQuasiModal() == wxID_CANCEL )
157  return COMPONENT_SELECTION();
158 
160  LIB_ALIAS* const alias = dlg.GetSelectedAlias( &sel.Unit );
161 
162  if( alias == nullptr ) // Dialog closed by OK button, but no symbol selected
163  return COMPONENT_SELECTION();
164 
165  if( sel.Unit == 0 )
166  sel.Unit = 1;
167 
168  sel.Fields = dlg.GetFields();
169 
170  if ( alias )
171  sel.Name = alias->GetName();
172 
173  if( dlg.IsExternalBrowserSelected() ) // User requested component browser.
174  sel = SelectComponentFromLibBrowser( aFilter, alias, sel.Unit, sel.Convert );
175 
176  if( !sel.Name.empty() )
177  {
178  aHistoryList.erase(
179  std::remove_if(
180  aHistoryList.begin(),
181  aHistoryList.end(),
182  [ &sel ]( COMPONENT_SELECTION const& i ) { return i.Name == sel.Name; } ),
183  aHistoryList.end() );
184 
185  aHistoryList.insert( aHistoryList.begin(), sel );
186  }
187 
188  return sel;
189 }
190 
191 
193  wxDC* aDC,
194  const SCHLIB_FILTER* aFilter,
195  SCH_BASE_FRAME::HISTORY_LIST& aHistoryList,
196  bool aUseLibBrowser )
197 {
198  SetRepeatItem( NULL );
200 
201  auto sel = SelectComponentFromLibrary( aFilter, aHistoryList,
202  aUseLibBrowser, 1, 1 );
203 
204  if( sel.Name.IsEmpty() )
205  {
206  m_canvas->SetIgnoreMouseEvents( false );
208  return NULL;
209  }
210 
211  m_canvas->SetIgnoreMouseEvents( false );
213 
214  wxString libsource; // the library name to use. If empty, load from any lib
215 
216  if( aFilter )
217  libsource = aFilter->GetLibSource();
218 
219  LIB_PART* part = Prj().SchLibs()->FindLibPart( LIB_ID( wxEmptyString, sel.Name ), libsource );
220 
221  if( !part )
222  {
223  wxString msg = wxString::Format( _(
224  "Failed to find part '%s' in library" ),
225  GetChars( sel.Name )
226  );
227  wxMessageBox( msg );
228  return NULL;
229  }
230 
231  SCH_COMPONENT* component = new SCH_COMPONENT( *part, m_CurrentSheet, sel.Unit, sel.Convert,
232  GetCrossHairPosition(), true );
233 
234  // Set the m_ChipName value, from component name in lib, for aliases
235  // Note if part is found, and if name is an alias of a component,
236  // alias exists because its root component was found
237  LIB_ID libId;
238 
239  libId.SetLibItemName( sel.Name, false );
240  component->SetLibId( libId );
241 
242  // Be sure the link to the corresponding LIB_PART is OK:
243  component->Resolve( Prj().SchLibs() );
244 
245  // Set any fields that have been modified
246  for( auto const& i : sel.Fields )
247  {
248  auto field = component->GetField( i.first );
249 
250  if( field )
251  field->SetText( i.second );
252  }
253 
254  // Set the component value that can differ from component name in lib, for aliases
255  component->GetField( VALUE )->SetText( sel.Name );
256 
257  MSG_PANEL_ITEMS items;
258 
259  component->SetCurrentSheetPath( &GetCurrentSheet() );
260  component->GetMsgPanelInfo( items );
261 
262  SetMsgPanel( items );
263  component->Draw( m_canvas, aDC, wxPoint( 0, 0 ), g_XorMode );
264  component->SetFlags( IS_NEW );
265 
266  if( m_autoplaceFields )
267  component->AutoplaceFields( /* aScreen */ NULL, /* aManual */ false );
268 
269  PrepareMoveItem( (SCH_ITEM*) component, aDC );
270 
271  return component;
272 }
273 
274 
276 {
277  SCH_SCREEN* screen = GetScreen();
278  SCH_ITEM* item = screen->GetCurItem();
279 
280  wxCHECK_RET( item != NULL && item->Type() == SCH_COMPONENT_T,
281  wxT( "Cannot change orientation of invalid schematic item." ) );
282 
283  SCH_COMPONENT* component = (SCH_COMPONENT*) item;
284 
286 
287  if( component->GetFlags() == 0 )
288  {
290  GetScreen()->SetCurItem( NULL );
291  }
292 
294 
295  component->SetOrientation( aOrientation );
296 
297  m_canvas->CrossHairOn( &dc );
298 
299  if( GetScreen()->TestDanglingEnds() )
300  m_canvas->Refresh();
301 
302  OnModify();
303 }
304 
305 
306 /*
307  * Handle select part in multi-unit part.
308  */
309 void SCH_EDIT_FRAME::OnSelectUnit( wxCommandEvent& aEvent )
310 {
311  SCH_SCREEN* screen = GetScreen();
312  SCH_ITEM* item = screen->GetCurItem();
313 
314  wxCHECK_RET( item != NULL && item->Type() == SCH_COMPONENT_T,
315  wxT( "Cannot select unit of invalid schematic item." ) );
316 
318 
320 
321  SCH_COMPONENT* component = (SCH_COMPONENT*) item;
322 
323  int unit = aEvent.GetId() + 1 - ID_POPUP_SCH_SELECT_UNIT1;
324 
325  if( LIB_PART* part = Prj().SchLibs()->FindLibPart( component->GetLibId() ) )
326  {
327  int unitCount = part->GetUnitCount();
328 
329  wxCHECK_RET( (unit >= 1) && (unit <= unitCount),
330  wxString::Format( wxT( "Cannot select unit %d from component " ), unit ) +
331  part->GetName() );
332 
333  if( unitCount <= 1 || component->GetUnit() == unit )
334  return;
335 
336  if( unit > unitCount )
337  unit = unitCount;
338 
339  STATUS_FLAGS flags = component->GetFlags();
340 
341  if( !flags ) // No command in progress: save in undo list
342  SaveCopyInUndoList( component, UR_CHANGED );
343 
344  if( flags )
345  component->Draw( m_canvas, &dc, wxPoint( 0, 0 ), g_XorMode, g_GhostColor );
346  else
347  component->Draw( m_canvas, &dc, wxPoint( 0, 0 ), g_XorMode );
348 
349  /* Update the unit number. */
350  component->SetUnitSelection( m_CurrentSheet, unit );
351  component->SetUnit( unit );
352  component->ClearFlags();
353  component->SetFlags( flags ); // Restore m_Flag modified by SetUnit()
354 
355  if( m_autoplaceFields )
356  component->AutoAutoplaceFields( GetScreen() );
357 
358  if( screen->TestDanglingEnds() )
359  m_canvas->Refresh();
360 
361  OnModify();
362  }
363 }
364 
365 
366 void SCH_EDIT_FRAME::ConvertPart( SCH_COMPONENT* DrawComponent, wxDC* DC )
367 {
368  if( !DrawComponent )
369  return;
370 
371  if( LIB_PART* part = Prj().SchLibs()->FindLibPart( DrawComponent->GetLibId() ) )
372  {
373  if( !part->HasConversion() )
374  {
375  DisplayError( this, wxT( "No convert found" ) );
376  return;
377  }
378 
379  STATUS_FLAGS flags = DrawComponent->GetFlags();
380 
381  if( DrawComponent->GetFlags() )
382  DrawComponent->Draw( m_canvas, DC, wxPoint( 0, 0 ), g_XorMode, g_GhostColor );
383  else
384  DrawComponent->Draw( m_canvas, DC, wxPoint( 0, 0 ), g_XorMode );
385 
386  DrawComponent->SetConvert( DrawComponent->GetConvert() + 1 );
387 
388  // ensure m_Convert = 0, 1 or 2
389  // 0 and 1 = shape 1 = not converted
390  // 2 = shape 2 = first converted shape
391  // > 2 is not used but could be used for more shapes
392  // like multiple shapes for a programmable component
393  // When m_Convert = val max, return to the first shape
394  if( DrawComponent->GetConvert() > 2 )
395  DrawComponent->SetConvert( 1 );
396 
397  // The alternate symbol may cause a change in the connection status so test the
398  // connections so the connection indicators are drawn correctly.
400  DrawComponent->ClearFlags();
401  DrawComponent->SetFlags( flags ); // Restore m_Flag (modified by SetConvert())
402 
403  /* Redraw the component in the new position. */
404  if( DrawComponent->IsMoving() )
405  DrawComponent->Draw( m_canvas, DC, wxPoint( 0, 0 ), g_XorMode, g_GhostColor );
406  else
407  DrawComponent->Draw( m_canvas, DC, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE );
408 
409  OnModify();
410  }
411 }
GR_DRAWMODE g_XorMode
Definition: gr_basic.cpp:51
void OrientComponent(COMPONENT_ORIENTATION_T aOrientation=CMP_NORMAL)
Function OrientComponent rotates and mirrors a component.
Definition: getpart.cpp:275
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
void GetMsgPanelInfo(std::vector< MSG_PANEL_ITEM > &aList) override
Function GetMsgPanelInfo populates aList of MSG_PANEL_ITEM objects with it's internal state for displ...
void SetFilter(const SCHLIB_FILTER *aFilter)
set a filter to display only libraries and/or components which match the filter
void AutoAutoplaceFields(SCH_SCREEN *aScreen)
Autoplace fields only if correct to do so automatically.
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:255
Part library alias object definition.
bool IsMoving() const
Definition: base_struct.h:218
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_player.h:60
void SetUnitAndConvert(int aUnit, int aConvert)
Set unit and convert, and set flag preventing them from automatically resetting to 1...
void SaveCopyInUndoList(SCH_ITEM *aItemToCopy, UNDO_REDO_T aTypeCommand, const wxPoint &aTransformPoint=wxPoint(0, 0))
Function SaveCopyInUndoList.
virtual void Refresh(bool eraseBackground=true, const wxRect *rect=NULL) override
Definition: draw_panel.cpp:326
This file is part of the common library.
void OnModify()
Function OnModify Must be called after a schematic change in order to set the "modify" flag of the cu...
Definition: schframe.cpp:768
bool Resolve(PART_LIBS *aLibs)
Assigns the current LIB_PART from aLibs which this symbol is based on.
const wxString GetLibraryName()
std::vector< COMPONENT_SELECTION > HISTORY_LIST
This file is part of the common libary.
void SetUnitSelection(SCH_SHEET_PATH *aSheet, int aUnitSelection)
Class LIB_ID.
Definition: lib_id.h:56
void MoveCursorToCrossHair()
Function MoveCursorToCrossHair warps the cursor to the current cross hair position.
Definition: draw_panel.cpp:348
PART_LIB * FindLibrary(const wxString &aName)
Function FindLibrary finds a part library by aName.
void SetSelectedComponent(const wxString &aComponentName)
Set the selected component.
Component library viewer main window.
Definition: viewlib_frame.h:49
void PrepareMoveItem(SCH_ITEM *aItem, wxDC *aDC)
Function PrepareMoveItem start moving aItem using the mouse.
Definition: schedit.cpp:783
void SetRepeatItem(SCH_ITEM *aItem)
Function SetRepeatItem clones aItem and owns that clone in this container.
Definition: schframe.cpp:466
void SetConvert(int aConvert)
static PTR Create(PART_LIBS *aLibs)
Factory function: create a model adapter in a reference-counting container.
#define IS_NEW
New item, just created.
Definition: base_struct.h:113
void SetCurrentSheetPath(const SCH_SHEET_PATH *aSheetPath)
SCH_SCREEN * GetScreen() const override
Function GetScreen returns a pointer to a BASE_SCREEN or one of its derivatives.
Definition: schframe.cpp:527
Dialog class to select a component from the libraries.
int GetConvert() const
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
SCH_SHEET_PATH * m_CurrentSheet
which sheet we are presently working on.
Definition: schframe.h:120
void SetLibId(const LIB_ID &aName, PART_LIBS *aLibs=NULL)
std::vector< std::pair< int, wxString > > GetFields() const
Get a list of fields edited by the user.
VTBL_ENTRY KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, KIWAY_PLAYER *aParent=NULL)
Function Player returns the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:302
a helper to handle the real device context used in KiCad
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:253
SCH_FIELD * GetField(int aFieldNdx) const
Returns a field in this symbol.
bool IsExternalBrowserSelected() const
Function IsExternalBrowserSelected.
const wxArrayString & GetAllowedLibList() const
Function GetAllowedLibList.
COMPONENT_SELECTION SelectComponentFromLibBrowser(const SCHLIB_FILTER *aFilter, LIB_ALIAS *aPreselectedAlias, int aUnit, int aConvert)
Function SelectComponentFromLibBrowser Calls the library viewer to select component to import into sc...
Definition: getpart.cpp:54
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Function SetMsgPanel clears the message panel and populates it with the contents of aList...
Definition: draw_frame.cpp:773
SCH_ITEM * GetCurItem() const
Function GetCurItem returns the currently selected SCH_ITEM, overriding BASE_SCREEN::GetCurItem().
int GetUnit(void)
int ShowQuasiModal()
LIB_ALIAS * GetSelectedAlias(int *aUnit=nullptr) const
To be called after this dialog returns from ShowModal().
SCH_SHEET_PATH & GetCurrentSheet()
Definition: schframe.cpp:572
Class LIB_PART defines a library part object.
void OnSelectUnit(wxCommandEvent &aEvent)
Definition: getpart.cpp:309
unsigned STATUS_FLAGS
Definition: base_struct.h:144
bool GetFilterPowerParts() const
Function GetFilterPowerParts.
void SetUnit(int aUnit)
Change the unit number to aUnit.
int SetLibItemName(const UTF8 &aLibItemName, bool aTestForRev=true)
Function SetLibItemName.
Definition: lib_id.cpp:232
std::vector< std::pair< int, wxString > > Fields
int GetConvert(void)
bool m_autoplaceFields
automatically place component fields
Definition: schframe.h:154
Class PART_LIBS is a collection of PART_LIBs.
Field Value of part, i.e. "3.3K".
EDA_DRAW_PANEL * m_canvas
The area to draw on.
Definition: draw_frame.h:92
#define GR_DEFAULT_DRAWMODE
Definition: general.h:70
Definition the SCH_COMPONENT class for Eeschema.
void CrossHairOn(wxDC *DC)
Definition: draw_panel.cpp:260
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
SCH_COMPONENT * Load_Component(wxDC *aDC, const SCHLIB_FILTER *aFilter, SCH_BASE_FRAME::HISTORY_LIST &aHistoryList, bool aUseLibBrowser)
Function Load_Component loads from a library and places a component.
Definition: getpart.cpp:192
see class PGM_BASE
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual)
Automatically orient all the fields in the component.
const wxString & GetName() const
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
#define INSTALL_UNBUFFERED_DC(name, parent)
bool TestDanglingEnds()
Function TestDanglingEnds tests all of the connectible objects in the schematic for unused connection...
Definition: sch_screen.cpp:915
void Draw(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aOffset, GR_DRAWMODE aDrawMode, COLOR4D aColor=COLOR4D::UNSPECIFIED) override
Function Draw Draw a schematic item.
void SetCurItem(SCH_ITEM *aItem)
Function SetCurItem sets the currently selected object, m_CurrentItem.
void SetIgnoreMouseEvents(bool aIgnore)
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:69
const LIB_ID & GetLibId() const
std::vector< MSG_PANEL_ITEM > MSG_PANEL_ITEMS
Definition: msgpanel.h:102
bool Destroy() override
Our version of Destroy() which is virtual from wxWidgets.
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:254
COMPONENT_SELECTION SelectComponentFromLibrary(const SCHLIB_FILTER *aFilter, std::vector< COMPONENT_SELECTION > &aHistoryList, bool aUseLibBrowser, int aUnit, int aConvert, const wxString &aHighlight=wxEmptyString, bool aAllowFields=true)
Function SelectComponentFromLib Calls the library viewer to select component to import into schematic...
Definition: getpart.cpp:94
Definition for part library class.
const wxString & GetLibSource() const
Function GetLibSource.
Message panel definition file.
Class PART_LIB is used to load, save, search, and otherwise manipulate part library files...
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:71
wxPoint GetCrossHairPosition(bool aInvertY=false) const
Function GetCrossHairPosition return the current cross hair position in logical (drawing) coordinates...
Class SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container clas...
COMPONENT_ORIENTATION_T
enum used in RotationMiroir()
Definition: schframe.h:70
VTBL_ENTRY bool ShowModal(wxString *aResult=NULL, wxWindow *aResultantFocusWindow=NULL)
Function ShowModal puts up this wxFrame as if it were a modal dialog, with all other instantiated wxF...
Definition of class LIB_EDIT_FRAME.
COLOR4D g_GhostColor
Draw color for moving objects.
Definition: common.cpp:57
void SetSelectedLibrary(const wxString &aLibName)
Set the selected library in the library window.
virtual void SetText(const wxString &aText)
Definition: eda_text.h:141
void ConvertPart(SCH_COMPONENT *DrawComponent, wxDC *DC)
Definition: getpart.cpp:366