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->GetPart()->IsMulti() && sel.Unit == 0 )
167  sel.Unit = 1;
168 
169  sel.Fields = dlg.GetFields();
170 
171  if ( alias )
172  sel.Name = alias->GetName();
173 
174  if( dlg.IsExternalBrowserSelected() ) // User requested component browser.
175  sel = SelectComponentFromLibBrowser( aFilter, alias, sel.Unit, sel.Convert );
176 
177  if( !sel.Name.empty() )
178  {
179  aHistoryList.erase(
180  std::remove_if(
181  aHistoryList.begin(),
182  aHistoryList.end(),
183  [ &sel ]( COMPONENT_SELECTION const& i ) { return i.Name == sel.Name; } ),
184  aHistoryList.end() );
185 
186  aHistoryList.insert( aHistoryList.begin(), sel );
187  }
188 
189  return sel;
190 }
191 
192 
194  wxDC* aDC,
195  const SCHLIB_FILTER* aFilter,
196  SCH_BASE_FRAME::HISTORY_LIST& aHistoryList,
197  bool aUseLibBrowser )
198 {
199  SetRepeatItem( NULL );
201 
202  auto sel = SelectComponentFromLibrary( aFilter, aHistoryList,
203  aUseLibBrowser, 1, 1 );
204 
205  if( sel.Name.IsEmpty() )
206  {
207  m_canvas->SetIgnoreMouseEvents( false );
209  return NULL;
210  }
211 
212  m_canvas->SetIgnoreMouseEvents( false );
214 
215  wxString libsource; // the library name to use. If empty, load from any lib
216 
217  if( aFilter )
218  libsource = aFilter->GetLibSource();
219 
220  LIB_PART* part = Prj().SchLibs()->FindLibPart( LIB_ID( wxEmptyString, sel.Name ), libsource );
221 
222  if( !part )
223  {
224  wxString msg = wxString::Format( _(
225  "Failed to find part '%s' in library" ),
226  GetChars( sel.Name )
227  );
228  wxMessageBox( msg );
229  return NULL;
230  }
231 
232  SCH_COMPONENT* component = new SCH_COMPONENT( *part, m_CurrentSheet, sel.Unit, sel.Convert,
233  GetCrossHairPosition(), true );
234 
235  // Set the m_ChipName value, from component name in lib, for aliases
236  // Note if part is found, and if name is an alias of a component,
237  // alias exists because its root component was found
238  LIB_ID libId;
239 
240  libId.SetLibItemName( TO_UTF8( sel.Name ), false );
241  component->SetLibId( libId );
242 
243  // Be sure the link to the corresponding LIB_PART is OK:
244  component->Resolve( Prj().SchLibs() );
245 
246  // Set any fields that have been modified
247  for( auto const& i : sel.Fields )
248  {
249  auto field = component->GetField( i.first );
250 
251  if( field )
252  field->SetText( i.second );
253  }
254 
255  // Set the component value that can differ from component name in lib, for aliases
256  component->GetField( VALUE )->SetText( sel.Name );
257 
258  MSG_PANEL_ITEMS items;
259 
260  component->SetCurrentSheetPath( &GetCurrentSheet() );
261  component->GetMsgPanelInfo( items );
262 
263  SetMsgPanel( items );
264  component->Draw( m_canvas, aDC, wxPoint( 0, 0 ), g_XorMode );
265  component->SetFlags( IS_NEW );
266 
267  if( m_autoplaceFields )
268  component->AutoplaceFields( /* aScreen */ NULL, /* aManual */ false );
269 
270  PrepareMoveItem( (SCH_ITEM*) component, aDC );
271 
272  return component;
273 }
274 
275 
277 {
278  SCH_SCREEN* screen = GetScreen();
279  SCH_ITEM* item = screen->GetCurItem();
280 
281  wxCHECK_RET( item != NULL && item->Type() == SCH_COMPONENT_T,
282  wxT( "Cannot change orientation of invalid schematic item." ) );
283 
284  SCH_COMPONENT* component = (SCH_COMPONENT*) item;
285 
287 
288  if( component->GetFlags() == 0 )
289  {
291  GetScreen()->SetCurItem( NULL );
292  }
293 
295 
296  component->SetOrientation( aOrientation );
297 
298  m_canvas->CrossHairOn( &dc );
299 
300  if( GetScreen()->TestDanglingEnds() )
301  m_canvas->Refresh();
302 
303  OnModify();
304 }
305 
306 
307 /*
308  * Handle select part in multi-unit part.
309  */
310 void SCH_EDIT_FRAME::OnSelectUnit( wxCommandEvent& aEvent )
311 {
312  SCH_SCREEN* screen = GetScreen();
313  SCH_ITEM* item = screen->GetCurItem();
314 
315  wxCHECK_RET( item != NULL && item->Type() == SCH_COMPONENT_T,
316  wxT( "Cannot select unit of invalid schematic item." ) );
317 
319 
321 
322  SCH_COMPONENT* component = (SCH_COMPONENT*) item;
323 
324  int unit = aEvent.GetId() + 1 - ID_POPUP_SCH_SELECT_UNIT1;
325 
326  if( LIB_PART* part = Prj().SchLibs()->FindLibPart( component->GetLibId() ) )
327  {
328  int unitCount = part->GetUnitCount();
329 
330  wxCHECK_RET( (unit >= 1) && (unit <= unitCount),
331  wxString::Format( wxT( "Cannot select unit %d from component " ), unit ) +
332  part->GetName() );
333 
334  if( unitCount <= 1 || component->GetUnit() == unit )
335  return;
336 
337  if( unit > unitCount )
338  unit = unitCount;
339 
340  STATUS_FLAGS flags = component->GetFlags();
341 
342  if( !flags ) // No command in progress: save in undo list
343  SaveCopyInUndoList( component, UR_CHANGED );
344 
345  if( flags )
346  component->Draw( m_canvas, &dc, wxPoint( 0, 0 ), g_XorMode, g_GhostColor );
347  else
348  component->Draw( m_canvas, &dc, wxPoint( 0, 0 ), g_XorMode );
349 
350  /* Update the unit number. */
351  component->SetUnitSelection( m_CurrentSheet, unit );
352  component->SetUnit( unit );
353  component->ClearFlags();
354  component->SetFlags( flags ); // Restore m_Flag modified by SetUnit()
355 
356  if( m_autoplaceFields )
357  component->AutoAutoplaceFields( GetScreen() );
358 
359  if( screen->TestDanglingEnds() )
360  m_canvas->Refresh();
361 
362  OnModify();
363  }
364 }
365 
366 
367 void SCH_EDIT_FRAME::ConvertPart( SCH_COMPONENT* DrawComponent, wxDC* DC )
368 {
369  if( !DrawComponent )
370  return;
371 
372  if( LIB_PART* part = Prj().SchLibs()->FindLibPart( DrawComponent->GetLibId() ) )
373  {
374  if( !part->HasConversion() )
375  {
376  DisplayError( this, wxT( "No convert found" ) );
377  return;
378  }
379 
380  STATUS_FLAGS flags = DrawComponent->GetFlags();
381 
382  if( DrawComponent->GetFlags() )
383  DrawComponent->Draw( m_canvas, DC, wxPoint( 0, 0 ), g_XorMode, g_GhostColor );
384  else
385  DrawComponent->Draw( m_canvas, DC, wxPoint( 0, 0 ), g_XorMode );
386 
387  DrawComponent->SetConvert( DrawComponent->GetConvert() + 1 );
388 
389  // ensure m_Convert = 0, 1 or 2
390  // 0 and 1 = shape 1 = not converted
391  // 2 = shape 2 = first converted shape
392  // > 2 is not used but could be used for more shapes
393  // like multiple shapes for a programmable component
394  // When m_Convert = val max, return to the first shape
395  if( DrawComponent->GetConvert() > 2 )
396  DrawComponent->SetConvert( 1 );
397 
398  // The alternate symbol may cause a change in the connection status so test the
399  // connections so the connection indicators are drawn correctly.
401  DrawComponent->ClearFlags();
402  DrawComponent->SetFlags( flags ); // Restore m_Flag (modified by SetConvert())
403 
404  /* Redraw the component in the new position. */
405  if( DrawComponent->IsMoving() )
406  DrawComponent->Draw( m_canvas, DC, wxPoint( 0, 0 ), g_XorMode, g_GhostColor );
407  else
408  DrawComponent->Draw( m_canvas, DC, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE );
409 
410  OnModify();
411  }
412 }
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:276
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 IsMulti() const
Function IsMulti.
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:761
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< std::pair< int, wxString > > GetFields() const
Get a list of fields edited by the user.
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:784
void SetRepeatItem(SCH_ITEM *aItem)
Function SetRepeatItem clones aItem and owns that clone in this container.
Definition: schframe.cpp:459
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:520
#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)
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:751
SCH_ITEM * GetCurItem() const
Function GetCurItem returns the currently selected SCH_ITEM, overriding BASE_SCREEN::GetCurItem().
int GetUnit(void)
int ShowQuasiModal()
SCH_SHEET_PATH & GetCurrentSheet()
Definition: schframe.cpp:565
Class LIB_PART defines a library part object.
void OnSelectUnit(wxCommandEvent &aEvent)
Definition: getpart.cpp:310
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...
LIB_ALIAS * GetSelectedAlias(int *aUnit) const
Function GetSelectedAlias To be called after this dialog returns from ShowModal().
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
LIB_PART * GetPart() const
Function GetPart gets the shared LIB_PART.
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:69
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:193
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:68
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:367