KiCad PCB EDA Suite
load_select_footprint.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) 2018 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
5  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 1992-2018 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 
26 #include <functional>
27 using namespace std::placeholders;
28 
29 #include <class_board.h>
30 #include <class_module.h>
31 #include <confirm.h>
35 #include <dialog_helpers.h>
36 #include <footprint_edit_frame.h>
37 #include <footprint_info_impl.h>
38 #include <footprint_tree_pane.h>
39 #include <footprint_viewer_frame.h>
40 #include <fp_lib_table.h>
41 #include <io_mgr.h>
42 #include <kicad_string.h>
43 #include <kiway.h>
44 #include <lib_id.h>
45 #include <macros.h>
46 #include <pcb_draw_panel_gal.h>
47 #include <pcb_edit_frame.h>
48 #include <pcbnew.h>
49 #include <pcbnew_settings.h>
50 #include <pgm_base.h>
51 #include <view/view_controls.h>
52 #include <widgets/lib_tree.h>
54 
55 #include "fp_tree_model_adapter.h"
56 
57 
58 static wxArrayString s_ModuleHistoryList;
59 static unsigned s_ModuleHistoryMaxCount = 8;
60 
61 static void AddModuleToHistory( const wxString& aName )
62 {
63  // Remove duplicates
64  for( int ii = s_ModuleHistoryList.GetCount() - 1; ii >= 0; --ii )
65  {
66  if( s_ModuleHistoryList[ ii ] == aName )
67  s_ModuleHistoryList.RemoveAt( (size_t) ii );
68  }
69 
70  // Add the new name at the beginning of the history list
71  s_ModuleHistoryList.Insert( aName, 0 );
72 
73  // Remove extra names
74  while( s_ModuleHistoryList.GetCount() >= s_ModuleHistoryMaxCount )
75  s_ModuleHistoryList.RemoveAt( s_ModuleHistoryList.GetCount() - 1 );
76 }
77 
78 
79 static void clearModuleItemFlags( BOARD_ITEM* aItem )
80 {
81  aItem->ClearFlags();
82 }
83 
84 #include <bitmaps.h>
86 {
87  bool is_last_fp_from_brd = IsCurrentFPFromBoard();
88 
89  MODULE* newModule;
91 
92  if( frame == NULL ) // happens if no board editor opened
93  return false;
94 
95  if( aModule == NULL )
96  {
97  if( !frame->GetBoard() || !frame->GetBoard()->GetFirstModule() )
98  return false;
99 
100  aModule = SelectFootprintFromBoard( frame->GetBoard() );
101  }
102 
103  if( aModule == NULL )
104  return false;
105 
106  if( !Clear_Pcb( true ) )
107  return false;
108 
109  newModule = (MODULE*) aModule->Duplicate();
110  newModule->SetParent( GetBoard() );
111  newModule->SetLink( aModule->m_Uuid );
112 
113  newModule->ClearFlags();
114  newModule->RunOnChildren( std::bind( &clearModuleItemFlags, _1 ) );
115 
116  AddModuleToBoard( newModule );
117 
118  // Clear references to any net info, because the footprint editor
119  // does know any thing about nets handled by the current edited board.
120  // Morever we do not want to save any reference to an unknown net when
121  // saving the footprint in lib cache
122  // so we force the ORPHANED dummy net info for all pads
123  newModule->ClearAllNets();
124 
125  GetCanvas()->GetViewControls()->SetCrossHairCursorPosition( VECTOR2D( 0, 0 ), false );
126  PlaceModule( newModule );
127  newModule->SetPosition( wxPoint( 0, 0 ) ); // cursor in GAL may not be initialized at the moment
128 
129  // Put it on FRONT layer,
130  // because this is the default in ModEdit, and in libs
131  if( newModule->GetLayer() != F_Cu )
132  newModule->Flip( newModule->GetPosition(), frame->Settings().m_FlipLeftRight );
133 
134  // Put it in orientation 0,
135  // because this is the default orientation in ModEdit, and in libs
136  newModule->SetOrientation( 0 );
137 
138  Zoom_Automatique( false );
139 
140  m_adapter->SetPreselectNode( newModule->GetFPID(), 0 );
141 
142  GetScreen()->ClearUndoRedoList();
143  GetScreen()->ClrModify();
144 
145  // Update the save items if needed.
146  if( !is_last_fp_from_brd )
147  {
148  ReCreateMenuBar();
149  ReCreateHToolbar();
150  }
151 
152  Update3DView( true );
153  updateView();
154  GetCanvas()->Refresh();
155  m_treePane->GetLibTree()->RefreshLibTree(); // update any previously-highlighted items
156 
157  return true;
158 }
159 
160 
162 {
163  // Close the current non-modal Lib browser if opened, and open a new one, in "modal" mode:
164  FOOTPRINT_VIEWER_FRAME* viewer;
166 
167  if( viewer )
168  {
169  viewer->Destroy();
170  // Destroy() does not immediately delete the viewer, if some events are pending.
171  // (for this reason delete operator cannot be used blindly with "top level" windows)
172  // so gives a slice of time to delete the viewer frame.
173  // This is especially important in OpenGL mode to avoid recreating context before
174  // the old one is deleted
175  wxSafeYield();
176  }
177 
178  SetFocus();
179 
180  // Creates the modal Lib browser:
182 
183  wxString fpid;
184  int ret = viewer->ShowModal( &fpid, this );
185  (void) ret; // make static analyser quiet
186 
187  viewer->Destroy();
188 
189  return fpid;
190 }
191 
192 
194 {
195  FP_LIB_TABLE* fpTable = Prj().PcbFootprintLibs();
196  wxString moduleName;
197  LIB_ID fpid;
198  MODULE* module = NULL;
199 
200  static wxString lastComponentName;
201 
202  // Load footprint files:
203  WX_PROGRESS_REPORTER* progressReporter = new WX_PROGRESS_REPORTER( this,
204  _( "Loading Footprint Libraries" ), 3 );
205  GFootprintList.ReadFootprintFiles( fpTable, nullptr, progressReporter );
206  bool cancel = progressReporter->WasCancelled();
207  progressReporter->Destroy();
208 
209  if( cancel )
210  return nullptr;
211 
214 
215  auto adapterPtr( FP_TREE_MODEL_ADAPTER::Create( this, fpTable ) );
216  auto adapter = static_cast<FP_TREE_MODEL_ADAPTER*>( adapterPtr.get() );
217 
218  std::vector<LIB_TREE_ITEM*> historyInfos;
219 
220  for( auto const& item : s_ModuleHistoryList )
221  {
222  LIB_TREE_ITEM* fp_info = GFootprintList.GetModuleInfo( item );
223 
224  // this can be null, for example, if the footprint has been deleted from a library.
225  if( fp_info != nullptr )
226  historyInfos.push_back( fp_info );
227  }
228 
229  adapter->DoAddLibrary( "-- " + _( "Recently Used" ) + " --", wxEmptyString, historyInfos, true );
230 
231  if( aPreselect.IsValid() )
232  adapter->SetPreselectNode( aPreselect, 0 );
233  else if( historyInfos.size() )
234  adapter->SetPreselectNode( historyInfos[0]->GetLibId(), 0 );
235 
236  adapter->AddLibraries();
237 
238  wxString title;
239  title.Printf( _( "Choose Footprint (%d items loaded)" ), adapter->GetItemCount() );
240 
241  DIALOG_CHOOSE_FOOTPRINT dialog( this, title, adapterPtr );
242 
243  if( dialog.ShowQuasiModal() == wxID_CANCEL )
244  return NULL;
245 
246  if( dialog.IsExternalBrowserSelected() )
247  {
248  // SelectFootprintFromLibBrowser() returns the "full" footprint name, i.e.
249  // <lib_name>/<footprint name> or LIB_ID format "lib_name:fp_name:rev#"
250  moduleName = SelectFootprintFromLibBrowser();
251 
252  if( moduleName.IsEmpty() ) // Cancel command
253  return NULL;
254  else
255  fpid.Parse( moduleName, LIB_ID::ID_PCB );
256  }
257  else
258  {
259  fpid = dialog.GetSelectedLibId();
260 
261  if( !fpid.IsValid() )
262  return NULL;
263  else
264  moduleName = fpid.Format();
265  }
266 
267  try
268  {
269  module = loadFootprint( fpid );
270  }
271  catch( const IO_ERROR& ioe )
272  {
273  wxLogDebug( wxT( "Error loading footprint '%s'.\n\nError: %s" ),
274  fpid.Format().c_str(),
275  ioe.What() );
276  }
277 
278  if( module )
279  {
280  lastComponentName = moduleName;
281  AddModuleToHistory( moduleName );
282  }
283 
284  return module;
285 }
286 
287 
289 {
290  MODULE* module = NULL;
291 
292  try
293  {
294  module = loadFootprint( aFootprintId );
295  }
296  catch( const IO_ERROR& ioe )
297  {
298  wxLogDebug( wxT( "An error occurred attemping to load footprint '%s'.\n\nError: %s" ),
299  aFootprintId.Format().c_str(), GetChars( ioe.What() ) );
300  }
301 
302  return module;
303 }
304 
305 
307 {
308  FP_LIB_TABLE* fptbl = Prj().PcbFootprintLibs();
309 
310  wxCHECK_MSG( fptbl, NULL, wxT( "Cannot look up LIB_ID in NULL FP_LIB_TABLE." ) );
311 
312  MODULE *module = nullptr;
313  try
314  {
315  module = fptbl->FootprintLoadWithOptionalNickname( aFootprintId );
316  }
317  catch( const IO_ERROR& ioe )
318  {
319  wxLogDebug( wxT( "An error occurred attemping to load footprint '%s'.\n\nError: %s" ),
320  aFootprintId.Format().c_str(), GetChars( ioe.What() ) );
321  }
322 
323  // If the module is found, clear all net info,
324  // to be sure there is no broken links
325  // to any netinfo list (should be not needed, but it can be edited from
326  // the footprint editor )
327  if( module )
328  module->ClearAllNets();
329 
330  return module;
331 }
332 
333 
335 {
336  static wxString oldName; // Save name of last module selected.
337 
338  wxString fpname;
339  wxString msg;
340  wxArrayString listnames;
341 
342  for( auto module : aPcb->Modules() )
343  listnames.Add( module->GetReference() );
344 
345  msg.Printf( _( "Footprints [%u items]" ), (unsigned) listnames.GetCount() );
346 
347  wxArrayString headers;
348 
349  headers.Add( _( "Footprint" ) );
350 
351  std::vector<wxArrayString> itemsToDisplay;
352 
353  // Conversion from wxArrayString to vector of ArrayString
354  for( unsigned i = 0; i < listnames.GetCount(); i++ )
355  {
356  wxArrayString item;
357 
358  item.Add( listnames[i] );
359  itemsToDisplay.push_back( item );
360  }
361 
362  EDA_LIST_DIALOG dlg( this, msg, headers, itemsToDisplay, wxEmptyString );
363 
364  if( dlg.ShowModal() == wxID_OK )
365  fpname = dlg.GetTextSelection();
366  else
367  return NULL;
368 
369  oldName = fpname;
370 
371  for( auto mod : aPcb->Modules() )
372  {
373  if( fpname == mod->GetReference() )
374  return mod;
375  }
376 
377  return nullptr;
378 }
379 
380 
381 bool FOOTPRINT_EDIT_FRAME::SaveLibraryAs( const wxString& aLibraryPath )
382 {
383  const wxString& curLibPath = aLibraryPath;
384  wxString dstLibPath = CreateNewLibrary();
385 
386  if( !dstLibPath )
387  return false; // user aborted in CreateNewLibrary()
388 
389  wxBusyCursor dummy;
390  wxString msg;
391 
394 
395  try
396  {
397  PLUGIN::RELEASER cur( IO_MGR::PluginFind( curType ) );
398  PLUGIN::RELEASER dst( IO_MGR::PluginFind( dstType ) );
399 
400  wxArrayString footprints;
401 
402  cur->FootprintEnumerate( footprints, curLibPath, false );
403 
404  for( unsigned i = 0; i < footprints.size(); ++i )
405  {
406  const MODULE* footprint = cur->GetEnumeratedFootprint( curLibPath, footprints[i] );
407  dst->FootprintSave( dstLibPath, footprint );
408 
409  msg = wxString::Format( _( "Footprint \"%s\" saved" ), footprints[i] );
410  SetStatusText( msg );
411  }
412  }
413  catch( const IO_ERROR& ioe )
414  {
415  DisplayError( this, ioe.What() );
416  return false;
417  }
418 
419  msg = wxString::Format( _( "Footprint library \"%s\" saved as \"%s\"." ),
420  curLibPath,
421  dstLibPath );
422 
423  DisplayInfoMessage( this, msg );
424 
425  SetStatusText( wxEmptyString );
426  return true;
427 }
428 
429 
430 static MODULE* s_ModuleInitialCopy = NULL; // Copy of module for abort/undo command
431 
432 static PICKED_ITEMS_LIST s_PickedList; // a pick-list to save initial module
433 // and dragged tracks
434 
435 
437 {
438  wxString moduleName;
439  wxArrayString fplist;
440 
441  // Build list of available fp references, to display them in dialog
442  for( auto fp : GetBoard()->Modules() )
443  fplist.Add( fp->GetReference() + wxT(" ( ") + fp->GetValue() + wxT(" )") );
444 
445  fplist.Sort();
446 
447  DIALOG_GET_FOOTPRINT_BY_NAME dlg( this, fplist );
448 
449  if( dlg.ShowModal() != wxID_OK ) //Aborted by user
450  return NULL;
451 
452  moduleName = dlg.GetValue();
453  moduleName.Trim( true );
454  moduleName.Trim( false );
455 
456  if( !moduleName.IsEmpty() )
457  {
458  for( auto mod : GetBoard()->Modules() )
459  {
460  if( mod->GetReference().CmpNoCase( moduleName ) == 0 )
461  return mod;
462  }
463  }
464 
465  return nullptr;
466 }
467 
468 
469 void PCB_BASE_FRAME::PlaceModule( MODULE* aModule, bool aRecreateRatsnest )
470 {
471  if( aModule == 0 )
472  return;
473 
474  OnModify();
475 
476  if( aModule->IsNew() )
477  {
478  SaveCopyInUndoList( aModule, UR_NEW );
479  }
480  else if( aModule->IsMoving() )
481  {
482  ITEM_PICKER picker( aModule, UR_CHANGED );
483  picker.SetLink( s_ModuleInitialCopy );
484  s_PickedList.PushItem( picker );
485  s_ModuleInitialCopy = NULL; // the picker is now owner of s_ModuleInitialCopy.
486  }
487 
488  if( s_PickedList.GetCount() )
489  {
490  SaveCopyInUndoList( s_PickedList, UR_UNSPECIFIED );
491 
492  // Clear list, but DO NOT delete items, because they are owned by the saved undo
493  // list and they therefore in use
495  }
496 
497  aModule->SetPosition( (wxPoint) GetCanvas()->GetViewControls()->GetCursorPosition() );
498  aModule->ClearFlags();
499 
500  delete s_ModuleInitialCopy;
502 
503  if( aRecreateRatsnest )
504  m_Pcb->GetConnectivity()->Update( aModule );
505 
506  if( aRecreateRatsnest )
507  Compile_Ratsnest( true );
508 
509  SetMsgPanel( aModule );
510 }
511 
512 
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:239
wxString SelectFootprintFromLibBrowser()
Function SelectFootprintFromLibBrowser launches the footprint viewer to select the name of a footprin...
void SetLink(const KIID &aLink)
Definition: class_module.h:550
static void AddModuleToHistory(const wxString &aName)
bool ShowModal(wxString *aFootprint, wxWindow *aParent) override
Function ShowModal.
wxString GetTextSelection(int aColumn=0)
Function GetTextSelection return the selected text from aColumn in the wxListCtrl in the dialog.
Definition: displlst.cpp:141
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction)
Function RunOnChildren.
FOOTPRINT_INFO * GetModuleInfo(const wxString &aFootprintId)
Get info for a module by id.
bool IsExternalBrowserSelected() const
Function IsExternalBrowserSelected.
This file is part of the common library.
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
VIEW_CONTROLS class definition.
A mix-in to provide polymorphism between items stored in libraries (symbols, aliases and footprints).
Definition: lib_tree_item.h:39
PROJECT & Prj()
Definition: kicad.cpp:317
static PICKED_ITEMS_LIST s_PickedList
bool IsMoving() const
Definition: base_struct.h:222
Component library viewer main window.
void DisplayErrors(wxTopLevelWindow *aCaller=NULL)
MODULE * SelectFootprintFromLibTree(LIB_ID aPreselect=LIB_ID())
Function SelectFootprintFromLibTree opens a dialog to select a footprint.
EDA_LIST_DIALOG.
void PushItem(const ITEM_PICKER &aItem)
Function PushItem pushes aItem to the top of the list.
const LIB_ID & GetFPID() const
Definition: class_module.h:219
Dialog class to select a footprint from the libraries.
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
bool IsValid() const
Definition: lib_id.h:171
void SetLink(EDA_ITEM *aItem)
unsigned GetCount() const
Function GetCount.
static PCB_FILE_T GuessPluginTypeFromLibPath(const wxString &aLibPath)
Function GuessPluginTypeFromLibPath returns a plugin type given a footprint library's libPath.
Definition: io_mgr.cpp:124
This file contains miscellaneous commonly used macros and functions.
bool IsNew() const
Definition: base_struct.h:220
const char * c_str() const
Definition: utf8.h:107
MODULE * SelectFootprintFromBoard(BOARD *aPcb)
Display the list of modules currently existing on the BOARD.
RELEASER releases a PLUGIN in the context of a potential thrown exception, through its destructor.
Definition: io_mgr.h:577
DIALOG_GET_FOOTPRINT_BY_NAME is a helper dialog to select a footprint by its reference One can enter ...
FOOTPRINT_LIST_IMPL GFootprintList
The global footprint info table.
static PTR Create(EDA_BASE_FRAME *aParent, LIB_TABLE *aLibs)
Factory function: create a model adapter in a reference-counting container.
void ClearAllNets()
Function ClearAllNets Clear (i.e.
static MODULE * s_ModuleInitialCopy
#define NULL
VECTOR2< double > VECTOR2D
Definition: vector2d.h:593
VTBL_ENTRY KIWAY_PLAYER * Player(FRAME_T aFrameType, bool doCreate=true, wxTopLevelWindow *aParent=NULL)
Function Player returns the KIWAY_PLAYER* given a FRAME_T.
Definition: kiway.cpp:341
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
MODULES & Modules()
Definition: class_board.h:229
bool SaveLibraryAs(const wxString &aLibraryPath)
Save a library to a new name and/or library type.
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:218
int ShowQuasiModal()
void Flip(const wxPoint &aCentre, bool aFlipLeftRight) override
Function Flip Flip this object, i.e.
MODULE * GetFirstModule() const
Gets the first module in the list (used in footprint viewer/editor) or NULL if none.
Definition: class_board.h:283
LIB_ID GetSelectedLibId() const
To be called after this dialog returns from ShowModal().
Helper dialog and control classes.
bool Load_Module_From_BOARD(MODULE *Module)
Load in Modedit a footprint from the main board.
void SetPosition(const wxPoint &aPos) override
PICKED_ITEMS_LIST is a holder to handle information on schematic or board items.
UTF8 Format() const
Definition: lib_id.cpp:237
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
static unsigned s_ModuleHistoryMaxCount
BOARD * GetBoard()
const KIID m_Uuid
Definition: base_struct.h:169
VTBL_ENTRY FP_LIB_TABLE * PcbFootprintLibs(KIWAY &aKiway)
Return the table of footprint libraries.
Definition: project.cpp:427
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:101
see class PGM_BASE
MODULE * LoadFootprint(const LIB_ID &aFootprintId)
Function LoadFootprint attempts to load aFootprintId from the footprint library table.
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
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:163
#define _(s)
Definition: 3d_actions.cpp:33
void SetOrientation(double newangle)
static PLUGIN * PluginFind(PCB_FILE_T aFileType)
Function PluginFind returns a PLUGIN which the caller can use to import, export, save,...
Definition: io_mgr.cpp:58
PCB_EDIT_FRAME is the main frame for Pcbnew.
PCBNEW_SETTINGS & Settings()
unsigned GetErrorCount() const
void ClearItemsList()
Function ClearItemsList deletes only the list of pickers, NOT the picked data itself.
bool Destroy() override
Our version of Destroy() which is virtual from wxWidgets.
bool ReadFootprintFiles(FP_LIB_TABLE *aTable, const wxString *aNickname=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr) override
Read all the footprints provided by the combination of aTable and aNickname.
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:258
static void clearModuleItemFlags(BOARD_ITEM *aItem)
MODULE * FootprintLoadWithOptionalNickname(const LIB_ID &aFootprintId)
Function FootprintLoadWithOptionalNickname loads a footprint having aFootprintId with possibly an emp...
MODULE * GetFootprintFromBoardByReference()
Function GetFootprintFromBoardByReference.
Module description (excepted pads)
BOARD * GetBoard() const
void PlaceModule(MODULE *aModule, bool aRecreateRatsnest=true)
Function PlaceModule places aModule at the current cursor position and updates module coordinates wit...
int Parse(const UTF8 &aId, LIB_ID_TYPE aType, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:122
PCB_FILE_T
Enum PCB_FILE_T is a set of file types that the IO_MGR knows about, and for which there has been a pl...
Definition: io_mgr.h:54
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition: confirm.cpp:267
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:76
const wxPoint GetPosition() const override
Definition: class_module.h:210
MODULE * loadFootprint(const LIB_ID &aFootprintId)
Function loadFootprint attempts to load aFootprintId from the footprint library table.
BOARD_ITEM * Duplicate() const
Function Duplicate creates a copy of a BOARD_ITEM.
static wxArrayString s_ModuleHistoryList
KIWAY Kiway