Eeschema: allow symbols to be edited in place.

ADDED: Support to allow schematic symbols to be edited in place.
This commit is contained in:
Wayne Stambaugh 2020-08-31 11:06:23 -04:00
parent 9f128f942c
commit c9fa46ace8
12 changed files with 255 additions and 27 deletions

View File

@ -71,6 +71,7 @@
bool LIB_EDIT_FRAME:: m_showDeMorgan = false;
BEGIN_EVENT_TABLE( LIB_EDIT_FRAME, EDA_DRAW_FRAME )
EVT_SIZE( LIB_EDIT_FRAME::OnSize )
@ -90,11 +91,13 @@ BEGIN_EVENT_TABLE( LIB_EDIT_FRAME, EDA_DRAW_FRAME )
END_EVENT_TABLE()
LIB_EDIT_FRAME::LIB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
SCH_BASE_FRAME( aKiway, aParent, FRAME_SCH_LIB_EDITOR, _( "Library Editor" ),
wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE,
LIB_EDIT_FRAME_NAME ),
m_unitSelectBox( nullptr )
m_unitSelectBox( nullptr ),
m_isSymbolFromSchematic( false )
{
SetShowDeMorgan( false );
m_SyncPinEdit = false;
@ -200,6 +203,15 @@ LIB_EDIT_FRAME::~LIB_EDIT_FRAME()
if( m_toolManager )
m_toolManager->ShutdownAllTools();
if( IsSymbolFromSchematic() )
{
delete m_my_part;
m_my_part = nullptr;
SCH_SCREEN* screen = GetScreen();
delete screen;
m_isSymbolFromSchematic = false;
}
// current screen is destroyed in EDA_DRAW_FRAME
SetScreen( m_dummyScreen );
@ -299,7 +311,10 @@ void LIB_EDIT_FRAME::setupUIConditions()
auto libMgrModifiedCond =
[this] ( const SELECTION& )
{
return m_libMgr->HasModifications();
if( IsSymbolFromSchematic() )
return GetScreen() && GetScreen()->IsModify();
else
return m_libMgr->HasModifications();
};
auto modifiedDocumentCondition =
@ -319,6 +334,7 @@ void LIB_EDIT_FRAME::setupUIConditions()
mgr->SetConditions( ACTIONS::saveAll, ENABLE( libMgrModifiedCond ) );
mgr->SetConditions( ACTIONS::save, ENABLE( haveSymbolCond && modifiedDocumentCondition ) );
mgr->SetConditions( EE_ACTIONS::saveInSchematic, ENABLE( libMgrModifiedCond ) );
mgr->SetConditions( ACTIONS::undo, ENABLE( haveSymbolCond && cond.UndoAvailable() ) );
mgr->SetConditions( ACTIONS::redo, ENABLE( haveSymbolCond && cond.RedoAvailable() ) );
mgr->SetConditions( ACTIONS::revert, ENABLE( haveSymbolCond && modifiedDocumentCondition ) );
@ -574,8 +590,6 @@ wxString LIB_EDIT_FRAME::SetCurLib( const wxString& aLibNickname )
m_libMgr->SetCurrentLib( aLibNickname );
ReCreateMenuBar();
return old;
}
@ -588,11 +602,18 @@ void LIB_EDIT_FRAME::SetCurPart( LIB_PART* aPart )
m_my_part = aPart;
// select the current component in the tree widget
if( m_my_part )
if( !IsSymbolFromSchematic() && m_my_part )
{
m_treePane->GetLibTree()->SelectLibId( m_my_part->GetLibId() );
}
else
{
m_treePane->GetLibTree()->Unselect();
m_libMgr->SetCurrentLib( wxEmptyString );
m_libMgr->SetCurrentPart( wxEmptyString );
}
wxString partName = m_my_part ? m_my_part->GetName() : wxString();
m_libMgr->SetCurrentPart( partName );
// retain in case this wxFrame is re-opened later on the same PROJECT
Prj().SetRString( PROJECT::SCH_LIBEDIT_CUR_PART, partName );
@ -600,17 +621,15 @@ void LIB_EDIT_FRAME::SetCurPart( LIB_PART* aPart )
// Ensure synchronized pin edit can be enabled only symbols with interchangeable units
m_SyncPinEdit = aPart && aPart->IsRoot() && aPart->IsMulti() && !aPart->UnitsLocked();
/* TODO: enable when we have schematic-symbol editing...
if( IsCurrentPartFromSchematic() )
if( IsSymbolFromSchematic() )
{
wxString msg;
msg.Printf( _( "Editing %s from schematic. Saving will update the schematic only." ),
partName );
msg.Printf( _( "Editing symbol %s from schematic. Saving will update the schematic "
"only." ), m_reference );
GetInfoBar()->RemoveAllButtons();
GetInfoBar()->ShowMessage( msg, wxICON_INFORMATION );
}
*/
m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD );
RebuildView();
@ -1124,3 +1143,41 @@ SELECTION& LIB_EDIT_FRAME::GetCurrentSelection()
{
return m_toolManager->GetTool<EE_SELECTION_TOOL>()->GetSelection();
}
void LIB_EDIT_FRAME::LoadSymbolFromSchematic( const std::unique_ptr<LIB_PART>& aSymbol,
const wxString& aReference, int aUnit, int aConvert )
{
std::unique_ptr<LIB_PART> symbol = aSymbol->Flatten();
wxCHECK( symbol, /* void */ );
if( m_my_part )
SetCurPart( nullptr );
m_isSymbolFromSchematic = true;
m_reference = aReference;
m_unit = aUnit > 0 ? aUnit : 1;
m_convert = aConvert > 0 ? aConvert : 1;
// The buffered screen for the part
SCH_SCREEN* tmpScreen = new SCH_SCREEN();
SetScreen( tmpScreen );
SetCurPart( symbol.release() );
m_toolManager->RunAction( ACTIONS::zoomFitScreen, true );
ReCreateMenuBar();
ReCreateHToolbar();
if( IsSearchTreeShown() )
{
wxCommandEvent evt;
OnToggleSearchTree( evt );
}
updateTitle();
RebuildSymbolUnitsList();
SetShowDeMorgan( GetCurPart()->HasConversion() );
DisplayCmpDoc();
Refresh();
}

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2014 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 2004-2019 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2004-2020 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2017 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
@ -65,6 +65,16 @@ class LIB_EDIT_FRAME : public SCH_BASE_FRAME
// Show the normal shape ( m_convert <= 1 ) or the converted shape ( m_convert > 1 )
int m_convert;
///< Flag if the symbol being edited was loaded directly from a schematic.
bool m_isSymbolFromSchematic;
/**
* The reference of the symbol.
*
* @note This is only valid when the current symbol was loaded from the schematic.
*/
wxString m_reference;
// True to force DeMorgan/normal tools selection enabled.
// They are enabled when the loaded component has graphic items for converted shape
// But under some circumstances (New component created) these tools must left enabled
@ -259,6 +269,8 @@ public:
void ClearMsgPanel() override { DisplayCmpDoc(); }
bool IsSymbolFromSchematic() const { return m_isSymbolFromSchematic; }
protected:
void setupUIConditions() override;
@ -440,6 +452,17 @@ public:
void KiwayMailIn( KIWAY_EXPRESS& mail ) override;
/**
* Load a symbol from the schematic to edit in place.
*
* @param aSymbol the symbol to edit.
* @param aReference the reference of the symbol to edit.
* @param aUnit the unit of the symbol to edit.
* @param aConvert the alternate body style of the symbol to edit.
*/
void LoadSymbolFromSchematic( const std::unique_ptr<LIB_PART>& aSymbol,
const wxString& aReference, int aUnit, int aConvert );
///> Restores the empty editor screen, without any part or library selected.
void emptyScreen();

View File

@ -27,6 +27,7 @@
#include <pgm_base.h>
#include <confirm.h>
#include <gestfich.h>
#include <widgets/infobar.h>
#include <tools/ee_actions.h>
#include <tools/lib_drawing_tools.h>
#include <lib_edit_frame.h>
@ -44,16 +45,24 @@
#include <dialog_helpers.h>
#include <wx/clipbrd.h>
void LIB_EDIT_FRAME::updateTitle()
{
wxString lib = GetCurLib();
wxString title = _( "Symbol Editor" );
if( GetCurPart() )
title += wxT( " \u2014 " ) + GetCurPart()->GetLibId().Format();
if( IsSymbolFromSchematic() )
{
title += wxString::Format( _( " \u2014 %s from schematic" ), m_reference );
}
else
{
if( GetCurPart() )
title += wxT( " \u2014 " ) + GetCurPart()->GetLibId().Format();
if( GetCurPart() && m_libMgr && m_libMgr->IsLibraryReadOnly( GetCurLib() ) )
title += " [Read Only Library]";
if( GetCurPart() && m_libMgr && m_libMgr->IsLibraryReadOnly( GetCurLib() ) )
title += _( " \u2014 [Read Only Library]" );
}
SetTitle( title );
}
@ -197,10 +206,12 @@ bool LIB_EDIT_FRAME::LoadComponentFromCurrentLib( const wxString& aAliasName, in
return true;
}
bool LIB_EDIT_FRAME::LoadOneLibraryPartAux( LIB_PART* aEntry, const wxString& aLibrary,
int aUnit, int aConvert )
{
wxString msg, rootName;
bool rebuildMenuAndToolbar = false;
if( !aEntry || aLibrary.empty() )
return false;
@ -211,6 +222,19 @@ bool LIB_EDIT_FRAME::LoadOneLibraryPartAux( LIB_PART* aEntry, const wxString& aL
return false;
}
// Symbols from the schematic are edited in place and not managed by the library manager.
if( IsSymbolFromSchematic() )
{
delete m_my_part;
m_my_part = nullptr;
SCH_SCREEN* screen = GetScreen();
delete screen;
SetScreen( m_dummyScreen );
m_isSymbolFromSchematic = false;
rebuildMenuAndToolbar = true;
}
LIB_PART* lib_part = m_libMgr->GetBufferedPart( aEntry->GetName(), aLibrary );
wxCHECK( lib_part, false );
@ -224,6 +248,13 @@ bool LIB_EDIT_FRAME::LoadOneLibraryPartAux( LIB_PART* aEntry, const wxString& aL
SetCurPart( new LIB_PART( *lib_part ) );
SetCurLib( aLibrary );
if( rebuildMenuAndToolbar )
{
ReCreateMenuBar();
ReCreateHToolbar();
GetInfoBar()->Dismiss();
}
m_toolManager->RunAction( ACTIONS::zoomFitScreen, true );
updateTitle();
RebuildSymbolUnitsList();

View File

@ -53,7 +53,12 @@ void LIB_EDIT_FRAME::ReCreateMenuBar()
fileMenu->AppendSeparator();
fileMenu->Add( ACTIONS::save );
fileMenu->Add( ACTIONS::saveCopyAs );
fileMenu->Add( ACTIONS::saveAll );
if( !IsSymbolFromSchematic() )
fileMenu->Add( ACTIONS::saveAll );
else
fileMenu->Add( EE_ACTIONS::saveInSchematic );
fileMenu->Add( ACTIONS::revert );
fileMenu->AppendSeparator();

View File

@ -86,7 +86,11 @@ void LIB_EDIT_FRAME::ReCreateHToolbar()
// Set up toolbar
m_mainToolBar->Add( EE_ACTIONS::newSymbol );
m_mainToolBar->Add( ACTIONS::saveAll );
if( !IsSymbolFromSchematic() )
m_mainToolBar->Add( ACTIONS::saveAll );
else
m_mainToolBar->Add( EE_ACTIONS::saveInSchematic );
m_mainToolBar->AddScaledSeparator( this );
m_mainToolBar->Add( ACTIONS::undo );

View File

@ -767,6 +767,7 @@ HIERARCHY_NAVIG_DLG* SCH_EDIT_FRAME::FindHierarchyNavigator()
return static_cast< HIERARCHY_NAVIG_DLG* >( navigator );
}
void SCH_EDIT_FRAME::UpdateHierarchyNavigator( bool aForceUpdate )
{
if( aForceUpdate )
@ -1216,6 +1217,7 @@ const BOX2I SCH_EDIT_FRAME::GetDocumentExtents() const
return BOX2I( VECTOR2I(0, 0), VECTOR2I( sizeX, sizeY ) );
}
void SCH_EDIT_FRAME::FixupJunctions()
{
// Save the current sheet, to retrieve it later
@ -1364,3 +1366,55 @@ void SCH_EDIT_FRAME::onSize( wxSizeEvent& aEvent )
// Skip() is called in the base class.
EDA_DRAW_FRAME::OnSize( aEvent );
}
void SCH_EDIT_FRAME::UpdateSymbolFromEditor( const LIB_PART& aSymbol )
{
wxString msg;
bool appendToUndo = false;
wxCHECK( m_toolManager, /* void */ );
EE_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<EE_SELECTION_TOOL>();
wxCHECK( selectionTool, /* void */ );
EE_SELECTION& selection = selectionTool->RequestSelection( EE_COLLECTOR::ComponentsOnly );
if( selection.Empty() )
return;
SCH_SCREEN* currentScreen = GetScreen();
wxCHECK( currentScreen, /* void */ );
// This should work for multiple selections of the same symbol even though the editor
// only works for a single symbol selection.
for( auto item : selection )
{
SCH_COMPONENT* symbol = dynamic_cast<SCH_COMPONENT*>( item );
wxCHECK( symbol, /* void */ );
// This needs to be done before the LIB_PART is changed to prevent stale library symbols in
// the schematic file.
currentScreen->Remove( symbol );
if( !symbol->IsNew() )
{
SaveCopyInUndoList( currentScreen, symbol, UNDO_REDO::CHANGED, appendToUndo );
appendToUndo = true;
}
symbol->SetLibSymbol( aSymbol.Flatten().release() );
currentScreen->Append( symbol );
selectionTool->SelectHighlightItem( symbol );
GetCanvas()->GetView()->Update( symbol );
}
if( selection.IsHover() )
m_toolManager->RunAction( EE_ACTIONS::clearSelection, true );
GetCanvas()->Refresh();
OnModify();
}

View File

@ -255,7 +255,7 @@ public:
void UpdateHierarchyNavigator( bool aForceUpdate = false );
/**
* @return a reference to the Hierarchy Navigator dialog if exists, or nullptr.
* @return a reference to the Hierarchy Navigator dialog if exists, or nullptr.
*/
HIERARCHY_NAVIG_DLG* FindHierarchyNavigator();
@ -937,6 +937,15 @@ public:
*/
void ConvertTimeStampUuids();
/**
* Update the #LIB_PART of the currently selected symbol.
*
* This is typically called from the symbol editor when editing symbols in place.
*
* @param aSymbol is the #LIB_PART to update.
*/
void UpdateSymbolFromEditor( const LIB_PART& aSymbol );
DECLARE_EVENT_TABLE()
};

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 CERN
* Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2019-2020 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -184,6 +184,11 @@ TOOL_ACTION EE_ACTIONS::toggleSyncedPinsMode( "eeschema.SymbolLibraryControl.tog
"Enabled by default for multiunit parts with interchangeable units." ),
pin2pin_xpm );
TOOL_ACTION EE_ACTIONS::saveInSchematic( "eeschema.SymbolLibraryControl.saveInSchematic",
AS_GLOBAL, 0, "",
_( "Save In Schematic" ), _( "Save the current symbol in the schematic" ),
import_part_xpm );
// LIB_DRAWING_TOOLS
//
@ -228,7 +233,6 @@ TOOL_ACTION EE_ACTIONS::finishDrawing( "eeschema.SymbolDrawing.finishDrawing",
_( "Finish Drawing" ), _( "Finish drawing shape" ),
checked_ok_xpm, AF_NONE );
// LIB_PIN_TOOL
//
TOOL_ACTION EE_ACTIONS::pushPinLength( "eeschema.PinEditing.pushPinLength",

View File

@ -176,6 +176,9 @@ public:
static TOOL_ACTION importSymbol;
static TOOL_ACTION exportSymbol;
// Library editor tool actions
static TOOL_ACTION saveInSchematic;
// Hierarchy navigation
static TOOL_ACTION enterSheet;
static TOOL_ACTION leaveSheet;

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 CERN
* Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2019-2020 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -455,6 +455,38 @@ int LIB_CONTROL::AddSymbolToSchematic( const TOOL_EVENT& aEvent )
}
int LIB_CONTROL::UpdateSymbolInSchematic( const TOOL_EVENT& aEvent )
{
wxCHECK( m_isLibEdit, 0 );
LIB_EDIT_FRAME* editFrame = getEditFrame<LIB_EDIT_FRAME>();
wxCHECK( editFrame, 0 );
LIB_PART* currentPart = editFrame->GetCurPart();
wxCHECK( currentPart, 0 );
SCH_EDIT_FRAME* schframe = (SCH_EDIT_FRAME*) m_frame->Kiway().Player( FRAME_SCH, false );
if( !schframe ) // happens when the schematic editor is not active (or closed)
{
DisplayErrorMessage( m_frame, _( "No schematic currently open." ) );
return 0;
}
schframe->UpdateSymbolFromEditor( *currentPart );
SCH_SCREEN* currentScreen = editFrame->GetScreen();
wxCHECK( currentScreen, 0 );
currentScreen->ClrModify();
return 0;
}
void LIB_CONTROL::setTransitions()
{
Go( &LIB_CONTROL::AddLibrary, ACTIONS::newLibrary.MakeEvent() );
@ -468,6 +500,8 @@ void LIB_CONTROL::setTransitions()
Go( &LIB_CONTROL::Save, ACTIONS::saveCopyAs.MakeEvent() ); // for symbols
Go( &LIB_CONTROL::Save, ACTIONS::saveAll.MakeEvent() );
Go( &LIB_CONTROL::Revert, ACTIONS::revert.MakeEvent() );
Go( &LIB_CONTROL::UpdateSymbolInSchematic,
EE_ACTIONS::saveInSchematic.MakeEvent() );
Go( &LIB_CONTROL::DuplicateSymbol, EE_ACTIONS::duplicateSymbol.MakeEvent() );
Go( &LIB_CONTROL::CutCopyDelete, EE_ACTIONS::deleteSymbol.MakeEvent() );

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 CERN
* Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2019-2020 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -32,9 +32,7 @@
class LIB_EDIT_FRAME;
/**
* LIB_CONTROL
*
* Handles actions for the various symbol editor and viewers.
* Handle actions for the various symbol editor and viewers.
*/
class LIB_CONTROL : public wxEvtHandler, public EE_TOOL_BASE<SCH_BASE_FRAME>
{
@ -61,6 +59,7 @@ public:
int ExportView( const TOOL_EVENT& aEvent );
int ExportSymbolAsSVG( const TOOL_EVENT& aEvent );
int AddSymbolToSchematic( const TOOL_EVENT& aEvent );
int UpdateSymbolInSchematic( const TOOL_EVENT& aEvent );
int OnDeMorgan( const TOOL_EVENT& aEvent );

View File

@ -61,6 +61,7 @@
#include <dialog_update_from_pcb.h>
#include <dialog_helpers.h>
int SCH_EDITOR_CONTROL::New( const TOOL_EVENT& aEvent )
{
m_frame->NewProject();
@ -233,12 +234,14 @@ int SCH_EDITOR_CONTROL::FindAndReplace( const TOOL_EVENT& aEvent )
return UpdateFind( aEvent );
}
int SCH_EDITOR_CONTROL::NavigateHierarchy( const TOOL_EVENT& aEvent )
{
m_frame->UpdateHierarchyNavigator( true );
return 0;
}
int SCH_EDITOR_CONTROL::UpdateFind( const TOOL_EVENT& aEvent )
{
wxFindReplaceData* data = m_frame->GetFindReplaceData();
@ -1505,6 +1508,7 @@ int SCH_EDITOR_CONTROL::EditWithLibEdit( const TOOL_EVENT& aEvent )
{
EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
EE_SELECTION& selection = selTool->RequestSelection( EE_COLLECTOR::ComponentsOnly );
SCH_SHEET_PATH& currentSheet = m_frame->GetCurrentSheet();
SCH_COMPONENT* sym = nullptr;
LIB_EDIT_FRAME* libEdit;
@ -1518,7 +1522,8 @@ int SCH_EDITOR_CONTROL::EditWithLibEdit( const TOOL_EVENT& aEvent )
libEdit = (LIB_EDIT_FRAME*) m_frame->Kiway().Player( FRAME_SCH_LIB_EDITOR, false );
if( libEdit )
libEdit->LoadComponentAndSelectLib( sym->GetLibId(), sym->GetUnit(), sym->GetConvert() );
libEdit->LoadSymbolFromSchematic( sym->GetPartRef(), sym->GetRef( &currentSheet ),
sym->GetUnit(), sym->GetConvert() );
return 0;
}