41#include <wx/display.h>
42#include <wx/evtloop.h>
46#include <wx/propgrid/propgrid.h>
47#include <wx/checklst.h>
48#include <wx/dataview.h>
49#include <wx/bmpbuttn.h>
50#include <wx/textctrl.h>
51#include <wx/stc/stc.h>
52#include <wx/combobox.h>
53#include <wx/odcombo.h>
55#include <wx/checkbox.h>
56#include <wx/spinctrl.h>
57#include <wx/splitter.h>
58#include <wx/radiobox.h>
59#include <wx/radiobut.h>
60#include <wx/variant.h>
64#include <nlohmann/json.hpp>
80 std::string title = aTitle.ToStdString();
81 size_t parenPos = title.rfind(
'(' );
83 if( parenPos != std::string::npos && parenPos > 0 )
85 size_t end = parenPos;
87 while(
end > 0 && title[
end - 1] ==
' ' )
90 return title.substr( 0,
end );
98 const wxSize& size,
long style,
const wxString&
name ) :
99 wxDialog( aParent, id, title, pos, size, style,
name ),
122 while( !kiwayHolder && aParent->GetParent() )
124 aParent = aParent->GetParent();
138 m_parentFrame = static_cast<EDA_BASE_FRAME*>( kiwayHolder );
139 TOOL_MANAGER* toolMgr = m_parentFrame->GetToolManager();
141 if( toolMgr && toolMgr->IsContextMenuActive() )
142 toolMgr->VetoContextMenuMouseWarp();
150 Kiway().SetBlockingDialog(
this );
168 wxString msg = wxString::Format(
"Opening dialog %s", GetTitle() );
184 std::function<void( wxWindowList& )> disconnectFocusHandlers =
185 [&]( wxWindowList& children )
187 for( wxWindow* child : children )
189 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
194 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
201 disconnectFocusHandlers( child->GetChildren() );
206 disconnectFocusHandlers( GetChildren() );
208 std::function<void( wxWindowList& )> disconnectUndoRedoHandlers =
209 [&]( wxWindowList& children )
211 for( wxWindow* child : children )
213 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
217 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
221 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( child ) )
226 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( child ) )
230 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( child ) )
234 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( child ) )
239 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( child ) )
244 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( child ) )
248 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( child ) )
252 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( child ) )
256 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( child ) )
260 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( child ) )
264 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( child ) )
270 disconnectUndoRedoHandlers( child->GetChildren() );
275 disconnectUndoRedoHandlers( GetChildren() );
294 if( wxSizer* sz = GetSizer() )
311 GetSizer()->SetSizeHints(
this );
318 SetSize( ConvertDialogToPixels( sz ) );
325 return ConvertDialogToPixels( sz ).x;
332 return ConvertDialogToPixels( sz ).y;
344 wxDialog::SetPosition( aNewPosition );
362 m_parent->SetFocus();
375 ret = wxDialog::Show( show );
377 wxRect savedDialogRect;
382 auto dlgIt = settings->CsInternals().m_dialogControlValues.find( key );
384 if( dlgIt != settings->CsInternals().m_dialogControlValues.end() )
386 auto geoIt = dlgIt->second.find(
"__geometry" );
388 if( geoIt != dlgIt->second.end() && geoIt->second.is_object() )
390 const nlohmann::json& g = geoIt->second;
391 savedDialogRect.SetPosition( wxPoint( g.value(
"x", 0 ), g.value(
"y", 0 ) ) );
392 savedDialogRect.SetSize( wxSize( g.value(
"w", 500 ), g.value(
"h", 300 ) ) );
397 if( savedDialogRect.GetSize().x != 0 && savedDialogRect.GetSize().y != 0 )
400 wxSize restoredSize = FromDIP( savedDialogRect.GetSize() );
404 SetSize( savedDialogRect.GetPosition().x, savedDialogRect.GetPosition().y,
405 wxDialog::GetSize().x, wxDialog::GetSize().y, 0 );
409 SetSize( savedDialogRect.GetPosition().x, savedDialogRect.GetPosition().y,
410 std::max( wxDialog::GetSize().x, restoredSize.x ),
411 std::max( wxDialog::GetSize().y, restoredSize.y ), 0 );
417 SetMinSize( wxDefaultSize );
418 InvalidateBestSize();
419 SetMinSize( GetBestSize() );
423 if( m_parent !=
nullptr )
425 if( wxDisplay::GetFromPoint( m_parent->GetPosition() )
426 != wxDisplay::GetFromPoint( savedDialogRect.GetPosition() ) )
440 if( wxDisplay::GetFromWindow(
this ) == wxNOT_FOUND )
453 m_eventLoop->Exit( GetReturnCode() );
456 ret = wxDialog::Show( show );
472 auto dlgIt = settings->CsInternals().m_dialogControlValues.find( key );
474 if( dlgIt == settings->CsInternals().m_dialogControlValues.end() )
477 dlgIt->second.erase(
"__geometry" );
496 int parentDisplay = wxDisplay::GetFromWindow( m_parent );
497 int myDisplay = wxDisplay::GetFromWindow(
this );
499 if( parentDisplay != wxNOT_FOUND && myDisplay != wxNOT_FOUND )
524 return wxDialog::Enable( enable );
530 auto getSiblingIndex =
531 [](
const wxWindow* parent,
const wxWindow* child )
533 wxString childClass = child->GetClassInfo()->GetClassName();
536 for(
const wxWindow* sibling : parent->GetChildren() )
538 if( sibling->GetClassInfo()->GetClassName() != childClass )
541 if( sibling == child )
551 [&](
const wxWindow* window )
553 std::string key = wxString( window->GetClassInfo()->GetClassName() ).ToStdString();
555 if( window->GetParent() )
556 key +=
"_" + std::to_string( getSiblingIndex( window->GetParent(), window ) );
561 std::string key =
makeKey( aWin );
563 for(
const wxWindow* parent = aWin->GetParent(); parent && parent !=
this; parent = parent->GetParent() )
580 wxPoint pos = GetPosition();
581 wxSize dipSize = ToDIP( GetSize() );
585 geom[
"w" ] = dipSize.x;
586 geom[
"h" ] = dipSize.y;
587 dlgMap[
"__geometry" ] = geom;
589 std::function<void( wxWindow* )> saveFn =
594 if( !props->GetPropertyOr(
"persist",
false ) )
606 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( win ) )
608 dlgMap[ key ] = combo->GetValue();
610 else if( wxOwnerDrawnComboBox* od_combo =
dynamic_cast<wxOwnerDrawnComboBox*
>( win ) )
612 dlgMap[ key ] = od_combo->GetSelection();
614 else if( wxTextEntry* textEntry =
dynamic_cast<wxTextEntry*
>( win ) )
616 dlgMap[ key ] = textEntry->GetValue();
618 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( win ) )
620 dlgMap[ key ] = choice->GetSelection();
622 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( win ) )
624 dlgMap[ key ] = check->GetValue();
626 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( win ) )
628 dlgMap[ key ] = spin->GetValue();
630 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( win ) )
632 dlgMap[ key ] = radio->GetValue();
634 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( win ) )
636 dlgMap[ key ] = radioBox->GetSelection();
638 else if( wxSplitterWindow* splitter =
dynamic_cast<wxSplitterWindow*
>( win ) )
640 dlgMap[ key ] = splitter->GetSashPosition();
642 else if( wxScrolledWindow* scrolled =
dynamic_cast<wxScrolledWindow*
>( win ) )
644 dlgMap[ key ] = scrolled->GetScrollPos( wxVERTICAL );
646 else if( wxNotebook* notebook =
dynamic_cast<wxNotebook*
>( win ) )
648 int index = notebook->GetSelection();
650 if(
index >= 0 &&
index < (
int) notebook->GetPageCount() )
651 dlgMap[ key ] = notebook->GetPageText( notebook->GetSelection() );
653 else if( wxAuiNotebook* auiNotebook =
dynamic_cast<wxAuiNotebook*
>( win ) )
655 int index = auiNotebook->GetSelection();
657 if(
index >= 0 &&
index < (
int) auiNotebook->GetPageCount() )
658 dlgMap[ key ] = auiNotebook->GetPageText( auiNotebook->GetSelection() );
662 dlgMap[ key ] =
grid->GetShownColumnsAsString();
666 for( wxWindow* child : win->GetChildren() )
672 if( !props->GetPropertyOr(
"persist",
false ) )
676 for( wxWindow* child : GetChildren() )
694 const std::map<std::string, nlohmann::json>& dlgMap = dlgIt->second;
696 std::function<void( wxWindow* )> loadFn =
701 if( !props->GetPropertyOr(
"persist",
false ) )
709 auto it = dlgMap.find( key );
711 if( it != dlgMap.end() )
713 const nlohmann::json& j = it->second;
717 if( j.is_number_integer() )
720 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( win ) )
723 combo->SetValue( wxString::FromUTF8( j.get<std::string>().c_str() ) );
725 else if( wxOwnerDrawnComboBox* od_combo =
dynamic_cast<wxOwnerDrawnComboBox*
>( win ) )
727 if( j.is_number_integer() )
729 int index = j.get<
int>();
731 if(
index >= 0 &&
index < (
int) od_combo->GetCount() )
732 od_combo->SetSelection(
index );
735 else if( wxTextEntry* textEntry =
dynamic_cast<wxTextEntry*
>( win ) )
738 textEntry->ChangeValue( wxString::FromUTF8( j.get<std::string>().c_str() ) );
740 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( win ) )
742 if( j.is_number_integer() )
744 int index = j.get<
int>();
746 if(
index >= 0 &&
index < (
int) choice->GetCount() )
747 choice->SetSelection(
index );
750 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( win ) )
753 check->SetValue( j.get<
bool>() );
755 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( win ) )
757 if( j.is_number_integer() )
758 spin->SetValue( j.get<
int>() );
760 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( win ) )
768 radio->SetValue(
true );
771 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( win ) )
773 if( j.is_number_integer() )
775 int index = j.get<
int>();
777 if(
index >= 0 &&
index < (
int) radioBox->GetCount() )
778 radioBox->SetSelection(
index );
781 else if( wxSplitterWindow* splitter =
dynamic_cast<wxSplitterWindow*
>( win ) )
783 if( j.is_number_integer() )
784 splitter->SetSashPosition( j.get<
int>() );
786 else if( wxScrolledWindow* scrolled =
dynamic_cast<wxScrolledWindow*
>( win ) )
788 if( j.is_number_integer() )
789 scrolled->SetScrollPos( wxVERTICAL, j.get<
int>() );
791 else if( wxNotebook* notebook =
dynamic_cast<wxNotebook*
>( win ) )
795 wxString pageTitle = wxString::FromUTF8( j.get<std::string>().c_str() );
797 for(
int page = 0; page < (int) notebook->GetPageCount(); ++page )
799 if( notebook->GetPageText( page ) == pageTitle )
800 notebook->ChangeSelection( page );
804 else if( wxAuiNotebook* auiNotebook =
dynamic_cast<wxAuiNotebook*
>( win ) )
808 wxString pageTitle = wxString::FromUTF8( j.get<std::string>().c_str() );
810 for(
int page = 0; page < (int) auiNotebook->GetPageCount(); ++page )
812 if( auiNotebook->GetPageText( page ) == pageTitle )
813 auiNotebook->ChangeSelection( page );
820 grid->ShowHideColumns( wxString::FromUTF8( j.get<std::string>().c_str() ) );
825 for( wxWindow* child : win->GetChildren() )
831 if( !props->GetPropertyOr(
"persist",
false ) )
835 for( wxWindow* child : GetChildren() )
844 aWindow->SetClientData( props );
859 for( wxWindow* child : children )
861 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
870#if defined( __WXMAC__ ) || defined( __WXMSW__ )
871 if( !textCtrl->GetStringSelection().IsEmpty() )
875 else if( textCtrl->IsEditable() )
877 textCtrl->SelectAll();
883 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
886 scintilla->Connect( wxEVT_SET_FOCUS,
890 if( !scintilla->GetSelectedText().IsEmpty() )
894 else if( scintilla->GetMarginWidth( 0 ) > 0 )
898 else if( scintilla->IsEditable() )
900 scintilla->SelectAll();
906 else if(
dynamic_cast<wxBitmapButton*
>( child ) !=
nullptr )
909 wxRect rect = child->GetRect();
911 child->ConvertDialogToPixels(
minSize );
913 rect.Inflate( std::max( 0,
minSize.x - rect.GetWidth() ),
914 std::max( 0,
minSize.y - rect.GetHeight() ) );
916 child->SetMinSize( rect.GetSize() );
917 child->SetSize( rect );
930 for( wxWindow* child : children )
932 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
937 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
942 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( child ) )
948 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( child ) )
951 m_currentValues[ choice ] =
static_cast<long>( choice->GetSelection() );
953 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( child ) )
958 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( child ) )
964 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( child ) )
970 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( child ) )
975 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( child ) )
978 m_currentValues[ radioBox ] =
static_cast<long>( radioBox->GetSelection() );
980 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( child ) )
985 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( child ) )
990 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( child ) )
995 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( child ) )
1013 if( before != after )
1015 m_undoStack.push_back( { aCtrl, before, after } );
1084 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aCtrl ) )
1085 return wxVariant( textCtrl->GetValue() );
1086 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aCtrl ) )
1087 return wxVariant( scintilla->GetText() );
1088 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( aCtrl ) )
1089 return wxVariant( combo->GetValue() );
1090 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( aCtrl ) )
1091 return wxVariant( (
long) choice->GetSelection() );
1092 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( aCtrl ) )
1093 return wxVariant( check->GetValue() );
1094 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( aCtrl ) )
1095 return wxVariant( (
long) spin->GetValue() );
1096 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( aCtrl ) )
1097 return wxVariant( spinD->GetValue() );
1098 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( aCtrl ) )
1099 return wxVariant( radio->GetValue() );
1100 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( aCtrl ) )
1101 return wxVariant( (
long) radioBox->GetSelection() );
1102 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( aCtrl ) )
1104 nlohmann::json j = nlohmann::json::array();
1105 int rows =
grid->GetNumberRows();
1106 int cols =
grid->GetNumberCols();
1108 for(
int r = 0; r < rows; ++r )
1110 nlohmann::json row = nlohmann::json::array();
1112 for(
int c = 0; c < cols; ++c )
1113 row.push_back( std::string(
grid->GetCellValue( r, c ).ToUTF8() ) );
1118 return wxVariant( wxString( j.dump() ) );
1120 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( aCtrl ) )
1124 for( wxPropertyGridIterator it = propGrid->GetIterator(); !it.AtEnd(); ++it )
1126 wxPGProperty* prop = *it;
1127 j[ prop->GetName().ToStdString() ] = prop->GetValueAsString().ToStdString();
1130 return wxVariant( wxString( j.dump() ) );
1132 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( aCtrl ) )
1134 nlohmann::json j = nlohmann::json::array();
1135 unsigned int count = checkList->GetCount();
1137 for(
unsigned int i = 0; i < count; ++i )
1139 if( checkList->IsChecked( i ) )
1143 return wxVariant( wxString( j.dump() ) );
1145 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( aCtrl ) )
1147 nlohmann::json j = nlohmann::json::array();
1148 unsigned int rows = dataList->GetItemCount();
1149 unsigned int cols = dataList->GetColumnCount();
1151 for(
unsigned int r = 0; r < rows; ++r )
1153 nlohmann::json row = nlohmann::json::array();
1155 for(
unsigned int c = 0; c < cols; ++c )
1158 dataList->GetValue( val, r, c );
1159 row.push_back( std::string( val.GetString().ToUTF8() ) );
1165 return wxVariant( wxString( j.dump() ) );
1174 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aCtrl ) )
1175 textCtrl->SetValue( aValue.GetString() );
1176 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aCtrl ) )
1177 scintilla->SetText( aValue.GetString() );
1178 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( aCtrl ) )
1179 combo->SetValue( aValue.GetString() );
1180 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( aCtrl ) )
1181 choice->SetSelection( (
int) aValue.GetLong() );
1182 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( aCtrl ) )
1183 check->SetValue( aValue.GetBool() );
1184 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( aCtrl ) )
1185 spin->SetValue( (
int) aValue.GetLong() );
1186 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( aCtrl ) )
1187 spinD->SetValue( aValue.GetDouble() );
1188 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( aCtrl ) )
1189 radio->SetValue( aValue.GetBool() );
1190 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( aCtrl ) )
1191 radioBox->SetSelection( (
int) aValue.GetLong() );
1192 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( aCtrl ) )
1194 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1198 int rows = std::min( (
int) j.size(),
grid->GetNumberRows() );
1200 for(
int r = 0; r < rows; ++r )
1202 nlohmann::json row = j[r];
1203 int cols = std::min( (
int) row.size(),
grid->GetNumberCols() );
1205 for(
int c = 0; c < cols; ++c )
1206 grid->SetCellValue( r, c, wxString( row[c].get<std::string>() ) );
1210 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( aCtrl ) )
1212 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1216 for(
auto it = j.begin(); it != j.end(); ++it )
1217 propGrid->SetPropertyValue( wxString( it.key() ), wxString( it.value().get<std::string>() ) );
1220 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( aCtrl ) )
1222 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1226 unsigned int count = checkList->GetCount();
1228 for(
unsigned int i = 0; i < count; ++i )
1229 checkList->Check( i,
false );
1231 for(
auto& idx : j )
1233 unsigned int i = idx.get<
unsigned int>();
1236 checkList->Check( i,
true );
1240 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( aCtrl ) )
1242 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1246 unsigned int rows = std::min(
static_cast<unsigned int>( j.size() ),
1247 static_cast<unsigned int>( dataList->GetItemCount() ) );
1249 for(
unsigned int r = 0; r < rows; ++r )
1251 nlohmann::json row = j[r];
1252 unsigned int cols = std::min( (
unsigned int) row.size(), dataList->GetColumnCount() );
1254 for(
unsigned int c = 0; c < cols; ++c )
1256 wxVariant val( wxString( row[c].get<std::string>() ) );
1257 dataList->SetValue( val, r, c );
1318 if( !GetTitle().StartsWith( wxS(
"*" ) ) )
1319 SetTitle( wxS(
"*" ) + GetTitle() );
1325 if( GetTitle().StartsWith( wxS(
"*" ) ) )
1326 SetTitle( GetTitle().AfterFirst(
'*' ) );
1338 return wxDialog::ShowModal();
1374 if( wxWindow* win = wxWindow::GetCapture() )
1375 win->ReleaseMouse();
1378 wxWindow* parent = GetParentForModalDialog( GetParent(), GetWindowStyle() );
1395 wxGUIEventLoop event_loop;
1404 return GetReturnCode();
1426 if( ( retCode == wxID_OK ) && ( !Validate() || !TransferDataFromWindow() ) )
1429 SetReturnCode( retCode );
1433 wxFAIL_MSG( wxT(
"Either DIALOG_SHIM::EndQuasiModal was called twice, or ShowQuasiModal wasn't called" ) );
1467 for( wxWindow* child : aWindow->GetChildren() )
1474 wxString msg = wxString::Format(
"Closing dialog %s", GetTitle() );
1492 const int id = aEvent.GetId();
1496 if(
id == GetAffirmativeId() )
1500 else if(
id == wxID_APPLY )
1509 else if(
id == wxID_CANCEL )
1532 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aEvent.GetEventObject() ) )
1534 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aEvent.GetEventObject() ) )
1544 int key = aEvt.GetKeyCode();
1547 if( aEvt.ControlDown() )
1549 if( aEvt.ShiftDown() )
1551 if( aEvt.AltDown() )
1554 int hotkey = key | mods;
1557 if( hotkey == (
MD_CTRL +
'Z') )
1568 if( aEvt.GetKeyCode() ==
'U' && aEvt.GetModifiers() == wxMOD_CONTROL )
1577 else if( ( aEvt.GetKeyCode() == WXK_RETURN || aEvt.GetKeyCode() == WXK_NUMPAD_ENTER ) && aEvt.ShiftDown() )
1579 wxObject* eventSource = aEvt.GetEventObject();
1581 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( eventSource ) )
1584 if( !textCtrl->IsMultiLine() )
1586 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
1590#if defined( __WXMAC__ ) || defined( __WXMSW__ )
1591 wxString eol =
"\r\n";
1593 wxString eol =
"\n";
1596 long pos = textCtrl->GetInsertionPoint();
1597 textCtrl->WriteText( eol );
1598 textCtrl->SetInsertionPoint( pos + eol.length() );
1601 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( eventSource ) )
1603 wxString eol =
"\n";
1605 switch( scintilla->GetEOLMode() )
1607 case wxSTC_EOL_CRLF: eol =
"\r\n";
break;
1608 case wxSTC_EOL_CR: eol =
"\r";
break;
1609 case wxSTC_EOL_LF: eol =
"\n";
break;
1612 long pos = scintilla->GetCurrentPos();
1613 scintilla->InsertText( pos, eol );
1614 scintilla->GotoPos( pos + eol.length() );
1620 else if( ( aEvt.GetKeyCode() == WXK_RETURN || aEvt.GetKeyCode() == WXK_NUMPAD_ENTER ) && aEvt.ControlDown() )
1622 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
1625 else if( aEvt.GetKeyCode() == WXK_TAB && !aEvt.ControlDown() )
1627 wxWindow* currentWindow = wxWindow::FindFocus();
1628 int currentIdx = -1;
1629 int delta = aEvt.ShiftDown() ? -1 : 1;
1636 idx = ( ( idx +
delta ) % size + size ) % size;
1639 for(
size_t i = 0; i <
m_tabOrder.size(); ++i )
1644 || ( currentWindow &&
m_tabOrder[i]->IsDescendant( currentWindow ) ) )
1646 currentIdx = (int) i;
1651 if( currentIdx >= 0 )
1653 advance( currentIdx );
1656 int startIdx = currentIdx;
1660 advance( currentIdx );
1662 if( currentIdx == startIdx )
1669 while(
dynamic_cast<wxTextEntry*
>(
m_tabOrder[ currentIdx ] ) ==
nullptr )
1670 advance( currentIdx );
1677 else if( aEvt.GetKeyCode() == WXK_ESCAPE )
1679 wxObject* eventSource = aEvt.GetEventObject();
1681 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( eventSource ) )
1687 textCtrl->SelectAll();
1691 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( eventSource ) )
1697 scintilla->SelectAll();
1709 wxStdDialogButtonSizer* sdbSizer =
dynamic_cast<wxStdDialogButtonSizer*
>( aSizer );
1712 [&]( wxButton* aButton )
1714 if( aLabels.count( aButton->GetId() ) > 0 )
1716 aButton->SetLabel( aLabels[ aButton->GetId() ] );
1722 switch( aButton->GetId() )
1724 case wxID_OK: aButton->SetLabel(
_(
"&OK" ) );
break;
1725 case wxID_CANCEL: aButton->SetLabel(
_(
"&Cancel" ) );
break;
1726 case wxID_YES: aButton->SetLabel(
_(
"&Yes" ) );
break;
1727 case wxID_NO: aButton->SetLabel(
_(
"&No" ) );
break;
1728 case wxID_APPLY: aButton->SetLabel(
_(
"&Apply" ) );
break;
1729 case wxID_SAVE: aButton->SetLabel(
_(
"&Save" ) );
break;
1730 case wxID_HELP: aButton->SetLabel(
_(
"&Help" ) );
break;
1731 case wxID_CONTEXT_HELP: aButton->SetLabel(
_(
"&Help" ) );
break;
1738 if( sdbSizer->GetAffirmativeButton() )
1739 setupButton( sdbSizer->GetAffirmativeButton() );
1741 if( sdbSizer->GetApplyButton() )
1742 setupButton( sdbSizer->GetApplyButton() );
1744 if( sdbSizer->GetNegativeButton() )
1745 setupButton( sdbSizer->GetNegativeButton() );
1747 if( sdbSizer->GetCancelButton() )
1748 setupButton( sdbSizer->GetCancelButton() );
1750 if( sdbSizer->GetHelpButton() )
1751 setupButton( sdbSizer->GetHelpButton() );
1755 if( sdbSizer->GetAffirmativeButton() )
1756 sdbSizer->GetAffirmativeButton()->SetDefault();
1759 for( wxSizerItem* item : aSizer->GetChildren() )
1761 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::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 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 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 focusParentCanvas()
Set focus back to the parent frame's tool canvas if available, otherwise to the parent window.
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 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