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  if( aUnit > 0 )
77  viewlibFrame->SetUnit( aUnit );
78 
79  if( aConvert > 0 )
80  viewlibFrame->SetConvert( aConvert );
81 
82  viewlibFrame->Refresh();
83 
85 
86  if( viewlibFrame->ShowModal( &sel.Name, this ) )
87  {
88  sel.Unit = viewlibFrame->GetUnit();
89  sel.Convert = viewlibFrame->GetConvert();
90  }
91 
92  viewlibFrame->Destroy();
93 
94  return sel;
95 }
96 
97 
99  const SCHLIB_FILTER* aFilter,
100  std::vector<COMPONENT_SELECTION>& aHistoryList,
101  bool aUseLibBrowser,
102  int aUnit,
103  int aConvert,
104  const wxString& aHighlight,
105  bool aAllowFields )
106 {
107  wxString dialogTitle;
108  PART_LIBS* libs = Prj().SchLibs();
109 
110  auto adapter( CMP_TREE_MODEL_ADAPTER::Create( libs ) );
111  bool loaded = false;
112 
113  if( aFilter )
114  {
115  const wxArrayString& liblist = aFilter->GetAllowedLibList();
116 
117  for( unsigned ii = 0; ii < liblist.GetCount(); ii++ )
118  {
119  PART_LIB* currLibrary = libs->FindLibrary( liblist[ii] );
120 
121  if( currLibrary )
122  {
123  loaded = true;
124  adapter->AddLibrary( *currLibrary );
125  }
126  }
127 
128  if( aFilter->GetFilterPowerParts() )
129  adapter->SetFilter( CMP_TREE_MODEL_ADAPTER::CMP_FILTER_POWER );
130 
131  }
132 
133  if( !loaded )
134  {
135  for( PART_LIB& lib : *libs )
136  {
137  adapter->AddLibrary( lib );
138  }
139  }
140 
141 
142  if( !aHistoryList.empty() )
143  {
144  wxArrayString history_list;
145 
146  for( auto const& i : aHistoryList )
147  history_list.push_back( i.Name );
148 
149  adapter->AddAliasList( "-- " + _( "History" ) + " --", history_list, NULL );
150  adapter->SetPreselectNode( aHistoryList[0].Name, aHistoryList[0].Unit );
151  }
152 
153  if( !aHighlight.IsEmpty() )
154  adapter->SetPreselectNode( aHighlight, /* aUnit */ 0 );
155 
156  dialogTitle.Printf( _( "Choose Component (%d items loaded)" ),
157  adapter->GetComponentsCount() );
158  DIALOG_CHOOSE_COMPONENT dlg( this, dialogTitle, adapter, aConvert, aAllowFields );
159 
160  if( dlg.ShowQuasiModal() == wxID_CANCEL )
161  return COMPONENT_SELECTION();
162 
164  LIB_ALIAS* const alias = dlg.GetSelectedAlias( &sel.Unit );
165 
166  if( alias == nullptr ) // Dialog closed by OK button, but no symbol selected
167  return COMPONENT_SELECTION();
168 
169  if( sel.Unit == 0 )
170  sel.Unit = 1;
171 
172  sel.Fields = dlg.GetFields();
173 
174  if ( alias )
175  sel.Name = alias->GetName();
176 
177  if( dlg.IsExternalBrowserSelected() ) // User requested component browser.
178  sel = SelectComponentFromLibBrowser( aFilter, alias, sel.Unit, sel.Convert );
179 
180  if( !sel.Name.empty() )
181  {
182  aHistoryList.erase(
183  std::remove_if(
184  aHistoryList.begin(),
185  aHistoryList.end(),
186  [ &sel ]( COMPONENT_SELECTION const& i ) { return i.Name == sel.Name; } ),
187  aHistoryList.end() );
188 
189  aHistoryList.insert( aHistoryList.begin(), sel );
190  }
191 
192  return sel;
193 }
194 
195 
197  wxDC* aDC,
198  const SCHLIB_FILTER* aFilter,
199  SCH_BASE_FRAME::HISTORY_LIST& aHistoryList,
200  bool aUseLibBrowser )
201 {
202  SetRepeatItem( NULL );
204 
205  auto sel = SelectComponentFromLibrary( aFilter, aHistoryList,
206  aUseLibBrowser, 1, 1 );
207 
208  if( sel.Name.IsEmpty() )
209  {
210  m_canvas->SetIgnoreMouseEvents( false );
212  return NULL;
213  }
214 
215  m_canvas->SetIgnoreMouseEvents( false );
217 
218  wxString libsource; // the library name to use. If empty, load from any lib
219 
220  if( aFilter )
221  libsource = aFilter->GetLibSource();
222 
223  LIB_PART* part = Prj().SchLibs()->FindLibPart( LIB_ID( wxEmptyString, sel.Name ), libsource );
224 
225  if( !part )
226  {
227  wxString msg = wxString::Format( _(
228  "Failed to find part '%s' in library" ),
229  GetChars( sel.Name )
230  );
231  wxMessageBox( msg );
232  return NULL;
233  }
234 
235  SCH_COMPONENT* component = new SCH_COMPONENT( *part, m_CurrentSheet, sel.Unit, sel.Convert,
236  GetCrossHairPosition(), true );
237 
238  // Set the m_ChipName value, from component name in lib, for aliases
239  // Note if part is found, and if name is an alias of a component,
240  // alias exists because its root component was found
241  LIB_ID libId;
242 
243  libId.SetLibItemName( TO_UTF8( sel.Name ), false );
244  component->SetLibId( libId );
245 
246  // Be sure the link to the corresponding LIB_PART is OK:
247  component->Resolve( Prj().SchLibs() );
248 
249  // Set any fields that have been modified
250  for( auto const& i : sel.Fields )
251  {
252  auto field = component->GetField( i.first );
253 
254  if( field )
255  field->SetText( i.second );
256  }
257 
258  // Set the component value that can differ from component name in lib, for aliases
259  component->GetField( VALUE )->SetText( sel.Name );
260 
261  MSG_PANEL_ITEMS items;
262 
263  component->SetCurrentSheetPath( &GetCurrentSheet() );
264  component->GetMsgPanelInfo( items );
265 
266  SetMsgPanel( items );
267  component->Draw( m_canvas, aDC, wxPoint( 0, 0 ), g_XorMode );
268  component->SetFlags( IS_NEW );
269 
270  if( m_autoplaceFields )
271  component->AutoplaceFields( /* aScreen */ NULL, /* aManual */ false );
272 
273  PrepareMoveItem( (SCH_ITEM*) component, aDC );
274 
275  return component;
276 }
277 
278 
280 {
281  SCH_SCREEN* screen = GetScreen();
282  SCH_ITEM* item = screen->GetCurItem();
283 
284  wxCHECK_RET( item != NULL && item->Type() == SCH_COMPONENT_T,
285  wxT( "Cannot change orientation of invalid schematic item." ) );
286 
287  SCH_COMPONENT* component = (SCH_COMPONENT*) item;
288 
290 
291  if( component->GetFlags() == 0 )
292  {
294  GetScreen()->SetCurItem( NULL );
295  }
296 
298 
299  component->SetOrientation( aOrientation );
300 
301  m_canvas->CrossHairOn( &dc );
302 
303  if( GetScreen()->TestDanglingEnds() )
304  m_canvas->Refresh();
305 
306  OnModify();
307 }
308 
309 
310 /*
311  * Handle select part in multi-unit part.
312  */
313 void SCH_EDIT_FRAME::OnSelectUnit( wxCommandEvent& aEvent )
314 {
315  SCH_SCREEN* screen = GetScreen();
316  SCH_ITEM* item = screen->GetCurItem();
317 
318  wxCHECK_RET( item != NULL && item->Type() == SCH_COMPONENT_T,
319  wxT( "Cannot select unit of invalid schematic item." ) );
320 
322 
324 
325  SCH_COMPONENT* component = (SCH_COMPONENT*) item;
326 
327  int unit = aEvent.GetId() + 1 - ID_POPUP_SCH_SELECT_UNIT1;
328 
329  if( LIB_PART* part = Prj().SchLibs()->FindLibPart( component->GetLibId() ) )
330  {
331  int unitCount = part->GetUnitCount();
332 
333  wxCHECK_RET( (unit >= 1) && (unit <= unitCount),
334  wxString::Format( wxT( "Cannot select unit %d from component " ), unit ) +
335  part->GetName() );
336 
337  if( unitCount <= 1 || component->GetUnit() == unit )
338  return;
339 
340  if( unit > unitCount )
341  unit = unitCount;
342 
343  STATUS_FLAGS flags = component->GetFlags();
344 
345  if( !flags ) // No command in progress: save in undo list
346  SaveCopyInUndoList( component, UR_CHANGED );
347 
348  if( flags )
349  component->Draw( m_canvas, &dc, wxPoint( 0, 0 ), g_XorMode, g_GhostColor );
350  else
351  component->Draw( m_canvas, &dc, wxPoint( 0, 0 ), g_XorMode );
352 
353  /* Update the unit number. */
354  component->SetUnitSelection( m_CurrentSheet, unit );
355  component->SetUnit( unit );
356  component->ClearFlags();
357  component->SetFlags( flags ); // Restore m_Flag modified by SetUnit()
358 
359  if( m_autoplaceFields )
360  component->AutoAutoplaceFields( GetScreen() );
361 
362  if( screen->TestDanglingEnds() )
363  m_canvas->Refresh();
364 
365  OnModify();
366  }
367 }
368 
369 
370 void SCH_EDIT_FRAME::ConvertPart( SCH_COMPONENT* DrawComponent, wxDC* DC )
371 {
372  if( !DrawComponent )
373  return;
374 
375  if( LIB_PART* part = Prj().SchLibs()->FindLibPart( DrawComponent->GetLibId() ) )
376  {
377  if( !part->HasConversion() )
378  {
379  DisplayError( this, wxT( "No convert found" ) );
380  return;
381  }
382 
383  STATUS_FLAGS flags = DrawComponent->GetFlags();
384 
385  if( DrawComponent->GetFlags() )
386  DrawComponent->Draw( m_canvas, DC, wxPoint( 0, 0 ), g_XorMode, g_GhostColor );
387  else
388  DrawComponent->Draw( m_canvas, DC, wxPoint( 0, 0 ), g_XorMode );
389 
390  DrawComponent->SetConvert( DrawComponent->GetConvert() + 1 );
391 
392  // ensure m_Convert = 0, 1 or 2
393  // 0 and 1 = shape 1 = not converted
394  // 2 = shape 2 = first converted shape
395  // > 2 is not used but could be used for more shapes
396  // like multiple shapes for a programmable component
397  // When m_Convert = val max, return to the first shape
398  if( DrawComponent->GetConvert() > 2 )
399  DrawComponent->SetConvert( 1 );
400 
401  // The alternate symbol may cause a change in the connection status so test the
402  // connections so the connection indicators are drawn correctly.
404  DrawComponent->ClearFlags();
405  DrawComponent->SetFlags( flags ); // Restore m_Flag (modified by SetConvert())
406 
407  /* Redraw the component in the new position. */
408  if( DrawComponent->IsMoving() )
409  DrawComponent->Draw( m_canvas, DC, wxPoint( 0, 0 ), g_XorMode, g_GhostColor );
410  else
411  DrawComponent->Draw( m_canvas, DC, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE );
412 
413  OnModify();
414  }
415 }
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:279
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)
Function AutoAutoplaceFields 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 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:762
bool Resolve(PART_LIBS *aLibs)
Function Resolve [re-]assigns the current LIB_PART from aLibs which this component 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)
void SetUnit(int aUnit)
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:460
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:521
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
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
Function GetField returns a field.
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:566
Class LIB_PART defines a library part object.
void OnSelectUnit(wxCommandEvent &aEvent)
Definition: getpart.cpp:313
unsigned STATUS_FLAGS
Definition: base_struct.h:144
bool GetFilterPowerParts() const
Function GetFilterPowerParts.
void SetUnit(int aUnit)
change the unit id to aUnit has maening only for multiple parts per package Also set the modified fla...
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:196
see class PGM_BASE
void AutoplaceFields(SCH_SCREEN *aScreen, bool aManual)
Function AutoplaceFields 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
void SetConvert(int aConvert)
#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:911
void Draw(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aOffset, GR_DRAWMODE aDrawMode, COLOR4D aColor=COLOR4D::UNSPECIFIED) override
Virtual function, from the base class SCH_ITEM::Draw.
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:98
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:69
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:370