When opening the Sync Sheet Pins dialog from the toolbar, the dialog now automatically selects the tab for the currently selected sheet. If no sheet is selected, it falls back to selecting the first tab with unsynced pins (those showing the exclamation mark icon). Fixes https://gitlab.com/kicad/code/kicad/-/issues/22344
231 lines
8.4 KiB
C++
231 lines
8.4 KiB
C++
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (C) 2023 Ethan Chien <[email protected]>
|
|
* 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_sync_sheet_pins.h"
|
|
#include "panel_sync_sheet_pins.h"
|
|
#include "sch_item.h"
|
|
#include "sch_label.h"
|
|
#include "sheet_synchronization_model.h"
|
|
#include "sync_sheet_pin_preference.h"
|
|
#include "sheet_synchronization_notifier.h"
|
|
#include "sheet_synchronization_agent.h"
|
|
#include "sheet_synchronization_item.h"
|
|
|
|
#include <memory>
|
|
#include <cstddef>
|
|
#include <sch_sheet_pin.h>
|
|
#include <sch_sheet.h>
|
|
#include <unordered_map>
|
|
#include <sch_drawing_tools.h>
|
|
|
|
|
|
DIALOG_SYNC_SHEET_PINS::DIALOG_SYNC_SHEET_PINS(
|
|
wxWindow* aParent, std::list<SCH_SHEET_PATH> aSheetPath,
|
|
std::shared_ptr<SHEET_SYNCHRONIZATION_AGENT> aAgent, SCH_SHEET* aInitialSheet ) :
|
|
DIALOG_SYNC_SHEET_PINS_BASE( aParent ), m_agent( std::move( aAgent ) ),
|
|
m_lastEditSheet( nullptr ), m_placeItemKind( PlaceItemKind::UNDEFINED ),
|
|
m_currentTemplate( nullptr )
|
|
{
|
|
wxImageList* imageList = new wxImageList( SYNC_SHEET_PIN_PREFERENCE::NORMAL_WIDTH,
|
|
SYNC_SHEET_PIN_PREFERENCE::NORMAL_HEIGHT );
|
|
|
|
for( const auto& [icon_idx, bitmap] : SYNC_SHEET_PIN_PREFERENCE::GetBookctrlPageIcon() )
|
|
{
|
|
imageList->Add( KiBitmap( bitmap, SYNC_SHEET_PIN_PREFERENCE::NORMAL_HEIGHT ) );
|
|
}
|
|
|
|
m_notebook->AssignImageList( imageList );
|
|
int count = -1;
|
|
int initialSelection = -1;
|
|
int firstUnsyncedPage = -1;
|
|
std::unordered_map<wxString, std::list<PANEL_SYNC_SHEET_PINS*>> sheet_instances;
|
|
|
|
for( const auto& sheet_path : aSheetPath )
|
|
{
|
|
auto sheet = sheet_path.Last();
|
|
wxString fileName = sheet->GetFileName();
|
|
PANEL_SYNC_SHEET_PINS* page = new PANEL_SYNC_SHEET_PINS( m_notebook, sheet, m_notebook,
|
|
++count, *m_agent, sheet_path );
|
|
bool hasUndefined = page->HasUndefinedSheetPing();
|
|
m_notebook->AddPage( page, sheet->GetShownName( true ), {}, hasUndefined );
|
|
page->UpdateForms();
|
|
|
|
if( aInitialSheet && sheet == aInitialSheet )
|
|
initialSelection = count;
|
|
|
|
if( firstUnsyncedPage < 0 && hasUndefined )
|
|
firstUnsyncedPage = count;
|
|
|
|
if( sheet_instances.find( fileName ) == sheet_instances.end() )
|
|
{
|
|
sheet_instances.try_emplace( fileName, std::list<PANEL_SYNC_SHEET_PINS*>{ page } );
|
|
}
|
|
else
|
|
{
|
|
sheet_instances[fileName].push_back( page );
|
|
}
|
|
|
|
m_panels.try_emplace( sheet, page );
|
|
}
|
|
|
|
for( auto& [sheet_name, panel_list] : sheet_instances )
|
|
{
|
|
if( panel_list.size() > 1 )
|
|
{
|
|
std::list<std::shared_ptr<SHEET_SYNCHRONIZATION_NOTIFIER>> sheet_change_notifiers;
|
|
std::list<SHEET_SYNCHRONIZATION_MODEL*> sheet_sync_models;
|
|
|
|
for( auto& panel : panel_list )
|
|
{
|
|
SHEET_SYNCHRONIZATION_MODEL* model =
|
|
panel->GetModel( SHEET_SYNCHRONIZATION_MODEL::HIRE_LABEL ).get();
|
|
sheet_sync_models.push_back( model );
|
|
sheet_change_notifiers.push_back(
|
|
std::make_shared<SHEET_FILE_CHANGE_NOTIFIER>( model, panel ) );
|
|
}
|
|
|
|
for( auto& notifier : sheet_change_notifiers )
|
|
{
|
|
for( auto& other : sheet_sync_models )
|
|
{
|
|
if( notifier->GetOwner() != other )
|
|
{
|
|
other->AddNotifier( notifier );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Select initial page: prefer the explicitly requested sheet, fall back to the first page
|
|
// with unsynced pins, or stay on the first page if all are synced
|
|
if( initialSelection >= 0 )
|
|
m_notebook->SetSelection( initialSelection );
|
|
else if( firstUnsyncedPage >= 0 )
|
|
m_notebook->SetSelection( firstUnsyncedPage );
|
|
|
|
Bind( wxEVT_CLOSE_WINDOW, &DIALOG_SYNC_SHEET_PINS::OnClose, this );
|
|
|
|
// Now all widgets have the size fixed, call FinishDialogSettings
|
|
finishDialogSettings();
|
|
}
|
|
|
|
|
|
DIALOG_SYNC_SHEET_PINS::~DIALOG_SYNC_SHEET_PINS() = default;
|
|
|
|
|
|
void DIALOG_SYNC_SHEET_PINS::OnClose( wxCloseEvent& aEvent )
|
|
{
|
|
aEvent.Skip();
|
|
}
|
|
|
|
|
|
void DIALOG_SYNC_SHEET_PINS::EndPlaceItem( EDA_ITEM* aNewItem )
|
|
{
|
|
if( !aNewItem )
|
|
return;
|
|
|
|
auto post_end_place_item =
|
|
std::shared_ptr<std::nullptr_t>( nullptr,
|
|
[&]( std::nullptr_t )
|
|
{
|
|
m_placementTemplateSet.erase( m_currentTemplate );
|
|
|
|
if( m_placementTemplateSet.empty() )
|
|
{
|
|
EndPlacement();
|
|
}
|
|
else
|
|
{
|
|
m_currentTemplate = *m_placementTemplateSet.begin();
|
|
}
|
|
} );
|
|
|
|
|
|
if( m_lastEditSheet && m_panels.find( m_lastEditSheet ) != m_panels.end() )
|
|
{
|
|
auto& panel = m_panels[m_lastEditSheet];
|
|
auto template_item = static_cast<SCH_HIERLABEL*>( m_currentTemplate );
|
|
auto new_item = static_cast<SCH_HIERLABEL*>( aNewItem );
|
|
|
|
//Usr may edit the name or shape while placing the new item , do sync if either differs
|
|
if( template_item->GetText() != new_item->GetText()
|
|
|| template_item->GetShape() != new_item->GetShape() )
|
|
{
|
|
m_agent->ModifyItem(
|
|
template_item,
|
|
[&]()
|
|
{
|
|
template_item->SetText( new_item->GetText() );
|
|
template_item->SetShape( new_item->GetShape() );
|
|
},
|
|
panel->GetSheetPath(),
|
|
PlaceItemKind::SHEET_PIN == m_placeItemKind
|
|
? SHEET_SYNCHRONIZATION_ITEM_KIND::HIERLABEL
|
|
: SHEET_SYNCHRONIZATION_ITEM_KIND::SHEET_PIN );
|
|
}
|
|
|
|
panel->UpdateForms();
|
|
|
|
if( PlaceItemKind::HIERLABEL == m_placeItemKind )
|
|
panel->GetModel( SHEET_SYNCHRONIZATION_MODEL::HIRE_LABEL )->DoNotify();
|
|
}
|
|
}
|
|
|
|
|
|
void DIALOG_SYNC_SHEET_PINS::PreparePlacementTemplate( SCH_SHEET* aSheet, PlaceItemKind aKind,
|
|
std::set<EDA_ITEM*> const& aPlacementTemplateSet )
|
|
{
|
|
if( aPlacementTemplateSet.empty() )
|
|
return;
|
|
|
|
m_lastEditSheet = aSheet;
|
|
m_placeItemKind = aKind;
|
|
m_placementTemplateSet = aPlacementTemplateSet;
|
|
m_currentTemplate = *m_placementTemplateSet.begin();
|
|
}
|
|
|
|
|
|
SCH_HIERLABEL* DIALOG_SYNC_SHEET_PINS::GetPlacementTemplate() const
|
|
{
|
|
if( !m_currentTemplate )
|
|
return {};
|
|
|
|
return static_cast<SCH_HIERLABEL*>( m_currentTemplate );
|
|
}
|
|
|
|
|
|
bool DIALOG_SYNC_SHEET_PINS::CanPlaceMore() const
|
|
{
|
|
return !m_placementTemplateSet.empty();
|
|
}
|
|
|
|
|
|
void DIALOG_SYNC_SHEET_PINS::EndPlacement()
|
|
{
|
|
m_placementTemplateSet.clear();
|
|
m_placeItemKind = PlaceItemKind::UNDEFINED;
|
|
m_currentTemplate = nullptr;
|
|
}
|