1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2019 CERN
5  * Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
23  */
24 
25 #include <kiway.h>
26 #include <sch_painter.h>
27 #include <tool/tool_manager.h>
28 #include <tools/ee_actions.h>
29 #include <tools/symbol_editor_control.h>
30 #include <symbol_edit_frame.h>
31 #include <symbol_library_manager.h>
32 #include <symbol_viewer_frame.h>
33 #include <symbol_tree_model_adapter.h>
34 #include <wildcards_and_files_ext.h>
35 #include <wildcards_and_files_ext.h>
36 #include <bitmaps/bitmap_types.h>
37 #include <confirm.h>
38 #include <wx/filedlg.h>
39 
40 
Init()41 bool SYMBOL_EDITOR_CONTROL::Init()
42 {
43     m_frame = getEditFrame<SCH_BASE_FRAME>();
44     m_selectionTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
45     m_isSymbolEditor = m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR );
46 
47     if( m_isSymbolEditor )
48     {
49         CONDITIONAL_MENU& ctxMenu = m_menu.GetMenu();
50         SYMBOL_EDIT_FRAME* editFrame = getEditFrame<SYMBOL_EDIT_FRAME>();
51 
52         wxCHECK( editFrame, false );
53 
54         auto libSelectedCondition =
55                 [ editFrame ]( const SELECTION& aSel )
56                 {
57                     LIB_ID sel = editFrame->GetTreeLIBID();
58                     return !sel.GetLibNickname().empty() && sel.GetLibItemName().empty();
59                 };
60         // The libInferredCondition allows you to do things like New Symbol and Paste with a
61         // symbol selected (in other words, when we know the library context even if the library
62         // itself isn't selected.
63         auto libInferredCondition =
64                 [ editFrame ]( const SELECTION& aSel )
65                 {
66                     LIB_ID sel = editFrame->GetTreeLIBID();
67                     return !sel.GetLibNickname().empty();
68                 };
69         auto pinnedLibSelectedCondition =
70                 [ editFrame ]( const SELECTION& aSel )
71                 {
72                     LIB_TREE_NODE* current = editFrame->GetCurrentTreeNode();
73                     return current && current->m_Type == LIB_TREE_NODE::LIB && current->m_Pinned;
74                 };
75         auto unpinnedLibSelectedCondition =
76                 [ editFrame ](const SELECTION& aSel )
77                 {
78                     LIB_TREE_NODE* current = editFrame->GetCurrentTreeNode();
79                     return current && current->m_Type == LIB_TREE_NODE::LIB && !current->m_Pinned;
80                 };
81         auto symbolSelectedCondition =
82                 [ editFrame ]( const SELECTION& aSel )
83                 {
84                     LIB_ID sel = editFrame->GetTreeLIBID();
85                     return !sel.GetLibNickname().empty() && !sel.GetLibItemName().empty();
86                 };
87         auto saveSymbolAsCondition =
88                 [ editFrame ]( const SELECTION& aSel )
89                 {
90                     LIB_ID sel = editFrame->GetTargetLibId();
91                     return !sel.GetLibNickname().empty() && !sel.GetLibItemName().empty();
92                 };
93 
94         ctxMenu.AddItem( ACTIONS::pinLibrary,            unpinnedLibSelectedCondition );
95         ctxMenu.AddItem( ACTIONS::unpinLibrary,          pinnedLibSelectedCondition );
96 
97         ctxMenu.AddSeparator();
98         ctxMenu.AddItem( EE_ACTIONS::newSymbol,          libInferredCondition );
99 
100         ctxMenu.AddSeparator();
101         ctxMenu.AddItem( ACTIONS::save,                  symbolSelectedCondition || libInferredCondition );
102         ctxMenu.AddItem( EE_ACTIONS::saveLibraryAs,      libSelectedCondition );
103         ctxMenu.AddItem( EE_ACTIONS::saveSymbolAs,       saveSymbolAsCondition );
104         ctxMenu.AddItem( ACTIONS::revert,                symbolSelectedCondition || libInferredCondition );
105 
106         ctxMenu.AddSeparator();
107         ctxMenu.AddItem( EE_ACTIONS::cutSymbol,          symbolSelectedCondition );
108         ctxMenu.AddItem( EE_ACTIONS::copySymbol,         symbolSelectedCondition );
109         ctxMenu.AddItem( EE_ACTIONS::pasteSymbol,        libInferredCondition );
110         ctxMenu.AddItem( EE_ACTIONS::duplicateSymbol,    symbolSelectedCondition );
111         ctxMenu.AddItem( EE_ACTIONS::deleteSymbol,       symbolSelectedCondition );
112 
113         ctxMenu.AddSeparator();
114         ctxMenu.AddItem( EE_ACTIONS::importSymbol,       libInferredCondition );
115         ctxMenu.AddItem( EE_ACTIONS::exportSymbol,       symbolSelectedCondition );
116 
117         // If we've got nothing else to show, at least show a hide tree option
118         ctxMenu.AddItem( EE_ACTIONS::hideSymbolTree,    !libInferredCondition );
119     }
120 
121     return true;
122 }
123 
124 
AddLibrary(const TOOL_EVENT & aEvent)125 int SYMBOL_EDITOR_CONTROL::AddLibrary( const TOOL_EVENT& aEvent )
126 {
127     bool createNew = aEvent.IsAction( &ACTIONS::newLibrary );
128 
129     if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
130         static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->AddLibraryFile( createNew );
131 
132     return 0;
133 }
134 
135 
EditSymbol(const TOOL_EVENT & aEvent)136 int SYMBOL_EDITOR_CONTROL::EditSymbol( const TOOL_EVENT& aEvent )
137 {
138     if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
139     {
140         SYMBOL_EDIT_FRAME* editFrame = static_cast<SYMBOL_EDIT_FRAME*>( m_frame );
141         int                unit = 0;
142         LIB_ID             partId = editFrame->GetTreeLIBID( &unit );
143 
144         editFrame->LoadSymbol( partId.GetLibItemName(), partId.GetLibNickname(), unit );
145     }
146 
147     return 0;
148 }
149 
150 
AddSymbol(const TOOL_EVENT & aEvent)151 int SYMBOL_EDITOR_CONTROL::AddSymbol( const TOOL_EVENT& aEvent )
152 {
153     if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
154     {
155         SYMBOL_EDIT_FRAME* editFrame = static_cast<SYMBOL_EDIT_FRAME*>( m_frame );
156 
157         LIB_ID          sel = editFrame->GetTreeLIBID();
158         const wxString& libName = sel.GetLibNickname();
159         wxString        msg;
160 
161         if( libName.IsEmpty() )
162         {
163             msg.Printf( _( "No symbol library selected." ), libName );
164             m_frame->ShowInfoBarError( msg );
165             return 0;
166         }
167 
168         if( editFrame->GetLibManager().IsLibraryReadOnly( libName ) )
169         {
170             msg.Printf( _( "Symbol library '%s' is not writable." ), libName );
171             m_frame->ShowInfoBarError( msg );
172             return 0;
173         }
174 
175         if( aEvent.IsAction( &EE_ACTIONS::newSymbol ) )
176             editFrame->CreateNewSymbol();
177         else if( aEvent.IsAction( &EE_ACTIONS::importSymbol ) )
178             editFrame->ImportSymbol();
179     }
180 
181     return 0;
182 }
183 
184 
Save(const TOOL_EVENT & aEvt)185 int SYMBOL_EDITOR_CONTROL::Save( const TOOL_EVENT& aEvt )
186 {
187     if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
188     {
189         SYMBOL_EDIT_FRAME* editFrame = static_cast<SYMBOL_EDIT_FRAME*>( m_frame );
190 
191         if( aEvt.IsAction( &EE_ACTIONS::save ) )
192             editFrame->Save();
193         else if( aEvt.IsAction( &EE_ACTIONS::saveLibraryAs ) )
194             editFrame->SaveLibraryAs();
195         else if( aEvt.IsAction( &EE_ACTIONS::saveSymbolAs ) )
196             editFrame->SaveSymbolAs();
197         else if( aEvt.IsAction( &EE_ACTIONS::saveAll ) )
198             editFrame->SaveAll();
199     }
200 
201     return 0;
202 }
203 
204 
Revert(const TOOL_EVENT & aEvent)205 int SYMBOL_EDITOR_CONTROL::Revert( const TOOL_EVENT& aEvent )
206 {
207     if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
208         static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->Revert();
209 
210     return 0;
211 }
212 
213 
ExportSymbol(const TOOL_EVENT & aEvent)214 int SYMBOL_EDITOR_CONTROL::ExportSymbol( const TOOL_EVENT& aEvent )
215 {
216     if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
217         static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->ExportSymbol();
218 
219     return 0;
220 }
221 
222 
CutCopyDelete(const TOOL_EVENT & aEvt)223 int SYMBOL_EDITOR_CONTROL::CutCopyDelete( const TOOL_EVENT& aEvt )
224 {
225     if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
226     {
227         SYMBOL_EDIT_FRAME* editFrame = static_cast<SYMBOL_EDIT_FRAME*>( m_frame );
228 
229         if( aEvt.IsAction( &EE_ACTIONS::cutSymbol ) || aEvt.IsAction( &EE_ACTIONS::copySymbol ) )
230             editFrame->CopySymbolToClipboard();
231 
232         if( aEvt.IsAction( &EE_ACTIONS::cutSymbol ) || aEvt.IsAction( &EE_ACTIONS::deleteSymbol ) )
233         {
234             LIB_ID          sel = editFrame->GetTreeLIBID();
235             const wxString& libName = sel.GetLibNickname();
236             wxString        msg;
237 
238             if( editFrame->GetLibManager().IsLibraryReadOnly( libName ) )
239             {
240                 msg.Printf( _( "Symbol library '%s' is not writable." ), libName );
241                 m_frame->ShowInfoBarError( msg );
242                 return 0;
243             }
244 
245             editFrame->DeleteSymbolFromLibrary();
246         }
247     }
248 
249     return 0;
250 }
251 
252 
DuplicateSymbol(const TOOL_EVENT & aEvent)253 int SYMBOL_EDITOR_CONTROL::DuplicateSymbol( const TOOL_EVENT& aEvent )
254 {
255     if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
256     {
257         SYMBOL_EDIT_FRAME* editFrame = static_cast<SYMBOL_EDIT_FRAME*>( m_frame );
258 
259         LIB_ID          sel = editFrame->GetTreeLIBID();
260         const wxString& libName = sel.GetLibNickname();
261         wxString        msg;
262 
263         if( editFrame->GetLibManager().IsLibraryReadOnly( libName ) )
264         {
265             msg.Printf( _( "Symbol library '%s' is not writable." ), libName );
266             m_frame->ShowInfoBarError( msg );
267             return 0;
268         }
269 
270         editFrame->DuplicateSymbol( aEvent.IsAction( &EE_ACTIONS::pasteSymbol ) );
271     }
272 
273     return 0;
274 }
275 
276 
OnDeMorgan(const TOOL_EVENT & aEvent)277 int SYMBOL_EDITOR_CONTROL::OnDeMorgan( const TOOL_EVENT& aEvent )
278 {
279     int convert = aEvent.IsAction( &EE_ACTIONS::showDeMorganStandard ) ?
280             LIB_ITEM::LIB_CONVERT::BASE : LIB_ITEM::LIB_CONVERT::DEMORGAN;
281 
282     if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
283     {
284         m_toolMgr->RunAction( ACTIONS::cancelInteractive, true );
285         m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
286 
287         SYMBOL_EDIT_FRAME* symbolEditor = static_cast<SYMBOL_EDIT_FRAME*>( m_frame );
288         symbolEditor->SetConvert( convert );
289 
290         m_toolMgr->ResetTools( TOOL_BASE::MODEL_RELOAD );
291         symbolEditor->RebuildView();
292     }
293     else if( m_frame->IsType( FRAME_SCH_VIEWER ) || m_frame->IsType( FRAME_SCH_VIEWER_MODAL ) )
294     {
295         SYMBOL_VIEWER_FRAME* symbolViewer = static_cast<SYMBOL_VIEWER_FRAME*>( m_frame );
296         symbolViewer->SetUnitAndConvert( symbolViewer->GetUnit(), convert );
297     }
298 
299     return 0;
300 }
301 
302 
PinLibrary(const TOOL_EVENT & aEvent)303 int SYMBOL_EDITOR_CONTROL::PinLibrary( const TOOL_EVENT& aEvent )
304 {
305     if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
306     {
307         SYMBOL_EDIT_FRAME* editFrame = static_cast<SYMBOL_EDIT_FRAME*>( m_frame );
308         LIB_TREE_NODE*  currentNode = editFrame->GetCurrentTreeNode();
309 
310         if( currentNode && !currentNode->m_Pinned )
311         {
312             currentNode->m_Pinned = true;
313             editFrame->RegenerateLibraryTree();
314         }
315     }
316 
317     return 0;
318 }
319 
320 
UnpinLibrary(const TOOL_EVENT & aEvent)321 int SYMBOL_EDITOR_CONTROL::UnpinLibrary( const TOOL_EVENT& aEvent )
322 {
323     if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
324     {
325         SYMBOL_EDIT_FRAME* editFrame = static_cast<SYMBOL_EDIT_FRAME*>( m_frame );
326         LIB_TREE_NODE*  currentNode = editFrame->GetCurrentTreeNode();
327 
328         if( currentNode && currentNode->m_Pinned )
329         {
330             currentNode->m_Pinned = false;
331             editFrame->RegenerateLibraryTree();
332         }
333     }
334 
335     return 0;
336 }
337 
338 
ToggleSymbolTree(const TOOL_EVENT & aEvent)339 int SYMBOL_EDITOR_CONTROL::ToggleSymbolTree( const TOOL_EVENT& aEvent )
340 {
341     if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
342     {
343         wxCommandEvent dummy;
344         static_cast<SYMBOL_EDIT_FRAME*>( m_frame )->OnToggleSymbolTree( dummy );
345     }
346 
347     return 0;
348 }
349 
350 
ShowElectricalTypes(const TOOL_EVENT & aEvent)351 int SYMBOL_EDITOR_CONTROL::ShowElectricalTypes( const TOOL_EVENT& aEvent )
352 {
353     KIGFX::SCH_RENDER_SETTINGS* renderSettings = m_frame->GetRenderSettings();
354     renderSettings->m_ShowPinsElectricalType = !renderSettings->m_ShowPinsElectricalType;
355 
356     // Update canvas
357     m_frame->GetCanvas()->GetView()->UpdateAllItems( KIGFX::REPAINT );
358     m_frame->GetCanvas()->Refresh();
359 
360     return 0;
361 }
362 
363 
ToggleSyncedPinsMode(const TOOL_EVENT & aEvent)364 int SYMBOL_EDITOR_CONTROL::ToggleSyncedPinsMode( const TOOL_EVENT& aEvent )
365 {
366     if( !m_isSymbolEditor )
367         return 0;
368 
369     SYMBOL_EDIT_FRAME* editFrame = getEditFrame<SYMBOL_EDIT_FRAME>();
370     editFrame->m_SyncPinEdit = !editFrame->m_SyncPinEdit;
371 
372     return 0;
373 }
374 
375 
ExportView(const TOOL_EVENT & aEvent)376 int SYMBOL_EDITOR_CONTROL::ExportView( const TOOL_EVENT& aEvent )
377 {
378     if( !m_isSymbolEditor )
379         return 0;
380 
381     SYMBOL_EDIT_FRAME* editFrame = getEditFrame<SYMBOL_EDIT_FRAME>();
382     LIB_SYMBOL*        symbol = editFrame->GetCurSymbol();
383 
384     if( !symbol )
385     {
386         wxMessageBox( _( "No symbol to export" ) );
387         return 0;
388     }
389 
390     wxString   file_ext = wxT( "png" );
391     wxString   mask = wxT( "*." ) + file_ext;
392     wxFileName fn( symbol->GetName() );
393     fn.SetExt( "png" );
394 
395     wxString projectPath = wxPathOnly( m_frame->Prj().GetProjectFullName() );
396 
397     wxFileDialog dlg( editFrame, _( "Image File Name" ), projectPath, fn.GetFullName(),
398                       PngFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
399 
400     if( dlg.ShowModal() == wxID_OK && !dlg.GetPath().IsEmpty() )
401     {
402         // calling wxYield is mandatory under Linux, after closing the file selector dialog
403         // to refresh the screen before creating the PNG or JPEG image from screen
404         wxYield();
405 
406         if( !SaveCanvasImageToFile( editFrame, dlg.GetPath(), BITMAP_TYPE::PNG ) )
407         {
408             wxMessageBox( wxString::Format( _( "Can't save file '%s'." ), dlg.GetPath() ) );
409         }
410     }
411 
412     return 0;
413 }
414 
415 
ExportSymbolAsSVG(const TOOL_EVENT & aEvent)416 int SYMBOL_EDITOR_CONTROL::ExportSymbolAsSVG( const TOOL_EVENT& aEvent )
417 {
418     if( !m_isSymbolEditor )
419         return 0;
420 
421     SYMBOL_EDIT_FRAME* editFrame = getEditFrame<SYMBOL_EDIT_FRAME>();
422     LIB_SYMBOL*        symbol = editFrame->GetCurSymbol();
423 
424     if( !symbol )
425     {
426         wxMessageBox( _( "No symbol to export" ) );
427         return 0;
428     }
429 
430     wxString   file_ext = SVGFileExtension;
431     wxFileName fn( symbol->GetName() );
432     fn.SetExt( SVGFileExtension );
433 
434     wxString pro_dir = wxPathOnly( m_frame->Prj().GetProjectFullName() );
435 
436     wxString fullFileName = wxFileSelector( _( "SVG File Name" ), pro_dir, fn.GetFullName(),
437                                             SVGFileExtension, SVGFileWildcard(), wxFD_SAVE,
438                                             m_frame );
439 
440     if( !fullFileName.IsEmpty() )
441     {
442         PAGE_INFO pageSave = editFrame->GetScreen()->GetPageSettings();
443         PAGE_INFO pageTemp = pageSave;
444 
445         wxSize symbolSize = symbol->GetUnitBoundingBox( editFrame->GetUnit(),
446                                                         editFrame->GetConvert() ).GetSize();
447 
448         // Add a small margin to the plot bounding box
449         pageTemp.SetWidthMils(  int( symbolSize.x * 1.2 ) );
450         pageTemp.SetHeightMils( int( symbolSize.y * 1.2 ) );
451 
452         editFrame->GetScreen()->SetPageSettings( pageTemp );
453         editFrame->SVGPlotSymbol( fullFileName );
454         editFrame->GetScreen()->SetPageSettings( pageSave );
455     }
456 
457     return 0;
458 }
459 
460 
AddSymbolToSchematic(const TOOL_EVENT & aEvent)461 int SYMBOL_EDITOR_CONTROL::AddSymbolToSchematic( const TOOL_EVENT& aEvent )
462 {
463     LIB_SYMBOL* libSymbol = nullptr;
464     LIB_ID      libId;
465     int         unit, convert;
466 
467     if( m_isSymbolEditor )
468     {
469         SYMBOL_EDIT_FRAME* editFrame = getEditFrame<SYMBOL_EDIT_FRAME>();
470 
471         libSymbol = editFrame->GetCurSymbol();
472         unit = editFrame->GetUnit();
473         convert = editFrame->GetConvert();
474 
475         if( libSymbol )
476             libId = libSymbol->GetLibId();
477     }
478     else
479     {
480         SYMBOL_VIEWER_FRAME* viewerFrame = getEditFrame<SYMBOL_VIEWER_FRAME>();
481 
482         if( viewerFrame->IsModal() )
483         {
484             // if we're modal then we just need to return the symbol selection; the caller is
485             // already in a EE_ACTIONS::placeSymbol coroutine.
486             viewerFrame->FinishModal();
487             return 0;
488         }
489         else
490         {
491             libSymbol = viewerFrame->GetSelectedSymbol();
492             unit      = viewerFrame->GetUnit();
493             convert   = viewerFrame->GetConvert();
494 
495             if( libSymbol )
496                 libId = libSymbol->GetLibId();
497         }
498     }
499 
500     if( libSymbol )
501     {
502         SCH_EDIT_FRAME* schframe = (SCH_EDIT_FRAME*) m_frame->Kiway().Player( FRAME_SCH, false );
503 
504         if( !schframe )      // happens when the schematic editor is not active (or closed)
505         {
506             DisplayErrorMessage( m_frame, _( "No schematic currently open." ) );
507             return 0;
508         }
509 
510         wxCHECK( libSymbol->GetLibId().IsValid(), 0 );
511 
512         SCH_SYMBOL* symbol = new SCH_SYMBOL( *libSymbol, libId, &schframe->GetCurrentSheet(),
513                                              unit, convert );
514 
515         symbol->SetParent( schframe->GetScreen() );
516 
517         if( schframe->eeconfig()->m_AutoplaceFields.enable )
518             symbol->AutoplaceFields( /* aScreen */ nullptr, /* aManual */ false );
519 
520         schframe->Raise();
521         schframe->GetToolManager()->RunAction( EE_ACTIONS::placeSymbol, true, symbol );
522     }
523 
524     return 0;
525 }
526 
527 
setTransitions()528 void SYMBOL_EDITOR_CONTROL::setTransitions()
529 {
530     Go( &SYMBOL_EDITOR_CONTROL::AddLibrary,            ACTIONS::newLibrary.MakeEvent() );
531     Go( &SYMBOL_EDITOR_CONTROL::AddLibrary,            ACTIONS::addLibrary.MakeEvent() );
532     Go( &SYMBOL_EDITOR_CONTROL::AddSymbol,             EE_ACTIONS::newSymbol.MakeEvent() );
533     Go( &SYMBOL_EDITOR_CONTROL::AddSymbol,             EE_ACTIONS::importSymbol.MakeEvent() );
534     Go( &SYMBOL_EDITOR_CONTROL::EditSymbol,            EE_ACTIONS::editSymbol.MakeEvent() );
535 
536     Go( &SYMBOL_EDITOR_CONTROL::Save,                  ACTIONS::save.MakeEvent() );
537     Go( &SYMBOL_EDITOR_CONTROL::Save,                  EE_ACTIONS::saveLibraryAs.MakeEvent() );
538     Go( &SYMBOL_EDITOR_CONTROL::Save,                  EE_ACTIONS::saveSymbolAs.MakeEvent() );
539     Go( &SYMBOL_EDITOR_CONTROL::Save,                  ACTIONS::saveAll.MakeEvent() );
540     Go( &SYMBOL_EDITOR_CONTROL::Revert,                ACTIONS::revert.MakeEvent() );
541 
542     Go( &SYMBOL_EDITOR_CONTROL::DuplicateSymbol,       EE_ACTIONS::duplicateSymbol.MakeEvent() );
543     Go( &SYMBOL_EDITOR_CONTROL::CutCopyDelete,         EE_ACTIONS::deleteSymbol.MakeEvent() );
544     Go( &SYMBOL_EDITOR_CONTROL::CutCopyDelete,         EE_ACTIONS::cutSymbol.MakeEvent() );
545     Go( &SYMBOL_EDITOR_CONTROL::CutCopyDelete,         EE_ACTIONS::copySymbol.MakeEvent() );
546     Go( &SYMBOL_EDITOR_CONTROL::DuplicateSymbol,       EE_ACTIONS::pasteSymbol.MakeEvent() );
547     Go( &SYMBOL_EDITOR_CONTROL::ExportSymbol,          EE_ACTIONS::exportSymbol.MakeEvent() );
548     Go( &SYMBOL_EDITOR_CONTROL::ExportView,            EE_ACTIONS::exportSymbolView.MakeEvent() );
549     Go( &SYMBOL_EDITOR_CONTROL::ExportSymbolAsSVG,     EE_ACTIONS::exportSymbolAsSVG.MakeEvent() );
550     Go( &SYMBOL_EDITOR_CONTROL::AddSymbolToSchematic,  EE_ACTIONS::addSymbolToSchematic.MakeEvent() );
551 
552     Go( &SYMBOL_EDITOR_CONTROL::OnDeMorgan,            EE_ACTIONS::showDeMorganStandard.MakeEvent() );
553     Go( &SYMBOL_EDITOR_CONTROL::OnDeMorgan,            EE_ACTIONS::showDeMorganAlternate.MakeEvent() );
554 
555     Go( &SYMBOL_EDITOR_CONTROL::ShowElectricalTypes,   EE_ACTIONS::showElectricalTypes.MakeEvent() );
556     Go( &SYMBOL_EDITOR_CONTROL::PinLibrary,            ACTIONS::pinLibrary.MakeEvent() );
557     Go( &SYMBOL_EDITOR_CONTROL::UnpinLibrary,          ACTIONS::unpinLibrary.MakeEvent() );
558     Go( &SYMBOL_EDITOR_CONTROL::ToggleSymbolTree,      EE_ACTIONS::showSymbolTree.MakeEvent() );
559     Go( &SYMBOL_EDITOR_CONTROL::ToggleSymbolTree,      EE_ACTIONS::hideSymbolTree.MakeEvent() );
560     Go( &SYMBOL_EDITOR_CONTROL::ToggleSyncedPinsMode,  EE_ACTIONS::toggleSyncedPinsMode.MakeEvent() );
561 }
562