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: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:754
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: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...
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
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