Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9389a2b7c5 | |||
| 97aa507dd4 | |||
| eed62789a8 | |||
| 17a29794a1 | |||
| c49a9497ff | |||
| 362366d6f5 | |||
| 372a9c3f51 | |||
| 8c2a6fc818 | |||
| 7054963d90 | |||
| b894e7fe91 |
@@ -348,6 +348,8 @@ set( COMMON_DLG_SRCS
|
||||
dialogs/dialog_color_picker_base.cpp
|
||||
dialogs/dialog_configure_paths.cpp
|
||||
dialogs/dialog_configure_paths_base.cpp
|
||||
dialogs/dialog_design_block_properties.cpp
|
||||
dialogs/dialog_design_block_properties_base.cpp
|
||||
dialogs/dialog_display_html_text_base.cpp
|
||||
dialogs/dialog_edit_library_tables.cpp
|
||||
dialogs/dialog_embed_files.cpp
|
||||
@@ -421,6 +423,7 @@ set( COMMON_WIDGET_SRCS
|
||||
widgets/bitmap_toggle.cpp
|
||||
widgets/button_row_panel.cpp
|
||||
widgets/color_swatch.cpp
|
||||
widgets/design_block_pane.cpp
|
||||
widgets/filter_combobox.cpp
|
||||
widgets/font_choice.cpp
|
||||
widgets/footprint_choice.cpp
|
||||
@@ -445,6 +448,7 @@ set( COMMON_WIDGET_SRCS
|
||||
widgets/mathplot.cpp
|
||||
widgets/msgpanel.cpp
|
||||
widgets/paged_dialog.cpp
|
||||
widgets/panel_design_block_chooser.cpp
|
||||
widgets/properties_panel.cpp
|
||||
widgets/search_pane.cpp
|
||||
widgets/search_pane_base.cpp
|
||||
@@ -607,6 +611,7 @@ set( COMMON_SRCS
|
||||
lib_table_grid_tricks.cpp
|
||||
lib_tree_model.cpp
|
||||
lib_tree_model_adapter.cpp
|
||||
design_block_tree_model_adapter.cpp
|
||||
marker_base.cpp
|
||||
origin_transforms.cpp
|
||||
printout.cpp
|
||||
@@ -640,6 +645,7 @@ set( COMMON_SRCS
|
||||
tool/construction_manager.cpp
|
||||
tool/common_tools.cpp
|
||||
tool/conditional_menu.cpp
|
||||
tool/design_block_control.cpp
|
||||
tool/edit_constraints.cpp
|
||||
tool/edit_points.cpp
|
||||
tool/editor_conditions.cpp
|
||||
|
||||
+13
-3
@@ -21,6 +21,10 @@
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef DESIGN_BLOCK_H
|
||||
#define DESIGN_BLOCK_H
|
||||
|
||||
#include <kicommon.h>
|
||||
#include <lib_id.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
@@ -41,6 +45,9 @@ public:
|
||||
const wxString& GetSchematicFile() const { return m_schematicFile; }
|
||||
void SetSchematicFile( const wxString& aFile ) { m_schematicFile = aFile; }
|
||||
|
||||
const wxString& GetBoardFile() const { return m_boardFile; }
|
||||
void SetBoardFile( const wxString& aFile ) { m_boardFile = aFile; }
|
||||
|
||||
void SetFields( nlohmann::ordered_map<wxString, wxString>& aFields )
|
||||
{
|
||||
m_fields = std::move( aFields );
|
||||
@@ -55,9 +62,12 @@ public:
|
||||
|
||||
private:
|
||||
LIB_ID m_lib_id;
|
||||
wxString m_schematicFile; ///< File name and path for schematic symbol.
|
||||
wxString m_libDescription; ///< File name and path for documentation file.
|
||||
wxString m_keywords; ///< Search keywords to find footprint in library.
|
||||
wxString m_schematicFile; // File name and path for schematic file.
|
||||
wxString m_boardFile; // File name and path for board file
|
||||
wxString m_libDescription; // File name and path for documentation file.
|
||||
wxString m_keywords; // Search keywords to find design block in library.
|
||||
|
||||
nlohmann::ordered_map<wxString, wxString> m_fields;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+73
-18
@@ -265,7 +265,10 @@ void DESIGN_BLOCK_IO::DesignBlockEnumerate( wxArrayString& aDesignBlockNames,
|
||||
wxDir dir( aLibraryPath );
|
||||
|
||||
if( !dir.IsOpened() )
|
||||
return;
|
||||
{
|
||||
THROW_IO_ERROR(
|
||||
wxString::Format( _( "Design block '%s' does not exist." ), aLibraryPath ) );
|
||||
}
|
||||
|
||||
wxString dirname;
|
||||
wxString fileSpec = wxT( "*." ) + wxString( FILEEXT::KiCadDesignBlockPathExtension );
|
||||
@@ -287,17 +290,23 @@ DESIGN_BLOCK* DESIGN_BLOCK_IO::DesignBlockLoad( const wxString& aLibraryPath,
|
||||
+ FILEEXT::KiCadDesignBlockPathExtension + wxFileName::GetPathSeparator();
|
||||
wxString dbSchPath = dbPath + aDesignBlockName + wxT( "." )
|
||||
+ FILEEXT::KiCadSchematicFileExtension;
|
||||
wxString dbPcbPath = dbPath + aDesignBlockName + wxT( "." ) + FILEEXT::KiCadPcbFileExtension;
|
||||
wxString dbMetadataPath = dbPath + aDesignBlockName + wxT( "." ) + FILEEXT::JsonFileExtension;
|
||||
|
||||
if( !wxFileExists( dbSchPath ) )
|
||||
return nullptr;
|
||||
if( !wxDir::Exists( dbPath ) )
|
||||
THROW_IO_ERROR( wxString::Format( _( "Design block '%s' does not exist." ), dbPath ) );
|
||||
|
||||
DESIGN_BLOCK* newDB = new DESIGN_BLOCK();
|
||||
|
||||
// Library name needs to be empty for when we fill it in with the correct library nickname
|
||||
// one layer above
|
||||
newDB->SetLibId( LIB_ID( wxEmptyString, aDesignBlockName ) );
|
||||
newDB->SetSchematicFile( dbSchPath );
|
||||
|
||||
if( wxFileExists( dbSchPath ) )
|
||||
newDB->SetSchematicFile( dbSchPath );
|
||||
|
||||
if( wxFileExists( dbPcbPath ) )
|
||||
newDB->SetBoardFile( dbPcbPath );
|
||||
|
||||
// Parse the JSON file if it exists
|
||||
if( wxFileExists( dbMetadataPath ) )
|
||||
@@ -333,16 +342,27 @@ DESIGN_BLOCK* DESIGN_BLOCK_IO::DesignBlockLoad( const wxString& aLibraryPath,
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
delete newDB;
|
||||
THROW_IO_ERROR( wxString::Format(
|
||||
_( "Design block metadata file '%s' could not be read." ), dbMetadataPath ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return newDB;
|
||||
}
|
||||
|
||||
|
||||
bool DESIGN_BLOCK_IO::DesignBlockExists( const wxString& aLibraryPath,
|
||||
const wxString& aDesignBlockName,
|
||||
const std::map<std::string, UTF8>* aProperties )
|
||||
{
|
||||
wxString dbPath = aLibraryPath + wxFileName::GetPathSeparator() + aDesignBlockName + wxT( "." )
|
||||
+ FILEEXT::KiCadDesignBlockPathExtension + wxFileName::GetPathSeparator();
|
||||
|
||||
return wxDir::Exists( dbPath );
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_IO::DesignBlockSave( const wxString& aLibraryPath,
|
||||
const DESIGN_BLOCK* aDesignBlock,
|
||||
const std::map<std::string, UTF8>* aProperties )
|
||||
@@ -353,12 +373,24 @@ void DESIGN_BLOCK_IO::DesignBlockSave( const wxString& aLibra
|
||||
THROW_IO_ERROR( _( "Design block does not have a valid library ID." ) );
|
||||
}
|
||||
|
||||
if( !wxFileExists( aDesignBlock->GetSchematicFile() ) )
|
||||
if( aDesignBlock->GetSchematicFile().IsEmpty() && aDesignBlock->GetBoardFile().IsEmpty() )
|
||||
{
|
||||
THROW_IO_ERROR( _( "Design block does not have a schematic or board file." ) );
|
||||
}
|
||||
|
||||
if( !aDesignBlock->GetSchematicFile().IsEmpty()
|
||||
&& !wxFileExists( aDesignBlock->GetSchematicFile() ) )
|
||||
{
|
||||
THROW_IO_ERROR( wxString::Format( _( "Schematic source file '%s' does not exist." ),
|
||||
aDesignBlock->GetSchematicFile() ) );
|
||||
}
|
||||
|
||||
if( !aDesignBlock->GetBoardFile().IsEmpty() && !wxFileExists( aDesignBlock->GetBoardFile() ) )
|
||||
{
|
||||
THROW_IO_ERROR( wxString::Format( _( "Board source file '%s' does not exist." ),
|
||||
aDesignBlock->GetBoardFile() ) );
|
||||
}
|
||||
|
||||
// Create the design block folder
|
||||
wxFileName dbFolder( aLibraryPath + wxFileName::GetPathSeparator()
|
||||
+ aDesignBlock->GetLibId().GetLibItemName() + wxT( "." )
|
||||
@@ -374,23 +406,46 @@ void DESIGN_BLOCK_IO::DesignBlockSave( const wxString& aLibra
|
||||
}
|
||||
}
|
||||
|
||||
// The new schematic file name is based on the design block name, not the source sheet name
|
||||
wxString dbSchematicFile = dbFolder.GetFullPath() + aDesignBlock->GetLibId().GetLibItemName()
|
||||
+ wxT( "." ) + FILEEXT::KiCadSchematicFileExtension;
|
||||
|
||||
// If the source and destination files are the same, then we don't need to copy the file
|
||||
// as we are just updating the metadata
|
||||
if( aDesignBlock->GetSchematicFile() != dbSchematicFile )
|
||||
if( !aDesignBlock->GetSchematicFile().IsEmpty() )
|
||||
{
|
||||
// Copy the source sheet file to the design block folder, under the design block name
|
||||
if( !wxCopyFile( aDesignBlock->GetSchematicFile(), dbSchematicFile ) )
|
||||
// The new schematic file name is based on the design block name, not the source sheet name
|
||||
wxString dbSchematicFile = dbFolder.GetFullPath()
|
||||
+ aDesignBlock->GetLibId().GetLibItemName() + wxT( "." )
|
||||
+ FILEEXT::KiCadSchematicFileExtension;
|
||||
|
||||
// If the source and destination files are the same, then we don't need to copy the file
|
||||
// as we are just updating the metadata
|
||||
if( aDesignBlock->GetSchematicFile() != dbSchematicFile )
|
||||
{
|
||||
THROW_IO_ERROR( wxString::Format(
|
||||
_( "Schematic file '%s' could not be saved as design block at '%s'." ),
|
||||
aDesignBlock->GetSchematicFile().GetData(), dbSchematicFile ) );
|
||||
// Copy the source sheet file to the design block folder, under the design block name
|
||||
if( !wxCopyFile( aDesignBlock->GetSchematicFile(), dbSchematicFile ) )
|
||||
{
|
||||
THROW_IO_ERROR( wxString::Format(
|
||||
_( "Schematic file '%s' could not be saved as design block at '%s'." ),
|
||||
aDesignBlock->GetSchematicFile().GetData(), dbSchematicFile ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !aDesignBlock->GetBoardFile().IsEmpty() )
|
||||
{
|
||||
// The new Board file name is based on the design block name, not the source sheet name
|
||||
wxString dbBoardFile = dbFolder.GetFullPath() + aDesignBlock->GetLibId().GetLibItemName()
|
||||
+ wxT( "." ) + FILEEXT::KiCadPcbFileExtension;
|
||||
|
||||
// If the source and destination files are the same, then we don't need to copy the file
|
||||
// as we are just updating the metadata
|
||||
if( aDesignBlock->GetBoardFile() != dbBoardFile )
|
||||
{
|
||||
// Copy the source sheet file to the design block folder, under the design block name
|
||||
if( !wxCopyFile( aDesignBlock->GetBoardFile(), dbBoardFile ) )
|
||||
{
|
||||
THROW_IO_ERROR( wxString::Format(
|
||||
_( "Board file '%s' could not be saved as design block at '%s'." ),
|
||||
aDesignBlock->GetBoardFile().GetData(), dbBoardFile ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wxString dbMetadataFile = dbFolder.GetFullPath() + aDesignBlock->GetLibId().GetLibItemName()
|
||||
+ wxT( "." ) + FILEEXT::JsonFileExtension;
|
||||
|
||||
@@ -76,10 +76,7 @@ public:
|
||||
}
|
||||
|
||||
bool DesignBlockExists( const wxString& aLibraryPath, const wxString& aDesignBlockName,
|
||||
const std::map<std::string, UTF8>* aProperties = nullptr )
|
||||
{
|
||||
return DesignBlockLoad( aLibraryPath, aDesignBlockName, true, aProperties ) != nullptr;
|
||||
}
|
||||
const std::map<std::string, UTF8>* aProperties = nullptr );
|
||||
|
||||
DESIGN_BLOCK* ImportDesignBlock( const wxString& aDesignBlockPath,
|
||||
wxString& aDesignBlockNameOut,
|
||||
|
||||
@@ -73,6 +73,23 @@ void DESIGN_BLOCK_LIB_TABLE_ROW::SetType( const wxString& aType )
|
||||
}
|
||||
|
||||
|
||||
bool DESIGN_BLOCK_LIB_TABLE_ROW::Refresh()
|
||||
{
|
||||
if( !plugin )
|
||||
{
|
||||
wxArrayString dummyList;
|
||||
|
||||
plugin.reset( DESIGN_BLOCK_IO_MGR::FindPlugin( type ) );
|
||||
SetLoaded( false );
|
||||
plugin->DesignBlockEnumerate( dummyList, GetFullURI( true ), true, GetProperties() );
|
||||
SetLoaded( true );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
DESIGN_BLOCK_LIB_TABLE::DESIGN_BLOCK_LIB_TABLE( DESIGN_BLOCK_LIB_TABLE* aFallBackTable ) :
|
||||
LIB_TABLE( aFallBackTable )
|
||||
{
|
||||
|
||||
+13
-9
@@ -25,30 +25,34 @@
|
||||
#include <project/project_file.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/tokenzr.h>
|
||||
#include <settings/app_settings.h>
|
||||
#include <string_utils.h>
|
||||
#include <eda_pattern_match.h>
|
||||
#include <design_block.h>
|
||||
#include <design_block_lib_table.h>
|
||||
#include <design_block_info.h>
|
||||
#include <design_block_tree_model_adapter.h>
|
||||
#include <tools/sch_design_block_control.h>
|
||||
|
||||
wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER>
|
||||
DESIGN_BLOCK_TREE_MODEL_ADAPTER::Create( EDA_BASE_FRAME* aParent, LIB_TABLE* aLibs,
|
||||
APP_SETTINGS_BASE::LIB_TREE& aSettings )
|
||||
APP_SETTINGS_BASE::LIB_TREE& aSettings,
|
||||
TOOL_INTERACTIVE* aContextMenuTool )
|
||||
{
|
||||
auto* adapter = new DESIGN_BLOCK_TREE_MODEL_ADAPTER( aParent, aLibs, aSettings );
|
||||
adapter->m_frame = aParent;
|
||||
auto* adapter = new DESIGN_BLOCK_TREE_MODEL_ADAPTER( aParent, aLibs, aSettings, aContextMenuTool );
|
||||
return wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER>( adapter );
|
||||
}
|
||||
|
||||
|
||||
DESIGN_BLOCK_TREE_MODEL_ADAPTER::DESIGN_BLOCK_TREE_MODEL_ADAPTER( EDA_BASE_FRAME* aParent,
|
||||
LIB_TABLE* aLibs,
|
||||
APP_SETTINGS_BASE::LIB_TREE& aSettings ) :
|
||||
LIB_TREE_MODEL_ADAPTER( aParent, wxT( "pinned_design_block_libs" ), aSettings ),
|
||||
LIB_TABLE* aLibs,
|
||||
APP_SETTINGS_BASE::LIB_TREE& aSettings,
|
||||
TOOL_INTERACTIVE* aContextMenuTool ) :
|
||||
LIB_TREE_MODEL_ADAPTER( aParent,
|
||||
wxT( "pinned_design_block_libs" ),
|
||||
Kiface().KifaceSettings()->m_DesignBlockChooserPanel.tree ),
|
||||
m_libs( (DESIGN_BLOCK_LIB_TABLE*) aLibs ),
|
||||
m_frame( aParent )
|
||||
m_frame( aParent ),
|
||||
m_contextMenuTool( aContextMenuTool )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -206,5 +210,5 @@ wxString DESIGN_BLOCK_TREE_MODEL_ADAPTER::GenerateInfo( LIB_ID const& aLibId, in
|
||||
|
||||
TOOL_INTERACTIVE* DESIGN_BLOCK_TREE_MODEL_ADAPTER::GetContextMenuTool()
|
||||
{
|
||||
return m_frame->GetToolManager()->GetTool<SCH_DESIGN_BLOCK_CONTROL>();
|
||||
return m_contextMenuTool;
|
||||
}
|
||||
+5
-2
@@ -35,7 +35,8 @@ public:
|
||||
*/
|
||||
static wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER> Create( EDA_BASE_FRAME* aParent,
|
||||
LIB_TABLE* aLibs,
|
||||
APP_SETTINGS_BASE::LIB_TREE& aSettings );
|
||||
APP_SETTINGS_BASE::LIB_TREE& aSettings,
|
||||
TOOL_INTERACTIVE* aContextMenuTool );
|
||||
|
||||
void AddLibraries( EDA_BASE_FRAME* aParent );
|
||||
void ClearLibraries();
|
||||
@@ -51,7 +52,8 @@ protected:
|
||||
* Constructor; takes a set of libraries to be included in the search.
|
||||
*/
|
||||
DESIGN_BLOCK_TREE_MODEL_ADAPTER( EDA_BASE_FRAME* aParent, LIB_TABLE* aLibs,
|
||||
APP_SETTINGS_BASE::LIB_TREE& aSettings );
|
||||
APP_SETTINGS_BASE::LIB_TREE& aSettings,
|
||||
TOOL_INTERACTIVE* aContextMenuTool );
|
||||
|
||||
std::vector<LIB_TREE_ITEM*> getDesignBlocks( EDA_BASE_FRAME* aParent,
|
||||
const wxString& aLibName );
|
||||
@@ -61,6 +63,7 @@ protected:
|
||||
protected:
|
||||
DESIGN_BLOCK_LIB_TABLE* m_libs;
|
||||
EDA_BASE_FRAME* m_frame;
|
||||
TOOL_INTERACTIVE* m_contextMenuTool;
|
||||
};
|
||||
|
||||
#endif // DESIGN_BLOCK_TREE_MODEL_ADAPTER_H
|
||||
+3
-3
@@ -24,16 +24,16 @@
|
||||
|
||||
|
||||
#include <dialogs/dialog_design_block_properties.h>
|
||||
#include <sch_edit_frame.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/tooltip.h>
|
||||
#include <grid_tricks.h>
|
||||
#include <widgets/std_bitmap_button.h>
|
||||
#include <bitmaps.h>
|
||||
|
||||
#include <design_block.h>
|
||||
|
||||
DIALOG_DESIGN_BLOCK_PROPERTIES::DIALOG_DESIGN_BLOCK_PROPERTIES( SCH_EDIT_FRAME* aParent,
|
||||
DESIGN_BLOCK* aDesignBlock ) :
|
||||
DIALOG_DESIGN_BLOCK_PROPERTIES::DIALOG_DESIGN_BLOCK_PROPERTIES( wxWindow* aParent,
|
||||
DESIGN_BLOCK* aDesignBlock ) :
|
||||
DIALOG_DESIGN_BLOCK_PROPERTIES_BASE( aParent ), m_designBlock( aDesignBlock )
|
||||
{
|
||||
if( !m_textName->IsEmpty() )
|
||||
+7
-2
@@ -22,6 +22,9 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef DIALOG_DESIGN_BLOCK_PROPERTIES_H
|
||||
#define DIALOG_DESIGN_BLOCK_PROPERTIES_H
|
||||
|
||||
#include <dialogs/dialog_design_block_properties_base.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
@@ -31,7 +34,7 @@ class DESIGN_BLOCK;
|
||||
class DIALOG_DESIGN_BLOCK_PROPERTIES : public DIALOG_DESIGN_BLOCK_PROPERTIES_BASE
|
||||
{
|
||||
public:
|
||||
DIALOG_DESIGN_BLOCK_PROPERTIES( SCH_EDIT_FRAME* aParent, DESIGN_BLOCK* aDesignBlock );
|
||||
DIALOG_DESIGN_BLOCK_PROPERTIES( wxWindow* aParent, DESIGN_BLOCK* aDesignBlock );
|
||||
~DIALOG_DESIGN_BLOCK_PROPERTIES() override;
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
@@ -50,6 +53,8 @@ public:
|
||||
private:
|
||||
void AdjustGridColumns( int aWidth );
|
||||
|
||||
DESIGN_BLOCK* m_designBlock;
|
||||
DESIGN_BLOCK* m_designBlock;
|
||||
nlohmann::ordered_map<wxString, wxString> m_fields;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -633,6 +633,46 @@ bool PANEL_DESIGN_BLOCK_LIB_TABLE::verifyTables()
|
||||
}
|
||||
}
|
||||
|
||||
for( DESIGN_BLOCK_LIB_TABLE* table : { global_model(), project_model() } )
|
||||
{
|
||||
if( !table )
|
||||
continue;
|
||||
|
||||
for( unsigned int r = 0; r < table->GetCount(); ++r )
|
||||
{
|
||||
DESIGN_BLOCK_LIB_TABLE_ROW& row =
|
||||
dynamic_cast<DESIGN_BLOCK_LIB_TABLE_ROW&>( table->At( r ) );
|
||||
|
||||
// Newly-added rows won't have set this yet
|
||||
row.SetParent( table );
|
||||
|
||||
if( !row.GetIsEnabled() )
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
if( row.Refresh() )
|
||||
{
|
||||
if( table == global_model() )
|
||||
m_parent->m_GlobalTableChanged = true;
|
||||
else
|
||||
m_parent->m_ProjectTableChanged = true;
|
||||
}
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
msg.Printf( _( "Design block library '%s' failed to load." ), row.GetNickName() );
|
||||
|
||||
wxWindow* topLevelParent = wxGetTopLevelParent( this );
|
||||
wxMessageDialog errdlg( topLevelParent, msg + wxS( "\n" ) + ioe.What(),
|
||||
_( "Error Loading Library" ) );
|
||||
errdlg.ShowModal();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,6 +70,60 @@ APP_SETTINGS_BASE::APP_SETTINGS_BASE( const std::string& aFilename, int aSchemaV
|
||||
m_params.emplace_back( new PARAM_LIST<wxString>( "find_replace.replace_history",
|
||||
&m_FindReplace.replace_history, {} ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "design_block_chooser.sash_pos_h",
|
||||
&m_DesignBlockChooserPanel.sash_pos_h, -1 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "design_block_chooser.sash_pos_v",
|
||||
&m_DesignBlockChooserPanel.sash_pos_v, -1 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "design_block_chooser.width",
|
||||
&m_DesignBlockChooserPanel.width, -1 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "design_block_chooser.height",
|
||||
&m_DesignBlockChooserPanel.height, -1 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "design_block_chooser.sort_mode",
|
||||
&m_DesignBlockChooserPanel.sort_mode, 0 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<bool>( "design_block_chooser.repeated_placement",
|
||||
&m_DesignBlockChooserPanel.repeated_placement, false ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<bool>( "design_block_chooser.place_as_sheet",
|
||||
&m_DesignBlockChooserPanel.place_as_sheet, false ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<bool>( "design_block_chooser.keep_annotations",
|
||||
&m_DesignBlockChooserPanel.keep_annotations, false ) );
|
||||
|
||||
m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>(
|
||||
"design_block_chooser.lib_tree.column_widths",
|
||||
[&]() -> nlohmann::json
|
||||
{
|
||||
nlohmann::json ret = {};
|
||||
|
||||
for( const auto& [name, width] : m_DesignBlockChooserPanel.tree.column_widths )
|
||||
ret[std::string( name.ToUTF8() )] = width;
|
||||
|
||||
return ret;
|
||||
},
|
||||
[&]( const nlohmann::json& aJson )
|
||||
{
|
||||
if( !aJson.is_object() )
|
||||
return;
|
||||
|
||||
m_DesignBlockChooserPanel.tree.column_widths.clear();
|
||||
|
||||
for( const auto& entry : aJson.items() )
|
||||
{
|
||||
if( !entry.value().is_number_integer() )
|
||||
continue;
|
||||
|
||||
m_DesignBlockChooserPanel.tree.column_widths[ entry.key() ] =
|
||||
entry.value().get<int>();
|
||||
}
|
||||
},
|
||||
{} ) );
|
||||
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "graphics.canvas_type",
|
||||
&m_Graphics.canvas_type, EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL ) );
|
||||
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
#include <tool/actions.h>
|
||||
#include <tool/library_editor_control.h>
|
||||
#include <tool/design_block_control.h>
|
||||
#include <widgets/design_block_pane.h>
|
||||
#include <widgets/panel_design_block_chooser.h>
|
||||
#include <dialog_design_block_properties.h>
|
||||
#include <mail_type.h>
|
||||
#include <kiway.h>
|
||||
|
||||
|
||||
DESIGN_BLOCK_CONTROL::~DESIGN_BLOCK_CONTROL()
|
||||
{
|
||||
}
|
||||
|
||||
DESIGN_BLOCK_CONTROL::DESIGN_BLOCK_CONTROL( const std::string& aName ) : TOOL_INTERACTIVE( aName )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_CONTROL::Reset( RESET_REASON aReason )
|
||||
{
|
||||
m_frame = getEditFrame<EDA_DRAW_FRAME>();
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_CONTROL::AddContextMenuItems( CONDITIONAL_MENU* aMenu )
|
||||
{
|
||||
auto pinnedLib =
|
||||
[this]( const SELECTION& aSel )
|
||||
{
|
||||
//
|
||||
LIB_TREE_NODE* current = getCurrentTreeNode();
|
||||
return current && current->m_Type == LIB_TREE_NODE::TYPE::LIBRARY
|
||||
&& current->m_Pinned;
|
||||
};
|
||||
|
||||
auto unpinnedLib =
|
||||
[this](const SELECTION& aSel )
|
||||
{
|
||||
LIB_TREE_NODE* current = getCurrentTreeNode();
|
||||
return current && current->m_Type == LIB_TREE_NODE::TYPE::LIBRARY
|
||||
&& !current->m_Pinned;
|
||||
};
|
||||
|
||||
auto isDesignBlock =
|
||||
[this](const SELECTION& aSel )
|
||||
{
|
||||
return this->selIsDesignBlock(aSel);
|
||||
};
|
||||
|
||||
aMenu->AddItem( ACTIONS::pinLibrary, unpinnedLib, 1 );
|
||||
aMenu->AddItem( ACTIONS::unpinLibrary, pinnedLib, 1 );
|
||||
aMenu->AddItem( ACTIONS::newLibrary, !isDesignBlock, 1 );
|
||||
aMenu->AddSeparator( 2 );
|
||||
|
||||
aMenu->AddSeparator( 400 );
|
||||
aMenu->AddItem( ACTIONS::hideLibraryTree, SELECTION_CONDITIONS::ShowAlways, 400 );
|
||||
}
|
||||
|
||||
|
||||
int DESIGN_BLOCK_CONTROL::PinLibrary( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
LIB_TREE_NODE* current = getCurrentTreeNode();
|
||||
|
||||
if( current && !current->m_Pinned )
|
||||
{
|
||||
m_frame->Prj().PinLibrary( current->m_LibId.GetLibNickname(),
|
||||
PROJECT::LIB_TYPE_T::DESIGN_BLOCK_LIB );
|
||||
current->m_Pinned = true;
|
||||
getDesignBlockPane()->RefreshLibs();
|
||||
notifyOtherFrames();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int DESIGN_BLOCK_CONTROL::UnpinLibrary( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
LIB_TREE_NODE* current = getCurrentTreeNode();
|
||||
|
||||
if( current && current->m_Pinned )
|
||||
{
|
||||
m_frame->Prj().UnpinLibrary( current->m_LibId.GetLibNickname(),
|
||||
PROJECT::LIB_TYPE_T::DESIGN_BLOCK_LIB );
|
||||
current->m_Pinned = false;
|
||||
getDesignBlockPane()->RefreshLibs();
|
||||
notifyOtherFrames();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int DESIGN_BLOCK_CONTROL::NewLibrary( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
if( getDesignBlockPane()->CreateNewDesignBlockLibrary() != wxEmptyString )
|
||||
{
|
||||
notifyOtherFrames();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int DESIGN_BLOCK_CONTROL::DeleteDesignBlock( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
LIB_TREE_NODE* current = getCurrentTreeNode();
|
||||
|
||||
if( !current )
|
||||
return -1;
|
||||
|
||||
if( getDesignBlockPane()->DeleteDesignBlockFromLibrary( current->m_LibId, true ) )
|
||||
{
|
||||
notifyOtherFrames();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int DESIGN_BLOCK_CONTROL::EditDesignBlockProperties( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
LIB_TREE_NODE* current = getCurrentTreeNode();
|
||||
|
||||
if( !current )
|
||||
return -1;
|
||||
|
||||
if( getDesignBlockPane()->EditDesignBlockProperties( current->m_LibId ) )
|
||||
{
|
||||
notifyOtherFrames();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int DESIGN_BLOCK_CONTROL::HideLibraryTree( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
m_frame->ToggleLibraryTree();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool DESIGN_BLOCK_CONTROL::selIsInLibrary( const SELECTION& aSel )
|
||||
{
|
||||
LIB_TREE_NODE* current = getCurrentTreeNode();
|
||||
return current
|
||||
&& ( current->m_Type == LIB_TREE_NODE::TYPE::LIBRARY
|
||||
|| current->m_Type == LIB_TREE_NODE::TYPE::ITEM );
|
||||
}
|
||||
|
||||
|
||||
bool DESIGN_BLOCK_CONTROL::selIsDesignBlock( const SELECTION& aSel )
|
||||
{
|
||||
LIB_TREE_NODE* current = getCurrentTreeNode();
|
||||
return current && current->m_Type == LIB_TREE_NODE::TYPE::ITEM;
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_CONTROL::setTransitions()
|
||||
{
|
||||
Go( &DESIGN_BLOCK_CONTROL::PinLibrary, ACTIONS::pinLibrary.MakeEvent() );
|
||||
Go( &DESIGN_BLOCK_CONTROL::UnpinLibrary, ACTIONS::unpinLibrary.MakeEvent() );
|
||||
Go( &DESIGN_BLOCK_CONTROL::NewLibrary, ACTIONS::newLibrary.MakeEvent() );
|
||||
Go( &DESIGN_BLOCK_CONTROL::HideLibraryTree, ACTIONS::hideLibraryTree.MakeEvent() );
|
||||
}
|
||||
|
||||
|
||||
LIB_ID DESIGN_BLOCK_CONTROL::getSelectedLibId()
|
||||
{
|
||||
getDesignBlockPane()->GetSelectedLibId();
|
||||
|
||||
return LIB_ID();
|
||||
}
|
||||
|
||||
|
||||
LIB_TREE_NODE* DESIGN_BLOCK_CONTROL::getCurrentTreeNode()
|
||||
{
|
||||
LIB_TREE* libTree = getDesignBlockPane()->GetDesignBlockPanel()->GetLibTree();
|
||||
return libTree ? libTree->GetCurrentTreeNode() : nullptr;
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_CONTROL::notifyOtherFrames()
|
||||
{
|
||||
std::string payload = "";
|
||||
|
||||
for( FRAME_T frame : m_framesToNotify )
|
||||
m_frame->Kiway().ExpressMail( frame, MAIL_RELOAD_LIB, payload );
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DESIGN_BLOCK_CONTROL_H
|
||||
#define DESIGN_BLOCK_CONTROL_H
|
||||
|
||||
#include <eda_draw_frame.h>
|
||||
#include <tool/tool_interactive.h>
|
||||
|
||||
class DESIGN_BLOCK_PANE;
|
||||
|
||||
/**
|
||||
* Handle schematic design block actions in the schematic editor.
|
||||
*/
|
||||
class DESIGN_BLOCK_CONTROL : public TOOL_INTERACTIVE, public wxEvtHandler
|
||||
{
|
||||
public:
|
||||
DESIGN_BLOCK_CONTROL( const std::string& aName );
|
||||
virtual ~DESIGN_BLOCK_CONTROL();
|
||||
|
||||
/// @copydoc TOOL_INTERACTIVE::Reset()
|
||||
void Reset( RESET_REASON aReason ) override;
|
||||
|
||||
void AddContextMenuItems( CONDITIONAL_MENU* aMenu );
|
||||
|
||||
int PinLibrary( const TOOL_EVENT& aEvent );
|
||||
int UnpinLibrary( const TOOL_EVENT& aEvent );
|
||||
|
||||
int NewLibrary( const TOOL_EVENT& aEvent );
|
||||
int DeleteLibrary( const TOOL_EVENT& aEvent );
|
||||
|
||||
int DeleteDesignBlock( const TOOL_EVENT& aEvent );
|
||||
int EditDesignBlockProperties( const TOOL_EVENT& aEvent );
|
||||
|
||||
int HideLibraryTree( const TOOL_EVENT& aEvent );
|
||||
|
||||
protected:
|
||||
bool selIsInLibrary( const SELECTION& aSel );
|
||||
bool selIsDesignBlock( const SELECTION& aSel );
|
||||
|
||||
LIB_ID getSelectedLibId();
|
||||
///< Set up handlers for various events.
|
||||
void setTransitions() override;
|
||||
|
||||
virtual DESIGN_BLOCK_PANE* getDesignBlockPane() = 0;
|
||||
LIB_TREE_NODE* getCurrentTreeNode();
|
||||
|
||||
/// Notify other frames that the design block lib table has changed
|
||||
std::vector<FRAME_T> m_framesToNotify;
|
||||
void notifyOtherFrames();
|
||||
|
||||
EDA_DRAW_FRAME* m_frame = nullptr;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,512 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <design_block.h>
|
||||
#include <design_block_lib_table.h>
|
||||
#include <paths.h>
|
||||
#include <env_paths.h>
|
||||
#include <pgm_base.h>
|
||||
#include <common.h>
|
||||
#include <kidialog.h>
|
||||
#include <widgets/design_block_pane.h>
|
||||
#include <dialog_design_block_properties.h>
|
||||
#include <widgets/panel_design_block_chooser.h>
|
||||
#include <kiface_base.h>
|
||||
#include <core/kicad_algo.h>
|
||||
#include <template_fieldnames.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/choicdlg.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/textdlg.h>
|
||||
#include <confirm.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
#include <tool/tool_manager.h>
|
||||
|
||||
DESIGN_BLOCK_PANE::DESIGN_BLOCK_PANE( EDA_DRAW_FRAME* aParent, const LIB_ID* aPreselect,
|
||||
std::vector<LIB_ID>& aHistoryList ) :
|
||||
WX_PANEL( aParent ),
|
||||
m_frame( aParent )
|
||||
{
|
||||
m_frame->Bind( EDA_LANG_CHANGED, &DESIGN_BLOCK_PANE::OnLanguageChanged, this );
|
||||
}
|
||||
|
||||
|
||||
DESIGN_BLOCK_PANE::~DESIGN_BLOCK_PANE()
|
||||
{
|
||||
m_frame->Unbind( EDA_LANG_CHANGED, &DESIGN_BLOCK_PANE::OnLanguageChanged, this );
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_PANE::OnLanguageChanged( wxCommandEvent& aEvent )
|
||||
{
|
||||
if( m_chooserPanel )
|
||||
m_chooserPanel->ShowChangedLanguage();
|
||||
|
||||
setLabelsAndTooltips();
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_PANE::SaveSettings()
|
||||
{
|
||||
m_chooserPanel->SaveSettings();
|
||||
}
|
||||
|
||||
|
||||
LIB_ID DESIGN_BLOCK_PANE::GetSelectedLibId( int* aUnit ) const
|
||||
{
|
||||
return m_chooserPanel->GetSelectedLibId( aUnit );
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_PANE::SelectLibId( const LIB_ID& aLibId )
|
||||
{
|
||||
m_chooserPanel->SelectLibId( aLibId );
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_PANE::RefreshLibs()
|
||||
{
|
||||
m_chooserPanel->RefreshLibs();
|
||||
}
|
||||
|
||||
|
||||
DESIGN_BLOCK* DESIGN_BLOCK_PANE::GetDesignBlock( const LIB_ID& aLibId, bool aUseCacheLib,
|
||||
bool aShowErrorMsg )
|
||||
{
|
||||
DESIGN_BLOCK_LIB_TABLE* prjLibs = m_frame->Prj().DesignBlockLibs();
|
||||
|
||||
wxCHECK_MSG( prjLibs, nullptr, wxS( "Invalid design block library table." ) );
|
||||
|
||||
DESIGN_BLOCK* designBlock = nullptr;
|
||||
|
||||
try
|
||||
{
|
||||
designBlock = prjLibs->DesignBlockLoadWithOptionalNickname( aLibId, true );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
if( aShowErrorMsg )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Error loading design block %s from library '%s'." ),
|
||||
aLibId.GetLibItemName().wx_str(),
|
||||
aLibId.GetLibNickname().wx_str() );
|
||||
DisplayErrorMessage( m_frame, msg, ioe.What() );
|
||||
}
|
||||
}
|
||||
|
||||
return designBlock;
|
||||
}
|
||||
|
||||
|
||||
DESIGN_BLOCK* DESIGN_BLOCK_PANE::GetSelectedDesignBlock( bool aUseCacheLib, bool aShowErrorMsg )
|
||||
{
|
||||
if( !GetSelectedLibId().IsValid() )
|
||||
return nullptr;
|
||||
|
||||
return GetDesignBlock( GetSelectedLibId(), aUseCacheLib, aShowErrorMsg );
|
||||
}
|
||||
|
||||
|
||||
wxString DESIGN_BLOCK_PANE::CreateNewDesignBlockLibrary( const wxString& aLibName,
|
||||
const wxString& aProposedName )
|
||||
{
|
||||
return createNewDesignBlockLibrary( aLibName, aProposedName, selectDesignBlockLibTable() );
|
||||
}
|
||||
|
||||
|
||||
wxString DESIGN_BLOCK_PANE::createNewDesignBlockLibrary( const wxString& aLibName,
|
||||
const wxString& aProposedName,
|
||||
DESIGN_BLOCK_LIB_TABLE* aTable )
|
||||
{
|
||||
if( aTable == nullptr )
|
||||
return wxEmptyString;
|
||||
|
||||
wxFileName fn;
|
||||
bool doAdd = false;
|
||||
bool isGlobal = ( aTable == &DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable() );
|
||||
wxString initialPath = aProposedName;
|
||||
|
||||
if( initialPath.IsEmpty() )
|
||||
initialPath = isGlobal ? PATHS::GetDefaultUserDesignBlocksPath()
|
||||
: m_frame->Prj().GetProjectPath();
|
||||
|
||||
if( aLibName.IsEmpty() )
|
||||
{
|
||||
fn = initialPath;
|
||||
|
||||
if( !m_frame->LibraryFileBrowser( false, fn, FILEEXT::KiCadDesignBlockLibPathWildcard(),
|
||||
FILEEXT::KiCadDesignBlockLibPathExtension, false,
|
||||
isGlobal, initialPath ) )
|
||||
{
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
doAdd = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fn = EnsureFileExtension( aLibName, FILEEXT::KiCadDesignBlockLibPathExtension );
|
||||
|
||||
if( !fn.IsAbsolute() )
|
||||
{
|
||||
fn.SetName( aLibName );
|
||||
fn.MakeAbsolute( initialPath );
|
||||
}
|
||||
}
|
||||
|
||||
// We can save libs only using DESIGN_BLOCK_IO_MGR::KICAD_SEXP format (.pretty libraries)
|
||||
DESIGN_BLOCK_IO_MGR::DESIGN_BLOCK_FILE_T piType = DESIGN_BLOCK_IO_MGR::KICAD_SEXP;
|
||||
wxString libPath = fn.GetFullPath();
|
||||
|
||||
try
|
||||
{
|
||||
IO_RELEASER<DESIGN_BLOCK_IO> pi( DESIGN_BLOCK_IO_MGR::FindPlugin( piType ) );
|
||||
|
||||
bool writable = false;
|
||||
bool exists = false;
|
||||
|
||||
try
|
||||
{
|
||||
writable = pi->IsLibraryWritable( libPath );
|
||||
exists = fn.Exists();
|
||||
}
|
||||
catch( const IO_ERROR& )
|
||||
{
|
||||
// best efforts....
|
||||
}
|
||||
|
||||
if( exists )
|
||||
{
|
||||
if( !writable )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Library %s is read only." ), libPath );
|
||||
m_frame->ShowInfoBarError( msg );
|
||||
return wxEmptyString;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Library %s already exists." ), libPath );
|
||||
KIDIALOG dlg( m_frame, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
|
||||
dlg.SetOKLabel( _( "Overwrite" ) );
|
||||
dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
|
||||
|
||||
if( dlg.ShowModal() == wxID_CANCEL )
|
||||
return wxEmptyString;
|
||||
|
||||
pi->DeleteLibrary( libPath );
|
||||
}
|
||||
}
|
||||
|
||||
pi->CreateLibrary( libPath );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayError( m_frame, ioe.What() );
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
if( doAdd )
|
||||
AddDesignBlockLibrary( libPath, aTable );
|
||||
|
||||
return libPath;
|
||||
}
|
||||
|
||||
|
||||
bool DESIGN_BLOCK_PANE::AddDesignBlockLibrary( const wxString& aFilename,
|
||||
DESIGN_BLOCK_LIB_TABLE* aTable )
|
||||
{
|
||||
if( aTable == nullptr )
|
||||
aTable = selectDesignBlockLibTable();
|
||||
|
||||
if( aTable == nullptr )
|
||||
return wxEmptyString;
|
||||
|
||||
bool isGlobal = ( aTable == &DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable() );
|
||||
|
||||
wxFileName fn( aFilename );
|
||||
|
||||
if( aFilename.IsEmpty() )
|
||||
{
|
||||
if( !m_frame->LibraryFileBrowser( true, fn, FILEEXT::KiCadDesignBlockLibPathWildcard(),
|
||||
FILEEXT::KiCadDesignBlockLibPathExtension, true, isGlobal,
|
||||
PATHS::GetDefaultUserDesignBlocksPath() ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
wxString libPath = fn.GetFullPath();
|
||||
wxString libName = fn.GetName();
|
||||
|
||||
if( libName.IsEmpty() )
|
||||
return false;
|
||||
|
||||
// Open a dialog to ask for a description
|
||||
wxString description = wxGetTextFromUser( _( "Enter a description for the library:" ),
|
||||
_( "Library Description" ), wxEmptyString, m_frame );
|
||||
|
||||
DESIGN_BLOCK_IO_MGR::DESIGN_BLOCK_FILE_T lib_type =
|
||||
DESIGN_BLOCK_IO_MGR::GuessPluginTypeFromLibPath( libPath );
|
||||
|
||||
if( lib_type == DESIGN_BLOCK_IO_MGR::FILE_TYPE_NONE )
|
||||
lib_type = DESIGN_BLOCK_IO_MGR::KICAD_SEXP;
|
||||
|
||||
wxString type = DESIGN_BLOCK_IO_MGR::ShowType( lib_type );
|
||||
|
||||
// KiCad lib is our default guess. So it might not have the .kicad_blocks extension
|
||||
// In this case, the extension is part of the library name
|
||||
if( lib_type == DESIGN_BLOCK_IO_MGR::KICAD_SEXP
|
||||
&& fn.GetExt() != FILEEXT::KiCadDesignBlockLibPathExtension )
|
||||
libName = fn.GetFullName();
|
||||
|
||||
// try to use path normalized to an environmental variable or project path
|
||||
wxString normalizedPath = NormalizePath( libPath, &Pgm().GetLocalEnvVariables(), &m_frame->Prj() );
|
||||
|
||||
try
|
||||
{
|
||||
DESIGN_BLOCK_LIB_TABLE_ROW* row = new DESIGN_BLOCK_LIB_TABLE_ROW(
|
||||
libName, normalizedPath, type, wxEmptyString, description );
|
||||
aTable->InsertRow( row );
|
||||
|
||||
if( isGlobal )
|
||||
DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable().Save(
|
||||
DESIGN_BLOCK_LIB_TABLE::GetGlobalTableFileName() );
|
||||
else
|
||||
m_frame->Prj().DesignBlockLibs()->Save( m_frame->Prj().DesignBlockLibTblName() );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayError( m_frame, ioe.What() );
|
||||
return false;
|
||||
}
|
||||
|
||||
LIB_ID libID( libName, wxEmptyString );
|
||||
RefreshLibs();
|
||||
SelectLibId( libID );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DESIGN_BLOCK_PANE::DeleteDesignBlockLibrary( const wxString& aLibName, bool aConfirm )
|
||||
{
|
||||
if( aLibName.IsEmpty() )
|
||||
{
|
||||
DisplayErrorMessage( m_frame, _( "Please select a library to delete." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !m_frame->Prj().DesignBlockLibs()->IsDesignBlockLibWritable( aLibName ) )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Library '%s' is read only." ), aLibName );
|
||||
m_frame->ShowInfoBarError( msg );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Confirmation
|
||||
wxString msg = wxString::Format( _( "Delete design block library '%s' from disk? This will "
|
||||
"delete all design blocks within the library." ),
|
||||
aLibName.GetData() );
|
||||
|
||||
if( aConfirm && !IsOK( m_frame, msg ) )
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
m_frame->Prj().DesignBlockLibs()->DesignBlockLibDelete( aLibName );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayError( m_frame, ioe.What() );
|
||||
return false;
|
||||
}
|
||||
|
||||
msg.Printf( _( "Design block library '%s' deleted" ), aLibName.GetData() );
|
||||
m_frame->SetStatusText( msg );
|
||||
|
||||
RefreshLibs();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DESIGN_BLOCK_PANE::DeleteDesignBlockFromLibrary( const LIB_ID& aLibId, bool aConfirm )
|
||||
{
|
||||
if( !aLibId.IsValid() )
|
||||
return false;
|
||||
|
||||
wxString libname = aLibId.GetLibNickname();
|
||||
wxString dbname = aLibId.GetLibItemName();
|
||||
|
||||
if( !m_frame->Prj().DesignBlockLibs()->IsDesignBlockLibWritable( libname ) )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Library '%s' is read only." ), libname );
|
||||
m_frame->ShowInfoBarError( msg );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Confirmation
|
||||
wxString msg = wxString::Format( _( "Delete design block '%s' in library '%s' from disk?" ),
|
||||
dbname.GetData(), libname.GetData() );
|
||||
|
||||
if( aConfirm && !IsOK( m_frame, msg ) )
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
m_frame->Prj().DesignBlockLibs()->DesignBlockDelete( libname, dbname );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayError( m_frame, ioe.What() );
|
||||
return false;
|
||||
}
|
||||
|
||||
msg.Printf( _( "Design block '%s' deleted from library '%s'" ), dbname.GetData(),
|
||||
libname.GetData() );
|
||||
|
||||
m_frame->SetStatusText( msg );
|
||||
|
||||
RefreshLibs();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DESIGN_BLOCK_PANE::EditDesignBlockProperties( const LIB_ID& aLibId )
|
||||
{
|
||||
if( !aLibId.IsValid() )
|
||||
return false;
|
||||
|
||||
wxString libname = aLibId.GetLibNickname();
|
||||
wxString dbname = aLibId.GetLibItemName();
|
||||
|
||||
if( !m_frame->Prj().DesignBlockLibs()->IsDesignBlockLibWritable( libname ) )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Library '%s' is read only." ), libname );
|
||||
m_frame->ShowInfoBarError( msg );
|
||||
return false;
|
||||
}
|
||||
|
||||
DESIGN_BLOCK* designBlock = GetDesignBlock( aLibId, true, true );
|
||||
|
||||
if( !designBlock )
|
||||
return false;
|
||||
|
||||
wxString originalName = designBlock->GetLibId().GetLibItemName();
|
||||
DIALOG_DESIGN_BLOCK_PROPERTIES dlg( m_frame, designBlock );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return false;
|
||||
|
||||
wxString newName = designBlock->GetLibId().GetLibItemName();
|
||||
|
||||
try
|
||||
{
|
||||
if( originalName != newName )
|
||||
{
|
||||
if( m_frame->Prj().DesignBlockLibs()->DesignBlockExists( libname, newName ) )
|
||||
if( !checkOverwrite( m_frame, libname, newName ) )
|
||||
return false;
|
||||
|
||||
m_frame->Prj().DesignBlockLibs()->DesignBlockSave( libname, designBlock );
|
||||
m_frame->Prj().DesignBlockLibs()->DesignBlockDelete( libname, originalName );
|
||||
}
|
||||
else
|
||||
m_frame->Prj().DesignBlockLibs()->DesignBlockSave( libname, designBlock );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayError( m_frame, ioe.What() );
|
||||
return false;
|
||||
}
|
||||
|
||||
RefreshLibs();
|
||||
SelectLibId( designBlock->GetLibId() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DESIGN_BLOCK_PANE::checkOverwrite( wxWindow* aFrame, wxString& libname, wxString& newName )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Design block '%s' already exists in library '%s'." ),
|
||||
newName.GetData(), libname.GetData() );
|
||||
|
||||
if( OKOrCancelDialog( aFrame, _( "Confirmation" ), msg, _( "Overwrite existing design block?" ),
|
||||
_( "Overwrite" ) )
|
||||
!= wxID_OK )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
DESIGN_BLOCK_LIB_TABLE* DESIGN_BLOCK_PANE::selectDesignBlockLibTable( bool aOptional )
|
||||
{
|
||||
// If no project is loaded, always work with the global table
|
||||
if( m_frame->Prj().IsNullProject() )
|
||||
{
|
||||
DESIGN_BLOCK_LIB_TABLE* ret = &DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable();
|
||||
|
||||
if( aOptional )
|
||||
{
|
||||
wxMessageDialog dlg( m_frame, _( "Add the library to the global library table?" ),
|
||||
_( "Add To Global Library Table" ), wxYES_NO );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
ret = nullptr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
wxArrayString libTableNames;
|
||||
libTableNames.Add( _( "Global" ) );
|
||||
libTableNames.Add( _( "Project" ) );
|
||||
|
||||
wxSingleChoiceDialog dlg( m_frame, _( "Choose the Library Table to add the library to:" ),
|
||||
_( "Add To Library Table" ), libTableNames );
|
||||
|
||||
if( aOptional )
|
||||
{
|
||||
dlg.FindWindow( wxID_CANCEL )->SetLabel( _( "Skip" ) );
|
||||
dlg.FindWindow( wxID_OK )->SetLabel( _( "Add" ) );
|
||||
}
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return nullptr;
|
||||
|
||||
switch( dlg.GetSelection() )
|
||||
{
|
||||
case 0: return &DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable();
|
||||
case 1: return m_frame->Prj().DesignBlockLibs();
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
#ifndef DESIGN_BLOCK_PANE_H
|
||||
#define DESIGN_BLOCK_PANE_H
|
||||
|
||||
#include <design_block_tree_model_adapter.h>
|
||||
#include <widgets/html_window.h>
|
||||
#include <widgets/wx_panel.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/filedlgcustomize.h>
|
||||
#include <eda_draw_frame.h>
|
||||
|
||||
|
||||
class DESIGN_BLOCK;
|
||||
class PANEL_DESIGN_BLOCK_CHOOSER;
|
||||
|
||||
|
||||
class DESIGN_BLOCK_PANE : public WX_PANEL
|
||||
{
|
||||
public:
|
||||
DESIGN_BLOCK_PANE( EDA_DRAW_FRAME* aParent, const LIB_ID* aPreselect, std::vector<LIB_ID>& aHistoryList );
|
||||
|
||||
~DESIGN_BLOCK_PANE() override;
|
||||
|
||||
virtual void OnLanguageChanged( wxCommandEvent& aEvent );
|
||||
|
||||
void SaveSettings();
|
||||
|
||||
LIB_ID GetSelectedLibId( int* aUnit = nullptr ) const;
|
||||
void SelectLibId( const LIB_ID& aLibId );
|
||||
|
||||
/**
|
||||
* Load design block from design block library table.
|
||||
*
|
||||
* @param aLibId is the design block library identifier to load.
|
||||
* @param aUseCacheLib set to true to fall back to cache library if design block is not found in
|
||||
* design block library table.
|
||||
* @param aShowErrorMessage set to true to show any error messages.
|
||||
* @return The design block found in the library or NULL if the design block was not found.
|
||||
*/
|
||||
DESIGN_BLOCK* GetDesignBlock( const LIB_ID& aLibId, bool aUseCacheLib, bool aShowErrorMsg );
|
||||
DESIGN_BLOCK* GetSelectedDesignBlock( bool aUseCacheLib, bool aShowErrorMsg );
|
||||
|
||||
void RefreshLibs();
|
||||
|
||||
/**
|
||||
* If a library name is given, creates a new design block library in the project folder
|
||||
* with the given name. If no library name is given it prompts user for a library path,
|
||||
* then creates a new design block library at that location.
|
||||
* If library exists, user is warned about that, and is given a chance
|
||||
* to abort the new creation, and in that case existing library is first deleted.
|
||||
*
|
||||
* @param aProposedName is the initial path and filename shown in the file chooser dialog.
|
||||
* @return The newly created library path if library was successfully created, else
|
||||
* wxEmptyString because user aborted or error.
|
||||
*/
|
||||
wxString CreateNewDesignBlockLibrary( const wxString& aLibName = wxEmptyString,
|
||||
const wxString& aProposedName = wxEmptyString );
|
||||
|
||||
/**
|
||||
* Add an existing library to either the global or project library table.
|
||||
*
|
||||
* @param aFileName the library to add; a file open dialog will be displayed if empty.
|
||||
* @return true if successfully added.
|
||||
*/
|
||||
bool AddDesignBlockLibrary( const wxString& aFilename, DESIGN_BLOCK_LIB_TABLE* aTable );
|
||||
|
||||
bool DeleteDesignBlockLibrary( const wxString& aLibName, bool aConfirm );
|
||||
|
||||
bool DeleteDesignBlockFromLibrary( const LIB_ID& aLibId, bool aConfirm );
|
||||
|
||||
bool EditDesignBlockProperties( const LIB_ID& aLibId );
|
||||
|
||||
PANEL_DESIGN_BLOCK_CHOOSER* GetDesignBlockPanel() const { return m_chooserPanel; }
|
||||
|
||||
protected:
|
||||
virtual void setLabelsAndTooltips() = 0;
|
||||
|
||||
EDA_DRAW_FRAME* m_frame = nullptr;
|
||||
PANEL_DESIGN_BLOCK_CHOOSER* m_chooserPanel = nullptr;
|
||||
|
||||
private:
|
||||
bool checkOverwrite( wxWindow* aFrame, wxString& libname, wxString& newName );
|
||||
DESIGN_BLOCK_LIB_TABLE* selectDesignBlockLibTable( bool aOptional = false );
|
||||
wxString createNewDesignBlockLibrary( const wxString& aLibName, const wxString& aProposedName,
|
||||
DESIGN_BLOCK_LIB_TABLE* aTable );
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The 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 as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DESIGN_BLOCK_PREVIEW_WIDGET_H
|
||||
#define DESIGN_BLOCK_PREVIEW_WIDGET_H
|
||||
|
||||
#include <wx/panel.h>
|
||||
#include <kiway.h>
|
||||
#include <gal_display_options_common.h>
|
||||
#include <class_draw_panel_gal.h>
|
||||
|
||||
|
||||
class LIB_ID;
|
||||
class DESIGN_BLOCK;
|
||||
class SCHEMATIC;
|
||||
class SCH_SHEET;
|
||||
class wxStaticText;
|
||||
class wxSizer;
|
||||
|
||||
|
||||
class DESIGN_BLOCK_PREVIEW_WIDGET : public wxPanel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Construct a design block preview widget.
|
||||
*
|
||||
* @param aParent - parent window
|
||||
*/
|
||||
DESIGN_BLOCK_PREVIEW_WIDGET( wxWindow* aParent ) : wxPanel( aParent ) {}
|
||||
~DESIGN_BLOCK_PREVIEW_WIDGET() = default;
|
||||
|
||||
|
||||
/**
|
||||
* Set the contents of the status label and display it.
|
||||
*/
|
||||
virtual void SetStatusText( const wxString& aText ) = 0;
|
||||
|
||||
/**
|
||||
* Set the currently displayed design block.
|
||||
*/
|
||||
virtual void DisplayDesignBlock( DESIGN_BLOCK* aDesignBlock ) = 0;
|
||||
|
||||
protected:
|
||||
void onSize( wxSizeEvent& aEvent );
|
||||
|
||||
void fitOnDrawArea(); // set the view scale to fit the item on screen and center
|
||||
};
|
||||
|
||||
|
||||
#endif // DESIGN_BLOCK_PREVIEW_WIDGET_H
|
||||
+32
-27
@@ -23,15 +23,18 @@
|
||||
|
||||
#include <pgm_base.h>
|
||||
#include <design_block.h>
|
||||
#include <design_block_pane.h>
|
||||
#include <design_block_lib_table.h>
|
||||
#include <panel_design_block_chooser.h>
|
||||
#include <design_block_preview_widget.h>
|
||||
#include <kiface_base.h>
|
||||
#include <sch_edit_frame.h>
|
||||
#include <kiway_holder.h>
|
||||
#include <eda_draw_frame.h>
|
||||
#include <widgets/lib_tree.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <project/project_file.h>
|
||||
#include <dialogs/html_message_box.h>
|
||||
#include <settings/app_settings.h>
|
||||
#include <string_utils.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/panel.h>
|
||||
@@ -46,24 +49,25 @@
|
||||
wxString PANEL_DESIGN_BLOCK_CHOOSER::g_designBlockSearchString;
|
||||
|
||||
|
||||
PANEL_DESIGN_BLOCK_CHOOSER::PANEL_DESIGN_BLOCK_CHOOSER( SCH_EDIT_FRAME* aFrame, wxWindow* aParent,
|
||||
PANEL_DESIGN_BLOCK_CHOOSER::PANEL_DESIGN_BLOCK_CHOOSER( EDA_DRAW_FRAME* aFrame,
|
||||
DESIGN_BLOCK_PANE* aParent,
|
||||
std::vector<LIB_ID>& aHistoryList,
|
||||
std::function<void()> aSelectHandler ) :
|
||||
std::function<void()> aSelectHandler,
|
||||
TOOL_INTERACTIVE* aContextMenuTool ) :
|
||||
|
||||
wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize ),
|
||||
m_dbl_click_timer( nullptr ),
|
||||
m_open_libs_timer( nullptr ),
|
||||
m_vsplitter( nullptr ),
|
||||
m_tree( nullptr ),
|
||||
m_preview( nullptr ),
|
||||
m_parent( aParent ),
|
||||
m_frame( aFrame ),
|
||||
m_selectHandler( std::move( aSelectHandler ) ),
|
||||
m_historyList( aHistoryList )
|
||||
{
|
||||
DESIGN_BLOCK_LIB_TABLE* libs = m_frame->Prj().DesignBlockLibs();
|
||||
|
||||
// Make sure settings are loaded before we start running multi-threaded design block loaders
|
||||
Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" );
|
||||
|
||||
// Load design block files:
|
||||
WX_PROGRESS_REPORTER* progressReporter =
|
||||
new WX_PROGRESS_REPORTER( aParent, _( "Loading Design Block Libraries" ), 1 );
|
||||
@@ -79,8 +83,7 @@ PANEL_DESIGN_BLOCK_CHOOSER::PANEL_DESIGN_BLOCK_CHOOSER( SCH_EDIT_FRAME* aFrame,
|
||||
if( DESIGN_BLOCK_LIB_TABLE::GetGlobalList().GetErrorCount() )
|
||||
displayErrors( aFrame );
|
||||
|
||||
m_adapter = DESIGN_BLOCK_TREE_MODEL_ADAPTER::Create( m_frame, libs,
|
||||
m_frame->eeconfig()->m_DesignBlockChooserPanel.tree );
|
||||
m_adapter = DESIGN_BLOCK_TREE_MODEL_ADAPTER::Create( m_frame, libs, m_frame->config()->m_DesignBlockChooserPanel.tree, aContextMenuTool );
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// Construct the actual panel
|
||||
@@ -99,19 +102,16 @@ PANEL_DESIGN_BLOCK_CHOOSER::PANEL_DESIGN_BLOCK_CHOOSER( SCH_EDIT_FRAME* aFrame,
|
||||
wxBoxSizer* treeSizer = new wxBoxSizer( wxVERTICAL );
|
||||
treePanel->SetSizer( treeSizer );
|
||||
|
||||
wxPanel* detailsPanel = new wxPanel( m_vsplitter );
|
||||
wxBoxSizer* detailsSizer = new wxBoxSizer( wxVERTICAL );
|
||||
detailsPanel->SetSizer( detailsSizer );
|
||||
m_detailsPanel = new wxPanel( m_vsplitter );
|
||||
m_detailsSizer = new wxBoxSizer( wxVERTICAL );
|
||||
m_detailsPanel->SetSizer( m_detailsSizer );
|
||||
|
||||
m_preview = new DESIGN_BLOCK_PREVIEW_WIDGET( detailsPanel, false,
|
||||
EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL );
|
||||
detailsSizer->Add( m_preview, 1, wxEXPAND, 5 );
|
||||
detailsPanel->Layout();
|
||||
detailsSizer->Fit( detailsPanel );
|
||||
m_detailsPanel->Layout();
|
||||
m_detailsSizer->Fit( m_detailsPanel );
|
||||
|
||||
m_vsplitter->SetSashGravity( 0.5 );
|
||||
m_vsplitter->SetMinimumPaneSize( 20 );
|
||||
m_vsplitter->SplitHorizontally( treePanel, detailsPanel );
|
||||
m_vsplitter->SplitHorizontally( treePanel, m_detailsPanel );
|
||||
|
||||
sizer->Add( m_vsplitter, 1, wxEXPAND, 5 );
|
||||
|
||||
@@ -168,17 +168,14 @@ void PANEL_DESIGN_BLOCK_CHOOSER::SaveSettings()
|
||||
{
|
||||
g_designBlockSearchString = m_tree->GetSearchString();
|
||||
|
||||
if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
|
||||
if( APP_SETTINGS_BASE* cfg = m_frame->config() )
|
||||
{
|
||||
// Save any changes to column widths, etc.
|
||||
m_adapter->SaveSettings();
|
||||
|
||||
cfg->m_DesignBlockChooserPanel.width = GetParent()->GetSize().x;
|
||||
cfg->m_DesignBlockChooserPanel.height = GetParent()->GetSize().y;
|
||||
|
||||
if( m_vsplitter )
|
||||
cfg->m_DesignBlockChooserPanel.sash_pos_v = m_vsplitter->GetSashPosition();
|
||||
|
||||
cfg->m_DesignBlockChooserPanel.sash_pos_v = m_vsplitter->GetSashPosition();
|
||||
cfg->m_DesignBlockChooserPanel.sort_mode = m_tree->GetSortMode();
|
||||
}
|
||||
}
|
||||
@@ -191,6 +188,14 @@ void PANEL_DESIGN_BLOCK_CHOOSER::ShowChangedLanguage()
|
||||
}
|
||||
|
||||
|
||||
void PANEL_DESIGN_BLOCK_CHOOSER::SetPreviewWidget( DESIGN_BLOCK_PREVIEW_WIDGET* aPreview )
|
||||
{
|
||||
m_preview = aPreview;
|
||||
m_detailsSizer->Add( m_preview, 1, wxEXPAND, 5 );
|
||||
Layout();
|
||||
}
|
||||
|
||||
|
||||
void PANEL_DESIGN_BLOCK_CHOOSER::OnChar( wxKeyEvent& aEvent )
|
||||
{
|
||||
if( aEvent.GetKeyCode() == WXK_ESCAPE )
|
||||
@@ -217,7 +222,7 @@ void PANEL_DESIGN_BLOCK_CHOOSER::OnChar( wxKeyEvent& aEvent )
|
||||
|
||||
void PANEL_DESIGN_BLOCK_CHOOSER::FinishSetup()
|
||||
{
|
||||
if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
|
||||
if( APP_SETTINGS_BASE* cfg = m_frame->config() )
|
||||
{
|
||||
auto horizPixelsFromDU =
|
||||
[&]( int x ) -> int
|
||||
@@ -226,7 +231,7 @@ void PANEL_DESIGN_BLOCK_CHOOSER::FinishSetup()
|
||||
return GetParent()->ConvertDialogToPixels( sz ).x;
|
||||
};
|
||||
|
||||
EESCHEMA_SETTINGS::PANEL_DESIGN_BLOCK_CHOOSER& panelCfg = cfg->m_DesignBlockChooserPanel;
|
||||
APP_SETTINGS_BASE::PANEL_DESIGN_BLOCK_CHOOSER& panelCfg = cfg->m_DesignBlockChooserPanel;
|
||||
|
||||
int w = panelCfg.width > 40 ? panelCfg.width : horizPixelsFromDU( 440 );
|
||||
int h = panelCfg.height > 40 ? panelCfg.height : horizPixelsFromDU( 340 );
|
||||
@@ -334,7 +339,7 @@ void PANEL_DESIGN_BLOCK_CHOOSER::onCloseTimer( wxTimerEvent& aEvent )
|
||||
|
||||
void PANEL_DESIGN_BLOCK_CHOOSER::onOpenLibsTimer( wxTimerEvent& aEvent )
|
||||
{
|
||||
if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
|
||||
if( APP_SETTINGS_BASE* cfg = m_frame->config() )
|
||||
m_adapter->OpenLibs( cfg->m_LibTree.open_libs );
|
||||
|
||||
// Bind this now se we don't spam the event queue with EVT_LIBITEM_SELECTED events during
|
||||
@@ -346,7 +351,7 @@ void PANEL_DESIGN_BLOCK_CHOOSER::onOpenLibsTimer( wxTimerEvent& aEvent )
|
||||
void PANEL_DESIGN_BLOCK_CHOOSER::onDesignBlockSelected( wxCommandEvent& aEvent )
|
||||
{
|
||||
if( GetSelectedLibId().IsValid() )
|
||||
m_preview->DisplayDesignBlock( m_frame->GetDesignBlock( GetSelectedLibId() ) );
|
||||
m_preview->DisplayDesignBlock( m_parent->GetDesignBlock( GetSelectedLibId(), true, true ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -425,7 +430,7 @@ void PANEL_DESIGN_BLOCK_CHOOSER::displayErrors( wxTopLevelWindow* aWindow )
|
||||
|
||||
HTML_MESSAGE_BOX dlg( aWindow, _( "Load Error" ) );
|
||||
|
||||
dlg.MessageSet( _( "Errors were encountered loading footprints:" ) );
|
||||
dlg.MessageSet( _( "Errors were encountered loading design blocks:" ) );
|
||||
|
||||
wxString msg;
|
||||
|
||||
+26
-18
@@ -31,24 +31,27 @@ class wxPanel;
|
||||
class wxTimer;
|
||||
class wxSplitterWindow;
|
||||
|
||||
class SCH_EDIT_FRAME;
|
||||
class EDA_DRAW_FRAME;
|
||||
class DESIGN_BLOCK_PANE;
|
||||
class DESIGN_BLOCK_PREVIEW_WIDGET;
|
||||
|
||||
|
||||
class PANEL_DESIGN_BLOCK_CHOOSER : public wxPanel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create dialog to choose design_block.
|
||||
*
|
||||
* @param aFrame the parent frame (usually a SCH_EDIT_FRAME or DESIGN_BLOCK_CHOOSER_FRAME)
|
||||
* @param aParent the parent window (usually a DIALOG_SHIM or DESIGN_BLOCK_CHOOSER_FRAME)
|
||||
* @param aAcceptHandler a handler to be called on double-click of a footprint
|
||||
* @param aEscapeHandler a handler to be called on <ESC>
|
||||
*/
|
||||
PANEL_DESIGN_BLOCK_CHOOSER( SCH_EDIT_FRAME* aFrame, wxWindow* aParent,
|
||||
/**
|
||||
* Panel for using design blocks.
|
||||
*
|
||||
* @param aFrame the parent frame (usually a SCH_EDIT_FRAME or PCB_EDIT_FRAME)
|
||||
* @param aParent the parent design block pane
|
||||
* @param aAcceptHandler a handler to be called on double-click of a footprint
|
||||
* @param aContextMenuTool the tool that will be used to provide an appropriate context menu
|
||||
* for the design block actions available in that frame
|
||||
*/
|
||||
PANEL_DESIGN_BLOCK_CHOOSER( EDA_DRAW_FRAME* aFrame, DESIGN_BLOCK_PANE* aParent,
|
||||
std::vector<LIB_ID>& aHistoryList,
|
||||
std::function<void()> aSelectHandler );
|
||||
std::function<void()> aSelectHandler,
|
||||
TOOL_INTERACTIVE* aContextMenuTool );
|
||||
|
||||
~PANEL_DESIGN_BLOCK_CHOOSER();
|
||||
|
||||
@@ -56,7 +59,9 @@ public:
|
||||
|
||||
void OnChar( wxKeyEvent& aEvent );
|
||||
|
||||
void FinishSetup();
|
||||
wxPanel* GetDetailsPanel() { return m_detailsPanel; }
|
||||
void SetPreviewWidget( DESIGN_BLOCK_PREVIEW_WIDGET* aPreview );
|
||||
void FinishSetup();
|
||||
|
||||
void SetPreselect( const LIB_ID& aPreselect );
|
||||
|
||||
@@ -105,16 +110,19 @@ protected:
|
||||
protected:
|
||||
static wxString g_designBlockSearchString;
|
||||
|
||||
wxTimer* m_dbl_click_timer;
|
||||
wxTimer* m_open_libs_timer;
|
||||
wxSplitterWindow* m_vsplitter;
|
||||
wxTimer* m_dbl_click_timer;
|
||||
wxTimer* m_open_libs_timer;
|
||||
wxSplitterWindow* m_vsplitter;
|
||||
wxPanel* m_detailsPanel;
|
||||
wxBoxSizer* m_detailsSizer;
|
||||
|
||||
wxObjectDataPtr<LIB_TREE_MODEL_ADAPTER> m_adapter;
|
||||
|
||||
LIB_TREE* m_tree;
|
||||
DESIGN_BLOCK_PREVIEW_WIDGET* m_preview;
|
||||
LIB_TREE* m_tree;
|
||||
DESIGN_BLOCK_PREVIEW_WIDGET* m_preview;
|
||||
|
||||
SCH_EDIT_FRAME* m_frame;
|
||||
DESIGN_BLOCK_PANE* m_parent;
|
||||
EDA_DRAW_FRAME* m_frame;
|
||||
std::function<void()> m_selectHandler;
|
||||
|
||||
std::vector<LIB_ID> m_historyList;
|
||||
@@ -99,8 +99,6 @@ set( EESCHEMA_DLGS
|
||||
dialogs/dialog_change_symbols_base.cpp
|
||||
dialogs/dialog_database_lib_settings_base.cpp
|
||||
dialogs/dialog_database_lib_settings.cpp
|
||||
dialogs/dialog_design_block_properties_base.cpp
|
||||
dialogs/dialog_design_block_properties.cpp
|
||||
dialogs/dialog_edit_symbols_libid.cpp
|
||||
dialogs/dialog_edit_symbols_libid_base.cpp
|
||||
dialogs/dialog_eeschema_page_settings.cpp
|
||||
@@ -278,16 +276,15 @@ set( EESCHEMA_SIM_SRCS
|
||||
)
|
||||
|
||||
set( EESCHEMA_WIDGETS
|
||||
widgets/design_block_pane.cpp
|
||||
widgets/design_block_preview_widget.cpp
|
||||
widgets/hierarchy_pane.cpp
|
||||
widgets/panel_design_block_chooser.cpp
|
||||
widgets/panel_sch_selection_filter_base.cpp
|
||||
widgets/panel_sch_selection_filter.cpp
|
||||
widgets/panel_symbol_chooser.cpp
|
||||
widgets/pin_shape_combobox.cpp
|
||||
widgets/pin_type_combobox.cpp
|
||||
widgets/symbol_diff_widget.cpp
|
||||
widgets/sch_design_block_pane.cpp
|
||||
widgets/sch_design_block_preview_widget.cpp
|
||||
widgets/sch_properties_panel.cpp
|
||||
widgets/sch_search_pane.cpp
|
||||
widgets/search_handlers.cpp
|
||||
@@ -357,8 +354,7 @@ set( EESCHEMA_SRCS
|
||||
bus-wire-junction.cpp
|
||||
connection_graph.cpp
|
||||
cross-probing.cpp
|
||||
design_block_tree_model_adapter.cpp
|
||||
design_block_utils.cpp
|
||||
sch_design_block_utils.cpp
|
||||
ee_collectors.cpp
|
||||
eeschema_config.cpp
|
||||
eeschema_helpers.cpp
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#include <tools/ee_actions.h>
|
||||
#include <tools/sch_editor_control.h>
|
||||
#include <advanced_config.h>
|
||||
#include <widgets/design_block_pane.h>
|
||||
#include <widgets/sch_design_block_pane.h>
|
||||
#include <wx/log.h>
|
||||
|
||||
SCH_ITEM* SCH_EDITOR_CONTROL::FindSymbolAndItem( const wxString* aPath, const wxString* aReference,
|
||||
|
||||
@@ -1,636 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <pgm_base.h>
|
||||
#include <kiway.h>
|
||||
#include <design_block.h>
|
||||
#include <design_block_lib_table.h>
|
||||
#include <design_block_pane.h>
|
||||
#include <sch_edit_frame.h>
|
||||
#include <wx/choicdlg.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/textdlg.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
#include <paths.h>
|
||||
#include <env_paths.h>
|
||||
#include <common.h>
|
||||
#include <kidialog.h>
|
||||
#include <confirm.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <ee_selection_tool.h>
|
||||
#include <dialogs/dialog_design_block_properties.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
|
||||
bool checkOverwrite( SCH_EDIT_FRAME* aFrame, wxString& libname, wxString& newName )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Design block '%s' already exists in library '%s'." ),
|
||||
newName.GetData(), libname.GetData() );
|
||||
|
||||
if( OKOrCancelDialog( aFrame, _( "Confirmation" ), msg, _( "Overwrite existing design block?" ),
|
||||
_( "Overwrite" ) )
|
||||
!= wxID_OK )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
DESIGN_BLOCK_LIB_TABLE* SCH_EDIT_FRAME::selectDesignBlockLibTable( bool aOptional )
|
||||
{
|
||||
// If no project is loaded, always work with the global table
|
||||
if( Prj().IsNullProject() )
|
||||
{
|
||||
DESIGN_BLOCK_LIB_TABLE* ret = &DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable();
|
||||
|
||||
if( aOptional )
|
||||
{
|
||||
wxMessageDialog dlg( this, _( "Add the library to the global library table?" ),
|
||||
_( "Add To Global Library Table" ), wxYES_NO );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
ret = nullptr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
wxArrayString libTableNames;
|
||||
libTableNames.Add( _( "Global" ) );
|
||||
libTableNames.Add( _( "Project" ) );
|
||||
|
||||
wxSingleChoiceDialog dlg( this, _( "Choose the Library Table to add the library to:" ),
|
||||
_( "Add To Library Table" ), libTableNames );
|
||||
|
||||
if( aOptional )
|
||||
{
|
||||
dlg.FindWindow( wxID_CANCEL )->SetLabel( _( "Skip" ) );
|
||||
dlg.FindWindow( wxID_OK )->SetLabel( _( "Add" ) );
|
||||
}
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return nullptr;
|
||||
|
||||
switch( dlg.GetSelection() )
|
||||
{
|
||||
case 0: return &DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable();
|
||||
case 1: return Prj().DesignBlockLibs();
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wxString SCH_EDIT_FRAME::CreateNewDesignBlockLibrary( const wxString& aLibName,
|
||||
const wxString& aProposedName )
|
||||
{
|
||||
return createNewDesignBlockLibrary( aLibName, aProposedName, selectDesignBlockLibTable() );
|
||||
}
|
||||
|
||||
|
||||
wxString SCH_EDIT_FRAME::createNewDesignBlockLibrary( const wxString& aLibName,
|
||||
const wxString& aProposedName,
|
||||
DESIGN_BLOCK_LIB_TABLE* aTable )
|
||||
{
|
||||
if( aTable == nullptr )
|
||||
return wxEmptyString;
|
||||
|
||||
wxFileName fn;
|
||||
bool doAdd = false;
|
||||
bool isGlobal = ( aTable == &DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable() );
|
||||
wxString initialPath = aProposedName;
|
||||
|
||||
if( initialPath.IsEmpty() )
|
||||
initialPath = isGlobal ? PATHS::GetDefaultUserDesignBlocksPath() : Prj().GetProjectPath();
|
||||
|
||||
if( aLibName.IsEmpty() )
|
||||
{
|
||||
fn = initialPath;
|
||||
|
||||
if( !LibraryFileBrowser( false, fn, FILEEXT::KiCadDesignBlockLibPathWildcard(),
|
||||
FILEEXT::KiCadDesignBlockLibPathExtension, false, isGlobal,
|
||||
initialPath ) )
|
||||
{
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
doAdd = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fn = EnsureFileExtension( aLibName, FILEEXT::KiCadDesignBlockLibPathExtension );
|
||||
|
||||
if( !fn.IsAbsolute() )
|
||||
{
|
||||
fn.SetName( aLibName );
|
||||
fn.MakeAbsolute( initialPath );
|
||||
}
|
||||
}
|
||||
|
||||
// We can save libs only using DESIGN_BLOCK_IO_MGR::KICAD_SEXP format (.pretty libraries)
|
||||
DESIGN_BLOCK_IO_MGR::DESIGN_BLOCK_FILE_T piType = DESIGN_BLOCK_IO_MGR::KICAD_SEXP;
|
||||
wxString libPath = fn.GetFullPath();
|
||||
|
||||
try
|
||||
{
|
||||
IO_RELEASER<DESIGN_BLOCK_IO> pi( DESIGN_BLOCK_IO_MGR::FindPlugin( piType ) );
|
||||
|
||||
bool writable = false;
|
||||
bool exists = false;
|
||||
|
||||
try
|
||||
{
|
||||
writable = pi->IsLibraryWritable( libPath );
|
||||
exists = fn.Exists();
|
||||
}
|
||||
catch( const IO_ERROR& )
|
||||
{
|
||||
// best efforts....
|
||||
}
|
||||
|
||||
if( exists )
|
||||
{
|
||||
if( !writable )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Library %s is read only." ), libPath );
|
||||
ShowInfoBarError( msg );
|
||||
return wxEmptyString;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Library %s already exists." ), libPath );
|
||||
KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
|
||||
dlg.SetOKLabel( _( "Overwrite" ) );
|
||||
dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
|
||||
|
||||
if( dlg.ShowModal() == wxID_CANCEL )
|
||||
return wxEmptyString;
|
||||
|
||||
pi->DeleteLibrary( libPath );
|
||||
}
|
||||
}
|
||||
|
||||
pi->CreateLibrary( libPath );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayError( this, ioe.What() );
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
if( doAdd )
|
||||
AddDesignBlockLibrary( libPath, aTable );
|
||||
|
||||
return libPath;
|
||||
}
|
||||
|
||||
|
||||
bool SCH_EDIT_FRAME::AddDesignBlockLibrary( const wxString& aFilename,
|
||||
DESIGN_BLOCK_LIB_TABLE* aTable )
|
||||
{
|
||||
if( aTable == nullptr )
|
||||
aTable = selectDesignBlockLibTable();
|
||||
|
||||
if( aTable == nullptr )
|
||||
return wxEmptyString;
|
||||
|
||||
bool isGlobal = ( aTable == &DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable() );
|
||||
|
||||
wxFileName fn( aFilename );
|
||||
|
||||
if( aFilename.IsEmpty() )
|
||||
{
|
||||
if( !LibraryFileBrowser( true, fn, FILEEXT::KiCadDesignBlockLibPathWildcard(),
|
||||
FILEEXT::KiCadDesignBlockLibPathExtension, true, isGlobal,
|
||||
PATHS::GetDefaultUserDesignBlocksPath() ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
wxString libPath = fn.GetFullPath();
|
||||
wxString libName = fn.GetName();
|
||||
|
||||
if( libName.IsEmpty() )
|
||||
return false;
|
||||
|
||||
// Open a dialog to ask for a description
|
||||
wxString description = wxGetTextFromUser( _( "Enter a description for the library:" ),
|
||||
_( "Library Description" ), wxEmptyString, this );
|
||||
|
||||
DESIGN_BLOCK_IO_MGR::DESIGN_BLOCK_FILE_T lib_type =
|
||||
DESIGN_BLOCK_IO_MGR::GuessPluginTypeFromLibPath( libPath );
|
||||
|
||||
if( lib_type == DESIGN_BLOCK_IO_MGR::FILE_TYPE_NONE )
|
||||
lib_type = DESIGN_BLOCK_IO_MGR::KICAD_SEXP;
|
||||
|
||||
wxString type = DESIGN_BLOCK_IO_MGR::ShowType( lib_type );
|
||||
|
||||
// KiCad lib is our default guess. So it might not have the .kicad_blocks extension
|
||||
// In this case, the extension is part of the library name
|
||||
if( lib_type == DESIGN_BLOCK_IO_MGR::KICAD_SEXP
|
||||
&& fn.GetExt() != FILEEXT::KiCadDesignBlockLibPathExtension )
|
||||
libName = fn.GetFullName();
|
||||
|
||||
// try to use path normalized to an environmental variable or project path
|
||||
wxString normalizedPath = NormalizePath( libPath, &Pgm().GetLocalEnvVariables(), &Prj() );
|
||||
|
||||
try
|
||||
{
|
||||
DESIGN_BLOCK_LIB_TABLE_ROW* row = new DESIGN_BLOCK_LIB_TABLE_ROW(
|
||||
libName, normalizedPath, type, wxEmptyString, description );
|
||||
aTable->InsertRow( row );
|
||||
|
||||
if( isGlobal )
|
||||
DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable().Save(
|
||||
DESIGN_BLOCK_LIB_TABLE::GetGlobalTableFileName() );
|
||||
else
|
||||
Prj().DesignBlockLibs()->Save( Prj().DesignBlockLibTblName() );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayError( this, ioe.What() );
|
||||
return false;
|
||||
}
|
||||
|
||||
LIB_ID libID( libName, wxEmptyString );
|
||||
m_designBlocksPane->RefreshLibs();
|
||||
m_designBlocksPane->SelectLibId( libID );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SCH_EDIT_FRAME::SaveSheetAsDesignBlock( const wxString& aLibraryName,
|
||||
SCH_SHEET_PATH& aSheetPath )
|
||||
{
|
||||
// Make sure the user has selected a library to save into
|
||||
if( m_designBlocksPane->GetSelectedLibId().GetLibNickname().empty() )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Please select a library to save the design block to." ) );
|
||||
return;
|
||||
}
|
||||
|
||||
// Just block all attempts to create design blocks with nested sheets at this point
|
||||
std::vector<SCH_ITEM*> sheets;
|
||||
aSheetPath.LastScreen()->GetSheets( &sheets );
|
||||
|
||||
if( !sheets.empty() )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Design blocks with nested sheets are not supported." ) );
|
||||
return;
|
||||
}
|
||||
|
||||
DESIGN_BLOCK blk;
|
||||
wxFileName fn = wxFileNameFromPath( aSheetPath.Last()->GetName() );
|
||||
|
||||
blk.SetLibId( LIB_ID( aLibraryName, fn.GetName() ) );
|
||||
|
||||
// Copy all fields from the sheet to the design block
|
||||
std::vector<SCH_FIELD>& shFields = aSheetPath.Last()->GetFields();
|
||||
nlohmann::ordered_map<wxString, wxString> dbFields;
|
||||
|
||||
for( int i = 0; i < (int) shFields.size(); i++ )
|
||||
{
|
||||
if( i == SHEETNAME || i == SHEETFILENAME )
|
||||
continue;
|
||||
|
||||
dbFields[shFields[i].GetCanonicalName()] = shFields[i].GetText();
|
||||
}
|
||||
|
||||
blk.SetFields( dbFields );
|
||||
|
||||
DIALOG_DESIGN_BLOCK_PROPERTIES dlg( this, &blk );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return;
|
||||
|
||||
// Save a temporary copy of the schematic file, as the plugin is just going to move it
|
||||
wxString tempFile = wxFileName::CreateTempFileName( "design_block" );
|
||||
if( !saveSchematicFile( aSheetPath.Last(), tempFile ) )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Error saving temporary schematic file to create design block." ) );
|
||||
wxRemoveFile( tempFile );
|
||||
return;
|
||||
}
|
||||
|
||||
blk.SetSchematicFile( tempFile );
|
||||
|
||||
try
|
||||
{
|
||||
wxString libName = blk.GetLibId().GetLibNickname();
|
||||
wxString newName = blk.GetLibId().GetLibItemName();
|
||||
|
||||
if( Prj().DesignBlockLibs()->DesignBlockExists( libName, newName ) )
|
||||
if( !checkOverwrite( this, libName, newName ) )
|
||||
return;
|
||||
|
||||
Prj().DesignBlockLibs()->DesignBlockSave( aLibraryName, &blk );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayError( this, ioe.What() );
|
||||
}
|
||||
|
||||
// Clean up the temporary file
|
||||
wxRemoveFile( tempFile );
|
||||
|
||||
m_designBlocksPane->RefreshLibs();
|
||||
m_designBlocksPane->SelectLibId( blk.GetLibId() );
|
||||
}
|
||||
|
||||
|
||||
void SCH_EDIT_FRAME::SaveSelectionAsDesignBlock( const wxString& aLibraryName )
|
||||
{
|
||||
// Make sure the user has selected a library to save into
|
||||
if( m_designBlocksPane->GetSelectedLibId().GetLibNickname().empty() )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Please select a library to save the design block to." ) );
|
||||
return;
|
||||
}
|
||||
|
||||
// Get all selected items
|
||||
EE_SELECTION selection = m_toolManager->GetTool<EE_SELECTION_TOOL>()->GetSelection();
|
||||
|
||||
if( selection.Empty() )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Please select some items to save as a design block." ) );
|
||||
return;
|
||||
}
|
||||
|
||||
// Just block all attempts to create design blocks with nested sheets at this point
|
||||
if( selection.HasType( SCH_SHEET_T ) )
|
||||
{
|
||||
if( selection.Size() == 1 )
|
||||
{
|
||||
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( selection.Front() );
|
||||
SCH_SHEET_PATH curPath = GetCurrentSheet();
|
||||
|
||||
curPath.push_back( sheet );
|
||||
SaveSheetAsDesignBlock( aLibraryName, curPath );
|
||||
}
|
||||
else
|
||||
DisplayErrorMessage( this, _( "Design blocks with nested sheets are not supported." ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
DESIGN_BLOCK blk;
|
||||
wxFileName fn = wxFileNameFromPath( GetScreen()->GetFileName() );
|
||||
|
||||
blk.SetLibId( LIB_ID( aLibraryName, fn.GetName() ) );
|
||||
|
||||
DIALOG_DESIGN_BLOCK_PROPERTIES dlg( this, &blk );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return;
|
||||
|
||||
// Create a temporary screen
|
||||
SCH_SCREEN* tempScreen = new SCH_SCREEN( m_schematic );
|
||||
|
||||
// Copy the selected items to the temporary screen
|
||||
for( EDA_ITEM* item : selection )
|
||||
{
|
||||
EDA_ITEM* copy = item->Clone();
|
||||
tempScreen->Append( static_cast<SCH_ITEM*>( copy ) );
|
||||
}
|
||||
|
||||
// Create a sheet for the temporary screen
|
||||
SCH_SHEET* tempSheet = new SCH_SHEET( m_schematic );
|
||||
tempSheet->SetScreen( tempScreen );
|
||||
|
||||
// Save a temporary copy of the schematic file, as the plugin is just going to move it
|
||||
wxString tempFile = wxFileName::CreateTempFileName( "design_block" );
|
||||
if( !saveSchematicFile( tempSheet, tempFile ) )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Error saving temporary schematic file to create design block." ) );
|
||||
wxRemoveFile( tempFile );
|
||||
return;
|
||||
}
|
||||
|
||||
blk.SetSchematicFile( tempFile );
|
||||
|
||||
try
|
||||
{
|
||||
wxString libName = blk.GetLibId().GetLibNickname();
|
||||
wxString newName = blk.GetLibId().GetLibItemName();
|
||||
|
||||
if( Prj().DesignBlockLibs()->DesignBlockExists( libName, newName ) )
|
||||
if( !checkOverwrite( this, libName, newName ) )
|
||||
return;
|
||||
|
||||
Prj().DesignBlockLibs()->DesignBlockSave( aLibraryName, &blk );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayError( this, ioe.What() );
|
||||
}
|
||||
|
||||
// Clean up the temporaries
|
||||
wxRemoveFile( tempFile );
|
||||
// This will also delete the screen
|
||||
delete tempSheet;
|
||||
|
||||
m_designBlocksPane->RefreshLibs();
|
||||
m_designBlocksPane->SelectLibId( blk.GetLibId() );
|
||||
}
|
||||
|
||||
|
||||
bool SCH_EDIT_FRAME::DeleteDesignBlockLibrary( const wxString& aLibName, bool aConfirm )
|
||||
{
|
||||
if( aLibName.IsEmpty() )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Please select a library to delete." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !Prj().DesignBlockLibs()->IsDesignBlockLibWritable( aLibName ) )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Library '%s' is read only." ), aLibName );
|
||||
ShowInfoBarError( msg );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Confirmation
|
||||
wxString msg = wxString::Format( _( "Delete design block library '%s' from disk? This will "
|
||||
"delete all design blocks within the library." ),
|
||||
aLibName.GetData() );
|
||||
|
||||
if( aConfirm && !IsOK( this, msg ) )
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
Prj().DesignBlockLibs()->DesignBlockLibDelete( aLibName );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayError( this, ioe.What() );
|
||||
return false;
|
||||
}
|
||||
|
||||
msg.Printf( _( "Design block library '%s' deleted" ), aLibName.GetData() );
|
||||
SetStatusText( msg );
|
||||
|
||||
m_designBlocksPane->RefreshLibs();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SCH_EDIT_FRAME::DeleteDesignBlockFromLibrary( const LIB_ID& aLibId, bool aConfirm )
|
||||
{
|
||||
if( !aLibId.IsValid() )
|
||||
return false;
|
||||
|
||||
wxString libname = aLibId.GetLibNickname();
|
||||
wxString dbname = aLibId.GetLibItemName();
|
||||
|
||||
if( !Prj().DesignBlockLibs()->IsDesignBlockLibWritable( libname ) )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Library '%s' is read only." ), libname );
|
||||
ShowInfoBarError( msg );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Confirmation
|
||||
wxString msg = wxString::Format( _( "Delete design block '%s' in library '%s' from disk?" ),
|
||||
dbname.GetData(), libname.GetData() );
|
||||
|
||||
if( aConfirm && !IsOK( this, msg ) )
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
Prj().DesignBlockLibs()->DesignBlockDelete( libname, dbname );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayError( this, ioe.What() );
|
||||
return false;
|
||||
}
|
||||
|
||||
msg.Printf( _( "Design block '%s' deleted from library '%s'" ), dbname.GetData(),
|
||||
libname.GetData() );
|
||||
|
||||
SetStatusText( msg );
|
||||
|
||||
m_designBlocksPane->RefreshLibs();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SCH_EDIT_FRAME::EditDesignBlockProperties( const LIB_ID& aLibId )
|
||||
{
|
||||
if( !aLibId.IsValid() )
|
||||
return false;
|
||||
|
||||
wxString libname = aLibId.GetLibNickname();
|
||||
wxString dbname = aLibId.GetLibItemName();
|
||||
|
||||
if( !Prj().DesignBlockLibs()->IsDesignBlockLibWritable( libname ) )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Library '%s' is read only." ), libname );
|
||||
ShowInfoBarError( msg );
|
||||
return false;
|
||||
}
|
||||
|
||||
DESIGN_BLOCK* designBlock = GetDesignBlock( aLibId, true, true );
|
||||
|
||||
if( !designBlock )
|
||||
return false;
|
||||
|
||||
wxString originalName = designBlock->GetLibId().GetLibItemName();
|
||||
DIALOG_DESIGN_BLOCK_PROPERTIES dlg( this, designBlock );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return false;
|
||||
|
||||
wxString newName = designBlock->GetLibId().GetLibItemName();
|
||||
|
||||
try
|
||||
{
|
||||
if( originalName != newName )
|
||||
{
|
||||
if( Prj().DesignBlockLibs()->DesignBlockExists( libname, newName ) )
|
||||
if( !checkOverwrite( this, libname, newName ) )
|
||||
return false;
|
||||
|
||||
Prj().DesignBlockLibs()->DesignBlockSave( libname, designBlock );
|
||||
Prj().DesignBlockLibs()->DesignBlockDelete( libname, originalName );
|
||||
}
|
||||
else
|
||||
Prj().DesignBlockLibs()->DesignBlockSave( libname, designBlock );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayError( this, ioe.What() );
|
||||
return false;
|
||||
}
|
||||
|
||||
m_designBlocksPane->RefreshLibs();
|
||||
m_designBlocksPane->SelectLibId( designBlock->GetLibId() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
DESIGN_BLOCK* SchGetDesignBlock( const LIB_ID& aLibId, DESIGN_BLOCK_LIB_TABLE* aLibTable,
|
||||
wxWindow* aParent, bool aShowErrorMsg )
|
||||
{
|
||||
wxCHECK_MSG( aLibTable, nullptr, wxS( "Invalid design block library table." ) );
|
||||
|
||||
DESIGN_BLOCK* designBlock = nullptr;
|
||||
|
||||
try
|
||||
{
|
||||
designBlock = aLibTable->DesignBlockLoadWithOptionalNickname( aLibId, true );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
if( aShowErrorMsg )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Error loading designblock %s from library '%s'." ),
|
||||
aLibId.GetLibItemName().wx_str(),
|
||||
aLibId.GetLibNickname().wx_str() );
|
||||
DisplayErrorMessage( aParent, msg, ioe.What() );
|
||||
}
|
||||
}
|
||||
|
||||
return designBlock;
|
||||
}
|
||||
|
||||
|
||||
DESIGN_BLOCK* SCH_EDIT_FRAME::GetDesignBlock( const LIB_ID& aLibId, bool aUseCacheLib,
|
||||
bool aShowErrorMsg )
|
||||
{
|
||||
return SchGetDesignBlock( aLibId, Prj().DesignBlockLibs(), this, aShowErrorMsg );
|
||||
}
|
||||
|
||||
|
||||
void SCH_EDIT_FRAME::UpdateDesignBlockOptions()
|
||||
{
|
||||
m_designBlocksPane->UpdateCheckboxes();
|
||||
}
|
||||
@@ -34,8 +34,8 @@
|
||||
#include <sch_edit_frame.h>
|
||||
#include <sch_painter.h>
|
||||
#include <schematic.h>
|
||||
#include <widgets/design_block_pane.h>
|
||||
#include <widgets/hierarchy_pane.h>
|
||||
#include <widgets/sch_design_block_pane.h>
|
||||
#include <widgets/sch_search_pane.h>
|
||||
#include <widgets/panel_sch_selection_filter.h>
|
||||
#include <widgets/properties_panel.h>
|
||||
|
||||
@@ -653,59 +653,6 @@ EESCHEMA_SETTINGS::EESCHEMA_SETTINGS() :
|
||||
m_params.emplace_back( new PARAM<bool>( "symbol_chooser.place_all_units",
|
||||
&m_SymChooserPanel.place_all_units, true ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "design_block_chooser.sash_pos_h",
|
||||
&m_DesignBlockChooserPanel.sash_pos_h, -1 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "design_block_chooser.sash_pos_v",
|
||||
&m_DesignBlockChooserPanel.sash_pos_v, -1 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "design_block_chooser.width",
|
||||
&m_DesignBlockChooserPanel.width, -1 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "design_block_chooser.height",
|
||||
&m_DesignBlockChooserPanel.height, -1 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "design_block_chooser.sort_mode",
|
||||
&m_DesignBlockChooserPanel.sort_mode, 0 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<bool>( "design_block_chooser.repeated_placement",
|
||||
&m_DesignBlockChooserPanel.repeated_placement, false ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<bool>( "design_block_chooser.place_as_sheet",
|
||||
&m_DesignBlockChooserPanel.place_as_sheet, false ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<bool>( "design_block_chooser.keep_annotations",
|
||||
&m_DesignBlockChooserPanel.keep_annotations, false ) );
|
||||
|
||||
m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>(
|
||||
"design_block_chooser.lib_tree.column_widths",
|
||||
[&]() -> nlohmann::json
|
||||
{
|
||||
nlohmann::json ret = {};
|
||||
|
||||
for( const auto& [name, width] : m_DesignBlockChooserPanel.tree.column_widths )
|
||||
ret[std::string( name.ToUTF8() )] = width;
|
||||
|
||||
return ret;
|
||||
},
|
||||
[&]( const nlohmann::json& aJson )
|
||||
{
|
||||
if( !aJson.is_object() )
|
||||
return;
|
||||
|
||||
m_DesignBlockChooserPanel.tree.column_widths.clear();
|
||||
|
||||
for( const auto& entry : aJson.items() )
|
||||
{
|
||||
if( !entry.value().is_number_integer() )
|
||||
continue;
|
||||
|
||||
m_DesignBlockChooserPanel.tree.column_widths[ entry.key() ] =
|
||||
entry.value().get<int>();
|
||||
}
|
||||
},
|
||||
{} ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<bool>( "import_graphics.interactive_placement",
|
||||
&m_ImportGraphics.interactive_placement, true ) );
|
||||
|
||||
|
||||
@@ -276,21 +276,6 @@ public:
|
||||
bool place_all_units;
|
||||
};
|
||||
|
||||
struct PANEL_DESIGN_BLOCK_CHOOSER
|
||||
{
|
||||
int sash_pos_h;
|
||||
int sash_pos_v;
|
||||
int width;
|
||||
int height;
|
||||
int sort_mode;
|
||||
bool repeated_placement;
|
||||
bool place_as_sheet;
|
||||
bool keep_annotations;
|
||||
|
||||
// For saving tree columns and widths
|
||||
LIB_TREE tree;
|
||||
};
|
||||
|
||||
struct DIALOG_IMPORT_GRAPHICS
|
||||
{
|
||||
bool interactive_placement;
|
||||
@@ -381,8 +366,6 @@ public:
|
||||
|
||||
PANEL_SYM_CHOOSER m_SymChooserPanel;
|
||||
|
||||
PANEL_DESIGN_BLOCK_CHOOSER m_DesignBlockChooserPanel;
|
||||
|
||||
DIALOG_IMPORT_GRAPHICS m_ImportGraphics;
|
||||
|
||||
SELECTION m_Selection;
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <pgm_base.h>
|
||||
#include <kiway.h>
|
||||
#include <design_block.h>
|
||||
#include <design_block_lib_table.h>
|
||||
#include <sch_design_block_pane.h>
|
||||
#include <sch_edit_frame.h>
|
||||
#include <wx/choicdlg.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/textdlg.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
#include <paths.h>
|
||||
#include <env_paths.h>
|
||||
#include <common.h>
|
||||
#include <kidialog.h>
|
||||
#include <confirm.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <ee_selection_tool.h>
|
||||
#include <dialogs/dialog_design_block_properties.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
bool checkOverwrite( wxWindow* aFrame, wxString& libname, wxString& newName )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Design block '%s' already exists in library '%s'." ),
|
||||
newName.GetData(), libname.GetData() );
|
||||
|
||||
if( OKOrCancelDialog( aFrame, _( "Confirmation" ), msg, _( "Overwrite existing design block?" ),
|
||||
_( "Overwrite" ) )
|
||||
!= wxID_OK )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SCH_EDIT_FRAME::SaveSheetAsDesignBlock( const wxString& aLibraryName,
|
||||
SCH_SHEET_PATH& aSheetPath )
|
||||
{
|
||||
// Make sure the user has selected a library to save into
|
||||
if( m_designBlocksPane->GetSelectedLibId().GetLibNickname().empty() )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Please select a library to save the design block to." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Just block all attempts to create design blocks with nested sheets at this point
|
||||
std::vector<SCH_ITEM*> sheets;
|
||||
aSheetPath.LastScreen()->GetSheets( &sheets );
|
||||
|
||||
if( !sheets.empty() )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Design blocks with nested sheets are not supported." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
DESIGN_BLOCK blk;
|
||||
wxFileName fn = wxFileNameFromPath( aSheetPath.Last()->GetName() );
|
||||
|
||||
blk.SetLibId( LIB_ID( aLibraryName, fn.GetName() ) );
|
||||
|
||||
// Copy all fields from the sheet to the design block
|
||||
std::vector<SCH_FIELD>& shFields = aSheetPath.Last()->GetFields();
|
||||
nlohmann::ordered_map<wxString, wxString> dbFields;
|
||||
|
||||
for( int i = 0; i < (int) shFields.size(); i++ )
|
||||
{
|
||||
if( i == SHEETNAME || i == SHEETFILENAME )
|
||||
continue;
|
||||
|
||||
dbFields[shFields[i].GetCanonicalName()] = shFields[i].GetText();
|
||||
}
|
||||
|
||||
blk.SetFields( dbFields );
|
||||
|
||||
DIALOG_DESIGN_BLOCK_PROPERTIES dlg( this, &blk );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return false;
|
||||
|
||||
wxString libName = blk.GetLibId().GetLibNickname();
|
||||
wxString newName = blk.GetLibId().GetLibItemName();
|
||||
|
||||
if( Prj().DesignBlockLibs()->DesignBlockExists( libName, newName )
|
||||
&& !checkOverwrite( this, libName, newName ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save a temporary copy of the schematic file, as the plugin is just going to move it
|
||||
wxString tempFile = wxFileName::CreateTempFileName( "design_block" );
|
||||
if( !saveSchematicFile( aSheetPath.Last(), tempFile ) )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Error saving temporary schematic file to create design block." ) );
|
||||
wxRemoveFile( tempFile );
|
||||
return false;
|
||||
}
|
||||
|
||||
blk.SetSchematicFile( tempFile );
|
||||
|
||||
bool success = false;
|
||||
try
|
||||
{
|
||||
success = Prj().DesignBlockLibs()->DesignBlockSave( aLibraryName, &blk )
|
||||
== DESIGN_BLOCK_LIB_TABLE::SAVE_OK;
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayError( this, ioe.What() );
|
||||
}
|
||||
|
||||
// Clean up the temporary file
|
||||
wxRemoveFile( tempFile );
|
||||
|
||||
m_designBlocksPane->RefreshLibs();
|
||||
m_designBlocksPane->SelectLibId( blk.GetLibId() );
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool SCH_EDIT_FRAME::SaveSelectionAsDesignBlock( const wxString& aLibraryName )
|
||||
{
|
||||
// Get all selected items
|
||||
EE_SELECTION selection = m_toolManager->GetTool<EE_SELECTION_TOOL>()->GetSelection();
|
||||
|
||||
if( selection.Empty() )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Please select some items to save as a design block." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure the user has selected a library to save into
|
||||
if( m_designBlocksPane->GetSelectedLibId().GetLibNickname().empty() )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Please select a library to save the design block to." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Just block all attempts to create design blocks with nested sheets at this point
|
||||
if( selection.HasType( SCH_SHEET_T ) )
|
||||
{
|
||||
if( selection.Size() == 1 )
|
||||
{
|
||||
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( selection.Front() );
|
||||
SCH_SHEET_PATH curPath = GetCurrentSheet();
|
||||
|
||||
curPath.push_back( sheet );
|
||||
SaveSheetAsDesignBlock( aLibraryName, curPath );
|
||||
}
|
||||
else
|
||||
DisplayErrorMessage( this, _( "Design blocks with nested sheets are not supported." ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DESIGN_BLOCK blk;
|
||||
wxFileName fn = wxFileNameFromPath( GetScreen()->GetFileName() );
|
||||
|
||||
blk.SetLibId( LIB_ID( aLibraryName, fn.GetName() ) );
|
||||
|
||||
DIALOG_DESIGN_BLOCK_PROPERTIES dlg( this, &blk );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return false;
|
||||
|
||||
wxString libName = blk.GetLibId().GetLibNickname();
|
||||
wxString newName = blk.GetLibId().GetLibItemName();
|
||||
|
||||
if( Prj().DesignBlockLibs()->DesignBlockExists( libName, newName )
|
||||
&& !checkOverwrite( this, libName, newName ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a temporary screen
|
||||
SCH_SCREEN* tempScreen = new SCH_SCREEN( m_schematic );
|
||||
|
||||
// Copy the selected items to the temporary screen
|
||||
for( EDA_ITEM* item : selection )
|
||||
{
|
||||
EDA_ITEM* copy = item->Clone();
|
||||
tempScreen->Append( static_cast<SCH_ITEM*>( copy ) );
|
||||
}
|
||||
|
||||
// Create a sheet for the temporary screen
|
||||
SCH_SHEET* tempSheet = new SCH_SHEET( m_schematic );
|
||||
tempSheet->SetScreen( tempScreen );
|
||||
|
||||
// Save a temporary copy of the schematic file, as the plugin is just going to move it
|
||||
wxString tempFile = wxFileName::CreateTempFileName( "design_block" );
|
||||
if( !saveSchematicFile( tempSheet, tempFile ) )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Error saving temporary schematic file to create design block." ) );
|
||||
wxRemoveFile( tempFile );
|
||||
return false;
|
||||
}
|
||||
|
||||
blk.SetSchematicFile( tempFile );
|
||||
|
||||
bool success = false;
|
||||
try
|
||||
{
|
||||
success = Prj().DesignBlockLibs()->DesignBlockSave( aLibraryName, &blk )
|
||||
== DESIGN_BLOCK_LIB_TABLE::SAVE_OK;
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayError( this, ioe.What() );
|
||||
}
|
||||
|
||||
// Clean up the temporaries
|
||||
wxRemoveFile( tempFile );
|
||||
// This will also delete the screen
|
||||
delete tempSheet;
|
||||
|
||||
m_designBlocksPane->RefreshLibs();
|
||||
m_designBlocksPane->SelectLibId( blk.GetLibId() );
|
||||
|
||||
return success;
|
||||
}
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <dialogs/dialog_schematic_find.h>
|
||||
#include <dialogs/dialog_book_reporter.h>
|
||||
#include <dialogs/dialog_symbol_fields_table.h>
|
||||
#include <widgets/design_block_pane.h>
|
||||
#include <widgets/sch_design_block_pane.h>
|
||||
#include <eeschema_id.h>
|
||||
#include <executable_names.h>
|
||||
#include <gal/graphics_abstraction_layer.h>
|
||||
@@ -212,7 +212,7 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
m_propertiesPanel->SetSplitterProportion( eeconfig()->m_AuiPanels.properties_splitter );
|
||||
|
||||
m_selectionFilterPanel = new PANEL_SCH_SELECTION_FILTER( this );
|
||||
m_designBlocksPane = new DESIGN_BLOCK_PANE( this, nullptr, m_designBlockHistoryList );
|
||||
m_designBlocksPane = new SCH_DESIGN_BLOCK_PANE( this, nullptr, m_designBlockHistoryList );
|
||||
|
||||
m_auimgr.SetManagedWindow( this );
|
||||
|
||||
|
||||
@@ -56,8 +56,7 @@ class SCH_FIELD;
|
||||
class SCH_JUNCTION;
|
||||
class SCHEMATIC;
|
||||
class SCH_COMMIT;
|
||||
class DESIGN_BLOCK;
|
||||
class DESIGN_BLOCK_PANE;
|
||||
class SCH_DESIGN_BLOCK_PANE;
|
||||
class DIALOG_BOOK_REPORTER;
|
||||
class DIALOG_ERC;
|
||||
class DIALOG_SYMBOL_FIELDS_TABLE;
|
||||
@@ -745,52 +744,11 @@ public:
|
||||
*/
|
||||
bool CreateArchiveLibrary( const wxString& aFileName );
|
||||
|
||||
/**
|
||||
* If a library name is given, creates a new design block library in the project folder
|
||||
* with the given name. If no library name is given it prompts user for a library path,
|
||||
* then creates a new design block library at that location.
|
||||
* If library exists, user is warned about that, and is given a chance
|
||||
* to abort the new creation, and in that case existing library is first deleted.
|
||||
*
|
||||
* @param aProposedName is the initial path and filename shown in the file chooser dialog.
|
||||
* @return The newly created library path if library was successfully created, else
|
||||
* wxEmptyString because user aborted or error.
|
||||
*/
|
||||
wxString CreateNewDesignBlockLibrary( const wxString& aLibName = wxEmptyString,
|
||||
const wxString& aProposedName = wxEmptyString );
|
||||
bool SaveSheetAsDesignBlock( const wxString& aLibraryName, SCH_SHEET_PATH& aSheetPath );
|
||||
|
||||
/**
|
||||
* Add an existing library to either the global or project library table.
|
||||
*
|
||||
* @param aFileName the library to add; a file open dialog will be displayed if empty.
|
||||
* @return true if successfully added.
|
||||
*/
|
||||
bool AddDesignBlockLibrary( const wxString& aFilename, DESIGN_BLOCK_LIB_TABLE* aTable );
|
||||
bool SaveSelectionAsDesignBlock( const wxString& aLibraryName );
|
||||
|
||||
void SaveSheetAsDesignBlock( const wxString& aLibraryName, SCH_SHEET_PATH& aSheetPath );
|
||||
|
||||
void SaveSelectionAsDesignBlock( const wxString& aLibraryName );
|
||||
|
||||
bool DeleteDesignBlockLibrary( const wxString& aLibName, bool aConfirm );
|
||||
|
||||
bool DeleteDesignBlockFromLibrary( const LIB_ID& aLibId, bool aConfirm );
|
||||
|
||||
bool EditDesignBlockProperties( const LIB_ID& aLibId );
|
||||
|
||||
|
||||
/**
|
||||
* Load design block from design block library table.
|
||||
*
|
||||
* @param aLibId is the design block library identifier to load.
|
||||
* @param aUseCacheLib set to true to fall back to cache library if design block is not found in
|
||||
* design block library table.
|
||||
* @param aShowErrorMessage set to true to show any error messages.
|
||||
* @return The design block found in the library or NULL if the design block was not found.
|
||||
*/
|
||||
DESIGN_BLOCK* GetDesignBlock( const LIB_ID& aLibId, bool aUseCacheLib = false,
|
||||
bool aShowErrorMsg = false );
|
||||
|
||||
DESIGN_BLOCK_PANE* GetDesignBlockPane() const { return m_designBlocksPane; }
|
||||
SCH_DESIGN_BLOCK_PANE* GetDesignBlockPane() const { return m_designBlocksPane; }
|
||||
|
||||
/**
|
||||
* Plot or print the current sheet to the clipboard.
|
||||
@@ -981,20 +939,6 @@ protected:
|
||||
void onPluginAvailabilityChanged( wxCommandEvent& aEvt );
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Prompts a user to select global or project library tables
|
||||
*
|
||||
* @return Pointer to library table selected or nullptr if none selected/canceled
|
||||
*/
|
||||
DESIGN_BLOCK_LIB_TABLE* selectDesignBlockLibTable( bool aOptional = false );
|
||||
|
||||
/**
|
||||
* Create a new library in the given table (presumed to be either the global or project
|
||||
* library table).
|
||||
*/
|
||||
wxString createNewDesignBlockLibrary( const wxString& aLibName, const wxString& aProposedName,
|
||||
DESIGN_BLOCK_LIB_TABLE* aTable );
|
||||
|
||||
private:
|
||||
// Called when resizing the Hierarchy Navigator panel
|
||||
void OnResizeHierarchyNavigator( wxSizeEvent& aEvent );
|
||||
@@ -1113,7 +1057,7 @@ private:
|
||||
|
||||
std::vector<LIB_ID> m_designBlockHistoryList;
|
||||
|
||||
DESIGN_BLOCK_PANE* m_designBlocksPane;
|
||||
SCH_DESIGN_BLOCK_PANE* m_designBlocksPane;
|
||||
|
||||
#ifdef KICAD_IPC_API
|
||||
std::unique_ptr<API_HANDLER_SCH> m_apiHandler;
|
||||
|
||||
@@ -37,9 +37,9 @@
|
||||
#include <tool/action_toolbar.h>
|
||||
#include <tools/ee_actions.h>
|
||||
#include <tools/ee_selection_tool.h>
|
||||
#include <widgets/design_block_pane.h>
|
||||
#include <widgets/hierarchy_pane.h>
|
||||
#include <widgets/wx_aui_utils.h>
|
||||
#include <widgets/sch_design_block_pane.h>
|
||||
#include <widgets/sch_properties_panel.h>
|
||||
#include <widgets/sch_search_pane.h>
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
#include <sch_line_wire_bus_tool.h>
|
||||
#include <tool/tool_action.h>
|
||||
|
||||
class DESIGN_BLOCK;
|
||||
|
||||
// Actions, being statically-defined, require specialized I18N handling. We continue to
|
||||
// use the _() macro so that string harvesting by the I18N framework doesn't have to be
|
||||
// specialized, but we don't translate on initialization and instead do it in the getters.
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <tool/tool_action.h>
|
||||
#include <tool/actions.h>
|
||||
|
||||
class DESIGN_BLOCK;
|
||||
class SCH_SYMBOL;
|
||||
class TOOL_EVENT;
|
||||
class TOOL_MANAGER;
|
||||
|
||||
@@ -20,57 +20,41 @@
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
#include <tool/library_editor_control.h>
|
||||
#include <sch_design_block_control.h>
|
||||
#include <design_block_pane.h>
|
||||
#include <panel_design_block_chooser.h>
|
||||
#include <dialog_design_block_properties.h>
|
||||
#include <ee_actions.h>
|
||||
#include <ee_selection_tool.h>
|
||||
#include <sch_design_block_control.h>
|
||||
#include <sch_edit_frame.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <widgets/sch_design_block_pane.h>
|
||||
#include <widgets/panel_design_block_chooser.h>
|
||||
|
||||
|
||||
SCH_DESIGN_BLOCK_CONTROL::~SCH_DESIGN_BLOCK_CONTROL()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool SCH_DESIGN_BLOCK_CONTROL::Init()
|
||||
{
|
||||
m_editFrame = getEditFrame<SCH_EDIT_FRAME>();
|
||||
m_frame = m_editFrame;
|
||||
m_selectionTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
|
||||
|
||||
auto pinnedLib =
|
||||
[this]( const SELECTION& aSel )
|
||||
{
|
||||
//
|
||||
LIB_TREE_NODE* current = getCurrentTreeNode();
|
||||
return current && current->m_Type == LIB_TREE_NODE::TYPE::LIBRARY
|
||||
&& current->m_Pinned;
|
||||
};
|
||||
auto unpinnedLib =
|
||||
[this](const SELECTION& aSel )
|
||||
{
|
||||
LIB_TREE_NODE* current = getCurrentTreeNode();
|
||||
return current && current->m_Type == LIB_TREE_NODE::TYPE::LIBRARY
|
||||
&& !current->m_Pinned;
|
||||
};
|
||||
m_framesToNotify = { FRAME_PCB_EDITOR };
|
||||
|
||||
auto isInLibrary =
|
||||
[this](const SELECTION& aSel )
|
||||
{
|
||||
LIB_TREE_NODE* current = getCurrentTreeNode();
|
||||
return current
|
||||
&& ( current->m_Type == LIB_TREE_NODE::TYPE::LIBRARY
|
||||
|| current->m_Type == LIB_TREE_NODE::TYPE::ITEM );
|
||||
return this->selIsInLibrary(aSel);
|
||||
};
|
||||
|
||||
auto isDesignBlock =
|
||||
[this](const SELECTION& aSel )
|
||||
{
|
||||
LIB_TREE_NODE* current = getCurrentTreeNode();
|
||||
return current && current->m_Type == LIB_TREE_NODE::TYPE::ITEM;
|
||||
return this->selIsDesignBlock(aSel);
|
||||
};
|
||||
|
||||
CONDITIONAL_MENU& ctxMenu = m_menu->GetMenu();
|
||||
|
||||
ctxMenu.AddItem( ACTIONS::pinLibrary, unpinnedLib, 1 );
|
||||
ctxMenu.AddItem( ACTIONS::unpinLibrary, pinnedLib, 1 );
|
||||
ctxMenu.AddItem( ACTIONS::newLibrary, !isDesignBlock, 1 );
|
||||
ctxMenu.AddSeparator( 1 );
|
||||
AddContextMenuItems( &ctxMenu );
|
||||
|
||||
ctxMenu.AddItem( EE_ACTIONS::placeDesignBlock, isDesignBlock, 50 );
|
||||
ctxMenu.AddSeparator( 50 );
|
||||
@@ -81,51 +65,10 @@ bool SCH_DESIGN_BLOCK_CONTROL::Init()
|
||||
ctxMenu.AddItem( EE_ACTIONS::deleteDesignBlock, isDesignBlock, 100 );
|
||||
ctxMenu.AddSeparator( 100 );
|
||||
|
||||
ctxMenu.AddItem( ACTIONS::hideLibraryTree, SELECTION_CONDITIONS::ShowAlways, 400 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int SCH_DESIGN_BLOCK_CONTROL::PinLibrary( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
LIB_TREE_NODE* current = getCurrentTreeNode();
|
||||
|
||||
if( current && !current->m_Pinned )
|
||||
{
|
||||
m_frame->Prj().PinLibrary( current->m_LibId.GetLibNickname(),
|
||||
PROJECT::LIB_TYPE_T::DESIGN_BLOCK_LIB );
|
||||
current->m_Pinned = true;
|
||||
getDesignBlockPane()->RefreshLibs();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int SCH_DESIGN_BLOCK_CONTROL::UnpinLibrary( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
LIB_TREE_NODE* current = getCurrentTreeNode();
|
||||
|
||||
if( current && current->m_Pinned )
|
||||
{
|
||||
m_frame->Prj().UnpinLibrary( current->m_LibId.GetLibNickname(),
|
||||
PROJECT::LIB_TYPE_T::DESIGN_BLOCK_LIB );
|
||||
current->m_Pinned = false;
|
||||
getDesignBlockPane()->RefreshLibs();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int SCH_DESIGN_BLOCK_CONTROL::NewLibrary( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
m_editFrame->CreateNewDesignBlockLibrary();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int SCH_DESIGN_BLOCK_CONTROL::SaveSheetAsDesignBlock( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
LIB_TREE_NODE* current = getCurrentTreeNode();
|
||||
@@ -133,8 +76,11 @@ int SCH_DESIGN_BLOCK_CONTROL::SaveSheetAsDesignBlock( const TOOL_EVENT& aEvent )
|
||||
if( !current )
|
||||
return -1;
|
||||
|
||||
m_editFrame->SaveSheetAsDesignBlock( current->m_LibId.GetLibNickname(),
|
||||
m_editFrame->GetCurrentSheet() );
|
||||
if( !m_editFrame->SaveSheetAsDesignBlock( current->m_LibId.GetLibNickname(),
|
||||
m_editFrame->GetCurrentSheet() ) )
|
||||
return -1;
|
||||
|
||||
notifyOtherFrames();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -147,67 +93,23 @@ int SCH_DESIGN_BLOCK_CONTROL::SaveSelectionAsDesignBlock( const TOOL_EVENT& aEve
|
||||
if( !current )
|
||||
return -1;
|
||||
|
||||
m_editFrame->SaveSelectionAsDesignBlock( current->m_LibId.GetLibNickname() );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int SCH_DESIGN_BLOCK_CONTROL::DeleteDesignBlock( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
LIB_TREE_NODE* current = getCurrentTreeNode();
|
||||
|
||||
if( !current )
|
||||
if( !m_editFrame->SaveSelectionAsDesignBlock( current->m_LibId.GetLibNickname() ) )
|
||||
return -1;
|
||||
|
||||
m_editFrame->DeleteDesignBlockFromLibrary( current->m_LibId, true );
|
||||
notifyOtherFrames();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int SCH_DESIGN_BLOCK_CONTROL::EditDesignBlockProperties( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
LIB_TREE_NODE* current = getCurrentTreeNode();
|
||||
|
||||
if( !current )
|
||||
return -1;
|
||||
|
||||
if( m_editFrame->EditDesignBlockProperties( current->m_LibId ) )
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int SCH_DESIGN_BLOCK_CONTROL::HideLibraryTree( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
m_editFrame->ToggleLibraryTree();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void SCH_DESIGN_BLOCK_CONTROL::setTransitions()
|
||||
{
|
||||
Go( &SCH_DESIGN_BLOCK_CONTROL::PinLibrary, ACTIONS::pinLibrary.MakeEvent() );
|
||||
Go( &SCH_DESIGN_BLOCK_CONTROL::UnpinLibrary, ACTIONS::unpinLibrary.MakeEvent() );
|
||||
|
||||
Go( &SCH_DESIGN_BLOCK_CONTROL::NewLibrary, ACTIONS::newLibrary.MakeEvent() );
|
||||
DESIGN_BLOCK_CONTROL::setTransitions();
|
||||
|
||||
Go( &SCH_DESIGN_BLOCK_CONTROL::SaveSheetAsDesignBlock, EE_ACTIONS::saveSheetAsDesignBlock.MakeEvent() );
|
||||
Go( &SCH_DESIGN_BLOCK_CONTROL::SaveSelectionAsDesignBlock, EE_ACTIONS::saveSelectionAsDesignBlock.MakeEvent() );
|
||||
Go( &SCH_DESIGN_BLOCK_CONTROL::DeleteDesignBlock, EE_ACTIONS::deleteDesignBlock.MakeEvent() );
|
||||
Go( &SCH_DESIGN_BLOCK_CONTROL::EditDesignBlockProperties, EE_ACTIONS::editDesignBlockProperties.MakeEvent() );
|
||||
|
||||
Go( &SCH_DESIGN_BLOCK_CONTROL::HideLibraryTree, ACTIONS::hideLibraryTree.MakeEvent() );
|
||||
}
|
||||
|
||||
|
||||
LIB_ID SCH_DESIGN_BLOCK_CONTROL::getSelectedLibId()
|
||||
{
|
||||
m_editFrame->GetDesignBlockPane()->GetSelectedLibId();
|
||||
|
||||
return LIB_ID();
|
||||
}
|
||||
|
||||
|
||||
@@ -215,10 +117,3 @@ DESIGN_BLOCK_PANE* SCH_DESIGN_BLOCK_CONTROL::getDesignBlockPane()
|
||||
{
|
||||
return m_editFrame->GetDesignBlockPane();
|
||||
}
|
||||
|
||||
|
||||
LIB_TREE_NODE* SCH_DESIGN_BLOCK_CONTROL::getCurrentTreeNode()
|
||||
{
|
||||
LIB_TREE* libTree = getDesignBlockPane()->GetDesignBlockPanel()->GetLibTree();
|
||||
return libTree ? libTree->GetCurrentTreeNode() : nullptr;
|
||||
}
|
||||
|
||||
@@ -25,40 +25,32 @@
|
||||
#ifndef SCH_DESIGN_BLOCK_CONTROL_H
|
||||
#define SCH_DESIGN_BLOCK_CONTROL_H
|
||||
|
||||
#include <sch_base_frame.h>
|
||||
#include <tools/ee_tool_base.h>
|
||||
#include <tool/design_block_control.h>
|
||||
|
||||
class DESIGN_BLOCK_PANE;
|
||||
class SCH_EDIT_FRAME;
|
||||
|
||||
/**
|
||||
* Handle schematic design block actions in the schematic editor.
|
||||
* Handle design block actions in the schematic editor.
|
||||
*/
|
||||
class SCH_DESIGN_BLOCK_CONTROL : public wxEvtHandler, public EE_TOOL_BASE<SCH_BASE_FRAME>
|
||||
class SCH_DESIGN_BLOCK_CONTROL : public DESIGN_BLOCK_CONTROL
|
||||
{
|
||||
public:
|
||||
SCH_DESIGN_BLOCK_CONTROL() : EE_TOOL_BASE<SCH_BASE_FRAME>( "eeschema.SchDesignBlockControl" ) {}
|
||||
SCH_DESIGN_BLOCK_CONTROL() : DESIGN_BLOCK_CONTROL( "eeschema.SchDesignBlockControl" ) {}
|
||||
virtual ~SCH_DESIGN_BLOCK_CONTROL();
|
||||
|
||||
/// @copydoc TOOL_INTERACTIVE::Init()
|
||||
bool Init() override;
|
||||
|
||||
int PinLibrary( const TOOL_EVENT& aEvent );
|
||||
int UnpinLibrary( const TOOL_EVENT& aEvent );
|
||||
|
||||
int NewLibrary( const TOOL_EVENT& aEvent );
|
||||
int DeleteLibrary( const TOOL_EVENT& aEvent );
|
||||
|
||||
int SaveSheetAsDesignBlock( const TOOL_EVENT& aEvent );
|
||||
int SaveSelectionAsDesignBlock( const TOOL_EVENT& aEvent );
|
||||
int DeleteDesignBlock( const TOOL_EVENT& aEvent );
|
||||
int EditDesignBlockProperties( const TOOL_EVENT& aEvent );
|
||||
|
||||
int HideLibraryTree( const TOOL_EVENT& aEvent );
|
||||
|
||||
private:
|
||||
LIB_ID getSelectedLibId();
|
||||
///< Set up handlers for various events.
|
||||
void setTransitions() override;
|
||||
|
||||
DESIGN_BLOCK_PANE* getDesignBlockPane();
|
||||
LIB_TREE_NODE* getCurrentTreeNode();
|
||||
DESIGN_BLOCK_PANE* getDesignBlockPane() override;
|
||||
|
||||
SCH_EDIT_FRAME* m_editFrame = nullptr;
|
||||
};
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#include <sch_edit_frame.h>
|
||||
#include <pgm_base.h>
|
||||
#include <design_block.h>
|
||||
#include <design_block_pane.h>
|
||||
#include <widgets/sch_design_block_pane.h>
|
||||
#include <eeschema_id.h>
|
||||
#include <confirm.h>
|
||||
#include <view/view_controls.h>
|
||||
@@ -623,8 +623,8 @@ int SCH_DRAWING_TOOLS::ImportSheet( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
if( m_frame->GetDesignBlockPane()->GetSelectedLibId().IsValid() )
|
||||
{
|
||||
designBlock =
|
||||
m_frame->GetDesignBlock( m_frame->GetDesignBlockPane()->GetSelectedLibId() );
|
||||
designBlock = m_frame->GetDesignBlockPane()->GetDesignBlock(
|
||||
m_frame->GetDesignBlockPane()->GetSelectedLibId(), true, true );
|
||||
|
||||
if( !designBlock )
|
||||
return 0;
|
||||
@@ -794,7 +794,7 @@ int SCH_DRAWING_TOOLS::ImportSheet( const TOOL_EVENT& aEvent )
|
||||
|
||||
sheetFileName = dlg.GetPath();
|
||||
|
||||
m_frame->UpdateDesignBlockOptions();
|
||||
m_frame->GetDesignBlockPane()->UpdateCheckboxes();
|
||||
}
|
||||
|
||||
if( sheetFileName.IsEmpty() )
|
||||
|
||||
+18
-55
@@ -22,7 +22,8 @@
|
||||
*/
|
||||
|
||||
#include <design_block.h>
|
||||
#include <widgets/design_block_pane.h>
|
||||
#include <widgets/sch_design_block_pane.h>
|
||||
#include <widgets/sch_design_block_preview_widget.h>
|
||||
#include <widgets/panel_design_block_chooser.h>
|
||||
#include <eeschema_settings.h>
|
||||
#include <kiface_base.h>
|
||||
@@ -36,6 +37,7 @@
|
||||
#include <wildcards_and_files_ext.h>
|
||||
#include <ee_actions.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tools/sch_design_block_control.h>
|
||||
|
||||
|
||||
// Do not make these static wxStrings; they need to respond to language changes
|
||||
@@ -43,10 +45,9 @@
|
||||
#define PLACE_AS_SHEET _( "Place as sheet" )
|
||||
#define KEEP_ANNOTATIONS _( "Keep annotations" )
|
||||
|
||||
DESIGN_BLOCK_PANE::DESIGN_BLOCK_PANE( SCH_EDIT_FRAME* aParent, const LIB_ID* aPreselect,
|
||||
SCH_DESIGN_BLOCK_PANE::SCH_DESIGN_BLOCK_PANE( SCH_EDIT_FRAME* aParent, const LIB_ID* aPreselect,
|
||||
std::vector<LIB_ID>& aHistoryList ) :
|
||||
WX_PANEL( aParent ),
|
||||
m_frame( aParent )
|
||||
DESIGN_BLOCK_PANE( aParent, aPreselect, aHistoryList )
|
||||
{
|
||||
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
|
||||
m_chooserPanel = new PANEL_DESIGN_BLOCK_CHOOSER( aParent, this, aHistoryList,
|
||||
@@ -54,7 +55,10 @@ DESIGN_BLOCK_PANE::DESIGN_BLOCK_PANE( SCH_EDIT_FRAME* aParent, const LIB_ID* aPr
|
||||
{
|
||||
aParent->GetToolManager()->RunAction(
|
||||
EE_ACTIONS::placeDesignBlock );
|
||||
} );
|
||||
},
|
||||
aParent->GetToolManager()->GetTool<SCH_DESIGN_BLOCK_CONTROL>()
|
||||
);
|
||||
m_chooserPanel->SetPreviewWidget(new SCH_DESIGN_BLOCK_PREVIEW_WIDGET( m_chooserPanel->GetDetailsPanel(), EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL, true ) );
|
||||
sizer->Add( m_chooserPanel, 1, wxEXPAND, 5 );
|
||||
|
||||
if( aPreselect && aPreselect->IsValid() )
|
||||
@@ -71,13 +75,13 @@ DESIGN_BLOCK_PANE::DESIGN_BLOCK_PANE( SCH_EDIT_FRAME* aParent, const LIB_ID* aPr
|
||||
UpdateCheckboxes();
|
||||
|
||||
// Set all checkbox handlers to the same function
|
||||
m_repeatedPlacement->Bind( wxEVT_CHECKBOX, &DESIGN_BLOCK_PANE::OnCheckBox, this );
|
||||
m_placeAsSheet->Bind( wxEVT_CHECKBOX, &DESIGN_BLOCK_PANE::OnCheckBox, this );
|
||||
m_keepAnnotations->Bind( wxEVT_CHECKBOX, &DESIGN_BLOCK_PANE::OnCheckBox, this );
|
||||
m_repeatedPlacement->Bind( wxEVT_CHECKBOX, &SCH_DESIGN_BLOCK_PANE::OnCheckBox, this );
|
||||
m_placeAsSheet->Bind( wxEVT_CHECKBOX, &SCH_DESIGN_BLOCK_PANE::OnCheckBox, this );
|
||||
m_keepAnnotations->Bind( wxEVT_CHECKBOX, &SCH_DESIGN_BLOCK_PANE::OnCheckBox, this );
|
||||
|
||||
cbSizer->Add( m_repeatedPlacement, 0, wxTOP|wxLEFT, 2 );
|
||||
cbSizer->Add( m_placeAsSheet, 0, wxTOP|wxLEFT, 2 );
|
||||
cbSizer->Add( m_keepAnnotations, 0, wxTOP|wxLEFT|wxBOTTOM, 2 );
|
||||
cbSizer->Add( m_repeatedPlacement, 0, wxTOP | wxLEFT, 2 );
|
||||
cbSizer->Add( m_placeAsSheet, 0, wxTOP | wxLEFT, 2 );
|
||||
cbSizer->Add( m_keepAnnotations, 0, wxTOP | wxLEFT | wxBOTTOM, 2 );
|
||||
|
||||
sizer->Add( cbSizer, 0, wxEXPAND, 5 );
|
||||
SetSizer( sizer );
|
||||
@@ -90,13 +94,7 @@ DESIGN_BLOCK_PANE::DESIGN_BLOCK_PANE( SCH_EDIT_FRAME* aParent, const LIB_ID* aPr
|
||||
}
|
||||
|
||||
|
||||
DESIGN_BLOCK_PANE::~DESIGN_BLOCK_PANE()
|
||||
{
|
||||
m_frame->Unbind( EDA_LANG_CHANGED, &DESIGN_BLOCK_PANE::OnLanguageChanged, this );
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_PANE::setLabelsAndTooltips()
|
||||
void SCH_DESIGN_BLOCK_PANE::setLabelsAndTooltips()
|
||||
{
|
||||
if( m_repeatedPlacement )
|
||||
{
|
||||
@@ -121,18 +119,7 @@ void DESIGN_BLOCK_PANE::setLabelsAndTooltips()
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_PANE::OnLanguageChanged( wxCommandEvent& aEvent )
|
||||
{
|
||||
if( m_chooserPanel )
|
||||
m_chooserPanel->ShowChangedLanguage();
|
||||
|
||||
setLabelsAndTooltips();
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_PANE::OnCheckBox( wxCommandEvent& aEvent )
|
||||
void SCH_DESIGN_BLOCK_PANE::OnCheckBox( wxCommandEvent& aEvent )
|
||||
{
|
||||
if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
|
||||
{
|
||||
@@ -143,7 +130,7 @@ void DESIGN_BLOCK_PANE::OnCheckBox( wxCommandEvent& aEvent )
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_PANE::UpdateCheckboxes()
|
||||
void SCH_DESIGN_BLOCK_PANE::UpdateCheckboxes()
|
||||
{
|
||||
if( EESCHEMA_SETTINGS* cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() ) )
|
||||
{
|
||||
@@ -154,30 +141,6 @@ void DESIGN_BLOCK_PANE::UpdateCheckboxes()
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_PANE::SaveSettings()
|
||||
{
|
||||
m_chooserPanel->SaveSettings();
|
||||
}
|
||||
|
||||
|
||||
LIB_ID DESIGN_BLOCK_PANE::GetSelectedLibId( int* aUnit ) const
|
||||
{
|
||||
return m_chooserPanel->GetSelectedLibId( aUnit );
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_PANE::SelectLibId( const LIB_ID& aLibId )
|
||||
{
|
||||
m_chooserPanel->SelectLibId( aLibId );
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_PANE::RefreshLibs()
|
||||
{
|
||||
m_chooserPanel->RefreshLibs();
|
||||
}
|
||||
|
||||
|
||||
FILEDLG_IMPORT_SHEET_CONTENTS::FILEDLG_IMPORT_SHEET_CONTENTS( EESCHEMA_SETTINGS* aSettings ) :
|
||||
m_cbRepeatedPlacement( nullptr ),
|
||||
m_cbPlaceAsSheet( nullptr ),
|
||||
@@ -20,9 +20,10 @@
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
#ifndef DESIGN_BLOCK_PANE_H
|
||||
#define DESIGN_BLOCK_PANE_H
|
||||
#ifndef SCH_DESIGN_BLOCK_PANE_H
|
||||
#define SCH_DESIGN_BLOCK_PANE_H
|
||||
|
||||
#include <widgets/design_block_pane.h>
|
||||
#include <design_block_tree_model_adapter.h>
|
||||
#include <widgets/html_window.h>
|
||||
#include <widgets/wx_panel.h>
|
||||
@@ -35,40 +36,11 @@ class SCH_EDIT_FRAME;
|
||||
class PANEL_DESIGN_BLOCK_CHOOSER;
|
||||
|
||||
|
||||
class DESIGN_BLOCK_PANE : public WX_PANEL
|
||||
class SCH_DESIGN_BLOCK_PANE : public DESIGN_BLOCK_PANE
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create dialog to choose design_block.
|
||||
*
|
||||
* @param aParent a SCH_BASE_FRAME parent window.
|
||||
* @param aAllowFieldEdits if false, all functions that allow the user to edit fields
|
||||
* (currently just footprint selection) will not be available.
|
||||
* @param aShowFootprints if false, all footprint preview and selection features are
|
||||
* disabled. This forces aAllowFieldEdits false too.
|
||||
*/
|
||||
DESIGN_BLOCK_PANE( SCH_EDIT_FRAME* aParent, const LIB_ID* aPreselect,
|
||||
std::vector<LIB_ID>& aHistoryList );
|
||||
|
||||
~DESIGN_BLOCK_PANE() override;
|
||||
|
||||
void SaveSettings();
|
||||
|
||||
/**
|
||||
* To be called after this dialog returns from ShowModal().
|
||||
*
|
||||
* For multi-unit design_blocks, if the user selects the design_block itself rather than picking
|
||||
* an individual unit, 0 will be returned in aUnit.
|
||||
* Beware that this is an invalid unit number - this should be replaced with whatever
|
||||
* default is desired (usually 1).
|
||||
*
|
||||
* @param aUnit if not NULL, the selected unit is filled in here.
|
||||
* @return the #LIB_ID of the design_block that has been selected.
|
||||
*/
|
||||
LIB_ID GetSelectedLibId( int* aUnit = nullptr ) const;
|
||||
void SelectLibId( const LIB_ID& aLibId );
|
||||
|
||||
void RefreshLibs();
|
||||
SCH_DESIGN_BLOCK_PANE( SCH_EDIT_FRAME* aParent, const LIB_ID* aPreselect,
|
||||
std::vector<LIB_ID>& aHistoryList );
|
||||
|
||||
/* Handler for checkbox events */
|
||||
void OnCheckBox( wxCommandEvent& aEvent );
|
||||
@@ -77,24 +49,13 @@ public:
|
||||
void OnSaveSheetAsDesignBlock( wxCommandEvent& aEvent );
|
||||
void OnSaveSelectionAsDesignBlock( wxCommandEvent& aEvent );
|
||||
|
||||
void OnDeleteLibrary( wxCommandEvent& aEvent );
|
||||
void OnDeleteDesignBlock( wxCommandEvent& aEvent );
|
||||
|
||||
PANEL_DESIGN_BLOCK_CHOOSER* GetDesignBlockPanel() const { return m_chooserPanel; }
|
||||
protected:
|
||||
void setLabelsAndTooltips() override;
|
||||
|
||||
protected:
|
||||
void setLabelsAndTooltips();
|
||||
|
||||
virtual void OnLanguageChanged( wxCommandEvent& aEvent );
|
||||
|
||||
protected:
|
||||
PANEL_DESIGN_BLOCK_CHOOSER* m_chooserPanel;
|
||||
|
||||
wxCheckBox* m_repeatedPlacement;
|
||||
wxCheckBox* m_placeAsSheet;
|
||||
wxCheckBox* m_keepAnnotations;
|
||||
|
||||
SCH_EDIT_FRAME* m_frame;
|
||||
wxCheckBox* m_repeatedPlacement;
|
||||
wxCheckBox* m_placeAsSheet;
|
||||
wxCheckBox* m_keepAnnotations;
|
||||
};
|
||||
|
||||
|
||||
@@ -105,9 +66,9 @@ class FILEDLG_IMPORT_SHEET_CONTENTS : public wxFileDialogCustomizeHook
|
||||
public:
|
||||
FILEDLG_IMPORT_SHEET_CONTENTS( EESCHEMA_SETTINGS* aSettings );
|
||||
|
||||
virtual void AddCustomControls( wxFileDialogCustomize& customizer ) override;
|
||||
void AddCustomControls( wxFileDialogCustomize& customizer ) override;
|
||||
|
||||
virtual void TransferDataFromCustomControls() override;
|
||||
void TransferDataFromCustomControls() override;
|
||||
|
||||
private:
|
||||
EESCHEMA_SETTINGS* m_settings;
|
||||
+13
-11
@@ -17,7 +17,6 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "design_block_preview_widget.h"
|
||||
#include <schematic.h>
|
||||
#include <sch_sheet.h>
|
||||
#include <sch_view.h>
|
||||
@@ -35,13 +34,16 @@
|
||||
#include <eeschema_settings.h>
|
||||
#include <eeschema_helpers.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <widgets/sch_design_block_preview_widget.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
|
||||
DESIGN_BLOCK_PREVIEW_WIDGET::DESIGN_BLOCK_PREVIEW_WIDGET( wxWindow* aParent, bool aIncludeStatus,
|
||||
EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType ) :
|
||||
wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ),
|
||||
SCH_DESIGN_BLOCK_PREVIEW_WIDGET::SCH_DESIGN_BLOCK_PREVIEW_WIDGET( wxWindow* aParent,
|
||||
EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType,
|
||||
bool aIncludeStatus ) :
|
||||
DESIGN_BLOCK_PREVIEW_WIDGET( aParent ),
|
||||
m_preview( nullptr ),
|
||||
m_status( nullptr ),
|
||||
m_statusPanel( nullptr ),
|
||||
@@ -131,11 +133,11 @@ DESIGN_BLOCK_PREVIEW_WIDGET::DESIGN_BLOCK_PREVIEW_WIDGET( wxWindow* aParent, boo
|
||||
SetSizer( m_outerSizer );
|
||||
Layout();
|
||||
|
||||
Connect( wxEVT_SIZE, wxSizeEventHandler( DESIGN_BLOCK_PREVIEW_WIDGET::onSize ), nullptr, this );
|
||||
Connect( wxEVT_SIZE, wxSizeEventHandler( SCH_DESIGN_BLOCK_PREVIEW_WIDGET::onSize ), nullptr, this );
|
||||
}
|
||||
|
||||
|
||||
DESIGN_BLOCK_PREVIEW_WIDGET::~DESIGN_BLOCK_PREVIEW_WIDGET()
|
||||
SCH_DESIGN_BLOCK_PREVIEW_WIDGET::~SCH_DESIGN_BLOCK_PREVIEW_WIDGET()
|
||||
{
|
||||
if( m_previewItem )
|
||||
m_preview->GetView()->Remove( m_previewItem );
|
||||
@@ -144,7 +146,7 @@ DESIGN_BLOCK_PREVIEW_WIDGET::~DESIGN_BLOCK_PREVIEW_WIDGET()
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_PREVIEW_WIDGET::SetStatusText( wxString const& aText )
|
||||
void SCH_DESIGN_BLOCK_PREVIEW_WIDGET::SetStatusText( wxString const& aText )
|
||||
{
|
||||
wxCHECK( m_statusPanel, /* void */ );
|
||||
|
||||
@@ -155,7 +157,7 @@ void DESIGN_BLOCK_PREVIEW_WIDGET::SetStatusText( wxString const& aText )
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_PREVIEW_WIDGET::onSize( wxSizeEvent& aEvent )
|
||||
void SCH_DESIGN_BLOCK_PREVIEW_WIDGET::onSize( wxSizeEvent& aEvent )
|
||||
{
|
||||
if( m_previewItem )
|
||||
{
|
||||
@@ -167,7 +169,7 @@ void DESIGN_BLOCK_PREVIEW_WIDGET::onSize( wxSizeEvent& aEvent )
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_PREVIEW_WIDGET::fitOnDrawArea()
|
||||
void SCH_DESIGN_BLOCK_PREVIEW_WIDGET::fitOnDrawArea()
|
||||
{
|
||||
if( !m_previewItem )
|
||||
return;
|
||||
@@ -191,7 +193,7 @@ void DESIGN_BLOCK_PREVIEW_WIDGET::fitOnDrawArea()
|
||||
}
|
||||
|
||||
|
||||
void DESIGN_BLOCK_PREVIEW_WIDGET::DisplayDesignBlock( DESIGN_BLOCK* aDesignBlock )
|
||||
void SCH_DESIGN_BLOCK_PREVIEW_WIDGET::DisplayDesignBlock( DESIGN_BLOCK* aDesignBlock )
|
||||
{
|
||||
KIGFX::VIEW* view = m_preview->GetView();
|
||||
|
||||
@@ -202,7 +204,7 @@ void DESIGN_BLOCK_PREVIEW_WIDGET::DisplayDesignBlock( DESIGN_BLOCK* aDesignBlock
|
||||
m_previewItem = nullptr;
|
||||
}
|
||||
|
||||
if( aDesignBlock )
|
||||
if( aDesignBlock && wxFileExists( aDesignBlock->GetSchematicFile() ) )
|
||||
{
|
||||
m_previewItem = EESCHEMA_HELPERS::LoadSchematic( aDesignBlock->GetSchematicFile(),
|
||||
SCH_IO_MGR::SCH_KICAD, false, true );
|
||||
+10
-11
@@ -17,10 +17,11 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DESIGN_BLOCK_PREVIEW_WIDGET_H
|
||||
#define DESIGN_BLOCK_PREVIEW_WIDGET_H
|
||||
#ifndef SCH_DESIGN_BLOCK_PREVIEW_WIDGET_H
|
||||
#define SCH_DESIGN_BLOCK_PREVIEW_WIDGET_H
|
||||
|
||||
#include <wx/panel.h>
|
||||
#include <widgets/design_block_preview_widget.h>
|
||||
#include <kiway.h>
|
||||
#include <gal_display_options_common.h>
|
||||
#include <class_draw_panel_gal.h>
|
||||
@@ -34,29 +35,27 @@ class wxStaticText;
|
||||
class wxSizer;
|
||||
|
||||
|
||||
class DESIGN_BLOCK_PREVIEW_WIDGET : public wxPanel
|
||||
class SCH_DESIGN_BLOCK_PREVIEW_WIDGET : public DESIGN_BLOCK_PREVIEW_WIDGET
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Construct a symbol preview widget.
|
||||
* Construct a schematic design block preview widget.
|
||||
*
|
||||
* @param aParent - parent window
|
||||
* @param aCanvasType = the type of canvas (GAL_TYPE_OPENGL or GAL_TYPE_CAIRO only)
|
||||
*/
|
||||
DESIGN_BLOCK_PREVIEW_WIDGET( wxWindow* aParent, bool aIncludeStatus,
|
||||
EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType );
|
||||
SCH_DESIGN_BLOCK_PREVIEW_WIDGET( wxWindow* aParent, EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType, bool aIncludeStatus );
|
||||
|
||||
~DESIGN_BLOCK_PREVIEW_WIDGET() override;
|
||||
~SCH_DESIGN_BLOCK_PREVIEW_WIDGET() override;
|
||||
|
||||
/**
|
||||
* Set the contents of the status label and display it.
|
||||
*/
|
||||
void SetStatusText( const wxString& aText );
|
||||
void SetStatusText( const wxString& aText ) override;
|
||||
|
||||
/**
|
||||
* Set the currently displayed symbol.
|
||||
*/
|
||||
void DisplayDesignBlock( DESIGN_BLOCK* aDesignBlock );
|
||||
void DisplayDesignBlock( DESIGN_BLOCK* aDesignBlock ) override;
|
||||
|
||||
protected:
|
||||
void onSize( wxSizeEvent& aEvent );
|
||||
@@ -78,4 +77,4 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
#endif // DESIGN_BLOCK_PREVIEW_WIDGET_H
|
||||
#endif
|
||||
@@ -71,6 +71,14 @@ public:
|
||||
|
||||
DESIGN_BLOCK_IO_MGR::DESIGN_BLOCK_FILE_T GetFileType() { return type; }
|
||||
|
||||
/**
|
||||
* Attempt to reload the library.
|
||||
*
|
||||
* @return true if a reload was required
|
||||
* @throw IO_ERROR if the reload was unsuccessful.
|
||||
*/
|
||||
bool Refresh() override;
|
||||
|
||||
protected:
|
||||
DESIGN_BLOCK_LIB_TABLE_ROW( const DESIGN_BLOCK_LIB_TABLE_ROW& aRow ) :
|
||||
LIB_TABLE_ROW( aRow ),
|
||||
|
||||
@@ -135,6 +135,21 @@ public:
|
||||
std::vector<wxString> open_libs; ///< list of libraries the user has open in the tree.
|
||||
};
|
||||
|
||||
struct PANEL_DESIGN_BLOCK_CHOOSER
|
||||
{
|
||||
int sash_pos_h;
|
||||
int sash_pos_v;
|
||||
int width;
|
||||
int height;
|
||||
int sort_mode;
|
||||
bool repeated_placement;
|
||||
bool place_as_sheet;
|
||||
bool keep_annotations;
|
||||
|
||||
// For saving tree columns and widths
|
||||
LIB_TREE tree;
|
||||
};
|
||||
|
||||
struct PRINTING
|
||||
{
|
||||
bool background; ///< Whether or not to print background color.
|
||||
@@ -179,6 +194,8 @@ public:
|
||||
|
||||
FIND_REPLACE m_FindReplace;
|
||||
|
||||
PANEL_DESIGN_BLOCK_CHOOSER m_DesignBlockChooserPanel;
|
||||
|
||||
GRAPHICS m_Graphics;
|
||||
|
||||
COLOR_PICKER m_ColorPicker;
|
||||
|
||||
@@ -357,6 +357,7 @@ set( PCBNEW_CLASS_SRCS
|
||||
menubar_footprint_editor.cpp
|
||||
menubar_pcb_editor.cpp
|
||||
pcb_base_edit_frame.cpp
|
||||
pcb_design_block_utils.cpp
|
||||
pcb_layer_box_selector.cpp
|
||||
pcb_edit_frame.cpp
|
||||
pcb_plotter.cpp
|
||||
@@ -398,6 +399,7 @@ set( PCBNEW_CLASS_SRCS
|
||||
tools/item_modification_routine.cpp
|
||||
tools/pad_tool.cpp
|
||||
tools/pcb_control.cpp
|
||||
tools/pcb_design_block_control.cpp
|
||||
tools/pcb_picker_tool.cpp
|
||||
tools/pcb_selection.cpp
|
||||
tools/pcb_selection_conditions.cpp
|
||||
@@ -422,6 +424,8 @@ set( PCBNEW_CLASS_SRCS
|
||||
widgets/panel_footprint_chooser.cpp
|
||||
widgets/panel_selection_filter.cpp
|
||||
widgets/panel_selection_filter_base.cpp
|
||||
widgets/pcb_design_block_pane.cpp
|
||||
widgets/pcb_design_block_preview_widget.cpp
|
||||
widgets/pcb_properties_panel.cpp
|
||||
widgets/pcb_search_pane.cpp
|
||||
widgets/search_handlers.cpp
|
||||
|
||||
@@ -951,6 +951,12 @@ BOARD_DESIGN_SETTINGS& BOARD::GetDesignSettings() const
|
||||
}
|
||||
|
||||
|
||||
void BOARD::SetDesignSettings( const BOARD_DESIGN_SETTINGS& aSettings )
|
||||
{
|
||||
*m_designSettings = aSettings;
|
||||
}
|
||||
|
||||
|
||||
int BOARD::GetMaxClearanceValue() const
|
||||
{
|
||||
if( !m_maxClearanceValue.has_value() )
|
||||
|
||||
@@ -694,6 +694,7 @@ public:
|
||||
* @return the BOARD_DESIGN_SETTINGS for this BOARD
|
||||
*/
|
||||
BOARD_DESIGN_SETTINGS& GetDesignSettings() const;
|
||||
void SetDesignSettings( const BOARD_DESIGN_SETTINGS& aSettings );
|
||||
|
||||
BOARD_STACKUP GetStackupOrDefault() const;
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include <tools/pcb_actions.h>
|
||||
#include <tools/pcb_selection_tool.h>
|
||||
#include <netlist_reader/netlist_reader.h>
|
||||
#include <widgets/pcb_design_block_pane.h>
|
||||
#include <wx/log.h>
|
||||
|
||||
/* Execute a remote command sent via a socket on port KICAD_PCB_PORT_SERVICE_NUMBER
|
||||
@@ -718,6 +719,10 @@ void PCB_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
|
||||
GetToolManager()->RunAction( ACTIONS::pluginsReload );
|
||||
break;
|
||||
|
||||
case MAIL_RELOAD_LIB:
|
||||
m_designBlocksPane->RefreshLibs();
|
||||
break;
|
||||
|
||||
// many many others.
|
||||
default:
|
||||
;
|
||||
|
||||
+4
-8
@@ -441,7 +441,9 @@ bool PCB_EDIT_FRAME::Files_io_from_id( int id )
|
||||
{
|
||||
if( id == ID_COPY_BOARD_AS )
|
||||
{
|
||||
success = SavePcbCopy( filename, createProject );
|
||||
success = SavePcbCopy(
|
||||
EnsureFileExtension( filename, FILEEXT::KiCadPcbFileExtension ),
|
||||
createProject );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1124,7 +1126,7 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool addToHistory,
|
||||
|
||||
bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName, bool aCreateProject, bool aHeadless )
|
||||
{
|
||||
wxFileName pcbFileName( EnsureFileExtension( aFileName, FILEEXT::KiCadPcbFileExtension ) );
|
||||
wxFileName pcbFileName( aFileName );
|
||||
|
||||
if( !IsWritable( pcbFileName ) )
|
||||
{
|
||||
@@ -1183,12 +1185,6 @@ bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName, bool aCreateProject
|
||||
rulesFile.GetFullPath() ) );
|
||||
}
|
||||
|
||||
if( !aHeadless )
|
||||
{
|
||||
DisplayInfoMessage( this, wxString::Format( _( "Board copied to:\n%s" ),
|
||||
pcbFileName.GetFullPath() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -234,6 +234,10 @@ void PCB_EDIT_FRAME::doReCreateMenuBar()
|
||||
showHidePanels->Add( PCB_ACTIONS::showSearch, ACTION_MENU::CHECK );
|
||||
showHidePanels->Add( PCB_ACTIONS::showLayersManager, ACTION_MENU::CHECK );
|
||||
showHidePanels->Add( PCB_ACTIONS::showNetInspector, ACTION_MENU::CHECK );
|
||||
|
||||
if( ADVANCED_CFG::GetCfg().m_EnableDesignBlocks )
|
||||
showHidePanels->Add( PCB_ACTIONS::showDesignBlockPanel, ACTION_MENU::CHECK, _( "Design Blocks" ) );
|
||||
|
||||
viewMenu->Add( showHidePanels );
|
||||
|
||||
viewMenu->AppendSeparator();
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <pgm_base.h>
|
||||
#include <kiway.h>
|
||||
#include <board_commit.h>
|
||||
#include <design_block.h>
|
||||
#include <design_block_lib_table.h>
|
||||
#include <widgets/pcb_design_block_pane.h>
|
||||
#include <pcb_edit_frame.h>
|
||||
#include <pcb_io/pcb_io.h>
|
||||
#include <pcb_io/pcb_io_mgr.h>
|
||||
#include <wx/choicdlg.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/textdlg.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
#include <paths.h>
|
||||
#include <env_paths.h>
|
||||
#include <common.h>
|
||||
#include <confirm.h>
|
||||
#include <kidialog.h>
|
||||
#include <locale_io.h>
|
||||
#include <netinfo.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tools/pcb_selection_tool.h>
|
||||
#include <dialogs/dialog_design_block_properties.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
bool checkOverwrite( wxWindow* aFrame, wxString& libname, wxString& newName )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Design block '%s' already exists in library '%s'." ),
|
||||
newName.GetData(), libname.GetData() );
|
||||
|
||||
if( OKOrCancelDialog( aFrame, _( "Confirmation" ), msg, _( "Overwrite existing design block?" ),
|
||||
_( "Overwrite" ) )
|
||||
!= wxID_OK )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PCB_EDIT_FRAME::saveBoardAsFile( BOARD* aBoard, const wxString& aFileName, bool aHeadless )
|
||||
{
|
||||
// Ensure the "C" locale is temporary set, before saving any file
|
||||
// It also avoid wxWidget alerts about locale issues, later, when using Python 3
|
||||
LOCALE_IO dummy;
|
||||
|
||||
wxFileName pcbFileName( aFileName );
|
||||
|
||||
if( !IsWritable( pcbFileName ) )
|
||||
{
|
||||
if( !aHeadless )
|
||||
{
|
||||
DisplayError( this,
|
||||
wxString::Format( _( "Insufficient permissions to write file '%s'." ),
|
||||
pcbFileName.GetFullPath() ) );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( PCB_IO_MGR::KICAD_SEXP ) );
|
||||
|
||||
wxASSERT( pcbFileName.IsAbsolute() );
|
||||
|
||||
pi->SaveBoard( pcbFileName.GetFullPath(), aBoard, nullptr );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
if( !aHeadless )
|
||||
{
|
||||
DisplayError( this, wxString::Format( _( "Error saving board file '%s'.\n%s" ),
|
||||
pcbFileName.GetFullPath(), ioe.What() ) );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PCB_EDIT_FRAME::SaveBoardAsDesignBlock( const wxString& aLibraryName )
|
||||
{
|
||||
// Make sure the user has selected a library to save into
|
||||
if( m_designBlocksPane->GetSelectedLibId().GetLibNickname().empty() )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Please select a library to save the design block to." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
DESIGN_BLOCK blk;
|
||||
wxFileName fn = wxFileNameFromPath( GetBoard()->GetFileName() );
|
||||
|
||||
blk.SetLibId( LIB_ID( aLibraryName, fn.GetName() ) );
|
||||
|
||||
DIALOG_DESIGN_BLOCK_PROPERTIES dlg( this, &blk );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return false;
|
||||
|
||||
wxString libName = blk.GetLibId().GetLibNickname();
|
||||
wxString newName = blk.GetLibId().GetLibItemName();
|
||||
|
||||
if( Prj().DesignBlockLibs()->DesignBlockExists( libName, newName )
|
||||
&& !checkOverwrite( this, libName, newName ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save a temporary copy of the schematic file, as the plugin is just going to move it
|
||||
wxString tempFile = wxFileName::CreateTempFileName( "design_block" );
|
||||
|
||||
if( !SavePcbCopy( tempFile, false, false ) )
|
||||
{
|
||||
DisplayErrorMessage( this,
|
||||
_( "Error saving temporary board file to create design block." ) );
|
||||
wxRemoveFile( tempFile );
|
||||
return false;
|
||||
}
|
||||
|
||||
blk.SetBoardFile( tempFile );
|
||||
|
||||
bool success = false;
|
||||
|
||||
try
|
||||
{
|
||||
success = Prj().DesignBlockLibs()->DesignBlockSave( aLibraryName, &blk )
|
||||
== DESIGN_BLOCK_LIB_TABLE::SAVE_OK;
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayError( this, ioe.What() );
|
||||
}
|
||||
|
||||
// Clean up the temporary file
|
||||
wxRemoveFile( tempFile );
|
||||
|
||||
m_designBlocksPane->RefreshLibs();
|
||||
m_designBlocksPane->SelectLibId( blk.GetLibId() );
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool PCB_EDIT_FRAME::SaveSelectionAsDesignBlock( const wxString& aLibraryName )
|
||||
{
|
||||
// Make sure the user has selected a library to save into
|
||||
if( m_designBlocksPane->GetSelectedLibId().GetLibNickname().empty() )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Please select a library to save the design block to." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get all selected items
|
||||
PCB_SELECTION selection = m_toolManager->GetTool<PCB_SELECTION_TOOL>()->GetSelection();
|
||||
|
||||
if( selection.Empty() )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Please select some items to save as a design block." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
DESIGN_BLOCK blk;
|
||||
wxFileName fn = wxFileNameFromPath( GetBoard()->GetFileName() );
|
||||
|
||||
blk.SetLibId( LIB_ID( aLibraryName, fn.GetName() ) );
|
||||
|
||||
DIALOG_DESIGN_BLOCK_PROPERTIES dlg( this, &blk );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return false;
|
||||
|
||||
wxString libName = blk.GetLibId().GetLibNickname();
|
||||
wxString newName = blk.GetLibId().GetLibItemName();
|
||||
|
||||
if( Prj().DesignBlockLibs()->DesignBlockExists( libName, newName )
|
||||
&& !checkOverwrite( this, libName, newName ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a temporary board
|
||||
BOARD* tempBoard = new BOARD();
|
||||
tempBoard->SetDesignSettings( GetBoard()->GetDesignSettings() );
|
||||
tempBoard->SetProject( &Prj(), true );
|
||||
tempBoard->SynchronizeProperties();
|
||||
|
||||
// Copy all net info into the new board
|
||||
for( NETINFO_ITEM* netInfo : GetBoard()->GetNetInfo() )
|
||||
{
|
||||
EDA_ITEM* copy = netInfo->Clone();
|
||||
tempBoard->Add( static_cast<BOARD_ITEM*>( copy ), ADD_MODE::APPEND, false );
|
||||
}
|
||||
|
||||
// Copy the selected items to the temporary board
|
||||
for( EDA_ITEM* item : selection )
|
||||
{
|
||||
EDA_ITEM* copy = item->Clone();
|
||||
tempBoard->Add( static_cast<BOARD_ITEM*>( copy ), ADD_MODE::APPEND, false );
|
||||
}
|
||||
|
||||
// Rebuild connectivity, remove any unused nets
|
||||
tempBoard->BuildListOfNets();
|
||||
tempBoard->BuildConnectivity();
|
||||
tempBoard->RemoveUnusedNets( nullptr );
|
||||
|
||||
wxString tempFile = wxFileName::CreateTempFileName( "design_block" );
|
||||
|
||||
if( !saveBoardAsFile( tempBoard, tempFile, false ) )
|
||||
{
|
||||
DisplayErrorMessage( this,
|
||||
_( "Error saving temporary board file to create design block." ) );
|
||||
wxRemoveFile( tempFile );
|
||||
return false;
|
||||
}
|
||||
|
||||
blk.SetBoardFile( tempFile );
|
||||
|
||||
bool success = false;
|
||||
|
||||
try
|
||||
{
|
||||
success = Prj().DesignBlockLibs()->DesignBlockSave( aLibraryName, &blk )
|
||||
== DESIGN_BLOCK_LIB_TABLE::SAVE_OK;
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
DisplayError( this, ioe.What() );
|
||||
}
|
||||
|
||||
// Clean up the temporary file
|
||||
wxRemoveFile( tempFile );
|
||||
|
||||
m_designBlocksPane->RefreshLibs();
|
||||
m_designBlocksPane->SelectLibId( blk.GetLibId() );
|
||||
|
||||
return success;
|
||||
}
|
||||
@@ -81,6 +81,7 @@
|
||||
#include <tools/convert_tool.h>
|
||||
#include <tools/drawing_tool.h>
|
||||
#include <tools/pcb_control.h>
|
||||
#include <tools/pcb_design_block_control.h>
|
||||
#include <tools/board_editor_control.h>
|
||||
#include <tools/board_inspection_tool.h>
|
||||
#include <tools/pcb_editor_conditions.h>
|
||||
@@ -104,6 +105,7 @@
|
||||
#include <dialog_drc.h> // for DIALOG_DRC_WINDOW_NAME definition
|
||||
#include <ratsnest/ratsnest_view_item.h>
|
||||
#include <widgets/appearance_controls.h>
|
||||
#include <widgets/pcb_design_block_pane.h>
|
||||
#include <widgets/pcb_search_pane.h>
|
||||
#include <widgets/wx_infobar.h>
|
||||
#include <widgets/panel_selection_filter.h>
|
||||
@@ -208,6 +210,7 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
m_inspectConstraintsDlg( nullptr ),
|
||||
m_footprintDiffDlg( nullptr ),
|
||||
m_boardSetupDlg( nullptr ),
|
||||
m_designBlocksPane( nullptr ),
|
||||
m_importProperties( nullptr ),
|
||||
m_eventCounterTimer( nullptr )
|
||||
{
|
||||
@@ -293,6 +296,7 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
m_appearancePanel = new APPEARANCE_CONTROLS( this, GetCanvas() );
|
||||
m_searchPane = new PCB_SEARCH_PANE( this );
|
||||
m_netInspectorPanel = new PCB_NET_INSPECTOR_PANEL( this, this );
|
||||
m_designBlocksPane = new PCB_DESIGN_BLOCK_PANE( this, nullptr, m_designBlockHistoryList );
|
||||
|
||||
m_auimgr.SetManagedWindow( this );
|
||||
|
||||
@@ -337,6 +341,20 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
.FloatingSize( FromDIP( 180 ), -1 )
|
||||
.CloseButton( false ) );
|
||||
|
||||
m_auimgr.AddPane( m_designBlocksPane, EDA_PANE().Name( DesignBlocksPaneName() )
|
||||
.Right().Layer( 5 )
|
||||
.Caption( _( "Design Blocks" ) )
|
||||
.CaptionVisible( true )
|
||||
.PaneBorder( true )
|
||||
.TopDockable( false )
|
||||
.BottomDockable( false )
|
||||
.CloseButton( true )
|
||||
.MinSize( FromDIP( wxSize( 240, 60 ) ) )
|
||||
.BestSize( FromDIP( wxSize( 300, 200 ) ) )
|
||||
.FloatingSize( FromDIP( wxSize( 800, 600 ) ) )
|
||||
.FloatingPosition( FromDIP( wxPoint( 50, 200 ) ) )
|
||||
.Show( true ) );
|
||||
|
||||
m_auimgr.AddPane( m_propertiesPanel, EDA_PANE().Name( PropertiesPaneName() )
|
||||
.Left().Layer( 5 )
|
||||
.Caption( _( "Properties" ) ).PaneBorder( false )
|
||||
@@ -374,6 +392,7 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
m_auimgr.GetPane( PropertiesPaneName() ).Show( GetPcbNewSettings()->m_AuiPanels.show_properties );
|
||||
m_auimgr.GetPane( NetInspectorPanelName() ).Show( m_show_net_inspector );
|
||||
m_auimgr.GetPane( SearchPaneName() ).Show( m_show_search );
|
||||
m_auimgr.GetPane( DesignBlocksPaneName() ).Show( GetPcbNewSettings()->m_AuiPanels.design_blocks_show );
|
||||
|
||||
// The selection filter doesn't need to grow in the vertical direction when docked
|
||||
m_auimgr.GetPane( "SelectionFilter" ).dock_proportion = 0;
|
||||
@@ -413,6 +432,13 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
}
|
||||
|
||||
m_appearancePanel->SetTabIndex( settings->m_AuiPanels.appearance_panel_tab );
|
||||
|
||||
if( settings->m_AuiPanels.design_blocks_show )
|
||||
{
|
||||
wxAuiPaneInfo& designBlocksPane = m_auimgr.GetPane( DesignBlocksPaneName() );
|
||||
SetAuiPaneSize( m_auimgr, designBlocksPane,
|
||||
settings->m_AuiPanels.design_blocks_panel_docked_width, -1 );
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@@ -741,6 +767,7 @@ void PCB_EDIT_FRAME::setupTools()
|
||||
m_toolManager->RegisterTool( new DRAWING_TOOL );
|
||||
m_toolManager->RegisterTool( new PCB_POINT_EDITOR );
|
||||
m_toolManager->RegisterTool( new PCB_CONTROL );
|
||||
m_toolManager->RegisterTool( new PCB_DESIGN_BLOCK_CONTROL );
|
||||
m_toolManager->RegisterTool( new BOARD_EDITOR_CONTROL );
|
||||
m_toolManager->RegisterTool( new BOARD_INSPECTION_TOOL );
|
||||
m_toolManager->RegisterTool( new BOARD_REANNOTATE_TOOL );
|
||||
@@ -860,6 +887,13 @@ void PCB_EDIT_FRAME::setupUIConditions()
|
||||
|
||||
mgr->SetConditions( ACTIONS::toggleBoundingBoxes, CHECK( cond.BoundingBoxes() ) );
|
||||
|
||||
auto hasElements =
|
||||
[ this ] ( const SELECTION& aSel )
|
||||
{
|
||||
return GetBoard() &&
|
||||
( !GetBoard()->IsEmpty() || !SELECTION_CONDITIONS::Idle( aSel ) );
|
||||
};
|
||||
|
||||
auto constrainedDrawingModeCond =
|
||||
[this]( const SELECTION& )
|
||||
{
|
||||
@@ -896,6 +930,12 @@ void PCB_EDIT_FRAME::setupUIConditions()
|
||||
return m_auimgr.GetPane( SearchPaneName() ).IsShown();
|
||||
};
|
||||
|
||||
auto designBlockCond =
|
||||
[ this ] (const SELECTION& aSel )
|
||||
{
|
||||
return m_auimgr.GetPane( DesignBlocksPaneName() ).IsShown();
|
||||
};
|
||||
|
||||
auto highContrastCond =
|
||||
[this] ( const SELECTION& )
|
||||
{
|
||||
@@ -939,6 +979,10 @@ void PCB_EDIT_FRAME::setupUIConditions()
|
||||
mgr->SetConditions( PCB_ACTIONS::showProperties, CHECK( propertiesCond ) );
|
||||
mgr->SetConditions( PCB_ACTIONS::showNetInspector, CHECK( netInspectorCond ) );
|
||||
mgr->SetConditions( PCB_ACTIONS::showSearch, CHECK( searchPaneCond ) );
|
||||
mgr->SetConditions( PCB_ACTIONS::showDesignBlockPanel, CHECK( designBlockCond ) );
|
||||
|
||||
mgr->SetConditions( PCB_ACTIONS::saveBoardAsDesignBlock, ENABLE( hasElements ) );
|
||||
mgr->SetConditions( PCB_ACTIONS::saveSelectionAsDesignBlock, ENABLE( SELECTION_CONDITIONS::NotEmpty ) );
|
||||
|
||||
auto isArcKeepCenterMode =
|
||||
[this]( const SELECTION& )
|
||||
@@ -1049,6 +1093,7 @@ void PCB_EDIT_FRAME::setupUIConditions()
|
||||
CURRENT_EDIT_TOOL( ACTIONS::embeddedFiles );
|
||||
CURRENT_EDIT_TOOL( ACTIONS::deleteTool );
|
||||
CURRENT_EDIT_TOOL( PCB_ACTIONS::placeFootprint );
|
||||
CURRENT_EDIT_TOOL( PCB_ACTIONS::placeDesignBlock );
|
||||
CURRENT_EDIT_TOOL( PCB_ACTIONS::routeSingleTrack);
|
||||
CURRENT_EDIT_TOOL( PCB_ACTIONS::routeDiffPair );
|
||||
CURRENT_EDIT_TOOL( PCB_ACTIONS::tuneSingleTrack);
|
||||
@@ -1476,6 +1521,19 @@ void PCB_EDIT_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
|
||||
cfg->m_AuiPanels.appearance_expand_layer_display = m_appearancePanel->IsLayerOptionsExpanded();
|
||||
cfg->m_AuiPanels.appearance_expand_net_display = m_appearancePanel->IsNetOptionsExpanded();
|
||||
}
|
||||
|
||||
wxAuiPaneInfo& designBlocksPane = m_auimgr.GetPane( DesignBlocksPaneName() );
|
||||
cfg->m_AuiPanels.design_blocks_show = designBlocksPane.IsShown();
|
||||
|
||||
if( designBlocksPane.IsDocked() )
|
||||
cfg->m_AuiPanels.design_blocks_panel_docked_width = m_designBlocksPane->GetSize().x;
|
||||
else
|
||||
{
|
||||
cfg->m_AuiPanels.design_blocks_panel_float_height = designBlocksPane.floating_size.y;
|
||||
cfg->m_AuiPanels.design_blocks_panel_float_width = designBlocksPane.floating_size.x;
|
||||
}
|
||||
|
||||
m_designBlocksPane->SaveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ class BOARD_NETLIST_UPDATER;
|
||||
class ACTION_MENU;
|
||||
class TOOL_ACTION;
|
||||
class DIALOG_BOARD_SETUP;
|
||||
class PCB_DESIGN_BLOCK_PANE;
|
||||
|
||||
#ifdef KICAD_IPC_API
|
||||
class KICAD_API_SERVER;
|
||||
@@ -314,6 +315,8 @@ public:
|
||||
|
||||
void ToggleSearch();
|
||||
|
||||
void ToggleLibraryTree() override;
|
||||
|
||||
/**
|
||||
* Create an ASCII footprint position file.
|
||||
*
|
||||
@@ -461,6 +464,12 @@ public:
|
||||
*/
|
||||
void RecreateCmpFileFromBoard( wxCommandEvent& aEvent );
|
||||
|
||||
bool SaveBoardAsDesignBlock( const wxString& aLibraryName );
|
||||
|
||||
bool SaveSelectionAsDesignBlock( const wxString& aLibraryName );
|
||||
|
||||
PCB_DESIGN_BLOCK_PANE* GetDesignBlockPane() const { return m_designBlocksPane; }
|
||||
|
||||
/**
|
||||
* Save footprints in a library:
|
||||
*
|
||||
@@ -823,6 +832,18 @@ protected:
|
||||
bool importFile( const wxString& aFileName, int aFileType,
|
||||
const std::map<std::string, UTF8>* aProperties = nullptr );
|
||||
|
||||
/**
|
||||
* @brief Save a board object to a file
|
||||
*
|
||||
* @param aBoard The board object to save
|
||||
* @param aFileName The file name to save the board to
|
||||
* @param aHeadless If true, suppresses informational output (e.g. to be used from the API)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
bool saveBoardAsFile( BOARD* aBoard, const wxString& aFileName, bool aHeadless = false );
|
||||
|
||||
|
||||
bool canCloseWindow( wxCloseEvent& aCloseEvent ) override;
|
||||
void doCloseWindow() override;
|
||||
|
||||
@@ -877,6 +898,9 @@ private:
|
||||
DIALOG_BOOK_REPORTER* m_footprintDiffDlg;
|
||||
DIALOG_BOARD_SETUP* m_boardSetupDlg;
|
||||
|
||||
std::vector<LIB_ID> m_designBlockHistoryList;
|
||||
PCB_DESIGN_BLOCK_PANE* m_designBlocksPane;
|
||||
|
||||
const std::map<std::string, UTF8>* m_importProperties; // Properties used for non-KiCad import.
|
||||
|
||||
/**
|
||||
|
||||
@@ -135,6 +135,18 @@ PCBNEW_SETTINGS::PCBNEW_SETTINGS()
|
||||
m_params.emplace_back( new PARAM<bool>( "aui.show_net_inspector",
|
||||
&m_AuiPanels.show_net_inspector, false ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<bool>( "aui.design_blocks_show",
|
||||
&m_AuiPanels.design_blocks_show, false ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "aui.design_blocks_panel_docked_width",
|
||||
&m_AuiPanels.design_blocks_panel_docked_width, -1 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "aui.design_blocks_panel_float_width",
|
||||
&m_AuiPanels.design_blocks_panel_float_width, -1 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "aui.design_blocks_panel_float_height",
|
||||
&m_AuiPanels.design_blocks_panel_float_height, -1 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "footprint_chooser.width",
|
||||
&m_FootprintChooser.width, -1 ) );
|
||||
|
||||
|
||||
@@ -150,6 +150,10 @@ public:
|
||||
bool show_properties;
|
||||
bool show_search;
|
||||
bool show_net_inspector;
|
||||
bool design_blocks_show;
|
||||
int design_blocks_panel_docked_width;
|
||||
int design_blocks_panel_float_width;
|
||||
int design_blocks_panel_float_height;
|
||||
};
|
||||
|
||||
struct DIALOG_CLEANUP
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include <tools/pcb_actions.h>
|
||||
#include <tools/pcb_selection_tool.h>
|
||||
#include <widgets/appearance_controls.h>
|
||||
#include <widgets/pcb_design_block_pane.h>
|
||||
#include <widgets/layer_box_selector.h>
|
||||
#include <widgets/layer_presentation.h>
|
||||
#include <widgets/pcb_properties_panel.h>
|
||||
@@ -835,3 +836,45 @@ void PCB_EDIT_FRAME::OnUpdateLayerSelectBox( wxUpdateUIEvent& aEvent )
|
||||
if( m_SelLayerBox->GetLayerSelection() != GetActiveLayer() )
|
||||
m_SelLayerBox->SetLayerSelection( GetActiveLayer() );
|
||||
}
|
||||
|
||||
|
||||
void PCB_EDIT_FRAME::ToggleLibraryTree()
|
||||
{
|
||||
PCBNEW_SETTINGS* cfg = GetPcbNewSettings();
|
||||
|
||||
wxCHECK( cfg, /* void */ );
|
||||
|
||||
wxAuiPaneInfo& db_library_pane = m_auimgr.GetPane( DesignBlocksPaneName() );
|
||||
|
||||
db_library_pane.Show( !db_library_pane.IsShown() );
|
||||
|
||||
if( db_library_pane.IsShown() )
|
||||
{
|
||||
if( db_library_pane.IsFloating() )
|
||||
{
|
||||
db_library_pane.FloatingSize( cfg->m_AuiPanels.design_blocks_panel_float_width,
|
||||
cfg->m_AuiPanels.design_blocks_panel_float_height );
|
||||
m_auimgr.Update();
|
||||
}
|
||||
else if( cfg->m_AuiPanels.design_blocks_panel_docked_width > 0 )
|
||||
{
|
||||
// SetAuiPaneSize also updates m_auimgr
|
||||
SetAuiPaneSize( m_auimgr, db_library_pane,
|
||||
cfg->m_AuiPanels.design_blocks_panel_docked_width, -1 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( db_library_pane.IsFloating() )
|
||||
{
|
||||
cfg->m_AuiPanels.design_blocks_panel_float_width = db_library_pane.floating_size.x;
|
||||
cfg->m_AuiPanels.design_blocks_panel_float_height = db_library_pane.floating_size.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
cfg->m_AuiPanels.design_blocks_panel_docked_width = m_designBlocksPane->GetSize().x;
|
||||
}
|
||||
|
||||
m_auimgr.Update();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -709,6 +709,13 @@ int BOARD_EDITOR_CONTROL::ToggleNetInspector( const TOOL_EVENT& aEvent )
|
||||
}
|
||||
|
||||
|
||||
int BOARD_EDITOR_CONTROL::ToggleLibraryTree( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
getEditFrame<PCB_EDIT_FRAME>()->ToggleLibraryTree();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int BOARD_EDITOR_CONTROL::ToggleSearch( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
getEditFrame<PCB_EDIT_FRAME>()->ToggleSearch();
|
||||
@@ -1743,6 +1750,7 @@ void BOARD_EDITOR_CONTROL::setTransitions()
|
||||
Go( &BOARD_EDITOR_CONTROL::ToggleLayersManager, PCB_ACTIONS::showLayersManager.MakeEvent() );
|
||||
Go( &BOARD_EDITOR_CONTROL::ToggleProperties, ACTIONS::showProperties.MakeEvent() );
|
||||
Go( &BOARD_EDITOR_CONTROL::ToggleNetInspector, PCB_ACTIONS::showNetInspector.MakeEvent() );
|
||||
Go( &BOARD_EDITOR_CONTROL::ToggleLibraryTree, PCB_ACTIONS::showDesignBlockPanel.MakeEvent() );
|
||||
Go( &BOARD_EDITOR_CONTROL::ToggleSearch, PCB_ACTIONS::showSearch.MakeEvent() );
|
||||
Go( &BOARD_EDITOR_CONTROL::TogglePythonConsole, PCB_ACTIONS::showPythonConsole.MakeEvent() );
|
||||
Go( &BOARD_EDITOR_CONTROL::RepairBoard, PCB_ACTIONS::repairBoard.MakeEvent() );
|
||||
|
||||
@@ -82,6 +82,7 @@ public:
|
||||
int ToggleNetInspector( const TOOL_EVENT& aEvent );
|
||||
int ToggleSearch( const TOOL_EVENT& aEvent );
|
||||
int TogglePythonConsole( const TOOL_EVENT& aEvent );
|
||||
int ToggleLibraryTree( const TOOL_EVENT& aEvent );
|
||||
|
||||
// Track & via size control
|
||||
int TrackWidthInc( const TOOL_EVENT& aEvent );
|
||||
|
||||
@@ -421,6 +421,51 @@ TOOL_ACTION PCB_ACTIONS::runDRC( TOOL_ACTION_ARGS()
|
||||
.Tooltip( _( "Show the design rules checker window" ) )
|
||||
.Icon( BITMAPS::erc ) );
|
||||
|
||||
// PCB_DESIGN_BLOCK_CONTROL
|
||||
TOOL_ACTION PCB_ACTIONS::placeDesignBlock( TOOL_ACTION_ARGS()
|
||||
.Name( "pcbnew.InteractiveDrawing.placeDesignBlock" )
|
||||
.Scope( AS_GLOBAL )
|
||||
.DefaultHotkey( MD_SHIFT + 'B' )
|
||||
.FriendlyName( _( "Place Design Block" ) )
|
||||
.Tooltip( _( "Add selected design block to current board" ) )
|
||||
.Icon( BITMAPS::add_component )
|
||||
.Flags( AF_ACTIVATE )
|
||||
.Parameter<DESIGN_BLOCK*>( nullptr ) );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::showDesignBlockPanel( TOOL_ACTION_ARGS()
|
||||
.Name( "pcbnew.PcbDesignBlockControl.showDesignBlockPanel" )
|
||||
.Scope( AS_GLOBAL )
|
||||
.FriendlyName( _( "Design Blocks" ) )
|
||||
.Tooltip( _( "Show/hide design blocks library" ) )
|
||||
.Icon( BITMAPS::search_tree ) );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::saveBoardAsDesignBlock( TOOL_ACTION_ARGS()
|
||||
.Name( "pcbnew.PcbDesignBlockControl.saveBoardAsDesignBlock" )
|
||||
.Scope( AS_GLOBAL )
|
||||
.FriendlyName( _( "Save Current Board as Design Block..." ) )
|
||||
.Tooltip( _( "Create a new design block from the current board" ) )
|
||||
.Icon( BITMAPS::new_component ) );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::saveSelectionAsDesignBlock( TOOL_ACTION_ARGS()
|
||||
.Name( "pcbnew.PcbDesignBlockControl.saveSelectionAsDesignBlock" )
|
||||
.Scope( AS_GLOBAL )
|
||||
.FriendlyName( _( "Save Selection as Design Block..." ) )
|
||||
.Tooltip( _( "Create a new design block from the current selection" ) )
|
||||
.Icon( BITMAPS::new_component ) );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::deleteDesignBlock( TOOL_ACTION_ARGS()
|
||||
.Name( "pcbnew.PcbDesignBlockControl.saveDeleteDesignBlock" )
|
||||
.Scope( AS_GLOBAL )
|
||||
.FriendlyName( _( "Delete Design Block" ) )
|
||||
.Tooltip( _( "Remove the selected design block from its library" ) )
|
||||
.Icon( BITMAPS::trash ) );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::editDesignBlockProperties( TOOL_ACTION_ARGS()
|
||||
.Name( "pcbnew.PcbDesignBlockControl.editDesignBlockProperties" )
|
||||
.Scope( AS_GLOBAL )
|
||||
.FriendlyName( _( "Properties..." ) )
|
||||
.Tooltip( _( "Edit properies of design block" ) )
|
||||
.Icon( BITMAPS::edit ) );
|
||||
|
||||
// EDIT_TOOL
|
||||
//
|
||||
|
||||
@@ -39,6 +39,7 @@ enum class ZONE_MODE
|
||||
GRAPHIC_POLYGON
|
||||
};
|
||||
|
||||
class DESIGN_BLOCK;
|
||||
|
||||
/**
|
||||
* Gather all the actions that are shared by tools.
|
||||
@@ -456,6 +457,14 @@ public:
|
||||
static TOOL_ACTION showPythonConsole;
|
||||
static TOOL_ACTION zonesManager;
|
||||
|
||||
// Design Block management
|
||||
static TOOL_ACTION placeDesignBlock;
|
||||
static TOOL_ACTION showDesignBlockPanel;
|
||||
static TOOL_ACTION saveBoardAsDesignBlock;
|
||||
static TOOL_ACTION saveSelectionAsDesignBlock;
|
||||
static TOOL_ACTION deleteDesignBlock;
|
||||
static TOOL_ACTION editDesignBlockProperties;
|
||||
|
||||
// Footprint editor tools
|
||||
|
||||
// We don't use ACTION::new here because we need to distinguish between New Library
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <board_design_settings.h>
|
||||
#include <board_item.h>
|
||||
#include <clipboard.h>
|
||||
#include <design_block.h>
|
||||
#include <dialogs/dialog_paste_special.h>
|
||||
#include <pcb_dimension.h>
|
||||
#include <gal/graphics_abstraction_layer.h>
|
||||
@@ -68,6 +69,7 @@
|
||||
#include <footprint_edit_frame.h>
|
||||
#include <footprint_editor_settings.h>
|
||||
#include <widgets/appearance_controls.h>
|
||||
#include <widgets/pcb_design_block_pane.h>
|
||||
#include <widgets/wx_progress_reporters.h>
|
||||
#include <widgets/wx_infobar.h>
|
||||
#include <wx/hyperlink.h>
|
||||
@@ -1265,6 +1267,48 @@ int PCB_CONTROL::AppendBoardFromFile( const TOOL_EVENT& aEvent )
|
||||
}
|
||||
|
||||
|
||||
int PCB_CONTROL::AppendDesignBlock( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
|
||||
|
||||
if( !editFrame )
|
||||
return 1;
|
||||
|
||||
DESIGN_BLOCK* designBlock = nullptr;
|
||||
|
||||
if( !editFrame->GetDesignBlockPane()->GetSelectedLibId().IsValid() )
|
||||
return 1;
|
||||
|
||||
|
||||
designBlock = editFrame->GetDesignBlockPane()->GetDesignBlock(
|
||||
editFrame->GetDesignBlockPane()->GetSelectedLibId(), true, true );
|
||||
|
||||
if( !designBlock || designBlock->GetBoardFile().IsEmpty() )
|
||||
return 1;
|
||||
|
||||
|
||||
PCB_IO_MGR::PCB_FILE_T pluginType = PCB_IO_MGR::KICAD_SEXP;
|
||||
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( pluginType ) );
|
||||
|
||||
if( !pi )
|
||||
return 1;
|
||||
|
||||
bool repeatPlacement = false;
|
||||
|
||||
if( APP_SETTINGS_BASE* cfg = editFrame->config() )
|
||||
repeatPlacement = cfg->m_DesignBlockChooserPanel.repeated_placement;
|
||||
|
||||
int ret = 0;
|
||||
|
||||
do
|
||||
{
|
||||
ret = AppendBoard( *pi, designBlock->GetBoardFile() );
|
||||
} while( repeatPlacement && ret == 0 );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
static void moveUnflaggedItems( const std::deque<T>& aList, std::vector<BOARD_ITEM*>& aTarget,
|
||||
bool aIsNew )
|
||||
@@ -1436,7 +1480,7 @@ bool PCB_CONTROL::placeBoardItems( BOARD_COMMIT* aCommit, std::vector<BOARD_ITEM
|
||||
}
|
||||
|
||||
|
||||
int PCB_CONTROL::AppendBoard( PCB_IO& pi, wxString& fileName )
|
||||
int PCB_CONTROL::AppendBoard( PCB_IO& pi, const wxString& fileName )
|
||||
{
|
||||
PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
|
||||
|
||||
@@ -1544,15 +1588,67 @@ int PCB_CONTROL::AppendBoard( PCB_IO& pi, wxString& fileName )
|
||||
brd->SetEnabledLayers( enabledLayers );
|
||||
brd->SetVisibleLayers( enabledLayers );
|
||||
|
||||
int ret = 0;
|
||||
|
||||
bool placeAsGroup = editFrame->config()
|
||||
? editFrame->config()->m_DesignBlockChooserPanel.place_as_sheet
|
||||
: false;
|
||||
|
||||
if( placeBoardItems( &commit, brd, false, false /* Don't reannotate dupes on Append Board */ ) )
|
||||
{
|
||||
commit.Push( _( "Append Board" ) );
|
||||
|
||||
if( placeAsGroup )
|
||||
{
|
||||
BOARD_COMMIT grpCommit( m_toolMgr );
|
||||
PCB_GROUP* group = new PCB_GROUP( brd );
|
||||
|
||||
// Get the selection tool selection
|
||||
PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool<PCB_SELECTION_TOOL>();
|
||||
PCB_SELECTION selection = selTool->GetSelection();
|
||||
|
||||
for( EDA_ITEM* eda_item : selection )
|
||||
{
|
||||
if( eda_item->IsBOARD_ITEM() )
|
||||
{
|
||||
if( static_cast<BOARD_ITEM*>( eda_item )->IsLocked() )
|
||||
group->SetLocked( true );
|
||||
}
|
||||
}
|
||||
|
||||
grpCommit.Add( group );
|
||||
|
||||
for( EDA_ITEM* eda_item : selection )
|
||||
{
|
||||
if( eda_item->IsBOARD_ITEM()
|
||||
&& !static_cast<BOARD_ITEM*>( eda_item )->GetParentFootprint() )
|
||||
{
|
||||
grpCommit.Stage( static_cast<BOARD_ITEM*>( eda_item ), CHT_GROUP );
|
||||
}
|
||||
}
|
||||
|
||||
grpCommit.Push( _( "Group Items" ), APPEND_UNDO );
|
||||
|
||||
selTool->ClearSelection();
|
||||
selTool->select( group );
|
||||
|
||||
m_toolMgr->PostEvent( EVENTS::SelectedItemsModified );
|
||||
m_frame->OnModify();
|
||||
m_frame->Refresh();
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
commit.Revert();
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
// Refresh the UI for the updated board properties
|
||||
editFrame->GetAppearancePanel()->OnBoardChanged();
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -2046,6 +2142,7 @@ void PCB_CONTROL::setTransitions()
|
||||
Go( &PCB_CONTROL::InteractiveDelete, ACTIONS::deleteTool.MakeEvent() );
|
||||
|
||||
// Append control
|
||||
Go( &PCB_CONTROL::AppendDesignBlock, PCB_ACTIONS::placeDesignBlock.MakeEvent() );
|
||||
Go( &PCB_CONTROL::AppendBoardFromFile, PCB_ACTIONS::appendBoard.MakeEvent() );
|
||||
Go( &PCB_CONTROL::DdAppendBoard, PCB_ACTIONS::ddAppendBoard.MakeEvent() );
|
||||
|
||||
@@ -2063,4 +2160,4 @@ void PCB_CONTROL::setTransitions()
|
||||
Go( &PCB_CONTROL::DdAddLibrary, ACTIONS::ddAddLibrary.MakeEvent() );
|
||||
Go( &PCB_CONTROL::DdImportFootprint, PCB_ACTIONS::ddImportFootprint.MakeEvent() );
|
||||
}
|
||||
// clang-format on
|
||||
// clang-format on
|
||||
|
||||
@@ -101,7 +101,8 @@ public:
|
||||
int InteractiveDelete( const TOOL_EVENT& aEvent );
|
||||
int Paste( const TOOL_EVENT& aEvent );
|
||||
int AppendBoardFromFile( const TOOL_EVENT& aEvent );
|
||||
int AppendBoard( PCB_IO& pi, wxString& fileName );
|
||||
int AppendDesignBlock( const TOOL_EVENT& aEvent );
|
||||
int AppendBoard( PCB_IO& pi, const wxString& fileName );
|
||||
int UpdateMessagePanel( const TOOL_EVENT& aEvent );
|
||||
|
||||
int FlipPcbView( const TOOL_EVENT& aEvent );
|
||||
@@ -137,7 +138,7 @@ private:
|
||||
* @param aAnchorAtOrigin = true if the items are translated so that the anchor is {0, 0}
|
||||
* (if false, the top-left item's origin will be used)
|
||||
* @param aReannotateDuplicates = true to reannotate any footprints with a designator
|
||||
that already exist in the board.
|
||||
* that already exist in the board.
|
||||
*/
|
||||
bool placeBoardItems( BOARD_COMMIT* aCommit, std::vector<BOARD_ITEM*>& aItems, bool aIsNew,
|
||||
bool aAnchorAtOrigin, bool aReannotateDuplicates );
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
#include <dialog_design_block_properties.h>
|
||||
#include <pcb_edit_frame.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
#include <tools/pcb_selection_tool.h>
|
||||
#include <tools/pcb_design_block_control.h>
|
||||
#include <widgets/pcb_design_block_pane.h>
|
||||
#include <widgets/panel_design_block_chooser.h>
|
||||
|
||||
|
||||
PCB_DESIGN_BLOCK_CONTROL::~PCB_DESIGN_BLOCK_CONTROL()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool PCB_DESIGN_BLOCK_CONTROL::Init()
|
||||
{
|
||||
m_editFrame = getEditFrame<PCB_EDIT_FRAME>();
|
||||
m_frame = m_editFrame;
|
||||
m_framesToNotify = { FRAME_SCH };
|
||||
|
||||
auto isInLibrary =
|
||||
[this](const SELECTION& aSel )
|
||||
{
|
||||
return this->selIsInLibrary(aSel);
|
||||
};
|
||||
|
||||
auto isDesignBlock =
|
||||
[this](const SELECTION& aSel )
|
||||
{
|
||||
return this->selIsDesignBlock(aSel);
|
||||
};
|
||||
|
||||
CONDITIONAL_MENU& ctxMenu = m_menu->GetMenu();
|
||||
AddContextMenuItems( &ctxMenu );
|
||||
|
||||
ctxMenu.AddItem( PCB_ACTIONS::placeDesignBlock, isDesignBlock, 50 );
|
||||
ctxMenu.AddSeparator( 50 );
|
||||
|
||||
ctxMenu.AddItem( PCB_ACTIONS::editDesignBlockProperties, isDesignBlock, 100 );
|
||||
ctxMenu.AddItem( PCB_ACTIONS::saveBoardAsDesignBlock, isInLibrary, 100 );
|
||||
ctxMenu.AddItem( PCB_ACTIONS::saveSelectionAsDesignBlock, isInLibrary, 100 );
|
||||
ctxMenu.AddItem( PCB_ACTIONS::deleteDesignBlock, isDesignBlock, 100 );
|
||||
ctxMenu.AddSeparator( 100 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int PCB_DESIGN_BLOCK_CONTROL::SaveBoardAsDesignBlock( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
LIB_TREE_NODE* current = getCurrentTreeNode();
|
||||
|
||||
if( !current )
|
||||
return -1;
|
||||
|
||||
if( !m_editFrame->SaveBoardAsDesignBlock( current->m_LibId.GetLibNickname() ) )
|
||||
return -1;
|
||||
|
||||
notifyOtherFrames();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int PCB_DESIGN_BLOCK_CONTROL::SaveSelectionAsDesignBlock( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
LIB_TREE_NODE* current = getCurrentTreeNode();
|
||||
|
||||
if( !current )
|
||||
return -1;
|
||||
|
||||
if( !m_editFrame->SaveSelectionAsDesignBlock( current->m_LibId.GetLibNickname() ) )
|
||||
return -1;
|
||||
|
||||
notifyOtherFrames();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void PCB_DESIGN_BLOCK_CONTROL::setTransitions()
|
||||
{
|
||||
Go( &PCB_DESIGN_BLOCK_CONTROL::SaveBoardAsDesignBlock, PCB_ACTIONS::saveBoardAsDesignBlock.MakeEvent() );
|
||||
Go( &PCB_DESIGN_BLOCK_CONTROL::SaveSelectionAsDesignBlock, PCB_ACTIONS::saveSelectionAsDesignBlock.MakeEvent() );
|
||||
Go( &PCB_DESIGN_BLOCK_CONTROL::DeleteDesignBlock, PCB_ACTIONS::deleteDesignBlock.MakeEvent() );
|
||||
Go( &PCB_DESIGN_BLOCK_CONTROL::EditDesignBlockProperties, PCB_ACTIONS::editDesignBlockProperties.MakeEvent() );
|
||||
}
|
||||
|
||||
|
||||
LIB_ID PCB_DESIGN_BLOCK_CONTROL::getSelectedLibId()
|
||||
{
|
||||
getDesignBlockPane()->GetSelectedLibId();
|
||||
|
||||
return LIB_ID();
|
||||
}
|
||||
|
||||
|
||||
DESIGN_BLOCK_PANE* PCB_DESIGN_BLOCK_CONTROL::getDesignBlockPane()
|
||||
{
|
||||
return m_editFrame->GetDesignBlockPane();
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PCB_DESIGN_BLOCK_CONTROL_H
|
||||
#define PCB_DESIGN_BLOCK_CONTROL_H
|
||||
|
||||
#include <tool/design_block_control.h>
|
||||
|
||||
class DESIGN_BLOCK_PANE;
|
||||
class PCB_EDIT_FRAME;
|
||||
|
||||
/**
|
||||
* Handle design block actions in the PCB editor.
|
||||
*/
|
||||
class PCB_DESIGN_BLOCK_CONTROL : public DESIGN_BLOCK_CONTROL
|
||||
{
|
||||
public:
|
||||
PCB_DESIGN_BLOCK_CONTROL() : DESIGN_BLOCK_CONTROL( "pcbnew.PcbDesignBlockControl" ) {}
|
||||
virtual ~PCB_DESIGN_BLOCK_CONTROL();
|
||||
|
||||
/// @copydoc TOOL_INTERACTIVE::Init()
|
||||
bool Init() override;
|
||||
|
||||
int SaveBoardAsDesignBlock( const TOOL_EVENT& aEvent );
|
||||
int SaveSelectionAsDesignBlock( const TOOL_EVENT& aEvent );
|
||||
|
||||
private:
|
||||
LIB_ID getSelectedLibId();
|
||||
///< Set up handlers for various events.
|
||||
void setTransitions() override;
|
||||
|
||||
DESIGN_BLOCK_PANE* getDesignBlockPane() override;
|
||||
|
||||
PCB_EDIT_FRAME* m_editFrame = nullptr;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <design_block.h>
|
||||
#include <widgets/pcb_design_block_pane.h>
|
||||
#include <widgets/pcb_design_block_preview_widget.h>
|
||||
#include <widgets/panel_design_block_chooser.h>
|
||||
#include <pcbnew_settings.h>
|
||||
#include <kiface_base.h>
|
||||
#include <pcb_edit_frame.h>
|
||||
#include <core/kicad_algo.h>
|
||||
#include <template_fieldnames.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <confirm.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
#include <tools/pcb_design_block_control.h>
|
||||
|
||||
// Do not make these static wxStrings; they need to respond to language changes
|
||||
#define REPEATED_PLACEMENT _( "Place repeated copies" )
|
||||
#define PLACE_AS_GROUP _( "Place as group" )
|
||||
#define KEEP_ANNOTATIONS _( "Keep annotations" )
|
||||
|
||||
PCB_DESIGN_BLOCK_PANE::PCB_DESIGN_BLOCK_PANE( PCB_EDIT_FRAME* aParent, const LIB_ID* aPreselect,
|
||||
std::vector<LIB_ID>& aHistoryList ) :
|
||||
DESIGN_BLOCK_PANE( aParent, aPreselect, aHistoryList )
|
||||
{
|
||||
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
|
||||
m_chooserPanel = new PANEL_DESIGN_BLOCK_CHOOSER( aParent, this, aHistoryList,
|
||||
[aParent]()
|
||||
{
|
||||
aParent->GetToolManager()->RunAction(
|
||||
PCB_ACTIONS::placeDesignBlock );
|
||||
},
|
||||
aParent->GetToolManager()->GetTool<PCB_DESIGN_BLOCK_CONTROL>()
|
||||
);
|
||||
m_chooserPanel->SetPreviewWidget(new PCB_DESIGN_BLOCK_PREVIEW_WIDGET( m_chooserPanel->GetDetailsPanel(), aParent ) );
|
||||
sizer->Add( m_chooserPanel, 1, wxEXPAND, 5 );
|
||||
|
||||
if( aPreselect && aPreselect->IsValid() )
|
||||
m_chooserPanel->SetPreselect( *aPreselect );
|
||||
|
||||
SetName( wxT( "Design Blocks" ) );
|
||||
|
||||
wxBoxSizer* cbSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_repeatedPlacement = new wxCheckBox( this, wxID_ANY, REPEATED_PLACEMENT );
|
||||
m_placeAsGroup = new wxCheckBox( this, wxID_ANY, PLACE_AS_GROUP );
|
||||
m_keepAnnotations = new wxCheckBox( this, wxID_ANY, KEEP_ANNOTATIONS );
|
||||
setLabelsAndTooltips();
|
||||
UpdateCheckboxes();
|
||||
|
||||
// Set all checkbox handlers to the same function
|
||||
m_repeatedPlacement->Bind( wxEVT_CHECKBOX, &PCB_DESIGN_BLOCK_PANE::OnCheckBox, this );
|
||||
m_placeAsGroup->Bind( wxEVT_CHECKBOX, &PCB_DESIGN_BLOCK_PANE::OnCheckBox, this );
|
||||
m_keepAnnotations->Bind( wxEVT_CHECKBOX, &PCB_DESIGN_BLOCK_PANE::OnCheckBox, this );
|
||||
|
||||
cbSizer->Add( m_repeatedPlacement, 0, wxTOP | wxLEFT, 2 );
|
||||
cbSizer->Add( m_placeAsGroup, 0, wxTOP | wxLEFT, 2 );
|
||||
cbSizer->Add( m_keepAnnotations, 0, wxTOP | wxLEFT | wxBOTTOM, 2 );
|
||||
|
||||
sizer->Add( cbSizer, 0, wxEXPAND, 5 );
|
||||
SetSizer( sizer );
|
||||
|
||||
m_chooserPanel->FinishSetup();
|
||||
Layout();
|
||||
|
||||
Bind( wxEVT_CHAR_HOOK, &PANEL_DESIGN_BLOCK_CHOOSER::OnChar, m_chooserPanel );
|
||||
}
|
||||
|
||||
|
||||
void PCB_DESIGN_BLOCK_PANE::setLabelsAndTooltips()
|
||||
{
|
||||
if( m_repeatedPlacement )
|
||||
{
|
||||
m_repeatedPlacement->SetLabel( REPEATED_PLACEMENT );
|
||||
m_repeatedPlacement->SetToolTip( _( "Place copies of the design block on subsequent "
|
||||
"clicks." ) );
|
||||
}
|
||||
|
||||
if( m_placeAsGroup )
|
||||
{
|
||||
m_placeAsGroup->SetLabel( PLACE_AS_GROUP );
|
||||
m_placeAsGroup->SetToolTip( _( "Place the design block as a group." ) );
|
||||
}
|
||||
|
||||
if( m_keepAnnotations )
|
||||
{
|
||||
m_keepAnnotations->SetLabel( KEEP_ANNOTATIONS );
|
||||
m_keepAnnotations->SetToolTip( _( "Preserve reference designators in the source "
|
||||
"layout. Otherwise, clear them." ) );
|
||||
}
|
||||
}
|
||||
|
||||
void PCB_DESIGN_BLOCK_PANE::OnCheckBox( wxCommandEvent& aEvent )
|
||||
{
|
||||
if( PCBNEW_SETTINGS* cfg = dynamic_cast<PCBNEW_SETTINGS*>( Kiface().KifaceSettings() ) )
|
||||
{
|
||||
cfg->m_DesignBlockChooserPanel.repeated_placement = m_repeatedPlacement->GetValue();
|
||||
cfg->m_DesignBlockChooserPanel.place_as_sheet = m_placeAsGroup->GetValue();
|
||||
cfg->m_DesignBlockChooserPanel.keep_annotations = m_keepAnnotations->GetValue();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PCB_DESIGN_BLOCK_PANE::UpdateCheckboxes()
|
||||
{
|
||||
if( PCBNEW_SETTINGS* cfg = dynamic_cast<PCBNEW_SETTINGS*>( Kiface().KifaceSettings() ) )
|
||||
{
|
||||
m_repeatedPlacement->SetValue( cfg->m_DesignBlockChooserPanel.repeated_placement );
|
||||
m_placeAsGroup->SetValue( cfg->m_DesignBlockChooserPanel.place_as_sheet );
|
||||
m_keepAnnotations->SetValue( cfg->m_DesignBlockChooserPanel.keep_annotations );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FILEDLG_IMPORT_SHEET_CONTENTS::FILEDLG_IMPORT_SHEET_CONTENTS( PCBNEW_SETTINGS* aSettings ) :
|
||||
m_cbRepeatedPlacement( nullptr ),
|
||||
m_cbPlaceAsSheet( nullptr ),
|
||||
m_cbKeepAnnotations( nullptr )
|
||||
{
|
||||
wxASSERT( aSettings );
|
||||
m_settings = aSettings;
|
||||
};
|
||||
|
||||
|
||||
void FILEDLG_IMPORT_SHEET_CONTENTS::TransferDataFromCustomControls()
|
||||
{
|
||||
m_settings->m_DesignBlockChooserPanel.repeated_placement = m_cbRepeatedPlacement->GetValue();
|
||||
m_settings->m_DesignBlockChooserPanel.place_as_sheet = m_cbPlaceAsSheet->GetValue();
|
||||
m_settings->m_DesignBlockChooserPanel.keep_annotations = m_cbKeepAnnotations->GetValue();
|
||||
}
|
||||
|
||||
|
||||
void FILEDLG_IMPORT_SHEET_CONTENTS::AddCustomControls( wxFileDialogCustomize& customizer )
|
||||
{
|
||||
m_cbRepeatedPlacement = customizer.AddCheckBox( REPEATED_PLACEMENT );
|
||||
m_cbRepeatedPlacement->SetValue( m_settings->m_DesignBlockChooserPanel.repeated_placement );
|
||||
m_cbPlaceAsSheet = customizer.AddCheckBox( PLACE_AS_GROUP );
|
||||
m_cbPlaceAsSheet->SetValue( m_settings->m_DesignBlockChooserPanel.place_as_sheet );
|
||||
m_cbKeepAnnotations = customizer.AddCheckBox( KEEP_ANNOTATIONS );
|
||||
m_cbKeepAnnotations->SetValue( m_settings->m_DesignBlockChooserPanel.keep_annotations );
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The 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
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
#ifndef PCB_DESIGN_BLOCK_PANE_H
|
||||
#define PCB_DESIGN_BLOCK_PANE_H
|
||||
|
||||
#include <widgets/design_block_pane.h>
|
||||
#include <design_block_tree_model_adapter.h>
|
||||
#include <widgets/html_window.h>
|
||||
#include <widgets/wx_panel.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/filedlgcustomize.h>
|
||||
#include <pcbnew_settings.h>
|
||||
|
||||
|
||||
class PCB_EDIT_FRAME;
|
||||
class PANEL_DESIGN_BLOCK_CHOOSER;
|
||||
|
||||
|
||||
class PCB_DESIGN_BLOCK_PANE : public DESIGN_BLOCK_PANE
|
||||
{
|
||||
public:
|
||||
PCB_DESIGN_BLOCK_PANE( PCB_EDIT_FRAME* aParent, const LIB_ID* aPreselect,
|
||||
std::vector<LIB_ID>& aHistoryList );
|
||||
|
||||
void OnCheckBox( wxCommandEvent& aEvent );
|
||||
void UpdateCheckboxes();
|
||||
|
||||
void OnSaveSheetAsDesignBlock( wxCommandEvent& aEvent );
|
||||
void OnSaveSelectionAsDesignBlock( wxCommandEvent& aEvent );
|
||||
|
||||
protected:
|
||||
void setLabelsAndTooltips() override;
|
||||
|
||||
wxCheckBox* m_repeatedPlacement;
|
||||
wxCheckBox* m_placeAsGroup;
|
||||
wxCheckBox* m_keepAnnotations;
|
||||
};
|
||||
|
||||
|
||||
// This is a helper class for the file dialog to allow the user to choose similar options
|
||||
// as the design block chooser when importing a sheet.
|
||||
class FILEDLG_IMPORT_SHEET_CONTENTS : public wxFileDialogCustomizeHook
|
||||
{
|
||||
public:
|
||||
FILEDLG_IMPORT_SHEET_CONTENTS( PCBNEW_SETTINGS* aSettings );
|
||||
|
||||
void AddCustomControls( wxFileDialogCustomize& customizer ) override;
|
||||
|
||||
void TransferDataFromCustomControls() override;
|
||||
|
||||
private:
|
||||
PCBNEW_SETTINGS* m_settings;
|
||||
|
||||
wxFileDialogCheckBox* m_cbRepeatedPlacement;
|
||||
wxFileDialogCheckBox* m_cbPlaceAsSheet;
|
||||
wxFileDialogCheckBox* m_cbKeepAnnotations;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS( FILEDLG_IMPORT_SHEET_CONTENTS );
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The 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 as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <board.h>
|
||||
#include <confirm.h>
|
||||
#include <pcb_view.h>
|
||||
#include <pcb_screen.h>
|
||||
#include <gal/gal_display_options.h>
|
||||
#include <gal/graphics_abstraction_layer.h>
|
||||
#include <math/vector2wx.h>
|
||||
#include <design_block_lib_table.h>
|
||||
#include <design_block.h>
|
||||
#include <footprint_preview_panel.h>
|
||||
#include <pgm_base.h>
|
||||
#include <pcb_painter.h>
|
||||
#include <pcb_edit_frame.h>
|
||||
#include <pcb_field.h>
|
||||
#include <pcb_io/pcb_io.h>
|
||||
#include <pcb_io/pcb_io_mgr.h>
|
||||
#include <project_pcb.h>
|
||||
#include <pcbnew_settings.h>
|
||||
//#include <pcb_helpers.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <widgets/pcb_design_block_preview_widget.h>
|
||||
#include <widgets/wx_progress_reporters.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
|
||||
PCB_DESIGN_BLOCK_PREVIEW_WIDGET::PCB_DESIGN_BLOCK_PREVIEW_WIDGET( wxWindow* aParent,
|
||||
PCB_EDIT_FRAME* aFrame ) :
|
||||
DESIGN_BLOCK_PREVIEW_WIDGET( aParent ), m_preview( nullptr ), m_status( nullptr ),
|
||||
m_statusPanel( nullptr ), m_statusSizer( nullptr ), m_previewItem( nullptr )
|
||||
{
|
||||
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
|
||||
COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
|
||||
PCBNEW_SETTINGS* app_settings = mgr.GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" );
|
||||
|
||||
m_galDisplayOptions.ReadConfig( *common_settings, app_settings->m_Window, this );
|
||||
m_galDisplayOptions.m_forceDisplayCursor = false;
|
||||
|
||||
m_preview = FOOTPRINT_PREVIEW_PANEL::New( &aFrame->Kiway(), this, aFrame );
|
||||
m_preview->SetStealsFocus( false );
|
||||
m_preview->ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
|
||||
m_preview->GetGAL()->SetAxesEnabled( false );
|
||||
|
||||
// Do not display the grid: the look is not good for a small canvas area.
|
||||
// But mainly, due to some strange bug I (JPC) was unable to fix, the grid creates
|
||||
// strange artifacts on Windows when Pcb is run from KiCad manager (but not in
|
||||
// stand alone...).
|
||||
m_preview->GetGAL()->SetGridVisibility( true );
|
||||
|
||||
// Early initialization of the canvas background color,
|
||||
// before any OnPaint event is fired for the canvas using a wrong bg color
|
||||
KIGFX::VIEW* view = m_preview->GetView();
|
||||
auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( view->GetPainter()->GetSettings() );
|
||||
|
||||
if( auto* theme = Pgm().GetSettingsManager().GetColorSettings( app_settings->m_ColorTheme ) )
|
||||
settings->LoadColors( theme );
|
||||
|
||||
const COLOR4D& backgroundColor = settings->GetBackgroundColor();
|
||||
const COLOR4D& foregroundColor = settings->GetCursorColor();
|
||||
|
||||
m_preview->GetGAL()->SetClearColor( backgroundColor );
|
||||
|
||||
m_outerSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_statusPanel = new wxPanel( this );
|
||||
m_statusPanel->SetBackgroundColour( backgroundColor.ToColour() );
|
||||
m_status = new wxStaticText( m_statusPanel, wxID_ANY, wxEmptyString );
|
||||
m_status->SetForegroundColour( settings->GetLayerColor( LAYER_REFERENCEPART ).ToColour() );
|
||||
m_statusSizer = new wxBoxSizer( wxVERTICAL );
|
||||
m_statusSizer->Add( 0, 0, 1 ); // add a spacer
|
||||
m_statusSizer->Add( m_status, 0, wxALIGN_CENTER );
|
||||
m_statusSizer->Add( 0, 0, 1 ); // add a spacer
|
||||
m_statusPanel->SetSizer( m_statusSizer );
|
||||
|
||||
// Give the status panel the same color scheme as the canvas so it isn't jarring when
|
||||
// switched to.
|
||||
m_statusPanel->SetBackgroundColour( backgroundColor.ToColour() );
|
||||
m_statusPanel->SetForegroundColour( foregroundColor.ToColour() );
|
||||
|
||||
// Give the preview panel a small top border to align its top with the status panel,
|
||||
// and give the status panel a small bottom border to align its bottom with the preview
|
||||
// panel.
|
||||
m_outerSizer->Add( m_preview, 1, wxTOP | wxEXPAND, 5 );
|
||||
m_outerSizer->Add( m_statusPanel, 1, wxBOTTOM | wxEXPAND, 5 );
|
||||
|
||||
// Hide the status panel to start
|
||||
m_statusPanel->Hide();
|
||||
|
||||
SetSizer( m_outerSizer );
|
||||
Layout();
|
||||
|
||||
Connect( wxEVT_SIZE, wxSizeEventHandler( PCB_DESIGN_BLOCK_PREVIEW_WIDGET::onSize ), nullptr, this );
|
||||
}
|
||||
|
||||
|
||||
PCB_DESIGN_BLOCK_PREVIEW_WIDGET::~PCB_DESIGN_BLOCK_PREVIEW_WIDGET()
|
||||
{
|
||||
if( m_previewItem )
|
||||
m_preview->GetView()->Remove( m_previewItem );
|
||||
|
||||
delete m_previewItem;
|
||||
}
|
||||
|
||||
|
||||
void PCB_DESIGN_BLOCK_PREVIEW_WIDGET::SetStatusText( wxString const& aText )
|
||||
{
|
||||
wxCHECK( m_statusPanel, /* void */ );
|
||||
|
||||
m_status->SetLabel( aText );
|
||||
m_preview->Hide();
|
||||
m_statusPanel->Show();
|
||||
Layout();
|
||||
}
|
||||
|
||||
|
||||
void PCB_DESIGN_BLOCK_PREVIEW_WIDGET::onSize( wxSizeEvent& aEvent )
|
||||
{
|
||||
if( m_previewItem )
|
||||
{
|
||||
fitOnDrawArea();
|
||||
m_preview->ForceRefresh();
|
||||
}
|
||||
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
void PCB_DESIGN_BLOCK_PREVIEW_WIDGET::fitOnDrawArea()
|
||||
{
|
||||
if( !m_previewItem )
|
||||
return;
|
||||
|
||||
// set the view scale to fit the item on screen
|
||||
KIGFX::VIEW* view = m_preview->GetView();
|
||||
|
||||
// Calculate the drawing area size, in internal units, for a scaling factor = 1.0
|
||||
view->SetScale( 1.0 );
|
||||
VECTOR2D clientSize = view->ToWorld( ToVECTOR2D( m_preview->GetClientSize() ), false );
|
||||
// Calculate the draw scale to fit the drawing area
|
||||
double scale = std::min( fabs( clientSize.x / m_itemBBox.GetWidth() ),
|
||||
fabs( clientSize.y / m_itemBBox.GetHeight() ) );
|
||||
|
||||
// Above calculation will yield an exact fit; add a bit of whitespace around block
|
||||
scale /= 1.2;
|
||||
|
||||
// Now fix the best scale
|
||||
view->SetScale( scale );
|
||||
view->SetCenter( m_itemBBox.Centre() );
|
||||
}
|
||||
|
||||
|
||||
void PCB_DESIGN_BLOCK_PREVIEW_WIDGET::DisplayDesignBlock( DESIGN_BLOCK* aDesignBlock )
|
||||
{
|
||||
KIGFX::VIEW* view = m_preview->GetView();
|
||||
|
||||
if( m_previewItem )
|
||||
{
|
||||
view->Clear();
|
||||
delete m_previewItem;
|
||||
m_previewItem = nullptr;
|
||||
}
|
||||
|
||||
if( aDesignBlock && wxFileExists( aDesignBlock->GetBoardFile() ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
IO_RELEASER<PCB_IO> pi( PCB_IO_MGR::PluginFind( PCB_IO_MGR::KICAD_SEXP ) );
|
||||
WX_PROGRESS_REPORTER progressReporter( this, _( "Loading PCB" ), 1 );
|
||||
|
||||
pi->SetProgressReporter( &progressReporter );
|
||||
|
||||
m_previewItem = pi->LoadBoard( aDesignBlock->GetBoardFile(), nullptr );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
// You wouldn't think boardFn.GetFullPath() would throw, but we get a stack buffer
|
||||
// underflow from ASAN. While it's probably an ASAN error, a second try/catch doesn't
|
||||
// cost us much.
|
||||
try
|
||||
{
|
||||
if( ioe.Problem() != wxT( "CANCEL" ) )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Error loading board file:\n%s" ),
|
||||
aDesignBlock->GetBoardFile() );
|
||||
DisplayErrorMessage( this, msg, ioe.What() );
|
||||
}
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
// That was already our best-efforts
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOX2I bBox;
|
||||
|
||||
if( m_previewItem )
|
||||
{
|
||||
for( BOARD_ITEM* item : m_previewItem->GetItemSet() )
|
||||
{
|
||||
view->Add( item );
|
||||
|
||||
if( item->Type() == PCB_FIELD_T )
|
||||
{
|
||||
if( !static_cast<const PCB_FIELD*>( item )->IsVisible() )
|
||||
continue;
|
||||
}
|
||||
|
||||
bBox.Merge( item->GetBoundingBox() );
|
||||
}
|
||||
}
|
||||
|
||||
m_itemBBox = bBox;
|
||||
|
||||
if( !m_preview->IsShownOnScreen() )
|
||||
{
|
||||
m_preview->Show();
|
||||
|
||||
if( m_statusPanel )
|
||||
m_statusPanel->Hide();
|
||||
|
||||
Layout(); // Ensure panel size is up to date.
|
||||
}
|
||||
|
||||
// Calculate the draw scale to fit the drawing area
|
||||
fitOnDrawArea();
|
||||
}
|
||||
|
||||
m_preview->ForceRefresh();
|
||||
m_preview->Show();
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The 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 as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PCB_DESIGN_BLOCK_PREVIEW_WIDGET_H
|
||||
#define PCB_DESIGN_BLOCK_PREVIEW_WIDGET_H
|
||||
|
||||
#include <wx/panel.h>
|
||||
#include <widgets/design_block_preview_widget.h>
|
||||
#include <kiway.h>
|
||||
#include <gal_display_options_common.h>
|
||||
#include <class_draw_panel_gal.h>
|
||||
|
||||
|
||||
class LIB_ID;
|
||||
class DESIGN_BLOCK;
|
||||
class SCHEMATIC;
|
||||
class PCB_SHEET;
|
||||
class wxStaticText;
|
||||
class wxSizer;
|
||||
|
||||
|
||||
class PCB_DESIGN_BLOCK_PREVIEW_WIDGET : public DESIGN_BLOCK_PREVIEW_WIDGET
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Construct a schematic design block preview widget.
|
||||
*
|
||||
* @param aParent - parent window
|
||||
*/
|
||||
PCB_DESIGN_BLOCK_PREVIEW_WIDGET( wxWindow* aParent, PCB_EDIT_FRAME* aFrame );
|
||||
|
||||
~PCB_DESIGN_BLOCK_PREVIEW_WIDGET() override;
|
||||
|
||||
/**
|
||||
* Set the contents of the status label and display it.
|
||||
*/
|
||||
void SetStatusText( const wxString& aText ) override;
|
||||
|
||||
/**
|
||||
* Set the currently displayed symbol.
|
||||
*/
|
||||
void DisplayDesignBlock( DESIGN_BLOCK* aDesignBlock ) override;
|
||||
|
||||
protected:
|
||||
void onSize( wxSizeEvent& aEvent );
|
||||
|
||||
void fitOnDrawArea(); // set the view scale to fit the item on screen and center
|
||||
|
||||
GAL_DISPLAY_OPTIONS_IMPL m_galDisplayOptions;
|
||||
EDA_DRAW_PANEL_GAL* m_preview;
|
||||
|
||||
wxStaticText* m_status;
|
||||
wxPanel* m_statusPanel;
|
||||
wxSizer* m_statusSizer;
|
||||
wxSizer* m_outerSizer;
|
||||
|
||||
BOARD* m_previewItem;
|
||||
|
||||
/// The bounding box of the current item
|
||||
BOX2I m_itemBBox;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user