KiCad PCB EDA Suite
dialog_lib_edit_pin_table.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) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
25 #include "lib_pin.h"
26 #include "pin_number.h"
27 
28 #include <boost/algorithm/string/join.hpp>
29 #include <queue>
30 #include <list>
31 #include <map>
32 
33 /* Avoid wxWidgets bug #16906 -- http://trac.wxwidgets.org/ticket/16906
34  *
35  * If multiple elements live in the root of a wxDataViewCtrl, using
36  * ItemsAdded() can run into an assertion failure. To avoid this, we avoid
37  * notifying the widget of changes, but rather reinitialize it.
38  *
39  * When a fix for this exists in wxWidgets, this is the place to turn it
40  * off.
41  */
42 #define REASSOCIATE_HACK
43 
45  public wxDataViewModel
46 {
47 public:
48  DataViewModel( LIB_PART& aPart );
49 
50  // wxDataViewModel
51  virtual unsigned int GetColumnCount() const override;
52  virtual wxString GetColumnType( unsigned int col ) const override;
53  virtual void GetValue( wxVariant&, const wxDataViewItem&, unsigned int ) const override;
54  virtual bool SetValue( const wxVariant&, const wxDataViewItem&, unsigned int ) override;
55  virtual wxDataViewItem GetParent( const wxDataViewItem& ) const override;
56  virtual bool IsContainer( const wxDataViewItem& ) const override;
57  virtual bool HasContainerColumns( const wxDataViewItem& ) const override;
58  virtual unsigned int GetChildren( const wxDataViewItem&, wxDataViewItemArray& ) const override;
59 
60  virtual int Compare( const wxDataViewItem& lhs,
61  const wxDataViewItem& rhs,
62  unsigned int col,
63  bool ascending ) const override;
64 
65  void SetGroupingColumn( int aCol );
66  void CalculateGrouping();
67  void Refresh();
68 
70 
71 #ifdef REASSOCIATE_HACK
72  void SetWidget( wxDataViewCtrl* aWidget ) { m_Widget = aWidget; }
73 #endif
74 
75  enum
76  {
77  NONE = -1,
79  PIN_NAME = 1,
80  PIN_TYPE = 2,
82  };
83 
84 private:
89 
90  class Item;
91  class Group;
92  class Pin;
93 
94  mutable std::list<Pin> m_Pins;
95  mutable std::map<wxString, Group> m_Groups;
96 
97  // like GetValue, but always returns a string
98  wxString GetString( const wxDataViewItem&, unsigned int ) const;
99 
100 #ifdef REASSOCIATE_HACK
101  wxDataViewCtrl* m_Widget;
102 #endif
103 };
104 
106 {
107 public:
108  virtual void GetValue( wxVariant& aValue, unsigned int aCol ) const = 0;
109  virtual wxString GetString( unsigned int aCol ) const = 0;
110  virtual wxDataViewItem GetParent() const = 0;
111  virtual bool IsContainer() const = 0;
112  virtual unsigned int GetChildren( wxDataViewItemArray& ) const = 0;
113 };
114 
116  public Item
117 {
118 public:
119  Group( unsigned int aGroupingColumn ) : m_GroupingColumn( aGroupingColumn ) {}
120 
121  virtual void GetValue( wxVariant& aValue, unsigned int aCol ) const override;
122  virtual wxString GetString( unsigned int aCol ) const override;
123  virtual wxDataViewItem GetParent() const override { return wxDataViewItem(); }
124  virtual bool IsContainer() const override { return true; }
125  virtual unsigned int GetChildren( wxDataViewItemArray& aItems ) const override
126  {
128  for( std::list<Pin*>::const_iterator i = m_Members.begin(); i != m_Members.end(); ++i )
129  aItems.push_back( wxDataViewItem( *i ) );
130 
131  return aItems.size();
132  }
133 
134  unsigned int GetCount() const { return m_Members.size(); }
135  void Add( Pin* aPin );
136 
137 private:
138  std::list<Pin*> m_Members;
139  unsigned int m_GroupingColumn;
140 };
141 
143  public Item
144 {
145 public:
146  Pin( DataViewModel& aModel,
147  LIB_PIN* aBacking ) : m_Model( aModel ), m_Backing( aBacking ), m_Group( 0 ) {}
148 
149  virtual void GetValue( wxVariant& aValue, unsigned int aCol ) const override;
150  virtual wxString GetString( unsigned int aCol ) const override;
151  virtual wxDataViewItem GetParent() const override { return wxDataViewItem( m_Group ); }
152  virtual bool IsContainer() const override { return false; }
153  virtual unsigned int GetChildren( wxDataViewItemArray& ) const override { return 0; }
154 
155  void SetGroup( Group* aGroup ) { m_Group = aGroup; }
156 
157 private:
161 };
162 
164  LIB_PART& aPart ) :
166  m_Model( new DataViewModel( aPart ) )
167 {
168 #ifdef REASSOCIATE_HACK
169  m_Model->SetWidget( m_Pins );
170 #endif
171  m_Pins->AssociateModel( m_Model.get() );
172 
174  wxDataViewTextRenderer* rend0 = new wxDataViewTextRenderer( wxT( "string" ), wxDATAVIEW_CELL_INERT );
175  wxDataViewColumn* col0 = new wxDataViewColumn( _( "Number" ),
176  rend0,
178  100,
179  wxAlignment( wxALIGN_LEFT | wxALIGN_TOP ),
180  wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE );
181  wxDataViewTextRenderer* rend1 = new wxDataViewTextRenderer( wxT( "string" ), wxDATAVIEW_CELL_INERT );
182  wxDataViewColumn* col1 = new wxDataViewColumn( _( "Name" ),
183  rend1,
185  100,
186  wxAlignment( wxALIGN_LEFT | wxALIGN_TOP ),
187  wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE );
188  wxDataViewIconTextRenderer* rend2 = new wxDataViewIconTextRenderer( wxT( "wxDataViewIconText" ), wxDATAVIEW_CELL_INERT );
189  wxDataViewColumn* col2 = new wxDataViewColumn( _( "Type" ),
190  rend2,
192  100,
193  wxAlignment( wxALIGN_LEFT | wxALIGN_TOP ),
194  wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE );
195  wxDataViewTextRenderer* rend3 = new wxDataViewTextRenderer( wxT( "string" ), wxDATAVIEW_CELL_INERT );
196  wxDataViewColumn* col3 = new wxDataViewColumn( _( "Position" ),
197  rend3,
199  100,
200  wxAlignment( wxALIGN_LEFT | wxALIGN_TOP ),
201  wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE );
202  m_Pins->AppendColumn( col0 );
203  m_Pins->SetExpanderColumn( col0 );
204  m_Pins->AppendColumn( col1 );
205  m_Pins->AppendColumn( col2 );
206  m_Pins->AppendColumn( col3 );
207 
208  UpdateSummary();
209 
210  GetSizer()->SetSizeHints(this);
211  Centre();
212 }
213 
214 
216 {
217 }
218 
219 
221 {
222  PinNumbers pins = m_Model->GetAllPinNumbers();
223 
224  m_Summary->SetValue( pins.GetSummary() );
225 }
226 
227 
229 {
230  m_Model->SetGroupingColumn( event.GetDataViewColumn()->GetModelColumn() );
231  event.Skip();
232 }
233 
234 
236  m_Part( aPart ),
237  m_GroupingColumn( 1 ),
238  m_UnitCount( m_Part.GetUnitCount() )
239 {
240 #ifdef REASSOCIATE_HACK
241  m_Widget = NULL;
242 #endif
243  aPart.GetPins( m_Backing );
245  for( LIB_PINS::const_iterator i = m_Backing.begin(); i != m_Backing.end(); ++i )
246  m_Pins.push_back( Pin( *this, *i ) );
247 
249 }
250 
251 
253 {
254  return 4;
255 }
256 
257 
259 {
260  switch( aCol )
261  {
262  case PIN_NUMBER:
263  return wxT( "string" );
264 
265  case PIN_NAME:
266  return wxT( "string" );
267 
268  case PIN_TYPE:
269  return wxT( "wxDataViewIconText" );
270 
271  case PIN_POSITION:
272  return wxT( "string" );
273  }
274 
275  assert( ! "Unhandled column" );
276  return wxT( "" );
277 }
278 
279 
281  const wxDataViewItem& aItem,
282  unsigned int aCol ) const
283 {
284  assert( aItem.IsOk() );
285 
286  reinterpret_cast<Item const*>( aItem.GetID() )->GetValue( aVal, aCol );
287 }
288 
289 
291  const wxDataViewItem&,
292  unsigned int )
293 {
294  return false;
295 }
296 
297 
298 wxDataViewItem DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::GetParent( const wxDataViewItem& aItem )
299 const
300 {
301  assert( aItem.IsOk() );
302 
303  return reinterpret_cast<Item const*>( aItem.GetID() )->GetParent();
304 }
305 
306 
307 bool DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::IsContainer( const wxDataViewItem& aItem ) const
308 {
309  if( aItem.IsOk() )
310  return reinterpret_cast<Item const*>( aItem.GetID() )->IsContainer();
311  else
312  return true;
313 }
314 
315 
317 {
318  return true;
319 }
320 
321 
322 unsigned int DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::GetChildren( const wxDataViewItem& aItem,
323  wxDataViewItemArray& aItems ) const
324 {
325  if( !aItem.IsOk() )
326  {
327  for( std::map<wxString, Group>::iterator i = m_Groups.begin(); i != m_Groups.end(); ++i )
328  if( i->second.GetCount() > 1 )
329  aItems.push_back( wxDataViewItem( &i->second ) );
330 
331  for( std::list<Pin>::iterator i = m_Pins.begin(); i != m_Pins.end(); ++i )
332  if( !i->GetParent().IsOk() )
333  aItems.push_back( wxDataViewItem( &*i ) );
334 
335  return aItems.size();
336  }
337  else
338  return reinterpret_cast<Item const*>( aItem.GetID() )->GetChildren( aItems );
339 }
340 
341 
342 int DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::Compare( const wxDataViewItem& aItem1,
343  const wxDataViewItem& aItem2,
344  unsigned int aCol,
345  bool aAscending ) const
346 {
347  wxString str1 = GetString( aItem1, aCol );
348  wxString str2 = GetString( aItem2, aCol );
349  int res = PinNumbers::Compare( str1, str2 );
350 
351  if( res == 0 )
352  res = ( aItem1.GetID() < aItem2.GetID() ) ? -1 : 1;
353 
354  return res * ( aAscending ? 1 : -1 );
355 }
356 
357 
359 {
360  if( m_GroupingColumn == aCol )
361  m_GroupingColumn = NONE;
362  else
363  m_GroupingColumn = aCol;
364 
365  Cleared();
366  CalculateGrouping();
367  Refresh();
368 }
369 
370 
372 {
373  m_Groups.clear();
374 
375  if( m_GroupingColumn != -1 )
376  {
377  wxVariant value;
378 
379  for( std::list<Pin>::iterator i = m_Pins.begin(); i != m_Pins.end(); ++i )
380  {
381  wxString str = i->GetString( m_GroupingColumn );
382  std::map<wxString, Group>::iterator j = m_Groups.find( str );
383 
384  if( j == m_Groups.end() )
385  j = m_Groups.insert( std::make_pair( str, m_GroupingColumn ) ).first;
386 
387  j->second.Add( &*i );
388  }
389  }
390  else
391  {
392  for( std::list<Pin>::iterator i = m_Pins.begin(); i != m_Pins.end(); ++i )
393  i->SetGroup( 0 );
394  }
395 }
396 
397 
399 {
400 #ifdef REASSOCIATE_HACK
401  m_Widget->AssociateModel( this );
402 #else
403  std::queue<wxDataViewItem> todo;
404  todo.push( wxDataViewItem() );
405 
406  while( !todo.empty() )
407  {
408  wxDataViewItem current = todo.front();
409  wxDataViewItemArray items;
410 
411  GetChildren( current, items );
412  ItemsAdded( current, items );
413 
414  for( wxDataViewItemArray::const_iterator i = items.begin(); i != items.end(); ++i )
415  {
416  if( IsContainer( *i ) )
417  todo.push( *i );
418  }
419 
420  todo.pop();
421  }
422 
423 #endif
424 }
425 
426 
428 {
429  PinNumbers ret;
430 
431  for( std::list<Pin>::const_iterator i = m_Pins.begin(); i != m_Pins.end(); ++i )
432  ret.insert( i->GetString( PIN_NUMBER ) );
433 
434  return ret;
435 }
436 
437 
438 wxString DIALOG_LIB_EDIT_PIN_TABLE::DataViewModel::GetString( const wxDataViewItem& aItem, unsigned int aCol ) const
439 {
440  assert( aItem.IsOk() );
441 
442  return reinterpret_cast<Item const*>( aItem.GetID() )->GetString( aCol );
443 }
444 
445 
447  unsigned int aCol ) const
448 {
449  if( aCol == m_GroupingColumn )
450  // shortcut
451  m_Members.front()->GetValue( aValue, aCol );
452  else if( aCol != PIN_TYPE )
453  aValue = GetString( aCol );
454  else
455  {
456  PinNumbers values;
457 
458  for( std::list<Pin*>::const_iterator i = m_Members.begin(); i != m_Members.end(); ++i )
459  values.insert( (*i)->GetString( aCol ) );
460 
461  if( values.size() > 1 )
462  aValue << wxDataViewIconText( boost::algorithm::join( values, "," ), wxNullIcon );
463  else
464  m_Members.front()->GetValue( aValue, aCol );
465  }
466 }
467 
468 
470 {
471  if( aCol == m_GroupingColumn )
472  return m_Members.front()->GetString( aCol );
473 
474  PinNumbers values;
475 
476  for( std::list<Pin*>::const_iterator i = m_Members.begin(); i != m_Members.end(); ++i )
477  values.insert( (*i)->GetString( aCol ) );
478 
479  if( values.size() > 1 )
480  return boost::algorithm::join( values, "," );
481  else
482  return m_Members.front()->GetString( aCol );
483 }
484 
485 
487 {
488  switch( GetCount() )
489  {
490  case 0:
491  aPin->SetGroup( 0 );
492  break;
493 
494  case 1:
495  m_Members.front()->SetGroup( this );
496  // fall through
497 
498  default:
499  aPin->SetGroup( this );
500  }
501 
502  m_Members.push_back( aPin );
503 }
504 
505 
507  unsigned int aCol ) const
508 {
509  switch( aCol )
510  {
511  case PIN_NUMBER:
512  case PIN_NAME:
513  case PIN_POSITION:
514  aValue = GetString( aCol );
515  break;
516 
517  case PIN_TYPE:
518  {
519  wxIcon icon;
520  icon.CopyFromBitmap( KiBitmap ( GetBitmap( m_Backing->GetType() ) ) );
521  aValue << wxDataViewIconText( m_Backing->GetElectricalTypeName(), icon );
522  }
523  break;
524  }
525 }
526 
527 
529 {
530  switch( aCol )
531  {
532  case PIN_NUMBER:
533  return m_Backing->GetNumberString();
534 
535  case PIN_NAME:
536  if( m_Model.m_UnitCount > 1 )
537  {
538  wxString name;
539  int unit = m_Backing->GetPartNumber();
540 
541  if( unit )
542  name << unit;
543  else
544  name << "com";
545 
546  name << ':';
547  name << m_Backing->GetName();
548  return name;
549  }
550  else
551  {
552  return m_Backing->GetName();
553  }
554 
555  case PIN_TYPE:
556  return m_Backing->GetElectricalTypeName();
557 
558  case PIN_POSITION:
559  {
560  wxPoint position = m_Backing->GetPosition();
561  wxString value;
562  value << "(" << position.x << "," << position.y << ")";
563  return value;
564  }
565  }
566 
567  return wxEmptyString;
568 }
static int Compare(PinNumber const &lhs, PinNumber const &rhs)
Definition: pin_number.cpp:110
virtual void GetValue(wxVariant &aValue, unsigned int aCol) const override
virtual void GetValue(wxVariant &, const wxDataViewItem &, unsigned int) const override
virtual wxString GetString(unsigned int aCol) const override
virtual void GetValue(wxVariant &aValue, unsigned int aCol) const =0
virtual void OnColumnHeaderRightClicked(wxDataViewEvent &aEvent) override
virtual void GetValue(wxVariant &aValue, unsigned int aCol) const override
virtual wxDataViewItem GetParent() const override
virtual wxDataViewItem GetParent() const =0
void insert(value_type const &v)
Definition: pin_number.h:57
virtual unsigned int GetChildren(const wxDataViewItem &, wxDataViewItemArray &) const override
void GetPins(LIB_PINS &aList, int aUnit=0, int aConvert=0)
Return a list of pin object pointers from the draw item list.
virtual wxString GetString(unsigned int aCol) const =0
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Function KiBitmap constructs a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:36
wxObjectDataPtr< DataViewModel > m_Model
wxString GetSummary() const
Definition: pin_number.cpp:70
virtual wxDataViewItem GetParent() const override
void Refresh()
virtual bool IsContainer(const wxDataViewItem &) const override
Class LIB_PART defines a library part object.
virtual wxString GetString(unsigned int aCol) const override
DIALOG_LIB_EDIT_PIN_TABLE(wxWindow *parent, LIB_PART &aPart)
virtual unsigned int GetColumnCount() const override
Class DIALOG_LIB_EDIT_PIN_TABLE_BASE.
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_draw_item.h:70
virtual unsigned int GetChildren(wxDataViewItemArray &) const =0
virtual int Compare(const wxDataViewItem &lhs, const wxDataViewItem &rhs, unsigned int col, bool ascending) const override
virtual unsigned int GetChildren(wxDataViewItemArray &) const override
virtual bool HasContainerColumns(const wxDataViewItem &) const override
virtual wxString GetColumnType(unsigned int col) const override
const char * name
Pin(DataViewModel &aModel, LIB_PIN *aBacking)
virtual unsigned int GetChildren(wxDataViewItemArray &aItems) const override
BITMAP_DEF GetBitmap(GRAPHIC_PINSHAPE shape)
Definition: pin_shape.cpp:70
container_type::size_type size() const
Definition: pin_number.h:58
virtual wxDataViewItem GetParent(const wxDataViewItem &) const override
virtual bool SetValue(const wxVariant &, const wxDataViewItem &, unsigned int) override
wxString GetString(const wxDataViewItem &, unsigned int) const