37#include <wx/display.h>
38#include <wx/evtloop.h>
43#include <wx/propgrid/propgrid.h>
44#include <wx/checklst.h>
45#include <wx/dataview.h>
46#include <wx/bmpbuttn.h>
47#include <wx/textctrl.h>
48#include <wx/stc/stc.h>
49#include <wx/combobox.h>
50#include <wx/odcombo.h>
52#include <wx/checkbox.h>
53#include <wx/spinctrl.h>
54#include <wx/splitter.h>
55#include <wx/radiobox.h>
56#include <wx/radiobut.h>
57#include <wx/variant.h>
61#include <nlohmann/json.hpp>
77 std::string title = aTitle.ToStdString();
78 size_t parenPos = title.rfind(
'(' );
80 if( parenPos != std::string::npos && parenPos > 0 )
82 size_t end = parenPos;
84 while(
end > 0 && title[
end - 1] ==
' ' )
87 return title.substr( 0,
end );
95 const wxSize& size,
long style,
const wxString&
name ) :
96 wxDialog( aParent, id, title, pos, size, style,
name ),
119 while( !kiwayHolder && aParent->GetParent() )
121 aParent = aParent->GetParent();
135 m_parentFrame = static_cast<EDA_BASE_FRAME*>( kiwayHolder );
136 TOOL_MANAGER* toolMgr = m_parentFrame->GetToolManager();
138 if( toolMgr && toolMgr->IsContextMenuActive() )
139 toolMgr->VetoContextMenuMouseWarp();
147 Kiway().SetBlockingDialog(
this );
165 wxString msg = wxString::Format(
"Opening dialog %s", GetTitle() );
181 std::function<void( wxWindowList& )> disconnectFocusHandlers =
182 [&]( wxWindowList& children )
184 for( wxWindow* child : children )
186 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
191 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
198 disconnectFocusHandlers( child->GetChildren() );
203 disconnectFocusHandlers( GetChildren() );
205 std::function<void( wxWindowList& )> disconnectUndoRedoHandlers =
206 [&]( wxWindowList& children )
208 for( wxWindow* child : children )
210 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
214 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
218 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( child ) )
223 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( child ) )
227 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( child ) )
231 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( child ) )
236 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( child ) )
241 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( child ) )
245 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( child ) )
249 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( child ) )
253 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( child ) )
257 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( child ) )
261 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( child ) )
267 disconnectUndoRedoHandlers( child->GetChildren() );
272 disconnectUndoRedoHandlers( GetChildren() );
277 binder->DetachFromDialogShim();
296 if( wxSizer* sz = GetSizer() )
313 GetSizer()->SetSizeHints(
this );
321 int displayIdx = wxDisplay::GetFromWindow(
this );
323 if( displayIdx == wxNOT_FOUND && m_parent )
324 displayIdx = wxDisplay::GetFromWindow( m_parent );
326 if( displayIdx == wxNOT_FOUND )
329 wxSize workArea = wxDisplay( (
unsigned int) displayIdx ).GetClientArea().GetSize();
331 if( workArea.x <= 0 || workArea.y <= 0 )
335 wxSize clampedMin( std::min(
minSize.x, workArea.x ), std::min(
minSize.y, workArea.y ) );
338 SetMinSize( clampedMin );
340 wxSize size = GetSize();
341 wxSize clampedSize( std::min( size.x, workArea.x ), std::min( size.y, workArea.y ) );
343 if( clampedSize != size )
344 SetSize( clampedSize );
351 SetSize( ConvertDialogToPixels( sz ) );
358 return ConvertDialogToPixels( sz ).x;
365 return ConvertDialogToPixels( sz ).y;
377 wxDialog::SetPosition( aNewPosition );
384 wxWindow* target = toolCanvas ? toolCanvas : m_parent;
391 if( !aDeferUntilFrameActive || !toolCanvas )
427 ret = wxDialog::Show( show );
429 wxRect savedDialogRect;
434 auto dlgIt = settings->CsInternals().m_dialogControlValues.find( key );
436 if( dlgIt != settings->CsInternals().m_dialogControlValues.end() )
438 auto geoIt = dlgIt->second.find(
"__geometry" );
440 if( geoIt != dlgIt->second.end() && geoIt->second.is_object() )
442 const nlohmann::json& g = geoIt->second;
443 savedDialogRect.SetPosition( wxPoint( g.value(
"x", 0 ), g.value(
"y", 0 ) ) );
444 savedDialogRect.SetSize( wxSize( g.value(
"w", 500 ), g.value(
"h", 300 ) ) );
449 if( savedDialogRect.GetSize().x != 0 && savedDialogRect.GetSize().y != 0 )
452 wxSize restoredSize = FromDIP( savedDialogRect.GetSize() );
456 SetSize( savedDialogRect.GetPosition().x, savedDialogRect.GetPosition().y,
457 wxDialog::GetSize().x, wxDialog::GetSize().y, 0 );
461 SetSize( savedDialogRect.GetPosition().x, savedDialogRect.GetPosition().y,
462 std::max( wxDialog::GetSize().x, restoredSize.x ),
463 std::max( wxDialog::GetSize().y, restoredSize.y ), 0 );
469 SetMinSize( wxDefaultSize );
470 InvalidateBestSize();
471 SetMinSize( GetBestSize() );
475 if( m_parent !=
nullptr )
477 if( wxDisplay::GetFromPoint( m_parent->GetPosition() )
478 != wxDisplay::GetFromPoint( savedDialogRect.GetPosition() ) )
494 wxPoint grabPoint = GetPosition();
495 grabPoint.x += GetSize().x / 2;
496 grabPoint.y += FromDIP( 15 );
498 if( wxDisplay::GetFromPoint( grabPoint ) == wxNOT_FOUND )
515 m_eventLoop->Exit( GetReturnCode() );
518 ret = wxDialog::Show( show );
534 auto dlgIt = settings->CsInternals().m_dialogControlValues.find( key );
536 if( dlgIt == settings->CsInternals().m_dialogControlValues.end() )
539 dlgIt->second.erase(
"__geometry" );
558 int parentDisplay = wxDisplay::GetFromWindow( m_parent );
559 int myDisplay = wxDisplay::GetFromWindow(
this );
561 if( parentDisplay != wxNOT_FOUND && myDisplay != wxNOT_FOUND )
586 return wxDialog::Enable( enable );
592 auto getSiblingIndex =
593 [](
const wxWindow* parent,
const wxWindow* child )
595 wxString childClass = child->GetClassInfo()->GetClassName();
598 for(
const wxWindow* sibling : parent->GetChildren() )
600 if( sibling->GetClassInfo()->GetClassName() != childClass )
603 if( sibling == child )
613 [&](
const wxWindow* window )
615 std::string key = wxString( window->GetClassInfo()->GetClassName() ).ToStdString();
617 if( window->GetParent() )
618 key +=
"_" + std::to_string( getSiblingIndex( window->GetParent(), window ) );
623 std::string key =
makeKey( aWin );
625 for(
const wxWindow* parent = aWin->GetParent(); parent && parent !=
this; parent = parent->GetParent() )
642 wxPoint pos = GetPosition();
643 wxSize dipSize = ToDIP( GetSize() );
647 geom[
"w" ] = dipSize.x;
648 geom[
"h" ] = dipSize.y;
649 dlgMap[
"__geometry" ] = geom;
651 std::function<void( wxWindow* )> saveFn =
656 if( !props->GetPropertyOr(
"persist",
false ) )
668 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( win ) )
670 dlgMap[ key ] = combo->GetValue();
672 else if( wxOwnerDrawnComboBox* od_combo =
dynamic_cast<wxOwnerDrawnComboBox*
>( win ) )
674 dlgMap[ key ] = od_combo->GetSelection();
676 else if( wxTextEntry* textEntry =
dynamic_cast<wxTextEntry*
>( win ) )
678 dlgMap[ key ] = textEntry->GetValue();
680 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( win ) )
682 dlgMap[ key ] = choice->GetSelection();
684 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( win ) )
686 dlgMap[ key ] = check->GetValue();
688 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( win ) )
690 dlgMap[ key ] = spin->GetValue();
692 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( win ) )
694 dlgMap[ key ] = radio->GetValue();
696 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( win ) )
698 dlgMap[ key ] = radioBox->GetSelection();
700 else if( wxSplitterWindow* splitter =
dynamic_cast<wxSplitterWindow*
>( win ) )
702 dlgMap[ key ] = splitter->GetSashPosition();
704 else if( wxScrolledWindow* scrolled =
dynamic_cast<wxScrolledWindow*
>( win ) )
706 dlgMap[ key ] = scrolled->GetScrollPos( wxVERTICAL );
708 else if( wxNotebook* notebook =
dynamic_cast<wxNotebook*
>( win ) )
710 int index = notebook->GetSelection();
712 if(
index >= 0 &&
index < (
int) notebook->GetPageCount() )
713 dlgMap[ key ] = notebook->GetPageText( notebook->GetSelection() );
715 else if( wxAuiNotebook* auiNotebook =
dynamic_cast<wxAuiNotebook*
>( win ) )
717 int index = auiNotebook->GetSelection();
719 if(
index >= 0 &&
index < (
int) auiNotebook->GetPageCount() )
720 dlgMap[ key ] = auiNotebook->GetPageText( auiNotebook->GetSelection() );
724 dlgMap[ key ] =
grid->GetShownColumnsAsString();
728 for( wxWindow* child : win->GetChildren() )
734 if( !props->GetPropertyOr(
"persist",
false ) )
738 for( wxWindow* child : GetChildren() )
756 const std::map<std::string, nlohmann::json>& dlgMap = dlgIt->second;
758 std::function<void( wxWindow* )> loadFn =
763 if( !props->GetPropertyOr(
"persist",
false ) )
771 auto it = dlgMap.find( key );
773 if( it != dlgMap.end() )
775 const nlohmann::json& j = it->second;
779 if( j.is_number_integer() )
783 else if( j.is_string() )
785 if( wxTextEntry* textEntry =
dynamic_cast<wxTextEntry*
>( win ) )
786 textEntry->ChangeValue( wxString::FromUTF8( j.get<std::string>().c_str() ) );
789 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( win ) )
792 combo->SetValue( wxString::FromUTF8( j.get<std::string>().c_str() ) );
794 else if( wxOwnerDrawnComboBox* od_combo =
dynamic_cast<wxOwnerDrawnComboBox*
>( win ) )
796 if( j.is_number_integer() )
798 int index = j.get<
int>();
800 if(
index >= 0 &&
index < (
int) od_combo->GetCount() )
801 od_combo->SetSelection(
index );
804 else if( wxTextEntry* textEntry =
dynamic_cast<wxTextEntry*
>( win ) )
807 textEntry->ChangeValue( wxString::FromUTF8( j.get<std::string>().c_str() ) );
809 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( win ) )
811 if( j.is_number_integer() )
813 int index = j.get<
int>();
815 if(
index >= 0 &&
index < (
int) choice->GetCount() )
816 choice->SetSelection(
index );
819 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( win ) )
822 check->SetValue( j.get<
bool>() );
824 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( win ) )
826 if( j.is_number_integer() )
827 spin->SetValue( j.get<
int>() );
829 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( win ) )
837 radio->SetValue(
true );
840 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( win ) )
842 if( j.is_number_integer() )
844 int index = j.get<
int>();
846 if(
index >= 0 &&
index < (
int) radioBox->GetCount() )
847 radioBox->SetSelection(
index );
850 else if( wxSplitterWindow* splitter =
dynamic_cast<wxSplitterWindow*
>( win ) )
852 if( j.is_number_integer() )
853 splitter->SetSashPosition( j.get<
int>() );
855 else if( wxScrolledWindow* scrolled =
dynamic_cast<wxScrolledWindow*
>( win ) )
857 if( j.is_number_integer() )
858 scrolled->SetScrollPos( wxVERTICAL, j.get<
int>() );
860 else if( wxNotebook* notebook =
dynamic_cast<wxNotebook*
>( win ) )
864 wxString pageTitle = wxString::FromUTF8( j.get<std::string>().c_str() );
866 for(
int page = 0; page < (int) notebook->GetPageCount(); ++page )
868 if( notebook->GetPageText( page ) == pageTitle )
869 notebook->ChangeSelection( page );
873 else if( wxAuiNotebook* auiNotebook =
dynamic_cast<wxAuiNotebook*
>( win ) )
877 wxString pageTitle = wxString::FromUTF8( j.get<std::string>().c_str() );
879 for(
int page = 0; page < (int) auiNotebook->GetPageCount(); ++page )
881 if( auiNotebook->GetPageText( page ) == pageTitle )
882 auiNotebook->ChangeSelection( page );
889 grid->ShowHideColumns( wxString::FromUTF8( j.get<std::string>().c_str() ) );
894 for( wxWindow* child : win->GetChildren() )
900 if( !props->GetPropertyOr(
"persist",
false ) )
904 for( wxWindow* child : GetChildren() )
913 aWindow->SetClientData( props );
934 [aUnitBinder](
const auto& aEntry )
936 return aEntry.second == aUnitBinder;
946 for( wxWindow* child : children )
948 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
957#if defined( __WXMAC__ ) || defined( __WXMSW__ )
958 if( !textCtrl->GetStringSelection().IsEmpty() )
962 else if( textCtrl->IsEditable() )
964 textCtrl->SelectAll();
970 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
973 scintilla->Connect( wxEVT_SET_FOCUS,
977 if( !scintilla->GetSelectedText().IsEmpty() )
981 else if( scintilla->GetMarginWidth( 0 ) > 0 )
985 else if( scintilla->IsEditable() )
987 scintilla->SelectAll();
993 else if(
dynamic_cast<wxBitmapButton*
>( child ) !=
nullptr )
996 wxRect rect = child->GetRect();
998 child->ConvertDialogToPixels(
minSize );
1000 rect.Inflate( std::max( 0,
minSize.x - rect.GetWidth() ),
1001 std::max( 0,
minSize.y - rect.GetHeight() ) );
1003 child->SetMinSize( rect.GetSize() );
1004 child->SetSize( rect );
1017 for( wxWindow* child : children )
1022 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
1027 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
1032 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( child ) )
1038 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( child ) )
1041 m_currentValues[ choice ] =
static_cast<long>( choice->GetSelection() );
1043 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( child ) )
1048 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( child ) )
1054 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( child ) )
1060 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( child ) )
1065 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( child ) )
1068 m_currentValues[ radioBox ] =
static_cast<long>( radioBox->GetSelection() );
1070 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( child ) )
1075 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( child ) )
1080 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( child ) )
1085 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( child ) )
1103 if( before != after )
1105 m_undoStack.push_back( { aCtrl, before, after } );
1174 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aCtrl ) )
1175 return wxVariant( textCtrl->GetValue() );
1176 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aCtrl ) )
1177 return wxVariant( scintilla->GetText() );
1178 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( aCtrl ) )
1179 return wxVariant( combo->GetValue() );
1180 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( aCtrl ) )
1181 return wxVariant( (
long) choice->GetSelection() );
1182 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( aCtrl ) )
1183 return wxVariant( check->GetValue() );
1184 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( aCtrl ) )
1185 return wxVariant( (
long) spin->GetValue() );
1186 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( aCtrl ) )
1187 return wxVariant( spinD->GetValue() );
1188 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( aCtrl ) )
1189 return wxVariant( radio->GetValue() );
1190 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( aCtrl ) )
1191 return wxVariant( (
long) radioBox->GetSelection() );
1192 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( aCtrl ) )
1196 table &&
table->HasUndoStateSerialization() )
1198 return wxVariant(
table->SerializeUndoState() );
1201 nlohmann::json j = nlohmann::json::array();
1202 int rows =
grid->GetNumberRows();
1203 int cols =
grid->GetNumberCols();
1205 for(
int r = 0; r < rows; ++r )
1207 nlohmann::json row = nlohmann::json::array();
1209 for(
int c = 0; c < cols; ++c )
1210 row.push_back( std::string(
grid->GetCellValue( r, c ).ToUTF8() ) );
1215 return wxVariant( wxString( j.dump() ) );
1217 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( aCtrl ) )
1221 for( wxPropertyGridIterator it = propGrid->GetIterator(); !it.AtEnd(); ++it )
1223 wxPGProperty* prop = *it;
1224 j[ prop->GetName().ToStdString() ] = prop->GetValueAsString().ToStdString();
1227 return wxVariant( wxString( j.dump() ) );
1229 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( aCtrl ) )
1231 nlohmann::json j = nlohmann::json::array();
1232 unsigned int count = checkList->GetCount();
1234 for(
unsigned int i = 0; i < count; ++i )
1236 if( checkList->IsChecked( i ) )
1240 return wxVariant( wxString( j.dump() ) );
1242 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( aCtrl ) )
1244 nlohmann::json j = nlohmann::json::array();
1245 unsigned int rows = dataList->GetItemCount();
1246 unsigned int cols = dataList->GetColumnCount();
1248 for(
unsigned int r = 0; r < rows; ++r )
1250 nlohmann::json row = nlohmann::json::array();
1252 for(
unsigned int c = 0; c < cols; ++c )
1255 dataList->GetValue( val, r, c );
1256 row.push_back( std::string( val.GetString().ToUTF8() ) );
1262 return wxVariant( wxString( j.dump() ) );
1271 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aCtrl ) )
1272 textCtrl->SetValue( aValue.GetString() );
1273 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aCtrl ) )
1274 scintilla->SetText( aValue.GetString() );
1275 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( aCtrl ) )
1276 combo->SetValue( aValue.GetString() );
1277 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( aCtrl ) )
1278 choice->SetSelection( (
int) aValue.GetLong() );
1279 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( aCtrl ) )
1280 check->SetValue( aValue.GetBool() );
1281 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( aCtrl ) )
1282 spin->SetValue( (
int) aValue.GetLong() );
1283 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( aCtrl ) )
1284 spinD->SetValue( aValue.GetDouble() );
1285 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( aCtrl ) )
1286 radio->SetValue( aValue.GetBool() );
1287 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( aCtrl ) )
1288 radioBox->SetSelection( (
int) aValue.GetLong() );
1289 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( aCtrl ) )
1292 table &&
table->HasUndoStateSerialization() )
1294 table->RestoreUndoState( aValue.GetString() );
1298 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1302 int rows = std::min( (
int) j.size(),
grid->GetNumberRows() );
1304 for(
int r = 0; r < rows; ++r )
1306 nlohmann::json row = j[r];
1307 int cols = std::min( (
int) row.size(),
grid->GetNumberCols() );
1309 for(
int c = 0; c < cols; ++c )
1310 grid->SetCellValue( r, c, wxString( row[c].get<std::string>() ) );
1314 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( aCtrl ) )
1316 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1320 for(
auto it = j.begin(); it != j.end(); ++it )
1321 propGrid->SetPropertyValue( wxString( it.key() ), wxString( it.value().get<std::string>() ) );
1324 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( aCtrl ) )
1326 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1330 unsigned int count = checkList->GetCount();
1332 for(
unsigned int i = 0; i < count; ++i )
1333 checkList->Check( i,
false );
1335 for(
auto& idx : j )
1337 unsigned int i = idx.get<
unsigned int>();
1340 checkList->Check( i,
true );
1344 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( aCtrl ) )
1346 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1350 unsigned int rows = std::min(
static_cast<unsigned int>( j.size() ),
1351 static_cast<unsigned int>( dataList->GetItemCount() ) );
1353 for(
unsigned int r = 0; r < rows; ++r )
1355 nlohmann::json row = j[r];
1356 unsigned int cols = std::min( (
unsigned int) row.size(), dataList->GetColumnCount() );
1358 for(
unsigned int c = 0; c < cols; ++c )
1360 wxVariant val( wxString( row[c].get<std::string>() ) );
1361 dataList->SetValue( val, r, c );
1422 if( !GetTitle().StartsWith( wxS(
"*" ) ) )
1423 SetTitle( wxS(
"*" ) + GetTitle() );
1429 if( GetTitle().StartsWith( wxS(
"*" ) ) )
1430 SetTitle( GetTitle().AfterFirst(
'*' ) );
1444 return wxDialog::ShowModal();
1480 if( wxWindow* win = wxWindow::GetCapture() )
1481 win->ReleaseMouse();
1484 wxWindow* parent = GetParentForModalDialog( GetParent(), GetWindowStyle() );
1501 wxGUIEventLoop event_loop;
1510 return GetReturnCode();
1532 if( ( retCode == wxID_OK ) && ( !Validate() || !TransferDataFromWindow() ) )
1535 SetReturnCode( retCode );
1539 wxFAIL_MSG( wxT(
"Either DIALOG_SHIM::EndQuasiModal was called twice, or ShowQuasiModal wasn't called" ) );
1573 for( wxWindow* child : aWindow->GetChildren() )
1580 wxString msg = wxString::Format(
"Closing dialog %s", GetTitle() );
1598 const int id = aEvent.GetId();
1602 if(
id == GetAffirmativeId() )
1606 else if(
id == wxID_APPLY )
1615 else if(
id == wxID_CANCEL )
1638 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aEvent.GetEventObject() ) )
1640 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aEvent.GetEventObject() ) )
1650 int key = aEvt.GetKeyCode();
1653 if( aEvt.ControlDown() )
1655 if( aEvt.ShiftDown() )
1657 if( aEvt.AltDown() )
1660 int hotkey = key | mods;
1663 if( hotkey == (
MD_CTRL +
'Z') )
1674 if( aEvt.GetKeyCode() ==
'U' && aEvt.GetModifiers() == wxMOD_CONTROL )
1683 else if( ( aEvt.GetKeyCode() == WXK_RETURN || aEvt.GetKeyCode() == WXK_NUMPAD_ENTER ) && aEvt.ShiftDown() )
1685 wxObject* eventSource = aEvt.GetEventObject();
1687 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( eventSource ) )
1690 if( !textCtrl->IsMultiLine() )
1692 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
1696#if defined( __WXMAC__ ) || defined( __WXMSW__ )
1697 wxString eol =
"\r\n";
1699 wxString eol =
"\n";
1702 long pos = textCtrl->GetInsertionPoint();
1703 textCtrl->WriteText( eol );
1704 textCtrl->SetInsertionPoint( pos + eol.length() );
1707 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( eventSource ) )
1709 wxString eol =
"\n";
1711 switch( scintilla->GetEOLMode() )
1713 case wxSTC_EOL_CRLF: eol =
"\r\n";
break;
1714 case wxSTC_EOL_CR: eol =
"\r";
break;
1715 case wxSTC_EOL_LF: eol =
"\n";
break;
1718 long pos = scintilla->GetCurrentPos();
1719 scintilla->InsertText( pos, eol );
1720 scintilla->GotoPos( pos + eol.length() );
1726 else if( ( aEvt.GetKeyCode() == WXK_RETURN || aEvt.GetKeyCode() == WXK_NUMPAD_ENTER ) && aEvt.ControlDown() )
1728 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
1731 else if( aEvt.GetKeyCode() == WXK_TAB && !aEvt.ControlDown() )
1733 wxWindow* currentWindow = wxWindow::FindFocus();
1734 int currentIdx = -1;
1735 int delta = aEvt.ShiftDown() ? -1 : 1;
1742 idx = ( ( idx +
delta ) % size + size ) % size;
1745 for(
size_t i = 0; i <
m_tabOrder.size(); ++i )
1750 || ( currentWindow &&
m_tabOrder[i]->IsDescendant( currentWindow ) ) )
1752 currentIdx = (int) i;
1757 if( currentIdx >= 0 )
1759 advance( currentIdx );
1762 int startIdx = currentIdx;
1766 advance( currentIdx );
1768 if( currentIdx == startIdx )
1775 while(
dynamic_cast<wxTextEntry*
>(
m_tabOrder[ currentIdx ] ) ==
nullptr )
1776 advance( currentIdx );
1783 else if( aEvt.GetKeyCode() == WXK_ESCAPE )
1785 wxObject* eventSource = aEvt.GetEventObject();
1787 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( eventSource ) )
1793 textCtrl->SelectAll();
1797 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( eventSource ) )
1803 scintilla->SelectAll();
1815 wxStdDialogButtonSizer* sdbSizer =
dynamic_cast<wxStdDialogButtonSizer*
>( aSizer );
1818 [&]( wxButton* aButton )
1820 if( aLabels.count( aButton->GetId() ) > 0 )
1822 aButton->SetLabel( aLabels[ aButton->GetId() ] );
1828 switch( aButton->GetId() )
1830 case wxID_OK: aButton->SetLabel(
_(
"&OK" ) );
break;
1831 case wxID_CANCEL: aButton->SetLabel(
_(
"&Cancel" ) );
break;
1832 case wxID_YES: aButton->SetLabel(
_(
"&Yes" ) );
break;
1833 case wxID_NO: aButton->SetLabel(
_(
"&No" ) );
break;
1834 case wxID_APPLY: aButton->SetLabel(
_(
"&Apply" ) );
break;
1835 case wxID_SAVE: aButton->SetLabel(
_(
"&Save" ) );
break;
1836 case wxID_HELP: aButton->SetLabel(
_(
"&Help" ) );
break;
1837 case wxID_CONTEXT_HELP: aButton->SetLabel(
_(
"&Help" ) );
break;
1844 if( sdbSizer->GetAffirmativeButton() )
1845 setupButton( sdbSizer->GetAffirmativeButton() );
1847 if( sdbSizer->GetApplyButton() )
1848 setupButton( sdbSizer->GetApplyButton() );
1850 if( sdbSizer->GetNegativeButton() )
1851 setupButton( sdbSizer->GetNegativeButton() );
1853 if( sdbSizer->GetCancelButton() )
1854 setupButton( sdbSizer->GetCancelButton() );
1856 if( sdbSizer->GetHelpButton() )
1857 setupButton( sdbSizer->GetHelpButton() );
1861 if( sdbSizer->GetAffirmativeButton() )
1862 sdbSizer->GetAffirmativeButton()->SetDefault();
1865 for( wxSizerItem* item : aSizer->GetChildren() )
1867 if( item->GetSizer() )
COMMON_SETTINGS_INTERNALS & CsInternals()
Dialog helper object to sit in the inheritance tree between wxDialog and any class written by wxFormB...
void SelectAllInTextCtrls(wxWindowList &children)
wxVariant getControlValue(wxWindow *aCtrl)
void onPropertyGridChanged(wxPropertyGridEvent &aEvent)
std::set< wxWindow * > m_noControlUndoRedo
std::vector< wxWindow * > m_tabOrder
void OnPaint(wxPaintEvent &event)
virtual void TearDownQuasiModal()
Override this method to perform dialog tear down actions not suitable for object dtor.
void recordControlChange(wxWindow *aCtrl)
int vertPixelsFromDU(int y) const
Convert an integer number of dialog units to pixels, vertically.
bool Show(bool show) override
std::vector< UNDO_STEP > m_redoStack
void setControlValue(wxWindow *aCtrl, const wxVariant &aValue)
wxGUIEventLoop * m_qmodal_loop
void onChildSetFocus(wxFocusEvent &aEvent)
void LoadControlState()
Load persisted control values from the current project's local settings.
void ExcludeFromControlUndoRedo(wxWindow *aWindow)
Opt a control out of the dialog's generic Ctrl+Z/Ctrl+Y undo/redo.
void UnregisterUnitBinder(UNIT_BINDER *aUnitBinder)
Remove a UNIT_BINDER from the control-state save/restore map.
void OptOut(wxWindow *aWindow)
Opt out of control state saving.
void SaveControlState()
Save control values and geometry to the current project's local settings.
void SetupStandardButtons(std::map< int, wxString > aLabels={})
WINDOW_DISABLER * m_qmodal_parent_disabler
void clampToWorkArea()
Shrink the dialog's minimum and current size down to the work area of the display it occupies,...
void onInitDialog(wxInitDialogEvent &aEvent)
void onSpinDoubleEvent(wxSpinDoubleEvent &aEvent)
void resetUndoRedoForNewContent(wxWindowList &aChildren)
Reset undo/redo tracking after dynamically replacing child panels.
int horizPixelsFromDU(int x) const
Convert an integer number of dialog units to pixels, horizontally.
void resetSize()
Clear the existing dialog size and position.
std::map< wxWindow *, wxString > m_beforeEditValues
void setSizeInDU(int x, int y)
Set the dialog to the given dimensions in "dialog units".
void onDataViewListChanged(wxDataViewEvent &aEvent)
void unregisterUnitBinders(wxWindow *aWindow)
Remove UNIT_BINDER registrations for a window and all its descendants.
bool IsQuasiModal() const
std::map< wxWindow *, UNIT_BINDER * > m_unitBinders
void EndQuasiModal(int retCode)
void RegisterUnitBinder(UNIT_BINDER *aUnitBinder, wxWindow *aWindow)
Register a UNIT_BINDER so that it can handle units in control-state save/restore.
void OnMove(wxMoveEvent &aEvent)
void onCommandEvent(wxCommandEvent &aEvent)
void CleanupAfterModalSubDialog()
std::string generateKey(const wxWindow *aWin) const
void PrepareForModalSubDialog()
void OnButton(wxCommandEvent &aEvent)
Properly handle the default button events when in the quasimodal mode when not calling EndQuasiModal ...
void onGridCellChanged(wxGridEvent &aEvent)
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
void registerUndoRedoHandlers(wxWindowList &aChildren)
wxWindow * m_initialFocusTarget
void OnSize(wxSizeEvent &aEvent)
bool Enable(bool enable) override
DIALOG_SHIM(wxWindow *aParent, wxWindowID id, const wxString &title, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER, const wxString &name=wxDialogNameStr)
void focusParentCanvas(bool aDeferUntilFrameActive=false)
Set focus back to the parent frame's tool canvas if available, otherwise to the parent window.
void SetPosition(const wxPoint &aNewPosition)
Force the position of the dialog to a new position.
void onSpinEvent(wxSpinEvent &aEvent)
void OnCloseWindow(wxCloseEvent &aEvent)
Properly handle the wxCloseEvent when in the quasimodal mode when not calling EndQuasiModal which is ...
std::map< wxWindow *, wxVariant > m_currentValues
EDA_BASE_FRAME * m_parentFrame
virtual void OnCharHook(wxKeyEvent &aEvt)
std::vector< UNDO_STEP > m_undoStack
void onStyledTextChanged(wxStyledTextEvent &aEvent)
The base frame for deriving all KiCad main window classes.
KIWAY_HOLDER(KIWAY *aKiway, HOLDER_TYPE aType)
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
void SetKiway(wxWindow *aDest, KIWAY *aKiway)
It is only used for debugging, since "this" is not a wxWindow*.
bool HasKiway() const
Safety check before asking for the Kiway reference.
HOLDER_TYPE GetType() const
void SetBlockingDialog(wxWindow *aWin)
virtual COMMON_SETTINGS * GetCommonSettings() const
virtual wxApp & App()
Return a bare naked wxApp which may come from wxPython, SINGLE_TOP, or kicad.exe.
bool SetProperty(const std::string &aKey, T &&aValue)
Set a property with the given key and value.
static PROPERTY_HOLDER * SafeCast(void *aPtr) noexcept
Safely cast a void pointer to PROPERTY_HOLDER*.
EDA_UNITS GetUserUnits() const
Temporarily disable a window, and then re-enable on destruction.
static std::string getDialogKeyFromTitle(const wxString &aTitle)
Strip parenthetical suffixes from dialog titles to create stable persistence keys.
static void recursiveDescent(wxSizer *aSizer, std::map< int, wxString > &aLabels)
const int minSize
Push and Shove router track width and via size dialog.
void ignore_unused(const T &)
void AddNavigationBreadcrumb(const wxString &aMsg, const wxString &aCategory)
Add a navigation breadcrumb.
static wxString makeKey(const wxString &aFirst, const wxString &aSecond)
Assemble a two part key as a simple concatenation of aFirst and aSecond parts, using a separator.
PGM_BASE & Pgm()
The global program "get" accessor.
std::map< std::string, std::map< std::string, nlohmann::json > > m_dialogControlValues
static const long long MM
std::vector< std::vector< std::string > > table