41#include <wx/display.h>
42#include <wx/evtloop.h>
47#include <wx/propgrid/propgrid.h>
48#include <wx/checklst.h>
49#include <wx/dataview.h>
50#include <wx/bmpbuttn.h>
51#include <wx/textctrl.h>
52#include <wx/stc/stc.h>
53#include <wx/combobox.h>
54#include <wx/odcombo.h>
56#include <wx/checkbox.h>
57#include <wx/spinctrl.h>
58#include <wx/splitter.h>
59#include <wx/radiobox.h>
60#include <wx/radiobut.h>
61#include <wx/variant.h>
65#include <nlohmann/json.hpp>
81 std::string title = aTitle.ToStdString();
82 size_t parenPos = title.rfind(
'(' );
84 if( parenPos != std::string::npos && parenPos > 0 )
86 size_t end = parenPos;
88 while(
end > 0 && title[
end - 1] ==
' ' )
91 return title.substr( 0,
end );
99 const wxSize& size,
long style,
const wxString&
name ) :
100 wxDialog( aParent, id, title, pos, size, style,
name ),
123 while( !kiwayHolder && aParent->GetParent() )
125 aParent = aParent->GetParent();
139 m_parentFrame = static_cast<EDA_BASE_FRAME*>( kiwayHolder );
140 TOOL_MANAGER* toolMgr = m_parentFrame->GetToolManager();
142 if( toolMgr && toolMgr->IsContextMenuActive() )
143 toolMgr->VetoContextMenuMouseWarp();
151 Kiway().SetBlockingDialog(
this );
169 wxString msg = wxString::Format(
"Opening dialog %s", GetTitle() );
185 std::function<void( wxWindowList& )> disconnectFocusHandlers =
186 [&]( wxWindowList& children )
188 for( wxWindow* child : children )
190 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
195 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
202 disconnectFocusHandlers( child->GetChildren() );
207 disconnectFocusHandlers( GetChildren() );
209 std::function<void( wxWindowList& )> disconnectUndoRedoHandlers =
210 [&]( wxWindowList& children )
212 for( wxWindow* child : children )
214 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
218 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
222 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( child ) )
227 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( child ) )
231 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( child ) )
235 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( child ) )
240 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( child ) )
245 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( child ) )
249 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( child ) )
253 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( child ) )
257 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( child ) )
261 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( child ) )
265 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( child ) )
271 disconnectUndoRedoHandlers( child->GetChildren() );
276 disconnectUndoRedoHandlers( GetChildren() );
295 if( wxSizer* sz = GetSizer() )
312 GetSizer()->SetSizeHints(
this );
319 SetSize( ConvertDialogToPixels( sz ) );
326 return ConvertDialogToPixels( sz ).x;
333 return ConvertDialogToPixels( sz ).y;
345 wxDialog::SetPosition( aNewPosition );
363 m_parent->SetFocus();
378 ret = wxDialog::Show( show );
380 wxRect savedDialogRect;
385 auto dlgIt = settings->CsInternals().m_dialogControlValues.find( key );
387 if( dlgIt != settings->CsInternals().m_dialogControlValues.end() )
389 auto geoIt = dlgIt->second.find(
"__geometry" );
391 if( geoIt != dlgIt->second.end() && geoIt->second.is_object() )
393 const nlohmann::json& g = geoIt->second;
394 savedDialogRect.SetPosition( wxPoint( g.value(
"x", 0 ), g.value(
"y", 0 ) ) );
395 savedDialogRect.SetSize( wxSize( g.value(
"w", 500 ), g.value(
"h", 300 ) ) );
400 if( savedDialogRect.GetSize().x != 0 && savedDialogRect.GetSize().y != 0 )
403 wxSize restoredSize = FromDIP( savedDialogRect.GetSize() );
407 SetSize( savedDialogRect.GetPosition().x, savedDialogRect.GetPosition().y,
408 wxDialog::GetSize().x, wxDialog::GetSize().y, 0 );
412 SetSize( savedDialogRect.GetPosition().x, savedDialogRect.GetPosition().y,
413 std::max( wxDialog::GetSize().x, restoredSize.x ),
414 std::max( wxDialog::GetSize().y, restoredSize.y ), 0 );
420 SetMinSize( wxDefaultSize );
421 InvalidateBestSize();
422 SetMinSize( GetBestSize() );
426 if( m_parent !=
nullptr )
428 if( wxDisplay::GetFromPoint( m_parent->GetPosition() )
429 != wxDisplay::GetFromPoint( savedDialogRect.GetPosition() ) )
443 if( wxDisplay::GetFromWindow(
this ) == wxNOT_FOUND )
456 m_eventLoop->Exit( GetReturnCode() );
459 ret = wxDialog::Show( show );
475 auto dlgIt = settings->CsInternals().m_dialogControlValues.find( key );
477 if( dlgIt == settings->CsInternals().m_dialogControlValues.end() )
480 dlgIt->second.erase(
"__geometry" );
499 int parentDisplay = wxDisplay::GetFromWindow( m_parent );
500 int myDisplay = wxDisplay::GetFromWindow(
this );
502 if( parentDisplay != wxNOT_FOUND && myDisplay != wxNOT_FOUND )
527 return wxDialog::Enable( enable );
533 auto getSiblingIndex =
534 [](
const wxWindow* parent,
const wxWindow* child )
536 wxString childClass = child->GetClassInfo()->GetClassName();
539 for(
const wxWindow* sibling : parent->GetChildren() )
541 if( sibling->GetClassInfo()->GetClassName() != childClass )
544 if( sibling == child )
554 [&](
const wxWindow* window )
556 std::string key = wxString( window->GetClassInfo()->GetClassName() ).ToStdString();
558 if( window->GetParent() )
559 key +=
"_" + std::to_string( getSiblingIndex( window->GetParent(), window ) );
564 std::string key =
makeKey( aWin );
566 for(
const wxWindow* parent = aWin->GetParent(); parent && parent !=
this; parent = parent->GetParent() )
583 wxPoint pos = GetPosition();
584 wxSize dipSize = ToDIP( GetSize() );
588 geom[
"w" ] = dipSize.x;
589 geom[
"h" ] = dipSize.y;
590 dlgMap[
"__geometry" ] = geom;
592 std::function<void( wxWindow* )> saveFn =
597 if( !props->GetPropertyOr(
"persist",
false ) )
609 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( win ) )
611 dlgMap[ key ] = combo->GetValue();
613 else if( wxOwnerDrawnComboBox* od_combo =
dynamic_cast<wxOwnerDrawnComboBox*
>( win ) )
615 dlgMap[ key ] = od_combo->GetSelection();
617 else if( wxTextEntry* textEntry =
dynamic_cast<wxTextEntry*
>( win ) )
619 dlgMap[ key ] = textEntry->GetValue();
621 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( win ) )
623 dlgMap[ key ] = choice->GetSelection();
625 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( win ) )
627 dlgMap[ key ] = check->GetValue();
629 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( win ) )
631 dlgMap[ key ] = spin->GetValue();
633 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( win ) )
635 dlgMap[ key ] = radio->GetValue();
637 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( win ) )
639 dlgMap[ key ] = radioBox->GetSelection();
641 else if( wxSplitterWindow* splitter =
dynamic_cast<wxSplitterWindow*
>( win ) )
643 dlgMap[ key ] = splitter->GetSashPosition();
645 else if( wxScrolledWindow* scrolled =
dynamic_cast<wxScrolledWindow*
>( win ) )
647 dlgMap[ key ] = scrolled->GetScrollPos( wxVERTICAL );
649 else if( wxNotebook* notebook =
dynamic_cast<wxNotebook*
>( win ) )
651 int index = notebook->GetSelection();
653 if(
index >= 0 &&
index < (
int) notebook->GetPageCount() )
654 dlgMap[ key ] = notebook->GetPageText( notebook->GetSelection() );
656 else if( wxAuiNotebook* auiNotebook =
dynamic_cast<wxAuiNotebook*
>( win ) )
658 int index = auiNotebook->GetSelection();
660 if(
index >= 0 &&
index < (
int) auiNotebook->GetPageCount() )
661 dlgMap[ key ] = auiNotebook->GetPageText( auiNotebook->GetSelection() );
665 dlgMap[ key ] =
grid->GetShownColumnsAsString();
669 for( wxWindow* child : win->GetChildren() )
675 if( !props->GetPropertyOr(
"persist",
false ) )
679 for( wxWindow* child : GetChildren() )
697 const std::map<std::string, nlohmann::json>& dlgMap = dlgIt->second;
699 std::function<void( wxWindow* )> loadFn =
704 if( !props->GetPropertyOr(
"persist",
false ) )
712 auto it = dlgMap.find( key );
714 if( it != dlgMap.end() )
716 const nlohmann::json& j = it->second;
720 if( j.is_number_integer() )
724 else if( j.is_string() )
726 if( wxTextEntry* textEntry =
dynamic_cast<wxTextEntry*
>( win ) )
727 textEntry->ChangeValue( wxString::FromUTF8( j.get<std::string>().c_str() ) );
730 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( win ) )
733 combo->SetValue( wxString::FromUTF8( j.get<std::string>().c_str() ) );
735 else if( wxOwnerDrawnComboBox* od_combo =
dynamic_cast<wxOwnerDrawnComboBox*
>( win ) )
737 if( j.is_number_integer() )
739 int index = j.get<
int>();
741 if(
index >= 0 &&
index < (
int) od_combo->GetCount() )
742 od_combo->SetSelection(
index );
745 else if( wxTextEntry* textEntry =
dynamic_cast<wxTextEntry*
>( win ) )
748 textEntry->ChangeValue( wxString::FromUTF8( j.get<std::string>().c_str() ) );
750 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( win ) )
752 if( j.is_number_integer() )
754 int index = j.get<
int>();
756 if(
index >= 0 &&
index < (
int) choice->GetCount() )
757 choice->SetSelection(
index );
760 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( win ) )
763 check->SetValue( j.get<
bool>() );
765 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( win ) )
767 if( j.is_number_integer() )
768 spin->SetValue( j.get<
int>() );
770 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( win ) )
778 radio->SetValue(
true );
781 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( win ) )
783 if( j.is_number_integer() )
785 int index = j.get<
int>();
787 if(
index >= 0 &&
index < (
int) radioBox->GetCount() )
788 radioBox->SetSelection(
index );
791 else if( wxSplitterWindow* splitter =
dynamic_cast<wxSplitterWindow*
>( win ) )
793 if( j.is_number_integer() )
794 splitter->SetSashPosition( j.get<
int>() );
796 else if( wxScrolledWindow* scrolled =
dynamic_cast<wxScrolledWindow*
>( win ) )
798 if( j.is_number_integer() )
799 scrolled->SetScrollPos( wxVERTICAL, j.get<
int>() );
801 else if( wxNotebook* notebook =
dynamic_cast<wxNotebook*
>( win ) )
805 wxString pageTitle = wxString::FromUTF8( j.get<std::string>().c_str() );
807 for(
int page = 0; page < (int) notebook->GetPageCount(); ++page )
809 if( notebook->GetPageText( page ) == pageTitle )
810 notebook->ChangeSelection( page );
814 else if( wxAuiNotebook* auiNotebook =
dynamic_cast<wxAuiNotebook*
>( win ) )
818 wxString pageTitle = wxString::FromUTF8( j.get<std::string>().c_str() );
820 for(
int page = 0; page < (int) auiNotebook->GetPageCount(); ++page )
822 if( auiNotebook->GetPageText( page ) == pageTitle )
823 auiNotebook->ChangeSelection( page );
830 grid->ShowHideColumns( wxString::FromUTF8( j.get<std::string>().c_str() ) );
835 for( wxWindow* child : win->GetChildren() )
841 if( !props->GetPropertyOr(
"persist",
false ) )
845 for( wxWindow* child : GetChildren() )
854 aWindow->SetClientData( props );
875 for( wxWindow* child : children )
877 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
886#if defined( __WXMAC__ ) || defined( __WXMSW__ )
887 if( !textCtrl->GetStringSelection().IsEmpty() )
891 else if( textCtrl->IsEditable() )
893 textCtrl->SelectAll();
899 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
902 scintilla->Connect( wxEVT_SET_FOCUS,
906 if( !scintilla->GetSelectedText().IsEmpty() )
910 else if( scintilla->GetMarginWidth( 0 ) > 0 )
914 else if( scintilla->IsEditable() )
916 scintilla->SelectAll();
922 else if(
dynamic_cast<wxBitmapButton*
>( child ) !=
nullptr )
925 wxRect rect = child->GetRect();
927 child->ConvertDialogToPixels(
minSize );
929 rect.Inflate( std::max( 0,
minSize.x - rect.GetWidth() ),
930 std::max( 0,
minSize.y - rect.GetHeight() ) );
932 child->SetMinSize( rect.GetSize() );
933 child->SetSize( rect );
946 for( wxWindow* child : children )
951 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( child ) )
956 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( child ) )
961 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( child ) )
967 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( child ) )
970 m_currentValues[ choice ] =
static_cast<long>( choice->GetSelection() );
972 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( child ) )
977 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( child ) )
983 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( child ) )
989 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( child ) )
994 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( child ) )
997 m_currentValues[ radioBox ] =
static_cast<long>( radioBox->GetSelection() );
999 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( child ) )
1004 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( child ) )
1009 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( child ) )
1014 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( child ) )
1032 if( before != after )
1034 m_undoStack.push_back( { aCtrl, before, after } );
1103 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aCtrl ) )
1104 return wxVariant( textCtrl->GetValue() );
1105 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aCtrl ) )
1106 return wxVariant( scintilla->GetText() );
1107 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( aCtrl ) )
1108 return wxVariant( combo->GetValue() );
1109 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( aCtrl ) )
1110 return wxVariant( (
long) choice->GetSelection() );
1111 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( aCtrl ) )
1112 return wxVariant( check->GetValue() );
1113 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( aCtrl ) )
1114 return wxVariant( (
long) spin->GetValue() );
1115 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( aCtrl ) )
1116 return wxVariant( spinD->GetValue() );
1117 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( aCtrl ) )
1118 return wxVariant( radio->GetValue() );
1119 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( aCtrl ) )
1120 return wxVariant( (
long) radioBox->GetSelection() );
1121 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( aCtrl ) )
1125 table &&
table->HasUndoStateSerialization() )
1127 return wxVariant(
table->SerializeUndoState() );
1130 nlohmann::json j = nlohmann::json::array();
1131 int rows =
grid->GetNumberRows();
1132 int cols =
grid->GetNumberCols();
1134 for(
int r = 0; r < rows; ++r )
1136 nlohmann::json row = nlohmann::json::array();
1138 for(
int c = 0; c < cols; ++c )
1139 row.push_back( std::string(
grid->GetCellValue( r, c ).ToUTF8() ) );
1144 return wxVariant( wxString( j.dump() ) );
1146 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( aCtrl ) )
1150 for( wxPropertyGridIterator it = propGrid->GetIterator(); !it.AtEnd(); ++it )
1152 wxPGProperty* prop = *it;
1153 j[ prop->GetName().ToStdString() ] = prop->GetValueAsString().ToStdString();
1156 return wxVariant( wxString( j.dump() ) );
1158 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( aCtrl ) )
1160 nlohmann::json j = nlohmann::json::array();
1161 unsigned int count = checkList->GetCount();
1163 for(
unsigned int i = 0; i < count; ++i )
1165 if( checkList->IsChecked( i ) )
1169 return wxVariant( wxString( j.dump() ) );
1171 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( aCtrl ) )
1173 nlohmann::json j = nlohmann::json::array();
1174 unsigned int rows = dataList->GetItemCount();
1175 unsigned int cols = dataList->GetColumnCount();
1177 for(
unsigned int r = 0; r < rows; ++r )
1179 nlohmann::json row = nlohmann::json::array();
1181 for(
unsigned int c = 0; c < cols; ++c )
1184 dataList->GetValue( val, r, c );
1185 row.push_back( std::string( val.GetString().ToUTF8() ) );
1191 return wxVariant( wxString( j.dump() ) );
1200 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aCtrl ) )
1201 textCtrl->SetValue( aValue.GetString() );
1202 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aCtrl ) )
1203 scintilla->SetText( aValue.GetString() );
1204 else if( wxComboBox* combo =
dynamic_cast<wxComboBox*
>( aCtrl ) )
1205 combo->SetValue( aValue.GetString() );
1206 else if( wxChoice* choice =
dynamic_cast<wxChoice*
>( aCtrl ) )
1207 choice->SetSelection( (
int) aValue.GetLong() );
1208 else if( wxCheckBox* check =
dynamic_cast<wxCheckBox*
>( aCtrl ) )
1209 check->SetValue( aValue.GetBool() );
1210 else if( wxSpinCtrl* spin =
dynamic_cast<wxSpinCtrl*
>( aCtrl ) )
1211 spin->SetValue( (
int) aValue.GetLong() );
1212 else if( wxSpinCtrlDouble* spinD =
dynamic_cast<wxSpinCtrlDouble*
>( aCtrl ) )
1213 spinD->SetValue( aValue.GetDouble() );
1214 else if( wxRadioButton* radio =
dynamic_cast<wxRadioButton*
>( aCtrl ) )
1215 radio->SetValue( aValue.GetBool() );
1216 else if( wxRadioBox* radioBox =
dynamic_cast<wxRadioBox*
>( aCtrl ) )
1217 radioBox->SetSelection( (
int) aValue.GetLong() );
1218 else if( wxGrid*
grid =
dynamic_cast<wxGrid*
>( aCtrl ) )
1221 table &&
table->HasUndoStateSerialization() )
1223 table->RestoreUndoState( aValue.GetString() );
1227 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1231 int rows = std::min( (
int) j.size(),
grid->GetNumberRows() );
1233 for(
int r = 0; r < rows; ++r )
1235 nlohmann::json row = j[r];
1236 int cols = std::min( (
int) row.size(),
grid->GetNumberCols() );
1238 for(
int c = 0; c < cols; ++c )
1239 grid->SetCellValue( r, c, wxString( row[c].get<std::string>() ) );
1243 else if( wxPropertyGrid* propGrid =
dynamic_cast<wxPropertyGrid*
>( aCtrl ) )
1245 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1249 for(
auto it = j.begin(); it != j.end(); ++it )
1250 propGrid->SetPropertyValue( wxString( it.key() ), wxString( it.value().get<std::string>() ) );
1253 else if( wxCheckListBox* checkList =
dynamic_cast<wxCheckListBox*
>( aCtrl ) )
1255 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1259 unsigned int count = checkList->GetCount();
1261 for(
unsigned int i = 0; i < count; ++i )
1262 checkList->Check( i,
false );
1264 for(
auto& idx : j )
1266 unsigned int i = idx.get<
unsigned int>();
1269 checkList->Check( i,
true );
1273 else if( wxDataViewListCtrl* dataList =
dynamic_cast<wxDataViewListCtrl*
>( aCtrl ) )
1275 nlohmann::json j = nlohmann::json::parse( aValue.GetString().ToStdString(),
nullptr,
false );
1279 unsigned int rows = std::min(
static_cast<unsigned int>( j.size() ),
1280 static_cast<unsigned int>( dataList->GetItemCount() ) );
1282 for(
unsigned int r = 0; r < rows; ++r )
1284 nlohmann::json row = j[r];
1285 unsigned int cols = std::min( (
unsigned int) row.size(), dataList->GetColumnCount() );
1287 for(
unsigned int c = 0; c < cols; ++c )
1289 wxVariant val( wxString( row[c].get<std::string>() ) );
1290 dataList->SetValue( val, r, c );
1351 if( !GetTitle().StartsWith( wxS(
"*" ) ) )
1352 SetTitle( wxS(
"*" ) + GetTitle() );
1358 if( GetTitle().StartsWith( wxS(
"*" ) ) )
1359 SetTitle( GetTitle().AfterFirst(
'*' ) );
1373 return wxDialog::ShowModal();
1409 if( wxWindow* win = wxWindow::GetCapture() )
1410 win->ReleaseMouse();
1413 wxWindow* parent = GetParentForModalDialog( GetParent(), GetWindowStyle() );
1430 wxGUIEventLoop event_loop;
1439 return GetReturnCode();
1461 if( ( retCode == wxID_OK ) && ( !Validate() || !TransferDataFromWindow() ) )
1464 SetReturnCode( retCode );
1468 wxFAIL_MSG( wxT(
"Either DIALOG_SHIM::EndQuasiModal was called twice, or ShowQuasiModal wasn't called" ) );
1502 for( wxWindow* child : aWindow->GetChildren() )
1509 wxString msg = wxString::Format(
"Closing dialog %s", GetTitle() );
1527 const int id = aEvent.GetId();
1531 if(
id == GetAffirmativeId() )
1535 else if(
id == wxID_APPLY )
1544 else if(
id == wxID_CANCEL )
1567 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( aEvent.GetEventObject() ) )
1569 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( aEvent.GetEventObject() ) )
1579 int key = aEvt.GetKeyCode();
1582 if( aEvt.ControlDown() )
1584 if( aEvt.ShiftDown() )
1586 if( aEvt.AltDown() )
1589 int hotkey = key | mods;
1592 if( hotkey == (
MD_CTRL +
'Z') )
1603 if( aEvt.GetKeyCode() ==
'U' && aEvt.GetModifiers() == wxMOD_CONTROL )
1612 else if( ( aEvt.GetKeyCode() == WXK_RETURN || aEvt.GetKeyCode() == WXK_NUMPAD_ENTER ) && aEvt.ShiftDown() )
1614 wxObject* eventSource = aEvt.GetEventObject();
1616 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( eventSource ) )
1619 if( !textCtrl->IsMultiLine() )
1621 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
1625#if defined( __WXMAC__ ) || defined( __WXMSW__ )
1626 wxString eol =
"\r\n";
1628 wxString eol =
"\n";
1631 long pos = textCtrl->GetInsertionPoint();
1632 textCtrl->WriteText( eol );
1633 textCtrl->SetInsertionPoint( pos + eol.length() );
1636 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( eventSource ) )
1638 wxString eol =
"\n";
1640 switch( scintilla->GetEOLMode() )
1642 case wxSTC_EOL_CRLF: eol =
"\r\n";
break;
1643 case wxSTC_EOL_CR: eol =
"\r";
break;
1644 case wxSTC_EOL_LF: eol =
"\n";
break;
1647 long pos = scintilla->GetCurrentPos();
1648 scintilla->InsertText( pos, eol );
1649 scintilla->GotoPos( pos + eol.length() );
1655 else if( ( aEvt.GetKeyCode() == WXK_RETURN || aEvt.GetKeyCode() == WXK_NUMPAD_ENTER ) && aEvt.ControlDown() )
1657 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
1660 else if( aEvt.GetKeyCode() == WXK_TAB && !aEvt.ControlDown() )
1662 wxWindow* currentWindow = wxWindow::FindFocus();
1663 int currentIdx = -1;
1664 int delta = aEvt.ShiftDown() ? -1 : 1;
1671 idx = ( ( idx +
delta ) % size + size ) % size;
1674 for(
size_t i = 0; i <
m_tabOrder.size(); ++i )
1679 || ( currentWindow &&
m_tabOrder[i]->IsDescendant( currentWindow ) ) )
1681 currentIdx = (int) i;
1686 if( currentIdx >= 0 )
1688 advance( currentIdx );
1691 int startIdx = currentIdx;
1695 advance( currentIdx );
1697 if( currentIdx == startIdx )
1704 while(
dynamic_cast<wxTextEntry*
>(
m_tabOrder[ currentIdx ] ) ==
nullptr )
1705 advance( currentIdx );
1712 else if( aEvt.GetKeyCode() == WXK_ESCAPE )
1714 wxObject* eventSource = aEvt.GetEventObject();
1716 if( wxTextCtrl* textCtrl =
dynamic_cast<wxTextCtrl*
>( eventSource ) )
1722 textCtrl->SelectAll();
1726 else if( wxStyledTextCtrl* scintilla =
dynamic_cast<wxStyledTextCtrl*
>( eventSource ) )
1732 scintilla->SelectAll();
1744 wxStdDialogButtonSizer* sdbSizer =
dynamic_cast<wxStdDialogButtonSizer*
>( aSizer );
1747 [&]( wxButton* aButton )
1749 if( aLabels.count( aButton->GetId() ) > 0 )
1751 aButton->SetLabel( aLabels[ aButton->GetId() ] );
1757 switch( aButton->GetId() )
1759 case wxID_OK: aButton->SetLabel(
_(
"&OK" ) );
break;
1760 case wxID_CANCEL: aButton->SetLabel(
_(
"&Cancel" ) );
break;
1761 case wxID_YES: aButton->SetLabel(
_(
"&Yes" ) );
break;
1762 case wxID_NO: aButton->SetLabel(
_(
"&No" ) );
break;
1763 case wxID_APPLY: aButton->SetLabel(
_(
"&Apply" ) );
break;
1764 case wxID_SAVE: aButton->SetLabel(
_(
"&Save" ) );
break;
1765 case wxID_HELP: aButton->SetLabel(
_(
"&Help" ) );
break;
1766 case wxID_CONTEXT_HELP: aButton->SetLabel(
_(
"&Help" ) );
break;
1773 if( sdbSizer->GetAffirmativeButton() )
1774 setupButton( sdbSizer->GetAffirmativeButton() );
1776 if( sdbSizer->GetApplyButton() )
1777 setupButton( sdbSizer->GetApplyButton() );
1779 if( sdbSizer->GetNegativeButton() )
1780 setupButton( sdbSizer->GetNegativeButton() );
1782 if( sdbSizer->GetCancelButton() )
1783 setupButton( sdbSizer->GetCancelButton() );
1785 if( sdbSizer->GetHelpButton() )
1786 setupButton( sdbSizer->GetHelpButton() );
1790 if( sdbSizer->GetAffirmativeButton() )
1791 sdbSizer->GetAffirmativeButton()->SetDefault();
1794 for( wxSizerItem* item : aSizer->GetChildren() )
1796 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 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
std::vector< std::vector< std::string > > table