Yet another overhaul to locking.

This unifies everything under a single architecture with a "don't
show again" dialog.  Since everything now goes through the same
path it should be reasonably easy to make it do whatever we want
in the future.

Right now it presents 3 options: modify only unlocked items, override
locks and modify all items, or cancel command.
This commit is contained in:
Jeff Young 2020-12-10 17:34:26 +00:00
parent 260219b0e6
commit 98330098ac
14 changed files with 904 additions and 156 deletions

View File

@ -173,6 +173,8 @@ set( COMMON_DLG_SRCS
dialogs/dialog_HTML_reporter_base.cpp dialogs/dialog_HTML_reporter_base.cpp
dialogs/dialog_image_editor.cpp dialogs/dialog_image_editor.cpp
dialogs/dialog_image_editor_base.cpp dialogs/dialog_image_editor_base.cpp
dialogs/dialog_locked_items_query.cpp
dialogs/dialog_locked_items_query_base.cpp
dialogs/dialog_migrate_settings.cpp dialogs/dialog_migrate_settings.cpp
dialogs/dialog_migrate_settings_base.cpp dialogs/dialog_migrate_settings_base.cpp
dialogs/dialog_page_settings_base.cpp dialogs/dialog_page_settings_base.cpp

View File

@ -0,0 +1,77 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* 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_locked_items_query.h>
#include <bitmaps.h>
DIALOG_LOCKED_ITEMS_QUERY::DIALOG_LOCKED_ITEMS_QUERY( wxWindow* aParent, int aLockedItemCount ) :
DIALOG_LOCKED_ITEMS_QUERY_BASE( aParent )
{
m_icon->SetBitmap( KiBitmap( locked_xpm ) );
m_messageLine1->SetLabel( wxString::Format( m_messageLine1->GetLabel(), aLockedItemCount ) );
m_sdbSizerOK->SetDefault();
Layout();
// Now all widgets have the size fixed, call FinishDialogSettings
finishDialogSettings();
}
void DIALOG_LOCKED_ITEMS_QUERY::onOverrideLocks( wxCommandEvent& event )
{
EndModal( wxID_APPLY );
}
void DIALOG_LOCKED_ITEMS_QUERY::onOkClick( wxCommandEvent& event )
{
EndModal( wxID_OK );
}
void DIALOG_LOCKED_ITEMS_QUERY::onCancelClick( wxCommandEvent& event )
{
EndModal( wxID_CANCEL );
}
int DIALOG_LOCKED_ITEMS_QUERY::ShowModal()
{
static int doNotShowValue = wxID_ANY;
if( doNotShowValue != wxID_ANY )
return doNotShowValue;
int ret = DIALOG_SHIM::ShowModal();
// Has the user asked not to show the dialog again
if( m_doNotShowBtn->IsChecked() && ret != wxID_CANCEL )
doNotShowValue = ret;
return ret;
}

View File

@ -0,0 +1,44 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* 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 DIALOG_LOCKED_ITEMS_QUERY_H
#define DIALOG_LOCKED_ITEMS_QUERY_H
#include <dialog_locked_items_query_base.h>
class DIALOG_LOCKED_ITEMS_QUERY : public DIALOG_LOCKED_ITEMS_QUERY_BASE
{
public:
/// This has no dependencies on calling wxFrame derivative, such as PCB_BASE_FRAME.
DIALOG_LOCKED_ITEMS_QUERY( wxWindow* aParent, int aLockedItemCount );
int ShowModal() override;
private:
void onOverrideLocks( wxCommandEvent& event ) override;
void onCancelClick( wxCommandEvent& event ) override;
void onOkClick( wxCommandEvent& event ) override;
};
#endif // DIALOG_LOCKED_ITEMS_QUERY_H

View File

@ -0,0 +1,91 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "dialog_locked_items_query_base.h"
///////////////////////////////////////////////////////////////////////////
DIALOG_LOCKED_ITEMS_QUERY_BASE::DIALOG_LOCKED_ITEMS_QUERY_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
wxBoxSizer* bSizerMain;
bSizerMain = new wxBoxSizer( wxVERTICAL );
wxFlexGridSizer* fgSizer4;
fgSizer4 = new wxFlexGridSizer( 0, 2, 10, 0 );
fgSizer4->SetFlexibleDirection( wxBOTH );
fgSizer4->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_icon = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
fgSizer4->Add( m_icon, 0, wxALL|wxALIGN_CENTER_VERTICAL, 10 );
wxBoxSizer* bSizer4;
bSizer4 = new wxBoxSizer( wxVERTICAL );
m_messageLine1 = new wxStaticText( this, wxID_ANY, _("The selection contains %d locked items."), wxDefaultPosition, wxDefaultSize, 0 );
m_messageLine1->Wrap( -1 );
bSizer4->Add( m_messageLine1, 0, wxALL, 5 );
m_messageLine2 = new wxStaticText( this, wxID_ANY, _("These items will be skipped unless you override the locks."), wxDefaultPosition, wxDefaultSize, 0 );
m_messageLine2->Wrap( -1 );
bSizer4->Add( m_messageLine2, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
fgSizer4->Add( bSizer4, 1, wxEXPAND, 5 );
fgSizer4->Add( 0, 0, 1, wxEXPAND, 5 );
m_doNotShowBtn = new wxCheckBox( this, wxID_ANY, _("Do not show again."), wxDefaultPosition, wxDefaultSize, 0 );
fgSizer4->Add( m_doNotShowBtn, 0, wxALL, 5 );
bSizerMain->Add( fgSizer4, 1, wxEXPAND|wxALL, 5 );
wxBoxSizer* bButtonSizer;
bButtonSizer = new wxBoxSizer( wxHORIZONTAL );
m_overrideBtn = new wxButton( this, wxID_ANY, _("Override Locks"), wxDefaultPosition, wxDefaultSize, 0 );
bButtonSizer->Add( m_overrideBtn, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
bButtonSizer->Add( 0, 0, 1, wxEXPAND, 5 );
m_sdbSizer = new wxStdDialogButtonSizer();
m_sdbSizerOK = new wxButton( this, wxID_OK );
m_sdbSizer->AddButton( m_sdbSizerOK );
m_sdbSizerCancel = new wxButton( this, wxID_CANCEL );
m_sdbSizer->AddButton( m_sdbSizerCancel );
m_sdbSizer->Realize();
bButtonSizer->Add( m_sdbSizer, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
bSizerMain->Add( bButtonSizer, 0, wxEXPAND|wxTOP|wxLEFT, 10 );
this->SetSizer( bSizerMain );
this->Layout();
bSizerMain->Fit( this );
// Connect Events
this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_LOCKED_ITEMS_QUERY_BASE::OnInitDlg ) );
m_overrideBtn->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LOCKED_ITEMS_QUERY_BASE::onOverrideLocks ), NULL, this );
m_sdbSizerCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LOCKED_ITEMS_QUERY_BASE::onCancelClick ), NULL, this );
m_sdbSizerOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LOCKED_ITEMS_QUERY_BASE::onOkClick ), NULL, this );
}
DIALOG_LOCKED_ITEMS_QUERY_BASE::~DIALOG_LOCKED_ITEMS_QUERY_BASE()
{
// Disconnect Events
this->Disconnect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_LOCKED_ITEMS_QUERY_BASE::OnInitDlg ) );
m_overrideBtn->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LOCKED_ITEMS_QUERY_BASE::onOverrideLocks ), NULL, this );
m_sdbSizerCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LOCKED_ITEMS_QUERY_BASE::onCancelClick ), NULL, this );
m_sdbSizerOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_LOCKED_ITEMS_QUERY_BASE::onOkClick ), NULL, this );
}

View File

@ -0,0 +1,462 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="15" />
<object class="Project" expanded="1">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
<property name="disconnect_events">1</property>
<property name="disconnect_mode">source_name</property>
<property name="disconnect_php_events">0</property>
<property name="disconnect_python_events">0</property>
<property name="embedded_files_path">res</property>
<property name="encoding">UTF-8</property>
<property name="event_generation">connect</property>
<property name="file">dialog_locked_items_query_base</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="indent_with_spaces"></property>
<property name="internationalize">1</property>
<property name="name">dialog_locked_items_query</property>
<property name="namespace"></property>
<property name="path">.</property>
<property name="precompiled_header"></property>
<property name="relative_path">1</property>
<property name="skip_lua_events">1</property>
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_enum">0</property>
<property name="use_microsoft_bom">0</property>
<object class="Dialog" expanded="1">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
<property name="center"></property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="enabled">1</property>
<property name="event_handler">impl_virtual</property>
<property name="extra_style"></property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">DIALOG_LOCKED_ITEMS_QUERY_BASE</property>
<property name="pos"></property>
<property name="size">-1,-1</property>
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
<property name="title">Locked Items</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnInitDialog">OnInitDlg</event>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizerMain</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxALL</property>
<property name="proportion">1</property>
<object class="wxFlexGridSizer" expanded="1">
<property name="cols">2</property>
<property name="flexible_direction">wxBOTH</property>
<property name="growablecols"></property>
<property name="growablerows"></property>
<property name="hgap">0</property>
<property name="minimum_size"></property>
<property name="name">fgSizer4</property>
<property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
<property name="permission">none</property>
<property name="rows">0</property>
<property name="vgap">10</property>
<object class="sizeritem" expanded="1">
<property name="border">10</property>
<property name="flag">wxALL|wxALIGN_CENTER_VERTICAL</property>
<property name="proportion">0</property>
<object class="wxStaticBitmap" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_icon</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizer4</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">The selection contains %d locked items.</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_messageLine1</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxBOTTOM|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">These items will be skipped unless you override the locks.</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_messageLine2</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="spacer" expanded="1">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Do not show again.</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_doNotShowBtn</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">10</property>
<property name="flag">wxEXPAND|wxTOP|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bButtonSizer</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="proportion">0</property>
<object class="wxButton" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="current"></property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="disabled"></property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="focus"></property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Override Locks</property>
<property name="margins"></property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_overrideBtn</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="position"></property>
<property name="pressed"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">onOverrideLocks</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="spacer" expanded="1">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL|wxALIGN_CENTER_VERTICAL</property>
<property name="proportion">0</property>
<object class="wxStdDialogButtonSizer" expanded="1">
<property name="Apply">0</property>
<property name="Cancel">1</property>
<property name="ContextHelp">0</property>
<property name="Help">0</property>
<property name="No">0</property>
<property name="OK">1</property>
<property name="Save">0</property>
<property name="Yes">0</property>
<property name="minimum_size"></property>
<property name="name">m_sdbSizer</property>
<property name="permission">protected</property>
<event name="OnCancelButtonClick">onCancelClick</event>
<event name="OnOKButtonClick">onOkClick</event>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</wxFormBuilder_Project>

View File

@ -0,0 +1,62 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#pragma once
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/intl.h>
#include "dialog_shim.h"
#include <wx/bitmap.h>
#include <wx/image.h>
#include <wx/icon.h>
#include <wx/statbmp.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/string.h>
#include <wx/stattext.h>
#include <wx/sizer.h>
#include <wx/checkbox.h>
#include <wx/button.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class DIALOG_LOCKED_ITEMS_QUERY_BASE
///////////////////////////////////////////////////////////////////////////////
class DIALOG_LOCKED_ITEMS_QUERY_BASE : public DIALOG_SHIM
{
private:
protected:
wxStaticBitmap* m_icon;
wxStaticText* m_messageLine1;
wxStaticText* m_messageLine2;
wxCheckBox* m_doNotShowBtn;
wxButton* m_overrideBtn;
wxStdDialogButtonSizer* m_sdbSizer;
wxButton* m_sdbSizerOK;
wxButton* m_sdbSizerCancel;
// Virtual event handlers, overide them in your derived class
virtual void OnInitDlg( wxInitDialogEvent& event ) { event.Skip(); }
virtual void onOverrideLocks( wxCommandEvent& event ) { event.Skip(); }
virtual void onCancelClick( wxCommandEvent& event ) { event.Skip(); }
virtual void onOkClick( wxCommandEvent& event ) { event.Skip(); }
public:
DIALOG_LOCKED_ITEMS_QUERY_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Locked Items"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~DIALOG_LOCKED_ITEMS_QUERY_BASE();
};

View File

@ -395,8 +395,7 @@ int CONVERT_TOOL::PolyToLines( const TOOL_EVENT& aEvent )
} }
} }
}, },
nullptr, true /* prompt user regarding locked items */ );
true /* confirm if contains locked items */ );
if( selection.Empty() ) if( selection.Empty() )
return 0; return 0;
@ -572,8 +571,7 @@ int CONVERT_TOOL::SegmentToArc( const TOOL_EVENT& aEvent )
} }
} }
}, },
nullptr, true /* prompt user regarding locked items */ );
true /* confirm if contains locked items */ );
EDA_ITEM* source = selection.Front(); EDA_ITEM* source = selection.Front();
VECTOR2I start, end, mid; VECTOR2I start, end, mid;

View File

@ -124,9 +124,7 @@ void EditToolSelectionFilter( GENERAL_COLLECTOR& aCollector, int aFlags,
EDIT_TOOL::EDIT_TOOL() : EDIT_TOOL::EDIT_TOOL() :
PCB_TOOL_BASE( "pcbnew.InteractiveEdit" ), PCB_TOOL_BASE( "pcbnew.InteractiveEdit" ),
m_selectionTool( NULL ), m_selectionTool( NULL ),
m_dragging( false ), m_dragging( false )
m_dismissInfobarOnNextSel( false ),
m_forceDeleteLockedItems( false )
{ {
} }
@ -306,8 +304,7 @@ int EDIT_TOOL::Drag( const TOOL_EVENT& aEvent )
{ {
EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS, sTool ); EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS, sTool );
}, },
nullptr, true /* prompt user regarding locked items */ );
true /* confirm if contains locked items */ );
if( selection.Empty() ) if( selection.Empty() )
return 0; return 0;
@ -372,8 +369,7 @@ int EDIT_TOOL::doMoveSelection( TOOL_EVENT aEvent, bool aPickReference )
{ {
EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS, sTool ); EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS, sTool );
}, },
nullptr, true /* prompt user regarding locked items */ );
true /* confirm if contains locked items */ );
if( selection.Empty() ) if( selection.Empty() )
return 0; return 0;
@ -628,7 +624,6 @@ int EDIT_TOOL::doMoveSelection( TOOL_EVENT aEvent, bool aPickReference )
} while( ( evt = Wait() ) ); // Assignment (instead of equality test) is intentional } while( ( evt = Wait() ) ); // Assignment (instead of equality test) is intentional
m_forceDeleteLockedItems = false;
controls->ForceCursorPosition( false ); controls->ForceCursorPosition( false );
controls->ShowCursor( false ); controls->ShowCursor( false );
controls->SetAutoPan( false ); controls->SetAutoPan( false );
@ -664,8 +659,7 @@ int EDIT_TOOL::ChangeTrackWidth( const TOOL_EVENT& aEvent )
{ {
EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS, sTool ); EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS, sTool );
}, },
nullptr, true /* prompt user regarding locked items */ );
true /* confirm if contains locked items */ );
for( EDA_ITEM* item : selection ) for( EDA_ITEM* item : selection )
{ {
@ -730,8 +724,7 @@ int EDIT_TOOL::FilletTracks( const TOOL_EVENT& aEvent )
EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS | EXCLUDE_TRANSIENTS, EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS | EXCLUDE_TRANSIENTS,
sTool ); sTool );
}, },
nullptr, !m_dragging /* prompt user regarding locked items */ );
!m_dragging /* confirm if contains locked items */ );
if( selection.Size() < 2 ) if( selection.Size() < 2 )
{ {
@ -981,8 +974,7 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS | EXCLUDE_TRANSIENTS, EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS | EXCLUDE_TRANSIENTS,
sTool ); sTool );
}, },
nullptr, !m_dragging /* prompt user regarding locked items */ );
!m_dragging /* confirm if contains locked items */ );
if( selection.Empty() ) if( selection.Empty() )
return 0; return 0;
@ -1084,8 +1076,7 @@ int EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS | EXCLUDE_TRANSIENTS, EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS | EXCLUDE_TRANSIENTS,
sTool ); sTool );
}, },
nullptr, !m_dragging /* prompt user regarding locked items */ );
!m_dragging /* confirm if contains locked items */ );
if( selection.Empty() ) if( selection.Empty() )
return 0; return 0;
@ -1184,8 +1175,7 @@ int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent )
EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS | EXCLUDE_TRANSIENTS, EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS | EXCLUDE_TRANSIENTS,
sTool ); sTool );
}, },
nullptr, !m_dragging /* prompt user regarding locked items */ );
!m_dragging /* confirm if contains locked items */ );
if( selection.Empty() ) if( selection.Empty() )
return 0; return 0;
@ -1258,7 +1248,9 @@ int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent )
bool isCut = aEvent.Parameter<PCB_ACTIONS::REMOVE_FLAGS>() == PCB_ACTIONS::REMOVE_FLAGS::CUT; bool isCut = aEvent.Parameter<PCB_ACTIONS::REMOVE_FLAGS>() == PCB_ACTIONS::REMOVE_FLAGS::CUT;
bool isAlt = aEvent.Parameter<PCB_ACTIONS::REMOVE_FLAGS>() == PCB_ACTIONS::REMOVE_FLAGS::ALT; bool isAlt = aEvent.Parameter<PCB_ACTIONS::REMOVE_FLAGS>() == PCB_ACTIONS::REMOVE_FLAGS::ALT;
// If we are in a "Cut" operation, then the copied selection exists already // If we are in a "Cut" operation, then the copied selection exists already and we want to
// delete exactly that; no more, no fewer. Any filtering for locked items must be done in
// the copyToClipboard() routine.
if( isCut ) if( isCut )
{ {
selectionCopy = m_selectionTool->GetSelection(); selectionCopy = m_selectionTool->GetSelection();
@ -1270,7 +1262,8 @@ int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent )
{ {
EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS | EXCLUDE_TRANSIENTS, EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS | EXCLUDE_TRANSIENTS,
sTool ); sTool );
} ); },
true /* prompt user regarding locked items */ );
} }
bool isHover = selectionCopy.IsHover(); bool isHover = selectionCopy.IsHover();
@ -1286,21 +1279,6 @@ int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent )
if( selectionCopy.Empty() ) if( selectionCopy.Empty() )
return 0; return 0;
// N.B. Setting the CUT flag prevents lock filtering as we only want to delete the items that
// were copied to the clipboard, no more, no fewer. Any filtering for locked items will be
// done in the copyToClipboard() routine
if( !m_forceDeleteLockedItems && !isCut )
{
// Second RequestSelection removes locked items but keeps a copy of their pointers
selectionCopy = m_selectionTool->RequestSelection(
[]( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, SELECTION_TOOL* sTool )
{
EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED, sTool );
},
&lockedItems );
}
// As we are about to remove items, they have to be removed from the selection first // As we are about to remove items, they have to be removed from the selection first
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true ); m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
@ -1451,34 +1429,6 @@ int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent )
else else
m_commit->Push( _( "Delete" ) ); m_commit->Push( _( "Delete" ) );
if( !m_forceDeleteLockedItems && !lockedItems.empty() )
{
m_toolMgr->RunAction( PCB_ACTIONS::selectItems, true, &lockedItems );
WX_INFOBAR* infobar = frame()->GetInfoBar();
wxString msg = _( "Locked items in the selection were not deleted." );
wxString link = _( "Delete locked items" );
wxHyperlinkCtrl* button = new wxHyperlinkCtrl( infobar, wxID_ANY, link, wxEmptyString );
button->Bind( wxEVT_COMMAND_HYPERLINK, std::function<void( wxHyperlinkEvent& aEvent )>(
[&]( wxHyperlinkEvent& aEvent )
{
m_forceDeleteLockedItems = true;
{
m_toolMgr->RunAction( ACTIONS::doDelete, true );
}
m_forceDeleteLockedItems = false;
frame()->GetInfoBar()->Dismiss();
m_dismissInfobarOnNextSel = false;
} ) );
infobar->RemoveAllButtons();
infobar->AddButton( button );
infobar->ShowMessageFor( msg, 4000, wxICON_INFORMATION );
m_dismissInfobarOnNextSel = true;
}
return 0; return 0;
} }
@ -1497,8 +1447,7 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent )
EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS | EXCLUDE_TRANSIENTS, EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED_PADS | EXCLUDE_TRANSIENTS,
sTool ); sTool );
}, },
nullptr, true /* prompt user regarding locked items */ );
true /* confirm if contains locked items */ );
if( selection.Empty() ) if( selection.Empty() )
return 0; return 0;
@ -1938,18 +1887,6 @@ int EDIT_TOOL::cutToClipboard( const TOOL_EVENT& aEvent )
} }
int EDIT_TOOL::onSelectionEvent( const TOOL_EVENT& aEvent )
{
if( m_dismissInfobarOnNextSel )
{
frame()->GetInfoBar()->Dismiss();
m_dismissInfobarOnNextSel = false;
}
return 0;
}
void EDIT_TOOL::setTransitions() void EDIT_TOOL::setTransitions()
{ {
Go( &EDIT_TOOL::GetAndPlace, PCB_ACTIONS::getAndPlace.MakeEvent() ); Go( &EDIT_TOOL::GetAndPlace, PCB_ACTIONS::getAndPlace.MakeEvent() );
@ -1974,9 +1911,6 @@ void EDIT_TOOL::setTransitions()
Go( &EDIT_TOOL::copyToClipboard, ACTIONS::copy.MakeEvent() ); Go( &EDIT_TOOL::copyToClipboard, ACTIONS::copy.MakeEvent() );
Go( &EDIT_TOOL::copyToClipboard, PCB_ACTIONS::copyWithReference.MakeEvent() ); Go( &EDIT_TOOL::copyToClipboard, PCB_ACTIONS::copyWithReference.MakeEvent() );
Go( &EDIT_TOOL::cutToClipboard, ACTIONS::cut.MakeEvent() ); Go( &EDIT_TOOL::cutToClipboard, ACTIONS::cut.MakeEvent() );
Go( &EDIT_TOOL::onSelectionEvent, EVENTS::SelectedEvent );
Go( &EDIT_TOOL::onSelectionEvent, EVENTS::UnselectedEvent );
} }

View File

@ -203,14 +203,10 @@ private:
bool pickReferencePoint( const wxString& aTooltip, const wxString& aSuccessMessage, bool pickReferencePoint( const wxString& aTooltip, const wxString& aSuccessMessage,
const wxString& aCanceledMessage, VECTOR2I& aReferencePoint ); const wxString& aCanceledMessage, VECTOR2I& aReferencePoint );
int onSelectionEvent( const TOOL_EVENT& aEvent );
private: private:
SELECTION_TOOL* m_selectionTool; // Selection tool used for obtaining selected items SELECTION_TOOL* m_selectionTool; // Selection tool used for obtaining selected items
bool m_dragging; // Indicates objects are being dragged right now bool m_dragging; // Indicates objects are being dragged right now
bool m_dismissInfobarOnNextSel;
bool m_forceDeleteLockedItems; // Delete even locked items if set
VECTOR2I m_cursor; // Last cursor position (needed for getModificationPoint() VECTOR2I m_cursor; // Last cursor position (needed for getModificationPoint()
// to avoid changes of edit reference point). // to avoid changes of edit reference point).

View File

@ -142,23 +142,28 @@ template< typename T >
size_t ALIGN_DISTRIBUTE_TOOL::GetSelections( ALIGNMENT_RECTS& aItems, ALIGNMENT_RECTS& aLocked, size_t ALIGN_DISTRIBUTE_TOOL::GetSelections( ALIGNMENT_RECTS& aItems, ALIGNMENT_RECTS& aLocked,
T aCompare ) T aCompare )
{ {
PCBNEW_SELECTION& selection = m_selectionTool->RequestSelection( PCBNEW_SELECTION& selection = m_selectionTool->RequestSelection(
[]( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, SELECTION_TOOL* sTool ) []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, SELECTION_TOOL* sTool )
{ {
EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS, sTool ); EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS, sTool );
} ); } );
if( selection.Size() <= 1 )
return 0;
std::vector<BOARD_ITEM*> lockedItems; std::vector<BOARD_ITEM*> lockedItems;
for( EDA_ITEM* item : selection )
{
BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
if( boardItem->IsLocked() )
lockedItems.push_back( boardItem );
}
selection = m_selectionTool->RequestSelection( selection = m_selectionTool->RequestSelection(
[]( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, SELECTION_TOOL* sTool ) []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, SELECTION_TOOL* sTool )
{ {
EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED, sTool ); EditToolSelectionFilter( aCollector, EXCLUDE_LOCKED, sTool );
}, },
&lockedItems ); true /* prompt user regarding locked items */ );
aItems = GetBoundingBoxes( selection ); aItems = GetBoundingBoxes( selection );
aLocked = GetBoundingBoxes( lockedItems ); aLocked = GetBoundingBoxes( lockedItems );
@ -174,17 +179,25 @@ int ALIGN_DISTRIBUTE_TOOL::AlignTop( const TOOL_EVENT& aEvent )
ALIGNMENT_RECTS itemsToAlign; ALIGNMENT_RECTS itemsToAlign;
ALIGNMENT_RECTS locked_items; ALIGNMENT_RECTS locked_items;
if( !GetSelections( itemsToAlign, locked_items, []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right) if( !GetSelections( itemsToAlign, locked_items,
{ return ( left.second.GetTop() < right.second.GetTop() ); } ) ) []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
{
return ( left.second.GetTop() < right.second.GetTop() );
} ) )
{
return 0; return 0;
}
BOARD_COMMIT commit( m_frame ); BOARD_COMMIT commit( m_frame );
commit.StageItems( m_selectionTool->GetSelection(), CHT_MODIFY ); commit.StageItems( m_selectionTool->GetSelection(), CHT_MODIFY );
auto targetTop = selectTarget( itemsToAlign, locked_items, []( const ALIGNMENT_RECT& aVal ) int targetTop = selectTarget( itemsToAlign, locked_items,
{ return aVal.second.GetTop(); } ); []( const ALIGNMENT_RECT& aVal )
{
return aVal.second.GetTop();
} );
// Move the selected items // Move the selected items
for( auto& i : itemsToAlign ) for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToAlign )
{ {
int difference = targetTop - i.second.GetTop(); int difference = targetTop - i.second.GetTop();
BOARD_ITEM* item = i.first; BOARD_ITEM* item = i.first;
@ -207,17 +220,25 @@ int ALIGN_DISTRIBUTE_TOOL::AlignBottom( const TOOL_EVENT& aEvent )
ALIGNMENT_RECTS itemsToAlign; ALIGNMENT_RECTS itemsToAlign;
ALIGNMENT_RECTS locked_items; ALIGNMENT_RECTS locked_items;
if( !GetSelections( itemsToAlign, locked_items, []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right) if( !GetSelections( itemsToAlign, locked_items,
{ return ( left.second.GetBottom() < right.second.GetBottom() ); } ) ) []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
{
return ( left.second.GetBottom() < right.second.GetBottom() );
} ) )
{
return 0; return 0;
}
BOARD_COMMIT commit( m_frame ); BOARD_COMMIT commit( m_frame );
commit.StageItems( m_selectionTool->GetSelection(), CHT_MODIFY ); commit.StageItems( m_selectionTool->GetSelection(), CHT_MODIFY );
auto targetBottom = selectTarget( itemsToAlign, locked_items, []( const ALIGNMENT_RECT& aVal ) auto targetBottom = selectTarget( itemsToAlign, locked_items,
{ return aVal.second.GetBottom(); } ); []( const ALIGNMENT_RECT& aVal )
{
return aVal.second.GetBottom();
} );
// Move the selected items // Move the selected items
for( auto& i : itemsToAlign ) for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToAlign )
{ {
int difference = targetBottom - i.second.GetBottom(); int difference = targetBottom - i.second.GetBottom();
BOARD_ITEM* item = i.first; BOARD_ITEM* item = i.first;
@ -255,17 +276,25 @@ int ALIGN_DISTRIBUTE_TOOL::doAlignLeft()
ALIGNMENT_RECTS itemsToAlign; ALIGNMENT_RECTS itemsToAlign;
ALIGNMENT_RECTS locked_items; ALIGNMENT_RECTS locked_items;
if( !GetSelections( itemsToAlign, locked_items, []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right) if( !GetSelections( itemsToAlign, locked_items,
{ return ( left.second.GetLeft() < right.second.GetLeft() ); } ) ) []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
{
return ( left.second.GetLeft() < right.second.GetLeft() );
} ) )
{
return 0; return 0;
}
BOARD_COMMIT commit( m_frame ); BOARD_COMMIT commit( m_frame );
commit.StageItems( m_selectionTool->GetSelection(), CHT_MODIFY ); commit.StageItems( m_selectionTool->GetSelection(), CHT_MODIFY );
auto targetLeft = selectTarget( itemsToAlign, locked_items, []( const ALIGNMENT_RECT& aVal ) auto targetLeft = selectTarget( itemsToAlign, locked_items,
{ return aVal.second.GetLeft(); } ); []( const ALIGNMENT_RECT& aVal )
{
return aVal.second.GetLeft();
} );
// Move the selected items // Move the selected items
for( auto& i : itemsToAlign ) for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToAlign )
{ {
int difference = targetLeft - i.second.GetLeft(); int difference = targetLeft - i.second.GetLeft();
BOARD_ITEM* item = i.first; BOARD_ITEM* item = i.first;
@ -303,17 +332,25 @@ int ALIGN_DISTRIBUTE_TOOL::doAlignRight()
ALIGNMENT_RECTS itemsToAlign; ALIGNMENT_RECTS itemsToAlign;
ALIGNMENT_RECTS locked_items; ALIGNMENT_RECTS locked_items;
if( !GetSelections( itemsToAlign, locked_items, []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right) if( !GetSelections( itemsToAlign, locked_items,
{ return ( left.second.GetRight() < right.second.GetRight() ); } ) ) []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
{
return ( left.second.GetRight() < right.second.GetRight() );
} ) )
{
return 0; return 0;
}
BOARD_COMMIT commit( m_frame ); BOARD_COMMIT commit( m_frame );
commit.StageItems( m_selectionTool->GetSelection(), CHT_MODIFY ); commit.StageItems( m_selectionTool->GetSelection(), CHT_MODIFY );
auto targetRight = selectTarget( itemsToAlign, locked_items, []( const ALIGNMENT_RECT& aVal ) auto targetRight = selectTarget( itemsToAlign, locked_items,
{ return aVal.second.GetRight(); } ); []( const ALIGNMENT_RECT& aVal )
{
return aVal.second.GetRight();
} );
// Move the selected items // Move the selected items
for( auto& i : itemsToAlign ) for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToAlign )
{ {
int difference = targetRight - i.second.GetRight(); int difference = targetRight - i.second.GetRight();
BOARD_ITEM* item = i.first; BOARD_ITEM* item = i.first;
@ -336,17 +373,25 @@ int ALIGN_DISTRIBUTE_TOOL::AlignCenterX( const TOOL_EVENT& aEvent )
ALIGNMENT_RECTS itemsToAlign; ALIGNMENT_RECTS itemsToAlign;
ALIGNMENT_RECTS locked_items; ALIGNMENT_RECTS locked_items;
if( !GetSelections( itemsToAlign, locked_items, []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right) if( !GetSelections( itemsToAlign, locked_items,
{ return ( left.second.GetCenter().x < right.second.GetCenter().x ); } ) ) []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
{
return ( left.second.GetCenter().x < right.second.GetCenter().x );
} ) )
{
return 0; return 0;
}
BOARD_COMMIT commit( m_frame ); BOARD_COMMIT commit( m_frame );
commit.StageItems( m_selectionTool->GetSelection(), CHT_MODIFY ); commit.StageItems( m_selectionTool->GetSelection(), CHT_MODIFY );
auto targetX = selectTarget( itemsToAlign, locked_items, []( const ALIGNMENT_RECT& aVal ) auto targetX = selectTarget( itemsToAlign, locked_items,
{ return aVal.second.GetCenter().x; } ); []( const ALIGNMENT_RECT& aVal )
{
return aVal.second.GetCenter().x;
} );
// Move the selected items // Move the selected items
for( auto& i : itemsToAlign ) for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToAlign )
{ {
int difference = targetX - i.second.GetCenter().x; int difference = targetX - i.second.GetCenter().x;
BOARD_ITEM* item = i.first; BOARD_ITEM* item = i.first;
@ -369,17 +414,25 @@ int ALIGN_DISTRIBUTE_TOOL::AlignCenterY( const TOOL_EVENT& aEvent )
ALIGNMENT_RECTS itemsToAlign; ALIGNMENT_RECTS itemsToAlign;
ALIGNMENT_RECTS locked_items; ALIGNMENT_RECTS locked_items;
if( !GetSelections( itemsToAlign, locked_items, []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right) if( !GetSelections( itemsToAlign, locked_items,
{ return ( left.second.GetCenter().y < right.second.GetCenter().y ); } ) ) []( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
{
return ( left.second.GetCenter().y < right.second.GetCenter().y );
} ) )
{
return 0; return 0;
}
BOARD_COMMIT commit( m_frame ); BOARD_COMMIT commit( m_frame );
commit.StageItems( m_selectionTool->GetSelection(), CHT_MODIFY ); commit.StageItems( m_selectionTool->GetSelection(), CHT_MODIFY );
auto targetY = selectTarget( itemsToAlign, locked_items, []( const ALIGNMENT_RECT& aVal ) auto targetY = selectTarget( itemsToAlign, locked_items,
{ return aVal.second.GetCenter().y; } ); []( const ALIGNMENT_RECT& aVal )
{
return aVal.second.GetCenter().y;
} );
// Move the selected items // Move the selected items
for( auto& i : itemsToAlign ) for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToAlign )
{ {
int difference = targetY - i.second.GetCenter().y; int difference = targetY - i.second.GetCenter().y;
BOARD_ITEM* item = i.first; BOARD_ITEM* item = i.first;
@ -404,8 +457,7 @@ int ALIGN_DISTRIBUTE_TOOL::DistributeHorizontally( const TOOL_EVENT& aEvent )
{ {
EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS, sTool ); EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS, sTool );
}, },
nullptr, true /* prompt user regarding locked items */ );
true /* confirm if contains locked items */ );
if( selection.Size() <= 1 ) if( selection.Size() <= 1 )
return 0; return 0;
@ -418,7 +470,9 @@ int ALIGN_DISTRIBUTE_TOOL::DistributeHorizontally( const TOOL_EVENT& aEvent )
// find the last item by reverse sorting // find the last item by reverse sorting
std::sort( itemsToDistribute.begin(), itemsToDistribute.end(), std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
[] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right) [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
{ return ( left.second.GetRight() > right.second.GetRight() ); } ); {
return ( left.second.GetRight() > right.second.GetRight() );
} );
const auto lastItem = itemsToDistribute.begin()->first; const auto lastItem = itemsToDistribute.begin()->first;
const auto maxRight = itemsToDistribute.begin()->second.GetRight(); const auto maxRight = itemsToDistribute.begin()->second.GetRight();
@ -426,12 +480,14 @@ int ALIGN_DISTRIBUTE_TOOL::DistributeHorizontally( const TOOL_EVENT& aEvent )
// sort to get starting order // sort to get starting order
std::sort( itemsToDistribute.begin(), itemsToDistribute.end(), std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
[] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right) [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
{ return ( left.second.GetX() < right.second.GetX() ); } ); {
return ( left.second.GetX() < right.second.GetX() );
} );
const auto minX = itemsToDistribute.begin()->second.GetX(); const auto minX = itemsToDistribute.begin()->second.GetX();
auto totalGap = maxRight - minX; auto totalGap = maxRight - minX;
int totalWidth = 0; int totalWidth = 0;
for( auto& i : itemsToDistribute ) for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToDistribute )
{ {
totalWidth += i.second.GetWidth(); totalWidth += i.second.GetWidth();
} }
@ -454,12 +510,13 @@ int ALIGN_DISTRIBUTE_TOOL::DistributeHorizontally( const TOOL_EVENT& aEvent )
void ALIGN_DISTRIBUTE_TOOL::doDistributeGapsHorizontally( ALIGNMENT_RECTS& itemsToDistribute, void ALIGN_DISTRIBUTE_TOOL::doDistributeGapsHorizontally( ALIGNMENT_RECTS& itemsToDistribute,
const BOARD_ITEM* lastItem, int totalGap ) const const BOARD_ITEM* lastItem,
int totalGap ) const
{ {
const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 ); const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
auto targetX = itemsToDistribute.begin()->second.GetX(); auto targetX = itemsToDistribute.begin()->second.GetX();
for( auto& i : itemsToDistribute ) for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToDistribute )
{ {
BOARD_ITEM* item = i.first; BOARD_ITEM* item = i.first;
@ -482,13 +539,15 @@ void ALIGN_DISTRIBUTE_TOOL::doDistributeCentersHorizontally( ALIGNMENT_RECTS &it
{ {
std::sort( itemsToDistribute.begin(), itemsToDistribute.end(), std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
[] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right) [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
{ return ( left.second.GetCenter().x < right.second.GetCenter().x ); } ); {
return ( left.second.GetCenter().x < right.second.GetCenter().x );
} );
const auto totalGap = ( itemsToDistribute.end()-1 )->second.GetCenter().x const auto totalGap = ( itemsToDistribute.end()-1 )->second.GetCenter().x
- itemsToDistribute.begin()->second.GetCenter().x; - itemsToDistribute.begin()->second.GetCenter().x;
const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 ); const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
auto targetX = itemsToDistribute.begin()->second.GetCenter().x; auto targetX = itemsToDistribute.begin()->second.GetCenter().x;
for( auto& i : itemsToDistribute ) for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToDistribute )
{ {
BOARD_ITEM* item = i.first; BOARD_ITEM* item = i.first;
@ -510,8 +569,7 @@ int ALIGN_DISTRIBUTE_TOOL::DistributeVertically( const TOOL_EVENT& aEvent )
{ {
EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS, sTool ); EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS, sTool );
}, },
nullptr, true /* prompt user regarding locked items */ );
true /* confirm if contains locked items */ );
if( selection.Size() <= 1 ) if( selection.Size() <= 1 )
return 0; return 0;
@ -524,20 +582,24 @@ int ALIGN_DISTRIBUTE_TOOL::DistributeVertically( const TOOL_EVENT& aEvent )
// find the last item by reverse sorting // find the last item by reverse sorting
std::sort( itemsToDistribute.begin(), itemsToDistribute.end(), std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
[] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right) [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
{ return ( left.second.GetBottom() > right.second.GetBottom() ); } ); {
return ( left.second.GetBottom() > right.second.GetBottom() );
} );
const auto maxBottom = itemsToDistribute.begin()->second.GetBottom(); const auto maxBottom = itemsToDistribute.begin()->second.GetBottom();
const auto lastItem = itemsToDistribute.begin()->first; const auto lastItem = itemsToDistribute.begin()->first;
// sort to get starting order // sort to get starting order
std::sort( itemsToDistribute.begin(), itemsToDistribute.end(), std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
[] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right) [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
{ return ( left.second.GetCenter().y < right.second.GetCenter().y ); } ); {
return ( left.second.GetCenter().y < right.second.GetCenter().y );
} );
auto minY = itemsToDistribute.begin()->second.GetY(); auto minY = itemsToDistribute.begin()->second.GetY();
auto totalGap = maxBottom - minY; auto totalGap = maxBottom - minY;
int totalHeight = 0; int totalHeight = 0;
for( auto& i : itemsToDistribute ) for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToDistribute )
{ {
totalHeight += i.second.GetHeight(); totalHeight += i.second.GetHeight();
} }
@ -565,7 +627,7 @@ void ALIGN_DISTRIBUTE_TOOL::doDistributeGapsVertically( ALIGNMENT_RECTS& itemsTo
const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 ); const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
auto targetY = itemsToDistribute.begin()->second.GetY(); auto targetY = itemsToDistribute.begin()->second.GetY();
for( auto& i : itemsToDistribute ) for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToDistribute )
{ {
BOARD_ITEM* item = i.first; BOARD_ITEM* item = i.first;
@ -588,13 +650,15 @@ void ALIGN_DISTRIBUTE_TOOL::doDistributeCentersVertically( ALIGNMENT_RECTS& item
{ {
std::sort( itemsToDistribute.begin(), itemsToDistribute.end(), std::sort( itemsToDistribute.begin(), itemsToDistribute.end(),
[] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right) [] ( const ALIGNMENT_RECT left, const ALIGNMENT_RECT right)
{ return ( left.second.GetCenter().y < right.second.GetCenter().y ); } ); {
return ( left.second.GetCenter().y < right.second.GetCenter().y );
} );
const auto totalGap = ( itemsToDistribute.end()-1 )->second.GetCenter().y const auto totalGap = ( itemsToDistribute.end()-1 )->second.GetCenter().y
- itemsToDistribute.begin()->second.GetCenter().y; - itemsToDistribute.begin()->second.GetCenter().y;
const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 ); const auto itemGap = totalGap / ( itemsToDistribute.size() - 1 );
auto targetY = itemsToDistribute.begin()->second.GetCenter().y; auto targetY = itemsToDistribute.begin()->second.GetCenter().y;
for( auto& i : itemsToDistribute ) for( std::pair<BOARD_ITEM*, EDA_RECT>& i : itemsToDistribute )
{ {
BOARD_ITEM* item = i.first; BOARD_ITEM* item = i.first;

View File

@ -71,8 +71,7 @@ int POSITION_RELATIVE_TOOL::PositionRelative( const TOOL_EVENT& aEvent )
{ {
EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS, sTool ); EditToolSelectionFilter( aCollector, EXCLUDE_TRANSIENTS, sTool );
}, },
nullptr, true /* prompt user regarding locked items */ );
true /* confirm if contains locked items */ );
if( selection.Empty() ) if( selection.Empty() )
return 0; return 0;

View File

@ -40,6 +40,7 @@ using namespace std::placeholders;
#include <confirm.h> #include <confirm.h>
#include <dialog_find.h> #include <dialog_find.h>
#include <dialog_filter_selection.h> #include <dialog_filter_selection.h>
#include <dialog_locked_items_query.h>
#include <class_draw_panel_gal.h> #include <class_draw_panel_gal.h>
#include <view/view_controls.h> #include <view/view_controls.h>
#include <preview_items/selection_area.h> #include <preview_items/selection_area.h>
@ -461,7 +462,6 @@ PCBNEW_SELECTION& SELECTION_TOOL::GetSelection()
PCBNEW_SELECTION& SELECTION_TOOL::RequestSelection( CLIENT_SELECTION_FILTER aClientFilter, PCBNEW_SELECTION& SELECTION_TOOL::RequestSelection( CLIENT_SELECTION_FILTER aClientFilter,
std::vector<BOARD_ITEM*>* aFiltered,
bool aConfirmLockedItems ) bool aConfirmLockedItems )
{ {
bool selectionEmpty = m_selection.Empty(); bool selectionEmpty = m_selection.Empty();
@ -475,14 +475,36 @@ PCBNEW_SELECTION& SELECTION_TOOL::RequestSelection( CLIENT_SELECTION_FILTER aCli
if( aConfirmLockedItems ) if( aConfirmLockedItems )
{ {
// Check if the selection contains locked items std::vector<BOARD_ITEM*> lockedItems;
for( EDA_ITEM* item : m_selection ) for( EDA_ITEM* item : m_selection )
{ {
if( static_cast<BOARD_ITEM*>( item )->IsLocked() ) BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
{
if( !IsOK( m_frame, _( "Selection contains locked items. Continue anyway?" ) ) )
ClearSelection();
if( boardItem->IsLocked() )
lockedItems.push_back( boardItem );
}
if( !lockedItems.empty() )
{
DIALOG_LOCKED_ITEMS_QUERY dlg( frame(), lockedItems.size() );
switch( dlg.ShowModal() )
{
case wxID_OK:
// remove locked items from selection
for( BOARD_ITEM* item : lockedItems )
unselect( item );
break;
case wxID_CANCEL:
// cancel operation
ClearSelection();
break;
case wxID_APPLY:
// continue with operation with current selection
break; break;
} }
} }
@ -523,9 +545,6 @@ PCBNEW_SELECTION& SELECTION_TOOL::RequestSelection( CLIENT_SELECTION_FILTER aCli
if( disposition == BEFORE ) if( disposition == BEFORE )
{ {
if( aFiltered )
aFiltered->push_back( item );
unhighlight( item, SELECTED, &m_selection ); unhighlight( item, SELECTED, &m_selection );
} }
} }

View File

@ -90,13 +90,14 @@ public:
/** /**
* Function RequestSelection() * Function RequestSelection()
* *
* Returns the current selection set, filtered according to aFlags * Returns the current selection set, filtered according to aFlags and aClientFilter.
* and aClientFilter.
* If the set is empty, performs the legacy-style hover selection. * If the set is empty, performs the legacy-style hover selection.
* @param aFiltered is an optional vector, that is filled with items removed by the filter *
* @param aConfirmLockedItems if true the user will be prompted if they want to drop locked
* items from the selection or override the locks
*/ */
PCBNEW_SELECTION& RequestSelection( CLIENT_SELECTION_FILTER aClientFilter, PCBNEW_SELECTION& RequestSelection( CLIENT_SELECTION_FILTER aClientFilter,
std::vector<BOARD_ITEM*>* aFiltered = nullptr, bool aConfirmLockedItems = false ); bool aConfirmLockedItems = false );
///> Select a single item under cursor event handler. ///> Select a single item under cursor event handler.
int CursorSelection( const TOOL_EVENT& aEvent ); int CursorSelection( const TOOL_EVENT& aEvent );

View File

@ -526,7 +526,6 @@ PCBNEW_SELECTION& SELECTION_TOOL::GetSelection()
PCBNEW_SELECTION& SELECTION_TOOL::RequestSelection( CLIENT_SELECTION_FILTER aClientFilter, PCBNEW_SELECTION& SELECTION_TOOL::RequestSelection( CLIENT_SELECTION_FILTER aClientFilter,
std::vector<BOARD_ITEM*>* aFiltered,
bool aConfirmLockedItems ) bool aConfirmLockedItems )
{ {