From e445249720ca428e4a19a5e9cf7855e4803dbc23 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Mon, 15 Jan 2024 17:29:55 +0000 Subject: [PATCH] ADDED: PCB tables. --- 3d-viewer/3d_canvas/board_adapter.h | 5 + .../3d_canvas/create_3Dgraphic_brd_items.cpp | 29 +- 3d-viewer/3d_canvas/create_layer_items.cpp | 17 + common/CMakeLists.txt | 2 + common/eda_item.cpp | 2 + common/eda_shape.cpp | 4 +- common/hash_eda.cpp | 4 + common/pcb.keywords | 12 + common/tool/actions.cpp | 79 +- common/widgets/lib_tree.cpp | 2 +- .../dialogs/dialog_tablecell_properties.cpp | 14 +- .../dialog_tablecell_properties_base.cpp | 4 +- .../dialog_tablecell_properties_base.fbp | 7053 +++++++++-------- .../dialog_tablecell_properties_base.h | 2 +- .../kicad_sexpr/sch_io_kicad_sexpr_parser.cpp | 9 +- eeschema/sch_item.h | 2 +- eeschema/sch_painter.cpp | 7 +- eeschema/sch_table.cpp | 64 +- eeschema/sch_tablecell.cpp | 35 + eeschema/sch_tablecell.h | 4 + eeschema/tools/ee_actions.cpp | 77 - eeschema/tools/ee_actions.h | 13 - eeschema/tools/ee_selection_tool.cpp | 12 +- eeschema/tools/sch_drawing_tools.cpp | 7 +- eeschema/tools/sch_edit_table_tool.cpp | 490 +- eeschema/tools/sch_edit_table_tool.h | 38 +- eeschema/tools/sch_edit_tool.cpp | 2 + include/core/typeinfo.h | 4 + include/tool/actions.h | 15 +- include/tool/edit_table_tool_base.h | 555 ++ pcbnew/CMakeLists.txt | 3 + pcbnew/array_creator.cpp | 1 + pcbnew/board.cpp | 33 +- pcbnew/board_commit.cpp | 3 +- pcbnew/collectors.cpp | 7 + .../dialogs/dialog_tablecell_properties.cpp | 477 ++ pcbnew/dialogs/dialog_tablecell_properties.h | 72 + .../dialog_tablecell_properties_base.cpp | 382 + .../dialog_tablecell_properties_base.fbp | 3445 ++++++++ .../dialog_tablecell_properties_base.h | 119 + pcbnew/drc/drc_engine.cpp | 1 + pcbnew/edit.cpp | 5 + pcbnew/footprint_edit_frame.cpp | 2 + pcbnew/menubar_pcb_editor.cpp | 1 + pcbnew/pcb_base_edit_frame.h | 2 + pcbnew/pcb_edit_frame.cpp | 3 + pcbnew/pcb_group.cpp | 1 + .../pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp | 82 +- .../pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h | 10 +- .../kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp | 253 +- .../kicad_sexpr/pcb_io_kicad_sexpr_parser.h | 7 +- pcbnew/pcb_painter.cpp | 175 +- pcbnew/pcb_painter.h | 2 + pcbnew/pcb_table.cpp | 450 ++ pcbnew/pcb_table.h | 250 + pcbnew/pcb_tablecell.cpp | 192 + pcbnew/pcb_tablecell.h | 85 + pcbnew/pcb_textbox.cpp | 6 +- pcbnew/pcb_textbox.h | 2 +- pcbnew/pcb_view.cpp | 17 +- pcbnew/toolbars_footprint_editor.cpp | 1 + pcbnew/toolbars_pcb_editor.cpp | 1 + pcbnew/tools/drawing_tool.cpp | 234 +- pcbnew/tools/drawing_tool.h | 5 + pcbnew/tools/edit_tool.cpp | 21 + pcbnew/tools/edit_tool_move_fct.cpp | 1 + pcbnew/tools/pcb_actions.cpp | 10 +- pcbnew/tools/pcb_actions.h | 1 + pcbnew/tools/pcb_edit_table_tool.cpp | 94 + pcbnew/tools/pcb_edit_table_tool.h | 68 + pcbnew/tools/pcb_point_editor.cpp | 76 +- pcbnew/tools/pcb_selection_tool.cpp | 167 +- pcbnew/tools/pcb_selection_tool.h | 8 + pcbnew/zone_filler.cpp | 4 + 74 files changed, 11148 insertions(+), 4194 deletions(-) create mode 100644 include/tool/edit_table_tool_base.h create mode 100644 pcbnew/dialogs/dialog_tablecell_properties.cpp create mode 100644 pcbnew/dialogs/dialog_tablecell_properties.h create mode 100644 pcbnew/dialogs/dialog_tablecell_properties_base.cpp create mode 100644 pcbnew/dialogs/dialog_tablecell_properties_base.fbp create mode 100644 pcbnew/dialogs/dialog_tablecell_properties_base.h create mode 100644 pcbnew/pcb_table.cpp create mode 100644 pcbnew/pcb_table.h create mode 100644 pcbnew/pcb_tablecell.cpp create mode 100644 pcbnew/pcb_tablecell.h create mode 100644 pcbnew/tools/pcb_edit_table_tool.cpp create mode 100644 pcbnew/tools/pcb_edit_table_tool.h diff --git a/3d-viewer/3d_canvas/board_adapter.h b/3d-viewer/3d_canvas/board_adapter.h index 68160c3d70..13827539e8 100644 --- a/3d-viewer/3d_canvas/board_adapter.h +++ b/3d-viewer/3d_canvas/board_adapter.h @@ -42,6 +42,8 @@ #include #include #include +#include +#include #include #include #include @@ -376,6 +378,9 @@ private: void addShape( const PCB_TEXTBOX* aTextBox, CONTAINER_2D_BASE* aContainer, const BOARD_ITEM* aOwner ); + void addTable( const PCB_TABLE* aTable, CONTAINER_2D_BASE* aContainer, + const BOARD_ITEM* aOwner ); + void addSolidAreasShapes( const ZONE* aZone, CONTAINER_2D_BASE* aDstContainer, PCB_LAYER_ID aLayerId ); diff --git a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp index dc1e4d5dbb..995c0d2653 100644 --- a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp +++ b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include // for PCB_RENDER_SETTINGS #include @@ -225,12 +226,17 @@ void BOARD_ADAPTER::addFootprintShapes( const FOOTPRINT* aFootprint, CONTAINER_2 PCB_TEXTBOX* textbox = static_cast( item ); if( textbox->GetLayer() == aLayerId ) - { - if( textbox->IsBorderEnabled() ) - addShape( textbox, aContainer, aFootprint ); + addShape( textbox, aContainer, aFootprint ); - addText( textbox, aContainer, aFootprint ); - } + break; + } + + case PCB_TABLE_T: + { + PCB_TABLE* table = static_cast( item ); + + if( table->GetLayer() == aLayerId ) + addTable( table, aContainer, aFootprint ); break; } @@ -726,7 +732,9 @@ void BOARD_ADAPTER::addShape( const PCB_TEXTBOX* aTextBox, CONTAINER_2D_BASE* aC // So for polygon, we use PCB_SHAPE::TransformShapeToPolygon if( aTextBox->GetShape() == SHAPE_T::RECTANGLE ) + { addShape( static_cast( aTextBox ), aContainer, aOwner ); + } else { SHAPE_POLY_SET polyList; @@ -739,6 +747,17 @@ void BOARD_ADAPTER::addShape( const PCB_TEXTBOX* aTextBox, CONTAINER_2D_BASE* aC } +void BOARD_ADAPTER::addTable( const PCB_TABLE* aTable, CONTAINER_2D_BASE* aContainer, + const BOARD_ITEM* aOwner ) +{ + // JEY TODO: tables + // add borders + + for( PCB_TABLECELL* cell : aTable->GetCells() ) + addText( cell, aContainer, aOwner ); +} + + void BOARD_ADAPTER::addSolidAreasShapes( const ZONE* aZone, CONTAINER_2D_BASE* aContainer, PCB_LAYER_ID aLayerId ) { diff --git a/3d-viewer/3d_canvas/create_layer_items.cpp b/3d-viewer/3d_canvas/create_layer_items.cpp index 94f52df48c..f0ec777459 100644 --- a/3d-viewer/3d_canvas/create_layer_items.cpp +++ b/3d-viewer/3d_canvas/create_layer_items.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -622,6 +623,10 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) addShape( static_cast( item ), layerContainer, item ); break; + case PCB_TABLE_T: + addTable( static_cast( item ), layerContainer, item ); + break; + case PCB_DIM_ALIGNED_T: case PCB_DIM_CENTER_T: case PCB_DIM_RADIAL_T: @@ -686,6 +691,10 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) break; } + case PCB_TABLE_T: + // JEY TODO: tables + break; + default: wxLogTrace( m_logTrace, wxT( "createLayers: item type: %d not implemented" ), item->Type() ); @@ -847,6 +856,10 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) addShape( static_cast( item ), layerContainer, item ); break; + case PCB_TABLE_T: + // JEY TODO: tables + break; + case PCB_DIM_ALIGNED_T: case PCB_DIM_CENTER_T: case PCB_DIM_RADIAL_T: @@ -942,6 +955,10 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) break; } + case PCB_TABLE_T: + // JEY TODO: tables + break; + default: break; } diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index a9499eb123..d1d885957b 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -680,6 +680,8 @@ set( PCB_COMMON_SRCS ${CMAKE_SOURCE_DIR}/pcbnew/pcb_target.cpp ${CMAKE_SOURCE_DIR}/pcbnew/pcb_reference_image.cpp ${CMAKE_SOURCE_DIR}/pcbnew/pcb_field.cpp + ${CMAKE_SOURCE_DIR}/pcbnew/pcb_table.cpp + ${CMAKE_SOURCE_DIR}/pcbnew/pcb_tablecell.cpp ${CMAKE_SOURCE_DIR}/pcbnew/pcb_text.cpp ${CMAKE_SOURCE_DIR}/pcbnew/pcb_textbox.cpp ${CMAKE_SOURCE_DIR}/pcbnew/project_pcb.cpp diff --git a/common/eda_item.cpp b/common/eda_item.cpp index 0b5450334e..3f0dd5d00f 100644 --- a/common/eda_item.cpp +++ b/common/eda_item.cpp @@ -349,6 +349,8 @@ static struct EDA_ITEM_DESC .Map( PCB_FIELD_T, _HKI( "Text" ) ) .Map( PCB_TEXT_T, _HKI( "Text" ) ) .Map( PCB_TEXTBOX_T, _HKI( "Text Box" ) ) + .Map( PCB_TABLE_T, _HKI( "Table" ) ) + .Map( PCB_TABLECELL_T, _HKI( "Table Cell" ) ) .Map( PCB_TRACE_T, _HKI( "Track" ) ) .Map( PCB_ARC_T, _HKI( "Track" ) ) .Map( PCB_VIA_T, _HKI( "Via" ) ) diff --git a/common/eda_shape.cpp b/common/eda_shape.cpp index 03f1f34b59..2ee69b67fd 100644 --- a/common/eda_shape.cpp +++ b/common/eda_shape.cpp @@ -2015,8 +2015,8 @@ static struct EDA_SHAPE_DESC &EDA_SHAPE::SetWidth, &EDA_SHAPE::GetWidth, PROPERTY_DISPLAY::PT_SIZE ) ); void ( EDA_SHAPE::*lineStyleSetter )( LINE_STYLE ) = &EDA_SHAPE::SetLineStyle; - propMgr.AddProperty( new PROPERTY_ENUM( - _HKI( "Line Style" ), lineStyleSetter, &EDA_SHAPE::GetLineStyle ) ); + propMgr.AddProperty( new PROPERTY_ENUM( _HKI( "Line Style" ), + lineStyleSetter, &EDA_SHAPE::GetLineStyle ) ); propMgr.AddProperty( new PROPERTY( _HKI( "Line Color" ), &EDA_SHAPE::SetLineColor, &EDA_SHAPE::GetLineColor ) ) diff --git a/common/hash_eda.cpp b/common/hash_eda.cpp index 164019363a..053583275b 100644 --- a/common/hash_eda.cpp +++ b/common/hash_eda.cpp @@ -296,6 +296,10 @@ size_t hash_fp_item( const EDA_ITEM* aItem, int aFlags ) } break; + case PCB_TABLE_T: + // JEY TODO: tables + break; + default: wxASSERT_MSG( false, "Unhandled type in function hash_fp_item() (exporter_gencad.cpp)" ); } diff --git a/common/pcb.keywords b/common/pcb.keywords index 810a9f3391..915c8b3fab 100644 --- a/common/pcb.keywords +++ b/common/pcb.keywords @@ -59,6 +59,7 @@ bottom bottom_left bottom_right castellated_pads +cells center chamfer chamfer_ratio @@ -66,6 +67,9 @@ circle clearance clearance_min color +cols +column_count +column_widths comment company connect @@ -108,6 +112,7 @@ exclude_from_pos_files exclude_from_bom extension_height extension_offset +external fab_layers_line_width fab_layers_text_dims face @@ -158,6 +163,7 @@ hatch_smoothing_level hatch_smoothing_value hatch_border_algorithm hatch_min_hole_area +header height hide hole_to_hole_min @@ -269,9 +275,12 @@ right rotate roundrect roundrect_rratio +rows +row_heights scale segment segment_width +separators setup sheetfile sheetname @@ -286,6 +295,7 @@ solder_paste_margin solder_paste_margin_ratio solder_paste_ratio solid +span stackup start status @@ -293,6 +303,8 @@ stroke style suffix suppress_zeroes +table +table_cell tags target title diff --git a/common/tool/actions.cpp b/common/tool/actions.cpp index 49d2e17038..36b67058aa 100644 --- a/common/tool/actions.cpp +++ b/common/tool/actions.cpp @@ -298,6 +298,83 @@ TOOL_ACTION ACTIONS::rightJustify( TOOL_ACTION_ARGS() .Tooltip( _( "Right-justify fields and text items" ) ) .Icon( BITMAPS::text_align_right ) ); +TOOL_ACTION ACTIONS::selectColumns( TOOL_ACTION_ARGS() + .Name( "common.InteractiveSelection.SelectColumns" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Select Column(s)" ) ) + .Tooltip( _( "Select complete column(s) containing the current selected cell(s)" ) ) + .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon + +TOOL_ACTION ACTIONS::selectRows( TOOL_ACTION_ARGS() + .Name( "common.InteractiveSelection.Rows" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Select Row(s)" ) ) + .Tooltip( _( "Select complete row(s) containing the current selected cell(s)" ) ) + .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon + +TOOL_ACTION ACTIONS::selectTable( TOOL_ACTION_ARGS() + .Name( "common.InteractiveSelection.SelectTable" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Select Table" ) ) + .Tooltip( _( "Select parent table of selected cell(s)" ) ) + .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon + +TOOL_ACTION ACTIONS::addRowAbove( TOOL_ACTION_ARGS() + .Name( "common.TableEditor.addRowAbove" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Add Row Above" ) ) + .Tooltip( _( "Insert a new table row above the selected cell(s)" ) ) + .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon + +TOOL_ACTION ACTIONS::addRowBelow( TOOL_ACTION_ARGS() + .Name( "common.TableEditor.addRowBelow" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Add Row Below" ) ) + .Tooltip( _( "Insert a new table row below the selected cell(s)" ) ) + .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon + +TOOL_ACTION ACTIONS::addColBefore( TOOL_ACTION_ARGS() + .Name( "common.TableEditor.addColBefore" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Add Column Before" ) ) + .Tooltip( _( "Insert a new table column before the selected cell(s)" ) ) + .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon + +TOOL_ACTION ACTIONS::addColAfter( TOOL_ACTION_ARGS() + .Name( "common.TableEditor.addColAfter" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Add Column After" ) ) + .Tooltip( _( "Insert a new table column after the selected cell(s)" ) ) + .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon + +TOOL_ACTION ACTIONS::deleteRows( TOOL_ACTION_ARGS() + .Name( "common.TableEditor.deleteRows" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Delete Row(s)" ) ) + .Tooltip( _( "Delete rows containing the currently selected cell(s)" ) ) + .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon + +TOOL_ACTION ACTIONS::deleteColumns( TOOL_ACTION_ARGS() + .Name( "common.TableEditor.deleteColumns" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Delete Column(s)" ) ) + .Tooltip( _( "Delete columns containing the currently selected cell(s)" ) ) + .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon + +TOOL_ACTION ACTIONS::mergeCells( TOOL_ACTION_ARGS() + .Name( "common.TableEditor.mergeCells" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Merge Cells" ) ) + .Tooltip( _( "Turn selected table cells into a single cell" ) ) + .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon + +TOOL_ACTION ACTIONS::unmergeCells( TOOL_ACTION_ARGS() + .Name( "common.TableEditor.unmergeCell" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Unmerge Cells" ) ) + .Tooltip( _( "Turn merged table cells back into separate cells." ) ) + .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon + TOOL_ACTION ACTIONS::activatePointEditor( TOOL_ACTION_ARGS() .Name( "common.Control.activatePointEditor" ) .Scope( AS_GLOBAL ) ); @@ -765,7 +842,7 @@ TOOL_ACTION ACTIONS::updatePreferences( TOOL_ACTION_ARGS() .Name( "common.Control.updatePreferences" ) .Scope( AS_GLOBAL ) ); -TOOL_ACTION ACTIONS::selectColumns( TOOL_ACTION_ARGS() +TOOL_ACTION ACTIONS::selectLibTreeColumns( TOOL_ACTION_ARGS() .Name( "common.Control.selectColumns" ) .Scope( AS_GLOBAL ) .FriendlyName( _( "Select Columns..." ) ) ); diff --git a/common/widgets/lib_tree.cpp b/common/widgets/lib_tree.cpp index 5086c67dbc..64738436ce 100644 --- a/common/widgets/lib_tree.cpp +++ b/common/widgets/lib_tree.cpp @@ -931,7 +931,7 @@ void LIB_TREE::onHeaderContextMenu( wxDataViewEvent& aEvent ) ACTION_MENU menu( true, nullptr ); - menu.Add( ACTIONS::selectColumns ); + menu.Add( ACTIONS::selectLibTreeColumns ); if( GetPopupMenuSelectionFromUser( menu ) != wxID_NONE ) { diff --git a/eeschema/dialogs/dialog_tablecell_properties.cpp b/eeschema/dialogs/dialog_tablecell_properties.cpp index 70fe1bd3c6..7a9fced636 100644 --- a/eeschema/dialogs/dialog_tablecell_properties.cpp +++ b/eeschema/dialogs/dialog_tablecell_properties.cpp @@ -393,7 +393,19 @@ bool DIALOG_TABLECELL_PROPERTIES::TransferDataFromWindow() m_table->SetSeparatorsStroke( stroke ); } - m_cell->SetText( m_textCtrl->GetValue() ); + wxString txt = m_textCtrl->GetValue(); + +#ifdef __WXMAC__ + // On macOS CTRL+Enter produces '\r' instead of '\n' regardless of EOL setting. + // Replace it now. + txt.Replace( "\r", "\n" ); +#elif defined( __WINDOWS__ ) + // On Windows, a new line is coded as \r\n. We use only \n in kicad files and in + // drawing routines so strip the \r char. + txt.Replace( "\r", "" ); +#endif + + m_cell->SetText( txt ); if( m_fontCtrl->HaveFontSelection() ) { diff --git a/eeschema/dialogs/dialog_tablecell_properties_base.cpp b/eeschema/dialogs/dialog_tablecell_properties_base.cpp index 624a1faff9..0ec8835f81 100644 --- a/eeschema/dialogs/dialog_tablecell_properties_base.cpp +++ b/eeschema/dialogs/dialog_tablecell_properties_base.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b) +// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf) // http://www.wxformbuilder.org/ // // PLEASE DO *NOT* EDIT THIS FILE! @@ -76,7 +76,7 @@ DIALOG_TABLECELL_PROPERTIES_BASE::DIALOG_TABLECELL_PROPERTIES_BASE( wxWindow* pa wxBoxSizer* bSizer16; bSizer16 = new wxBoxSizer( wxVERTICAL ); - m_textEntrySizer = new wxGridBagSizer( 4, 3 ); + m_textEntrySizer = new wxGridBagSizer( 3, 3 ); m_textEntrySizer->SetFlexibleDirection( wxBOTH ); m_textEntrySizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); m_textEntrySizer->SetEmptyCellSize( wxSize( 0,2 ) ); diff --git a/eeschema/dialogs/dialog_tablecell_properties_base.fbp b/eeschema/dialogs/dialog_tablecell_properties_base.fbp index c57f228180..2bb1251531 100644 --- a/eeschema/dialogs/dialog_tablecell_properties_base.fbp +++ b/eeschema/dialogs/dialog_tablecell_properties_base.fbp @@ -1,149 +1,3191 @@ - + - - - - C++ - 1 - source_name - 0 - 0 - res - UTF-8 - connect - dialog_tablecell_properties_base - 1000 - none - - - 1 - dialog_tablecell_properties_base - - . - - 1 - 1 - 1 - 1 - UI - 0 - 1 - 0 - - 0 - wxAUI_MGR_DEFAULT + + + + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + dialog_tablecell_properties_base + 1000 + none + + + 1 + dialog_tablecell_properties_base + + . + + 1 + 1 + 1 + 1 + UI + 0 + 1 + 0 + + 0 + wxAUI_MGR_DEFAULT + + + + 1 + 0 + 1 + impl_virtual + + + + 0 + wxID_ANY + + + DIALOG_TABLECELL_PROPERTIES_BASE + + -1,-1 + wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER + DIALOG_SHIM; dialog_shim.h + Table Cell Properties + + 0 + + + + + + bMainSizer + wxVERTICAL + none + + 5 + wxEXPAND|wxBOTTOM + 0 + + 1 + 1 + 1 + 1 + + + + + - + + 1 + 0 + 1 1 + 0 + Dock + 0 + Left + 0 + 500 1 - impl_virtual - + 1 - 0 + 0 + 1 + wxSHOW_EFFECT_NONE wxID_ANY + + 0 + + 0 - DIALOG_TABLECELL_PROPERTIES_BASE + 1 + m_infoBar + 1 + + + protected + 1 - -1,-1 - wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER - DIALOG_SHIM; dialog_shim.h - Table Cell Properties + Resizable + 1 + wxSHOW_EFFECT_NONE + + WX_INFOBAR; widgets/wx_infobar.h; forward_declare + 0 - 0 - + + + + 10 + wxEXPAND|wxRIGHT|wxLEFT + 1 + + + bColumns + wxHORIZONTAL + none + + 6 + wxEXPAND|wxTOP + 1 + - bMainSizer + bCellContentMargins wxVERTICAL none - - 5 - wxEXPAND|wxBOTTOM - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 500 - 1 - - 1 - - 0 - 1 - wxSHOW_EFFECT_NONE - wxID_ANY - - 0 - - - 0 - - 1 - m_infoBar - 1 - - - protected - 1 - - Resizable - 1 - wxSHOW_EFFECT_NONE - - WX_INFOBAR; widgets/wx_infobar.h; forward_declare - 0 - - - - - + + 1 + wxEXPAND|wxTOP|wxBOTTOM + 1 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + 0 + + 0 + 0 + wxID_ANY + 0 + 0 + + 0 + + + 0 + 500,-1 + 1 + m_textCtrl + 1 + + + protected + 1 + + 0 + Resizable + 1 + + ; forward_declare + 0 + 4 + 0 + + 1 + 0 + 0 + + + wxBORDER_SUNKEN + onMultiLineTCLostFocus + - - 10 - wxEXPAND|wxRIGHT|wxLEFT - 1 - - - bColumns - wxHORIZONTAL - none - - 6 + + + + 10 + wxEXPAND|wxBOTTOM|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_notebook + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + + + Table + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_tablePage + 1 + + + protected + 1 + + Resizable + 1 + + ; ; forward_declare + 0 + + + + wxTAB_TRAVERSAL + + + bSizer16 + wxVERTICAL + none + + 5 + wxEXPAND|wxALL + 1 + + 0,2 + wxBOTH + 1 + + 3 + + m_textEntrySizer + wxFLEX_GROWMODE_SPECIFIED + protected + 3 + + 2 + 2 + 0 + wxBOTTOM + 0 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + External border + + 0 + + + 0 + + 1 + m_borderCheckbox + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + onBorderChecked + + + + 20 + 1 + 2 + wxLEFT + 0 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Header border + + 0 + + + 0 + + 1 + m_headerBorder + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + 1 + 0 + wxALIGN_CENTER_VERTICAL + 2 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Width: + 0 + + 0 + + + 0 + + 1 + m_borderWidthLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + 2 + 1 + wxEXPAND + 2 + 1 + + + bSizer7 + wxHORIZONTAL + none + + 5 + wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + -1,-1 + 0 + -1,-1 + 1 + m_borderWidthCtrl + 1 + + + protected + 1 + + Resizable + 1 + -1,-1 + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + 3 + wxALIGN_CENTER_VERTICAL|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + mm + 0 + + 0 + + + 0 + -1,-1 + 1 + m_borderWidthUnits + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + 15 + wxALIGN_CENTER_VERTICAL|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Color: + 0 + + 0 + + + 0 + + 1 + m_borderColorLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; Not forward_declare + 0 + + + + + -1 + + + + 5 + + 0 + + 0 + protected + 5 + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_panelBorderColor + 1 + + + protected + 1 + + Resizable + 1 + + ; ; forward_declare + 0 + + + + wxBORDER_SIMPLE|wxTAB_TRAVERSAL + + + bSizer2 + wxVERTICAL + none + + 5 + wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + COLOR_SWATCH + 1 + + + 1 + + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + + 0 + + + 0 + + 1 + m_borderColorSwatch + 1 + + + protected + 1 + + Resizable + + 1 + + COLOR_SWATCH; widgets/color_swatch.h; forward_declare + 0 + + + + + + + + + + + + + 5 + 1 + 0 + wxALIGN_CENTER_VERTICAL + 3 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Style: + 0 + + 0 + + + 0 + + 1 + m_borderStyleLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + 2 + 1 + wxEXPAND + 3 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + 200,-1 + 1 + m_borderStyleCombo + 1 + + + protected + 1 + + Resizable + -1 + 1 + + wxCB_READONLY + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + 5 + 1 + 0 + wxEXPAND + 4 + 1 + + 20 + protected + 0 + + + + 15 + 2 + 0 + wxALIGN_CENTER_VERTICAL|wxRIGHT + 5 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Row lines + + 0 + + + 0 + + 1 + m_rowSeparators + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + onBorderChecked + + + + 20 + 1 + 2 + wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT + 5 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Column lines + + 0 + + + 0 + + 1 + m_colSeparators + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + onBorderChecked + + + + 5 + 1 + 0 + wxALIGN_CENTER_VERTICAL + 7 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Width: + 0 + + 0 + + + 0 + + 1 + m_separatorsWidthLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + 2 + 1 + wxEXPAND + 7 + 1 + + + bSizer71 + wxHORIZONTAL + none + + 5 + wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + -1,-1 + 0 + -1,-1 + 1 + m_separatorsWidthCtrl + 1 + + + protected + 1 + + Resizable + 1 + -1,-1 + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + 3 + wxALIGN_CENTER_VERTICAL|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + mm + 0 + + 0 + + + 0 + -1,-1 + 1 + m_separatorsWidthUnits + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + 15 + wxALIGN_CENTER_VERTICAL|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Color: + 0 + + 0 + + + 0 + + 1 + m_separatorsColorLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; Not forward_declare + 0 + + + + + -1 + + + + 5 + + 0 + + 0 + protected + 5 + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_panelSeparatorsColor + 1 + + + protected + 1 + + Resizable + 1 + + ; ; forward_declare + 0 + + + + wxBORDER_SIMPLE|wxTAB_TRAVERSAL + + + bSizer21 + wxVERTICAL + none + + 5 + wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + COLOR_SWATCH + 1 + + + 1 + + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + + 0 + + + 0 + + 1 + m_separatorsColorSwatch + 1 + + + protected + 1 + + Resizable + + 1 + + COLOR_SWATCH; widgets/color_swatch.h; forward_declare + 0 + + + + + + + + + + + + + 5 + 1 + 0 + wxALIGN_CENTER_VERTICAL + 8 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Style: + 0 + + 0 + + + 0 + + 1 + m_separatorsStyleLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + 2 + 1 + wxALIGN_CENTER_VERTICAL|wxEXPAND + 8 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + 200,-1 + 1 + m_separatorsStyleCombo + 1 + + + protected + 1 + + Resizable + -1 + 1 + + wxCB_READONLY + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + Cell + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_cellPage + 1 + + + protected + 1 + + Resizable + 1 + + ; ; forward_declare + 0 + + + + wxTAB_TRAVERSAL + + + bSizer13 + wxVERTICAL + none + + 5 + wxEXPAND|wxALL + 1 + + + bMargins + wxVERTICAL + none + + 10 + wxBOTTOM + 0 + + + bSizeCtrlSizer + wxHORIZONTAL + none + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 0 + + 1 + + + 0 + 0 + wxID_ANY + + + 0 + + 0 + + + 0 + + 1 + m_separator1 + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Bold + + 0 + + 0 + + + 0 + + 1 + m_bold + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + Bold + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Italic + + 0 + + 0 + + + 0 + + 1 + m_italic + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + Italic + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 0 + + 1 + + + 0 + 0 + wxID_ANY + + + 0 + + 0 + + + 0 + + 1 + m_separator2 + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Align left + + 0 + + 0 + + + 0 + + 1 + m_hAlignLeft + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + Align left + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Align center + + 0 + + 0 + + + 0 + + 1 + m_hAlignCenter + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + Align horizontal center + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Align right + + 0 + + 0 + + + 0 + + 1 + m_hAlignRight + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + Align right + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 0 + + 1 + + + 0 + 0 + wxID_ANY + + + 0 + + 0 + + + 0 + + 1 + m_separator3 + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Align top + + 0 + + 0 + + + 0 + + 1 + m_vAlignTop + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + Align top + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Align middle + + 0 + + 0 + + + 0 + + 1 + m_vAlignCenter + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + Align vertical center + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Align bottom + + 0 + + 0 + + + 0 + + 1 + m_vAlignBottom + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + Align bottom + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 0 + + 1 + + + 0 + 0 + wxID_ANY + + + 0 + + 0 + + + 0 + + 1 + m_separator4 + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + 5 + wxEXPAND|wxBOTTOM + 0 + + -1,5 + wxBOTH + 1 + + 5 + + gbSizer2 + wxFLEX_GROWMODE_SPECIFIED + none + 4 + + 1 + 1 + 0 + wxALIGN_CENTER_VERTICAL|wxLEFT + 0 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Font: + 0 + + 0 + + + 0 + + 1 + m_fontLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + 3 + 1 + wxALIGN_CENTER_VERTICAL|wxEXPAND + 0 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + "Default Font" "KiCad Font" + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_fontCtrl + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + FONT_CHOICE; widgets/font_choice.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + 1 + 0 + wxALIGN_CENTER_VERTICAL + 1 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Size: + 0 + + 0 + + + 0 + + 1 + m_textSizeLabel + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + 5 + 3 + 1 + wxALIGN_CENTER_VERTICAL + 1 + 1 + + + bSizer15 + wxHORIZONTAL + none + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + -1,-1 + 0 + -1,-1 + 1 + m_textSizeCtrl + 1 + + + protected + 1 + + Resizable + 1 + -1,-1 + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + 3 + wxLEFT|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + mm + 0 + + 0 + + + 0 + -1,-1 + 1 + m_textSizeUnits + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + 5 wxEXPAND|wxTOP 1 - - - bCellContentMargins - wxVERTICAL - none - - 1 - wxEXPAND|wxTOP|wxBOTTOM - 1 - + + 2 + wxBOTH + + + 5 + + fgSizer1 + wxFLEX_GROWMODE_SPECIFIED + none + 0 + 6 + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Text color: + 0 + + 0 + + + 0 + + 1 + m_textColorLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_panelTextColor + 1 + + + protected + 1 + + Resizable + 1 + + ; ; forward_declare + 0 + + + + wxBORDER_SIMPLE|wxTAB_TRAVERSAL + + + bSizer221 + wxVERTICAL + none + + 5 + wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL + 0 + 1 1 1 @@ -152,3427 +3194,436 @@ - 0 1 0 + COLOR_SWATCH 1 + 1 + 0 Dock 0 Left + 0 1 1 - 0 0 0 wxID_ANY - 0 - 0 + 0 0 - 500,-1 + -1,-1 1 - m_textCtrl + m_textColorSwatch 1 protected 1 - 0 Resizable + 1 - ; forward_declare - 0 - 4 + COLOR_SWATCH; widgets/color_swatch.h; forward_declare 0 - 1 - 0 - 0 - wxBORDER_SUNKEN - onMultiLineTCLostFocus - - - - - - 10 - wxEXPAND|wxBOTTOM|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - m_notebook - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - - - - - Table - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - m_tablePage - 1 - - - protected - 1 - - Resizable - 1 - - ; ; forward_declare - 0 - - - - wxTAB_TRAVERSAL - - - bSizer16 - wxVERTICAL - none - - 5 - wxEXPAND|wxALL - 1 - - 0,2 - wxBOTH - 1 - - 3 - - m_textEntrySizer - wxFLEX_GROWMODE_SPECIFIED - protected - 4 - - 2 - 2 - 0 - wxBOTTOM - 0 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - External border - - 0 - - - 0 - - 1 - m_borderCheckbox - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - onBorderChecked - - - - 20 - 1 - 2 - wxLEFT - 0 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Header border - - 0 - - - 0 - - 1 - m_headerBorder - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - 5 - 1 - 0 - wxALIGN_CENTER_VERTICAL - 2 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Width: - 0 - - 0 - - - 0 - - 1 - m_borderWidthLabel - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - - - -1 - - - - 5 - 2 - 1 - wxEXPAND - 2 - 1 - - - bSizer7 - wxHORIZONTAL - none - - 5 - wxEXPAND - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - 0 - -1,-1 - 0 - -1,-1 - 1 - m_borderWidthCtrl - 1 - - - protected - 1 - - Resizable - 1 - -1,-1 - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - 3 - wxALIGN_CENTER_VERTICAL|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - mm - 0 - - 0 - - - 0 - -1,-1 - 1 - m_borderWidthUnits - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - - - -1 - - - - 15 - wxALIGN_CENTER_VERTICAL|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Color: - 0 - - 0 - - - 0 - - 1 - m_borderColorLabel - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; Not forward_declare - 0 - - - - - -1 - - - - 5 - - 0 - - 0 - protected - 5 - - - - 5 - wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - m_panelBorderColor - 1 - - - protected - 1 - - Resizable - 1 - - ; ; forward_declare - 0 - - - - wxBORDER_SIMPLE|wxTAB_TRAVERSAL - - - bSizer2 - wxVERTICAL - none - - 5 - wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - COLOR_SWATCH - 1 - - - 1 - - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - - 0 - - - 0 - - 1 - m_borderColorSwatch - 1 - - - protected - 1 - - Resizable - - 1 - - COLOR_SWATCH; widgets/color_swatch.h; forward_declare - 0 - - - - - - - - - - - - - 5 - 1 - 0 - wxALIGN_CENTER_VERTICAL - 3 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Style: - 0 - - 0 - - - 0 - - 1 - m_borderStyleLabel - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - - - -1 - - - - 5 - 2 - 1 - wxEXPAND - 3 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - 200,-1 - 1 - m_borderStyleCombo - 1 - - - protected - 1 - - Resizable - -1 - 1 - - wxCB_READONLY - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - 5 - 1 - 0 - wxEXPAND - 4 - 1 - - 20 - protected - 0 - - - - 15 - 2 - 0 - wxALIGN_CENTER_VERTICAL|wxRIGHT - 5 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Row lines - - 0 - - - 0 - - 1 - m_rowSeparators - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - onBorderChecked - - - - 20 - 1 - 2 - wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT - 5 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Column lines - - 0 - - - 0 - - 1 - m_colSeparators - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - onBorderChecked - - - - 5 - 1 - 0 - wxALIGN_CENTER_VERTICAL - 7 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Width: - 0 - - 0 - - - 0 - - 1 - m_separatorsWidthLabel - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - - - -1 - - - - 5 - 2 - 1 - wxEXPAND - 7 - 1 - - - bSizer71 - wxHORIZONTAL - none - - 5 - wxEXPAND - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - 0 - -1,-1 - 0 - -1,-1 - 1 - m_separatorsWidthCtrl - 1 - - - protected - 1 - - Resizable - 1 - -1,-1 - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - 3 - wxALIGN_CENTER_VERTICAL|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - mm - 0 - - 0 - - - 0 - -1,-1 - 1 - m_separatorsWidthUnits - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - - - -1 - - - - 15 - wxALIGN_CENTER_VERTICAL|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Color: - 0 - - 0 - - - 0 - - 1 - m_separatorsColorLabel - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; Not forward_declare - 0 - - - - - -1 - - - - 5 - - 0 - - 0 - protected - 5 - - - - 5 - wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - m_panelSeparatorsColor - 1 - - - protected - 1 - - Resizable - 1 - - ; ; forward_declare - 0 - - - - wxBORDER_SIMPLE|wxTAB_TRAVERSAL - - - bSizer21 - wxVERTICAL - none - - 5 - wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - COLOR_SWATCH - 1 - - - 1 - - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - - 0 - - - 0 - - 1 - m_separatorsColorSwatch - 1 - - - protected - 1 - - Resizable - - 1 - - COLOR_SWATCH; widgets/color_swatch.h; forward_declare - 0 - - - - - - - - - - - - - 5 - 1 - 0 - wxALIGN_CENTER_VERTICAL - 8 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Style: - 0 - - 0 - - - 0 - - 1 - m_separatorsStyleLabel - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - - - -1 - - - - 5 - 2 - 1 - wxALIGN_CENTER_VERTICAL|wxEXPAND - 8 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - 200,-1 - 1 - m_separatorsStyleCombo - 1 - - - protected - 1 - - Resizable - -1 - 1 - - wxCB_READONLY - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - Cell - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - m_cellPage - 1 - - - protected - 1 - - Resizable - 1 - - ; ; forward_declare - 0 - - - - wxTAB_TRAVERSAL - - - bSizer13 - wxVERTICAL - none - - 5 - wxEXPAND|wxALL - 1 - - - bMargins - wxVERTICAL - none - - 10 - wxBOTTOM - 0 - - - bSizeCtrlSizer - wxHORIZONTAL - none - - 5 - wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - 0 - - - - - 1 - 0 - 1 - - 1 - - 0 - 0 - - Dock - 0 - Left - 0 - - 1 - - - 0 - 0 - wxID_ANY - - - 0 - - 0 - - - 0 - - 1 - m_separator1 - 1 - - - protected - 1 - - - - Resizable - 1 - 21,21 - wxBORDER_NONE - BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - 5 - wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - 0 - - - - - 1 - 0 - 1 - - 1 - - 0 - 0 - - Dock - 0 - Left - 1 - - 1 - - - 0 - 0 - wxID_ANY - Bold - - 0 - - 0 - - - 0 - - 1 - m_bold - 1 - - - protected - 1 - - - - Resizable - 1 - 21,21 - wxBORDER_NONE - BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare - 0 - Bold - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - 5 - wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - 0 - - - - - 1 - 0 - 1 - - 1 - - 0 - 0 - - Dock - 0 - Left - 1 - - 1 - - - 0 - 0 - wxID_ANY - Italic - - 0 - - 0 - - - 0 - - 1 - m_italic - 1 - - - protected - 1 - - - - Resizable - 1 - 21,21 - wxBORDER_NONE - BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare - 0 - Italic - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - 5 - wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - 0 - - - - - 1 - 0 - 1 - - 1 - - 0 - 0 - - Dock - 0 - Left - 0 - - 1 - - - 0 - 0 - wxID_ANY - - - 0 - - 0 - - - 0 - - 1 - m_separator2 - 1 - - - protected - 1 - - - - Resizable - 1 - 21,21 - wxBORDER_NONE - BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - 5 - wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - 0 - - - - - 1 - 0 - 1 - - 1 - - 0 - 0 - - Dock - 0 - Left - 1 - - 1 - - - 0 - 0 - wxID_ANY - Align left - - 0 - - 0 - - - 0 - - 1 - m_hAlignLeft - 1 - - - protected - 1 - - - - Resizable - 1 - 21,21 - wxBORDER_NONE - BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare - 0 - Align left - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - 5 - wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - 0 - - - - - 1 - 0 - 1 - - 1 - - 0 - 0 - - Dock - 0 - Left - 1 - - 1 - - - 0 - 0 - wxID_ANY - Align center - - 0 - - 0 - - - 0 - - 1 - m_hAlignCenter - 1 - - - protected - 1 - - - - Resizable - 1 - 21,21 - wxBORDER_NONE - BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare - 0 - Align horizontal center - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - 5 - wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - 0 - - - - - 1 - 0 - 1 - - 1 - - 0 - 0 - - Dock - 0 - Left - 1 - - 1 - - - 0 - 0 - wxID_ANY - Align right - - 0 - - 0 - - - 0 - - 1 - m_hAlignRight - 1 - - - protected - 1 - - - - Resizable - 1 - 21,21 - wxBORDER_NONE - BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare - 0 - Align right - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - 5 - wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - 0 - - - - - 1 - 0 - 1 - - 1 - - 0 - 0 - - Dock - 0 - Left - 0 - - 1 - - - 0 - 0 - wxID_ANY - - - 0 - - 0 - - - 0 - - 1 - m_separator3 - 1 - - - protected - 1 - - - - Resizable - 1 - 21,21 - wxBORDER_NONE - BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - 5 - wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - 0 - - - - - 1 - 0 - 1 - - 1 - - 0 - 0 - - Dock - 0 - Left - 1 - - 1 - - - 0 - 0 - wxID_ANY - Align top - - 0 - - 0 - - - 0 - - 1 - m_vAlignTop - 1 - - - protected - 1 - - - - Resizable - 1 - 21,21 - wxBORDER_NONE - BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare - 0 - Align top - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - 5 - wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - 0 - - - - - 1 - 0 - 1 - - 1 - - 0 - 0 - - Dock - 0 - Left - 1 - - 1 - - - 0 - 0 - wxID_ANY - Align middle - - 0 - - 0 - - - 0 - - 1 - m_vAlignCenter - 1 - - - protected - 1 - - - - Resizable - 1 - 21,21 - wxBORDER_NONE - BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare - 0 - Align vertical center - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - 5 - wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - 0 - - - - - 1 - 0 - 1 - - 1 - - 0 - 0 - - Dock - 0 - Left - 1 - - 1 - - - 0 - 0 - wxID_ANY - Align bottom - - 0 - - 0 - - - 0 - - 1 - m_vAlignBottom - 1 - - - protected - 1 - - - - Resizable - 1 - 21,21 - wxBORDER_NONE - BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare - 0 - Align bottom - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - 5 - wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - 0 - - - - - 1 - 0 - 1 - - 1 - - 0 - 0 - - Dock - 0 - Left - 0 - - 1 - - - 0 - 0 - wxID_ANY - - - 0 - - 0 - - - 0 - - 1 - m_separator4 - 1 - - - protected - 1 - - - - Resizable - 1 - 21,21 - wxBORDER_NONE - BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - 5 - wxEXPAND|wxBOTTOM - 0 - - -1,5 - wxBOTH - 1 - - 5 - - gbSizer2 - wxFLEX_GROWMODE_SPECIFIED - none - 4 - - 1 - 1 - 0 - wxALIGN_CENTER_VERTICAL|wxLEFT - 0 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Font: - 0 - - 0 - - - 0 - - 1 - m_fontLabel - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - - - -1 - - - - 5 - 3 - 1 - wxALIGN_CENTER_VERTICAL|wxEXPAND - 0 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - "Default Font" "KiCad Font" - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - m_fontCtrl - 1 - - - protected - 1 - - Resizable - 0 - 1 - - - FONT_CHOICE; widgets/font_choice.h; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - 5 - 1 - 0 - wxALIGN_CENTER_VERTICAL - 1 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Size: - 0 - - 0 - - - 0 - - 1 - m_textSizeLabel - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - - - -1 - - - - 5 - 3 - 1 - wxALIGN_CENTER_VERTICAL - 1 - 1 - - - bSizer15 - wxHORIZONTAL - none - - 5 - wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - 0 - -1,-1 - 0 - -1,-1 - 1 - m_textSizeCtrl - 1 - - - protected - 1 - - Resizable - 1 - -1,-1 - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - 3 - wxLEFT|wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - mm - 0 - - 0 - - - 0 - -1,-1 - 1 - m_textSizeUnits - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - - - -1 - - - - - - - - 5 - wxEXPAND|wxTOP - 1 - - 2 - wxBOTH - - - 5 - - fgSizer1 - wxFLEX_GROWMODE_SPECIFIED - none - 0 - 6 - - 5 - wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Text color: - 0 - - 0 - - - 0 - - 1 - m_textColorLabel - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - - - -1 - - - - 5 - wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - m_panelTextColor - 1 - - - protected - 1 - - Resizable - 1 - - ; ; forward_declare - 0 - - - - wxBORDER_SIMPLE|wxTAB_TRAVERSAL - - - bSizer221 - wxVERTICAL - none - - 5 - wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - COLOR_SWATCH - 1 - - - 1 - - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - - 0 - - - 0 - -1,-1 - 1 - m_textColorSwatch - 1 - - - protected - 1 - - Resizable - - 1 - - COLOR_SWATCH; widgets/color_swatch.h; forward_declare - 0 - - - - - - - - - - - 5 - wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Background fill: - 0 - - 0 - - - 0 - - 1 - m_fillColorLabel - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - - - -1 - - - - 5 - wxALIGN_CENTER_VERTICAL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - m_panelFillColor - 1 - - - protected - 1 - - Resizable - 1 - - ; ; forward_declare - 0 - - - - wxBORDER_SIMPLE|wxTAB_TRAVERSAL - - - bSizer22 - wxVERTICAL - none - - 5 - wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - COLOR_SWATCH - 1 - - - 1 - - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - - 0 - - - 0 - -1,-1 - 1 - m_fillColorSwatch - 1 - - - protected - 1 - - Resizable - - 1 - - COLOR_SWATCH; widgets/color_swatch.h; forward_declare - 0 - - - - - - - - - - - - - - + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Background fill: + 0 + + 0 + + + 0 + + 1 + m_fillColorLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_panelFillColor + 1 + + + protected + 1 + + Resizable + 1 + + ; ; forward_declare + 0 + + + + wxBORDER_SIMPLE|wxTAB_TRAVERSAL + + + bSizer22 + wxVERTICAL + none + + 5 + wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + COLOR_SWATCH + 1 + + + 1 + + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + + 0 + + + 0 + -1,-1 + 1 + m_fillColorSwatch + 1 + + + protected + 1 + + Resizable + + 1 + + COLOR_SWATCH; widgets/color_swatch.h; forward_declare + 0 + + + + + + + + + + + + - - 5 - wxEXPAND - 0 - - - bButtons - wxHORIZONTAL - none - - 5 - wxEXPAND - 1 - - 0 - protected - 0 - - - - 5 - wxALIGN_CENTER_VERTICAL|wxRIGHT - 0 - - 1 - 1 - 1 - 1 - - - - - 0 - - - - - 1 - 0 - 1 - - 1 - - 0 - 0 - - Dock - 0 - Left - 1 - - 1 - - - 0 - 0 - wxID_ANY - Apply && Go to Next Cell - - 0 - - 0 - - - 0 - - 1 - m_applyButton - 1 - - - protected - 1 - - - - Resizable - 1 - - - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - OnApply - - - - 10 - wxALIGN_CENTER_VERTICAL|wxRIGHT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - (Option+Tab) - 0 - - 0 - - - 0 - - 1 - m_hotkeyHint - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - - - -1 - - - - 5 - wxEXPAND|wxALL - 0 - - 0 - 1 - 0 - 0 - 0 - 1 - 0 - 0 - - m_sdbSizer1 - protected - - - - + + + + 5 + wxEXPAND + 0 + + + bButtons + wxHORIZONTAL + none + + 5 + wxEXPAND + 1 + + 0 + protected + 0 + + + + 5 + wxALIGN_CENTER_VERTICAL|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Apply && Go to Next Cell + + 0 + + 0 + + + 0 + + 1 + m_applyButton + 1 + + + protected + 1 + + + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnApply + + + + 10 + wxALIGN_CENTER_VERTICAL|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + (Option+Tab) + 0 + + 0 + + + 0 + + 1 + m_hotkeyHint + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxEXPAND|wxALL + 0 + + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + + m_sdbSizer1 + protected + + + + + + diff --git a/eeschema/dialogs/dialog_tablecell_properties_base.h b/eeschema/dialogs/dialog_tablecell_properties_base.h index 1152174ec1..65720fb484 100644 --- a/eeschema/dialogs/dialog_tablecell_properties_base.h +++ b/eeschema/dialogs/dialog_tablecell_properties_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b) +// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf) // http://www.wxformbuilder.org/ // // PLEASE DO *NOT* EDIT THIS FILE! diff --git a/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_parser.cpp b/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_parser.cpp index 707985f908..bf63ea1e12 100644 --- a/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_parser.cpp +++ b/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_parser.cpp @@ -4226,6 +4226,10 @@ void SCH_IO_KICAD_SEXPR_PARSER::parseSchTextBoxContent( SCH_TEXTBOX* aTextBox ) cell->SetColSpan( parseInt( "column span" ) ); cell->SetRowSpan( parseInt( "row span" ) ); } + else + { + Expecting( "at, size, stroke, fill, effects or uuid" ); + } NeedRIGHT(); break; @@ -4252,7 +4256,10 @@ void SCH_IO_KICAD_SEXPR_PARSER::parseSchTextBoxContent( SCH_TEXTBOX* aTextBox ) break; default: - Expecting( "at, size, stroke, fill, effects or uuid" ); + if( SCH_TABLECELL* cell = dynamic_cast( aTextBox ) ) + Expecting( "at, size, stroke, fill, effects, span or uuid" ); + else + Expecting( "at, size, stroke, fill, effects or uuid" ); } } diff --git a/eeschema/sch_item.h b/eeschema/sch_item.h index 7a1e525572..a2fec7f373 100644 --- a/eeschema/sch_item.h +++ b/eeschema/sch_item.h @@ -301,7 +301,7 @@ public: * This is a pure virtual function. Derived classes must implement this. */ virtual double Similarity( const SCH_ITEM& aItem ) const = 0; - virtual bool operator==( const SCH_ITEM& aItem ) const = 0; + virtual bool operator==( const SCH_ITEM& aOtherItem ) const = 0; /** * Print a schematic item. diff --git a/eeschema/sch_painter.cpp b/eeschema/sch_painter.cpp index c9ff1f292c..eefc1764d3 100644 --- a/eeschema/sch_painter.cpp +++ b/eeschema/sch_painter.cpp @@ -2418,11 +2418,8 @@ void SCH_PAINTER::draw( const SCH_TEXTBOX* aTextBox, int aLayer ) void SCH_PAINTER::draw( const SCH_TABLE* aTable, int aLayer ) { - const_cast( aTable )->RunOnChildren( - [&]( SCH_ITEM* aChild ) - { - draw( static_cast( aChild ), aLayer ); - } ); + for( SCH_TABLECELL* cell : aTable->GetCells() ) + draw( static_cast( cell ), aLayer ); if( aLayer == LAYER_SELECTION_SHADOWS ) return; diff --git a/eeschema/sch_table.cpp b/eeschema/sch_table.cpp index 6d464fbdf9..b320aebd05 100644 --- a/eeschema/sch_table.cpp +++ b/eeschema/sch_table.cpp @@ -66,10 +66,7 @@ SCH_TABLE::SCH_TABLE( const SCH_TABLE& aTable ) : m_rowHeights = aTable.m_rowHeights; for( SCH_TABLECELL* src : aTable.m_cells ) - m_cells.push_back( new SCH_TABLECELL( *src ) ); - - for( SCH_TABLECELL* dest : m_cells ) - dest->SetParent( this ); + AddCell( new SCH_TABLECELL( *src ) ); } @@ -139,6 +136,8 @@ VECTOR2I SCH_TABLE::GetEnd() const void SCH_TABLE::Normalize() { + // JEY TODO: pukes on rotated tables... + int y = GetPosition().y; for( int row = 0; row < GetRowCount(); ++row ) @@ -151,20 +150,29 @@ void SCH_TABLE::Normalize() int colWidth = m_colWidths[ col ]; SCH_TABLECELL* cell = GetCell( row, col ); - cell->SetPosition( VECTOR2I( x, y ) ); - cell->SetEnd( cell->GetStart() + VECTOR2I( colWidth, rowHeight ) ); + VECTOR2I pos( x, y ); + + if( cell->GetPosition() != pos ) + { + cell->SetPosition( pos ); + cell->ClearRenderCache(); + } + + VECTOR2I end = cell->GetStart() + VECTOR2I( colWidth, rowHeight ); if( cell->GetColSpan() > 1 || cell->GetRowSpan() > 1 ) { - VECTOR2I extraSize; - for( int ii = col + 1; ii < col + cell->GetColSpan(); ++ii ) - extraSize.x += m_colWidths[ii]; + end.x += m_colWidths[ii]; for( int ii = row + 1; ii < row + cell->GetRowSpan(); ++ii ) - extraSize.y += m_rowHeights[ii]; + end.y += m_rowHeights[ii]; + } - cell->SetEnd( cell->GetEnd() + extraSize ); + if( cell->GetEnd() != end ) + { + cell->SetEnd( end ); + cell->ClearRenderCache(); } x += colWidth; @@ -198,6 +206,8 @@ void SCH_TABLE::Rotate( const VECTOR2I& aCenter ) { for( SCH_TABLECELL* cell : m_cells ) cell->Rotate( aCenter ); + + Normalize(); } @@ -599,36 +609,48 @@ static struct SCH_TABLE_DESC &EDA_SHAPE::SetStartY, &EDA_SHAPE::GetStartY, PROPERTY_DISPLAY::PT_COORD, ORIGIN_TRANSFORMS::ABS_Y_COORD ) ); + const wxString tableProps = _( "Table Properties" ); + propMgr.AddProperty( new PROPERTY( _HKI( "External Border" ), - &SCH_TABLE::SetStrokeExternal, &SCH_TABLE::StrokeExternal ) ); + &SCH_TABLE::SetStrokeExternal, &SCH_TABLE::StrokeExternal ), + tableProps ); propMgr.AddProperty( new PROPERTY( _HKI( "Header Border" ), - &SCH_TABLE::SetStrokeHeader, &SCH_TABLE::StrokeHeader ) ); + &SCH_TABLE::SetStrokeHeader, &SCH_TABLE::StrokeHeader ), + tableProps ); propMgr.AddProperty( new PROPERTY( _HKI( "Border Width" ), &SCH_TABLE::SetBorderWidth, &SCH_TABLE::GetBorderWidth, - PROPERTY_DISPLAY::PT_SIZE ) ); + PROPERTY_DISPLAY::PT_SIZE ), + tableProps ); propMgr.AddProperty( new PROPERTY_ENUM( _HKI( "Border Style" ), - &SCH_TABLE::SetBorderStyle, &SCH_TABLE::GetBorderStyle ) ); + &SCH_TABLE::SetBorderStyle, &SCH_TABLE::GetBorderStyle ), + tableProps ); propMgr.AddProperty( new PROPERTY( _HKI( "Border Color" ), - &SCH_TABLE::SetBorderColor, &SCH_TABLE::GetBorderColor ) ); + &SCH_TABLE::SetBorderColor, &SCH_TABLE::GetBorderColor ), + tableProps ); propMgr.AddProperty( new PROPERTY( _HKI( "Row Separators" ), - &SCH_TABLE::SetStrokeRows, &SCH_TABLE::StrokeRows ) ); + &SCH_TABLE::SetStrokeRows, &SCH_TABLE::StrokeRows ), + tableProps ); propMgr.AddProperty( new PROPERTY( _HKI( "Cell Separators" ), - &SCH_TABLE::SetStrokeColumns, &SCH_TABLE::StrokeColumns ) ); + &SCH_TABLE::SetStrokeColumns, &SCH_TABLE::StrokeColumns ), + tableProps ); propMgr.AddProperty( new PROPERTY( _HKI( "Separators Width" ), &SCH_TABLE::SetSeparatorsWidth, &SCH_TABLE::GetSeparatorsWidth, - PROPERTY_DISPLAY::PT_SIZE ) ); + PROPERTY_DISPLAY::PT_SIZE ), + tableProps ); propMgr.AddProperty( new PROPERTY_ENUM( _HKI( "Separators Style" ), - &SCH_TABLE::SetSeparatorsStyle, &SCH_TABLE::GetSeparatorsStyle ) ); + &SCH_TABLE::SetSeparatorsStyle, &SCH_TABLE::GetSeparatorsStyle ), + tableProps ); propMgr.AddProperty( new PROPERTY( _HKI( "Separators Color" ), - &SCH_TABLE::SetSeparatorsColor, &SCH_TABLE::GetSeparatorsColor ) ); + &SCH_TABLE::SetSeparatorsColor, &SCH_TABLE::GetSeparatorsColor ), + tableProps ); } } _SCH_TABLE_DESC; diff --git a/eeschema/sch_tablecell.cpp b/eeschema/sch_tablecell.cpp index 64da3414da..9c5d157c1c 100644 --- a/eeschema/sch_tablecell.cpp +++ b/eeschema/sch_tablecell.cpp @@ -135,6 +135,41 @@ void SCH_TABLECELL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector( aOtherItem ); + + double similarity = 1.0; + + if( m_colSpan != other.m_colSpan ) + similarity *= 0.9; + + if( m_rowSpan != other.m_rowSpan ) + similarity *= 0.9; + + similarity *= SCH_TEXTBOX::Similarity( other ); + + return similarity; +} + + +bool SCH_TABLECELL::operator==( const SCH_ITEM& aOtherItem ) const +{ + if( aOtherItem.Type() != Type() ) + return false; + + const SCH_TABLECELL& other = static_cast( aOtherItem ); + + return m_colSpan == other.m_colSpan + && m_rowSpan == other.m_rowSpan + && SCH_TEXTBOX::operator==( other ); +} + + + static struct SCH_TABLECELL_DESC { SCH_TABLECELL_DESC() diff --git a/eeschema/sch_tablecell.h b/eeschema/sch_tablecell.h index fb33909d4a..86e9da3ae9 100644 --- a/eeschema/sch_tablecell.h +++ b/eeschema/sch_tablecell.h @@ -71,6 +71,10 @@ public: void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector& aList ) override; + double Similarity( const SCH_ITEM& aOther ) const override; + + bool operator==( const SCH_ITEM& aOther ) const override; + protected: int m_colSpan; int m_rowSpan; diff --git a/eeschema/tools/ee_actions.cpp b/eeschema/tools/ee_actions.cpp index afa4282c25..c6709ab511 100644 --- a/eeschema/tools/ee_actions.cpp +++ b/eeschema/tools/ee_actions.cpp @@ -145,83 +145,6 @@ TOOL_ACTION EE_ACTIONS::syncSelection( TOOL_ACTION_ARGS() .Name( "eeschema.InteractiveSelection.SyncSelection" ) .Scope( AS_GLOBAL ) ); -TOOL_ACTION EE_ACTIONS::selectColumns( TOOL_ACTION_ARGS() - .Name( "eeschema.InteractiveSelection.SelectColumns" ) - .Scope( AS_GLOBAL ) - .FriendlyName( _( "Select Column(s)" ) ) - .Tooltip( _( "Select complete column(s) containing the current selected cell(s)" ) ) - .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon - -TOOL_ACTION EE_ACTIONS::selectRows( TOOL_ACTION_ARGS() - .Name( "eeschema.InteractiveSelection.Rows" ) - .Scope( AS_GLOBAL ) - .FriendlyName( _( "Select Row(s)" ) ) - .Tooltip( _( "Select complete row(s) containing the current selected cell(s)" ) ) - .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon - -TOOL_ACTION EE_ACTIONS::selectTable( TOOL_ACTION_ARGS() - .Name( "eeschema.InteractiveSelection.SelectTable" ) - .Scope( AS_GLOBAL ) - .FriendlyName( _( "Select Table" ) ) - .Tooltip( _( "Select parent table of selected cell(s)" ) ) - .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon - -TOOL_ACTION EE_ACTIONS::addRowAbove( TOOL_ACTION_ARGS() - .Name( "eeschema.TableEditor.addRowAbove" ) - .Scope( AS_GLOBAL ) - .FriendlyName( _( "Add Row Above" ) ) - .Tooltip( _( "Insert a new table row above the selected cell(s)" ) ) - .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon - -TOOL_ACTION EE_ACTIONS::addRowBelow( TOOL_ACTION_ARGS() - .Name( "eeschema.TableEditor.addRowBelow" ) - .Scope( AS_GLOBAL ) - .FriendlyName( _( "Add Row Below" ) ) - .Tooltip( _( "Insert a new table row below the selected cell(s)" ) ) - .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon - -TOOL_ACTION EE_ACTIONS::addColumnBefore( TOOL_ACTION_ARGS() - .Name( "eeschema.TableEditor.addColumnBefore" ) - .Scope( AS_GLOBAL ) - .FriendlyName( _( "Add Column Before" ) ) - .Tooltip( _( "Insert a new table column before the selected cell(s)" ) ) - .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon - -TOOL_ACTION EE_ACTIONS::addColumnAfter( TOOL_ACTION_ARGS() - .Name( "eeschema.TableEditor.addColumnAfter" ) - .Scope( AS_GLOBAL ) - .FriendlyName( _( "Add Column After" ) ) - .Tooltip( _( "Insert a new table column after the selected cell(s)" ) ) - .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon - -TOOL_ACTION EE_ACTIONS::deleteRows( TOOL_ACTION_ARGS() - .Name( "eeschema.TableEditor.deleteRows" ) - .Scope( AS_GLOBAL ) - .FriendlyName( _( "Delete Row(s)" ) ) - .Tooltip( _( "Delete rows containing the currently selected cell(s)" ) ) - .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon - -TOOL_ACTION EE_ACTIONS::deleteColumns( TOOL_ACTION_ARGS() - .Name( "eeschema.TableEditor.deleteColumns" ) - .Scope( AS_GLOBAL ) - .FriendlyName( _( "Delete Column(s)" ) ) - .Tooltip( _( "Delete columns containing the currently selected cell(s)" ) ) - .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon - -TOOL_ACTION EE_ACTIONS::mergeCells( TOOL_ACTION_ARGS() - .Name( "eeschema.TableEditor.mergeCells" ) - .Scope( AS_GLOBAL ) - .FriendlyName( _( "Merge Cells" ) ) - .Tooltip( _( "Turn selected table cells into a single cell" ) ) - .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon - -TOOL_ACTION EE_ACTIONS::unmergeCells( TOOL_ACTION_ARGS() - .Name( "eeschema.TableEditor.unmergeCell" ) - .Scope( AS_GLOBAL ) - .FriendlyName( _( "Unmerge Cells" ) ) - .Tooltip( _( "Turn merged table cells back into separate cells." ) ) - .Icon( BITMAPS::spreadsheet ) ); // JEY TODO: need icon - // SYMBOL_EDITOR_CONTROL // TOOL_ACTION EE_ACTIONS::saveLibraryAs( TOOL_ACTION_ARGS() diff --git a/eeschema/tools/ee_actions.h b/eeschema/tools/ee_actions.h index 2b9966a58e..99e573fc9c 100644 --- a/eeschema/tools/ee_actions.h +++ b/eeschema/tools/ee_actions.h @@ -69,19 +69,6 @@ public: /// Selection synchronization (PCB -> SCH) static TOOL_ACTION syncSelection; - // Tables - static TOOL_ACTION selectRows; - static TOOL_ACTION selectColumns; - static TOOL_ACTION selectTable; - static TOOL_ACTION addRowAbove; - static TOOL_ACTION addRowBelow; - static TOOL_ACTION addColumnBefore; - static TOOL_ACTION addColumnAfter; - static TOOL_ACTION deleteRows; - static TOOL_ACTION deleteColumns; - static TOOL_ACTION mergeCells; - static TOOL_ACTION unmergeCells; - // Locking static TOOL_ACTION toggleLock; static TOOL_ACTION lock; diff --git a/eeschema/tools/ee_selection_tool.cpp b/eeschema/tools/ee_selection_tool.cpp index ada738ba83..c80fdef14e 100644 --- a/eeschema/tools/ee_selection_tool.cpp +++ b/eeschema/tools/ee_selection_tool.cpp @@ -280,9 +280,9 @@ bool EE_SELECTION_TOOL::Init() menu.AddItem( EE_ACTIONS::clearHighlight, haveHighlight && EE_CONDITIONS::Idle, 1 ); menu.AddSeparator( haveHighlight && EE_CONDITIONS::Idle, 1 ); - menu.AddItem( EE_ACTIONS::selectColumns, tableCellSelection && EE_CONDITIONS::Idle, 2 ); - menu.AddItem( EE_ACTIONS::selectRows, tableCellSelection && EE_CONDITIONS::Idle, 2 ); - menu.AddItem( EE_ACTIONS::selectTable, tableCellSelection && EE_CONDITIONS::Idle, 2 ); + menu.AddItem( ACTIONS::selectColumns, tableCellSelection && EE_CONDITIONS::Idle, 2 ); + menu.AddItem( ACTIONS::selectRows, tableCellSelection && EE_CONDITIONS::Idle, 2 ); + menu.AddItem( ACTIONS::selectTable, tableCellSelection && EE_CONDITIONS::Idle, 2 ); menu.AddSeparator( 100 ); menu.AddItem( EE_ACTIONS::drawWire, schEditCondition && EE_CONDITIONS::Empty, 100 ); @@ -2545,9 +2545,9 @@ void EE_SELECTION_TOOL::setTransitions() Go( &EE_SELECTION_TOOL::Main, EE_ACTIONS::selectionActivate.MakeEvent() ); Go( &EE_SELECTION_TOOL::SelectNode, EE_ACTIONS::selectNode.MakeEvent() ); Go( &EE_SELECTION_TOOL::SelectConnection, EE_ACTIONS::selectConnection.MakeEvent() ); - Go( &EE_SELECTION_TOOL::SelectColumns, EE_ACTIONS::selectColumns.MakeEvent() ); - Go( &EE_SELECTION_TOOL::SelectRows, EE_ACTIONS::selectRows.MakeEvent() ); - Go( &EE_SELECTION_TOOL::SelectTable, EE_ACTIONS::selectTable.MakeEvent() ); + Go( &EE_SELECTION_TOOL::SelectColumns, ACTIONS::selectColumns.MakeEvent() ); + Go( &EE_SELECTION_TOOL::SelectRows, ACTIONS::selectRows.MakeEvent() ); + Go( &EE_SELECTION_TOOL::SelectTable, ACTIONS::selectTable.MakeEvent() ); Go( &EE_SELECTION_TOOL::ClearSelection, EE_ACTIONS::clearSelection.MakeEvent() ); diff --git a/eeschema/tools/sch_drawing_tools.cpp b/eeschema/tools/sch_drawing_tools.cpp index 1f2cde2ec6..20e368c03e 100644 --- a/eeschema/tools/sch_drawing_tools.cpp +++ b/eeschema/tools/sch_drawing_tools.cpp @@ -2165,13 +2165,14 @@ int SCH_DRAWING_TOOLS::DrawTable( const TOOL_EVENT& aEvent ) else if( table && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) ) { VECTOR2I gridSize = grid.GetGridSize( grid.GetItemGrid( table ) ); + int fontSize = schematic->Settings().m_DefaultTextSize; VECTOR2I origin( table->GetPosition() ); VECTOR2I requestedSize( cursorPos - origin ); - int colCount = std::max( 1, requestedSize.x / ( gridSize.x * 24 ) ); - int rowCount = std::max( 1, requestedSize.y / ( gridSize.y * 8 ) ); + int colCount = std::max( 1, requestedSize.x / ( fontSize * 15 ) ); + int rowCount = std::max( 1, requestedSize.y / ( fontSize * 2 ) ); - VECTOR2I cellSize( std::max( gridSize.x * 4, requestedSize.x / colCount ), + VECTOR2I cellSize( std::max( gridSize.x * 5, requestedSize.x / colCount ), std::max( gridSize.y * 2, requestedSize.y / rowCount ) ); cellSize.x = KiROUND( (double) cellSize.x / gridSize.x ) * gridSize.x; diff --git a/eeschema/tools/sch_edit_table_tool.cpp b/eeschema/tools/sch_edit_table_tool.cpp index e522bc5edc..9aceff8909 100644 --- a/eeschema/tools/sch_edit_table_tool.cpp +++ b/eeschema/tools/sch_edit_table_tool.cpp @@ -21,16 +21,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include -#include -#include #include -#include -#include -#include -#include -#include -#include #include @@ -44,78 +35,13 @@ bool SCH_EDIT_TABLE_TOOL::Init() { EE_TOOL_BASE::Init(); - auto tableCellSelection = EE_CONDITIONS::MoreThan( 0 ) - && EE_CONDITIONS::OnlyTypes( { SCH_TABLECELL_T } ); - - auto tableCellBlockSelection = - [&]( const SELECTION& sel ) - { - if( sel.CountType( SCH_TABLECELL_T ) < 2 ) - return false; - - int colMin = std::numeric_limits::max(); - int colMax = 0; - int rowMin = std::numeric_limits::max(); - int rowMax = 0; - int selectedArea = 0; - - for( EDA_ITEM* item : sel ) - { - wxCHECK2( item->Type() == SCH_TABLECELL_T, continue ); - - SCH_TABLECELL* cell = static_cast( item ); - colMin = std::min( colMin, cell->GetColumn() ); - colMax = std::max( colMax, cell->GetColumn() + cell->GetColSpan() ); - rowMin = std::min( rowMin, cell->GetRow() ); - rowMax = std::max( rowMax, cell->GetRow() + cell->GetRowSpan() ); - - selectedArea += cell->GetColSpan() * cell->GetRowSpan(); - } - - return selectedArea == ( colMax - colMin ) * ( rowMax - rowMin ); - }; - - auto mergedCellsSelection = - [&]( const SELECTION& sel ) - { - for( EDA_ITEM* item : sel ) - { - if( SCH_TABLECELL* cell = dynamic_cast( item ) ) - { - if( cell->GetColSpan() > 1 || cell->GetRowSpan() > 1 ) - return true; - } - } - - return false; - }; - - // - // Add editing actions to the selection tool menu - // - CONDITIONAL_MENU& selToolMenu = m_selectionTool->GetToolMenu().GetMenu(); - - selToolMenu.AddSeparator( 100 ); - selToolMenu.AddItem( EE_ACTIONS::addRowAbove, tableCellSelection && EE_CONDITIONS::Idle, 100 ); - selToolMenu.AddItem( EE_ACTIONS::addRowBelow, tableCellSelection && EE_CONDITIONS::Idle, 100 ); - selToolMenu.AddItem( EE_ACTIONS::addColumnBefore, tableCellSelection && EE_CONDITIONS::Idle, 100 ); - selToolMenu.AddItem( EE_ACTIONS::addColumnAfter, tableCellSelection && EE_CONDITIONS::Idle, 100 ); - - selToolMenu.AddSeparator( 100 ); - selToolMenu.AddItem( EE_ACTIONS::deleteRows, tableCellSelection && EE_CONDITIONS::Idle, 100 ); - selToolMenu.AddItem( EE_ACTIONS::deleteColumns, tableCellSelection && EE_CONDITIONS::Idle, 100 ); - - selToolMenu.AddSeparator( 100 ); - selToolMenu.AddItem( EE_ACTIONS::mergeCells, tableCellSelection && tableCellBlockSelection, 100 ); - selToolMenu.AddItem( EE_ACTIONS::unmergeCells, tableCellSelection && mergedCellsSelection, 100 ); - - selToolMenu.AddSeparator( 100 ); + addMenus( m_selectionTool->GetToolMenu().GetMenu() ); return true; } -SCH_TABLECELL* copyCell( SCH_TABLECELL* aSource ) +SCH_TABLECELL* SCH_EDIT_TABLE_TOOL::copyCell( SCH_TABLECELL* aSource ) { SCH_TABLECELL* cell = new SCH_TABLECELL(); @@ -127,415 +53,23 @@ SCH_TABLECELL* copyCell( SCH_TABLECELL* aSource ) } -int SCH_EDIT_TABLE_TOOL::AddRowAbove( const TOOL_EVENT& aEvent ) +const SELECTION& SCH_EDIT_TABLE_TOOL::getTableCellSelection() { - EE_SELECTION& selection = m_selectionTool->RequestSelection( { SCH_TABLECELL_T } ); - SCH_TABLECELL* topmost = nullptr; - - for( EDA_ITEM* item : selection ) - { - SCH_TABLECELL* cell = static_cast( item ); - - if( !topmost || cell->GetRow() < topmost->GetRow() ) - topmost = cell; - } - - if( !topmost ) - return 0; - - int row = topmost->GetRow(); - SCH_TABLE* table = static_cast( topmost->GetParent() ); - SCH_COMMIT commit( m_toolMgr ); - - // Make a copy of the source row before things start moving around - std::vector sources; - sources.reserve( table->GetColCount() ); - - for( int col = 0; col < table->GetColCount(); ++col ) - sources.push_back( table->GetCell( row, col ) ); - - commit.Modify( table, m_frame->GetScreen() ); - - for( int col = 0; col < table->GetColCount(); ++col ) - { - SCH_TABLECELL* cell = copyCell( sources[col] ); - table->InsertCell( row * table->GetColCount(), cell ); - } - - table->Normalize(); - - commit.Push( _( "Add Row Above" ) ); - - return 0; -} - - -int SCH_EDIT_TABLE_TOOL::AddRowBelow( const TOOL_EVENT& aEvent ) -{ - EE_SELECTION& selection = m_selectionTool->RequestSelection( { SCH_TABLECELL_T } ); - SCH_TABLECELL* bottommost = nullptr; - - if( selection.Empty() ) - return 0; - - for( EDA_ITEM* item : selection ) - { - SCH_TABLECELL* cell = static_cast( item ); - - if( !bottommost || cell->GetRow() > bottommost->GetRow() ) - bottommost = cell; - } - - if( !bottommost ) - return 0; - - int row = bottommost->GetRow(); - SCH_TABLE* table = static_cast( bottommost->GetParent() ); - SCH_COMMIT commit( m_toolMgr ); - - // Make a copy of the source row before things start moving around - std::vector sources; - sources.reserve( table->GetColCount() ); - - for( int col = 0; col < table->GetColCount(); ++col ) - sources.push_back( table->GetCell( row, col ) ); - - commit.Modify( table, m_frame->GetScreen() ); - - for( int col = 0; col < table->GetColCount(); ++col ) - { - SCH_TABLECELL* cell = copyCell( sources[col] ); - table->InsertCell( ( row + 1 ) * table->GetColCount(), cell ); - } - - table->Normalize(); - - commit.Push( _( "Add Row Below" ) ); - - return 0; -} - - -int SCH_EDIT_TABLE_TOOL::AddColumnBefore( const TOOL_EVENT& aEvent ) -{ - EE_SELECTION& selection = m_selectionTool->RequestSelection( { SCH_TABLECELL_T } ); - SCH_TABLECELL* leftmost = nullptr; - - for( EDA_ITEM* item : selection ) - { - SCH_TABLECELL* cell = static_cast( item ); - - if( !leftmost || cell->GetColumn() < leftmost->GetColumn() ) - leftmost = cell; - } - - if( !leftmost ) - return 0; - - int col = leftmost->GetColumn(); - SCH_TABLE* table = static_cast( leftmost->GetParent() ); - int rowCount = table->GetRowCount(); - SCH_COMMIT commit( m_toolMgr ); - - // Make a copy of the source column before things start moving around - std::vector sources; - sources.reserve( rowCount ); - - for( int row = 0; row < rowCount; ++row ) - sources.push_back( table->GetCell( row, col ) ); - - commit.Modify( table, m_frame->GetScreen() ); - table->SetColCount( table->GetColCount() + 1 ); - - for( int row = 0; row < rowCount; ++row ) - { - SCH_TABLECELL* cell = copyCell( sources[row] ); - table->InsertCell( row * table->GetColCount() + col, cell ); - } - - table->Normalize(); - - commit.Push( _( "Add Column Before" ) ); - - return 0; -} - - -int SCH_EDIT_TABLE_TOOL::AddColumnAfter( const TOOL_EVENT& aEvent ) -{ - EE_SELECTION& selection = m_selectionTool->RequestSelection( { SCH_TABLECELL_T } ); - SCH_TABLECELL* rightmost = nullptr; - - for( EDA_ITEM* item : selection ) - { - SCH_TABLECELL* cell = static_cast( item ); - - if( !rightmost || cell->GetColumn() > rightmost->GetColumn() ) - rightmost = cell; - } - - if( !rightmost ) - return 0; - - int col = rightmost->GetColumn(); - SCH_TABLE* table = static_cast( rightmost->GetParent() ); - int rowCount = table->GetRowCount(); - SCH_COMMIT commit( m_toolMgr ); - - // Make a copy of the source column before things start moving around - std::vector sources; - sources.reserve( rowCount ); - - for( int row = 0; row < rowCount; ++row ) - sources.push_back( table->GetCell( row, col ) ); - - commit.Modify( table, m_frame->GetScreen() ); - table->SetColCount( table->GetColCount() + 1 ); - - for( int row = 0; row < rowCount; ++row ) - { - SCH_TABLECELL* cell = copyCell( sources[row] ); - table->InsertCell( row * table->GetColCount() + col + 1, cell ); - } - - table->Normalize(); - - commit.Push( _( "Add Column After" ) ); - - return 0; -} - - -int SCH_EDIT_TABLE_TOOL::DeleteColumns( const TOOL_EVENT& aEvent ) -{ - EE_SELECTION& selection = m_selectionTool->RequestSelection( { SCH_TABLECELL_T } ); - - if( selection.Empty() ) - return 0; - - SCH_TABLE* table = static_cast( selection[0]->GetParent() ); - int deleted = 0; - - for( int col = 0; col < table->GetColCount(); ++col ) - { - bool deleteColumn = false; - - for( int row = 0; row < table->GetRowCount(); ++row ) - { - if( table->GetCell( row, col )->IsSelected() ) - { - deleteColumn = true; - break; - } - } - - if( deleteColumn ) - { - for( int row = 0; row < table->GetRowCount(); ++row ) - table->GetCell( row, col )->SetFlags( STRUCT_DELETED ); - - deleted++; - } - } - - SCH_COMMIT commit( m_toolMgr ); - - if( deleted == table->GetColCount() ) - { - commit.Remove( table, m_frame->GetScreen() ); - } - else - { - commit.Modify( table, m_frame->GetScreen() ); - - table->DeleteMarkedCells(); - table->SetColCount( table->GetColCount() - deleted ); - table->Normalize(); - } - - if( deleted > 1 ) - commit.Push( _( "Delete Columns" ) ); - else - commit.Push( _( "Delete Column" ) ); - - return 0; -} - - -int SCH_EDIT_TABLE_TOOL::DeleteRows( const TOOL_EVENT& aEvent ) -{ - EE_SELECTION& selection = m_selectionTool->RequestSelection( { SCH_TABLECELL_T } ); - - if( selection.Empty() ) - return 0; - - SCH_TABLE* table = static_cast( selection[0]->GetParent() ); - int deleted = 0; - - for( int row = 0; row < table->GetRowCount(); ++row ) - { - bool deleteRow = false; - - for( int col = 0; col < table->GetColCount(); ++col ) - { - if( table->GetCell( row, col )->IsSelected() ) - { - deleteRow = true; - break; - } - } - - if( deleteRow ) - { - for( int col = 0; col < table->GetColCount(); ++col ) - table->GetCell( row, col )->SetFlags( STRUCT_DELETED ); - - deleted++; - } - } - - SCH_COMMIT commit( m_toolMgr ); - - if( deleted == table->GetRowCount() ) - { - commit.Remove( table, m_frame->GetScreen() ); - } - else - { - commit.Modify( table, m_frame->GetScreen() ); - - table->DeleteMarkedCells(); - table->Normalize(); - } - - if( deleted > 1 ) - commit.Push( _( "Delete Rows" ) ); - else - commit.Push( _( "Delete Row" ) ); - - return 0; -} - - -int SCH_EDIT_TABLE_TOOL::MergeCells( const TOOL_EVENT& aEvent ) -{ - EE_SELECTION& sel = m_selectionTool->RequestSelection( { SCH_TABLECELL_T } ); - - if( sel.Empty() ) - return 0; - - int colMin = std::numeric_limits::max(); - int colMax = 0; - int rowMin = std::numeric_limits::max(); - int rowMax = 0; - - SCH_COMMIT commit( m_toolMgr ); - SCH_TABLE* table = static_cast( sel[0]->GetParent() ); - - for( EDA_ITEM* item : sel ) - { - wxCHECK2( item->Type() == SCH_TABLECELL_T, continue ); - - SCH_TABLECELL* cell = static_cast( item ); - colMin = std::min( colMin, cell->GetColumn() ); - colMax = std::max( colMax, cell->GetColumn() + cell->GetColSpan() ); - rowMin = std::min( rowMin, cell->GetRow() ); - rowMax = std::max( rowMax, cell->GetRow() + cell->GetRowSpan() ); - } - - wxString content; - VECTOR2I extents; - - for( int row = rowMin; row < rowMax; ++row ) - { - extents.y += table->GetRowHeight( row ); - extents.x = 0; - - for( int col = colMin; col < colMax; ++col ) - { - extents.x += table->GetColWidth( col ); - - SCH_TABLECELL* cell = table->GetCell( row, col ); - - if( !cell->GetText().IsEmpty() ) - { - if( !content.IsEmpty() ) - content += "\n"; - - content += cell->GetText(); - } - - commit.Modify( cell, m_frame->GetScreen() ); - cell->SetColSpan( 0 ); - cell->SetRowSpan( 0 ); - cell->SetText( wxEmptyString ); - } - } - - SCH_TABLECELL* topLeft = table->GetCell( rowMin, colMin ); - topLeft->SetColSpan( colMax - colMin ); - topLeft->SetRowSpan( rowMax - rowMin ); - topLeft->SetText( content ); - topLeft->SetEnd( topLeft->GetStart() + extents ); - - table->Normalize(); - commit.Push( _( "Merge Cells" ) ); - - return 0; -} - - -int SCH_EDIT_TABLE_TOOL::UnmergeCells( const TOOL_EVENT& aEvent ) -{ - EE_SELECTION& sel = m_selectionTool->RequestSelection( { SCH_TABLECELL_T } ); - - if( sel.Empty() ) - return 0; - - SCH_COMMIT commit( m_toolMgr ); - SCH_TABLE* table = static_cast( sel[0]->GetParent() ); - - for( EDA_ITEM* item : sel ) - { - wxCHECK2( item->Type() == SCH_TABLECELL_T, continue ); - - SCH_TABLECELL* cell = static_cast( item ); - int rowSpan = cell->GetRowSpan(); - int colSpan = cell->GetColSpan(); - - for( int row = cell->GetRow(); row < cell->GetRow() + rowSpan; ++row ) - { - for( int col = cell->GetColumn(); col < cell->GetColumn() + colSpan; ++col ) - { - SCH_TABLECELL* target = table->GetCell( row, col ); - commit.Modify( target, m_frame->GetScreen() ); - target->SetColSpan( 1 ); - target->SetRowSpan( 1 ); - - VECTOR2I extents( table->GetColWidth( col ), table->GetRowHeight( row ) ); - target->SetEnd( target->GetStart() + extents ); - } - } - } - - table->Normalize(); - commit.Push( _( "Unmerge Cells" ) ); - - return 0; + return m_selectionTool->RequestSelection( { SCH_TABLECELL_T } ); } void SCH_EDIT_TABLE_TOOL::setTransitions() { - Go( &SCH_EDIT_TABLE_TOOL::AddRowAbove, EE_ACTIONS::addRowAbove.MakeEvent() ); - Go( &SCH_EDIT_TABLE_TOOL::AddRowBelow, EE_ACTIONS::addRowBelow.MakeEvent() ); + Go( &SCH_EDIT_TABLE_TOOL::AddRowAbove, ACTIONS::addRowAbove.MakeEvent() ); + Go( &SCH_EDIT_TABLE_TOOL::AddRowBelow, ACTIONS::addRowBelow.MakeEvent() ); - Go( &SCH_EDIT_TABLE_TOOL::AddColumnBefore, EE_ACTIONS::addColumnBefore.MakeEvent() ); - Go( &SCH_EDIT_TABLE_TOOL::AddColumnAfter, EE_ACTIONS::addColumnAfter.MakeEvent() ); + Go( &SCH_EDIT_TABLE_TOOL::AddColumnBefore, ACTIONS::addColBefore.MakeEvent() ); + Go( &SCH_EDIT_TABLE_TOOL::AddColumnAfter, ACTIONS::addColAfter.MakeEvent() ); - Go( &SCH_EDIT_TABLE_TOOL::DeleteRows, EE_ACTIONS::deleteRows.MakeEvent() ); - Go( &SCH_EDIT_TABLE_TOOL::DeleteColumns, EE_ACTIONS::deleteColumns.MakeEvent() ); + Go( &SCH_EDIT_TABLE_TOOL::DeleteRows, ACTIONS::deleteRows.MakeEvent() ); + Go( &SCH_EDIT_TABLE_TOOL::DeleteColumns, ACTIONS::deleteColumns.MakeEvent() ); - Go( &SCH_EDIT_TABLE_TOOL::MergeCells, EE_ACTIONS::mergeCells.MakeEvent() ); - Go( &SCH_EDIT_TABLE_TOOL::UnmergeCells, EE_ACTIONS::unmergeCells.MakeEvent() ); + Go( &SCH_EDIT_TABLE_TOOL::MergeCells, ACTIONS::mergeCells.MakeEvent() ); + Go( &SCH_EDIT_TABLE_TOOL::UnmergeCells, ACTIONS::unmergeCells.MakeEvent() ); } diff --git a/eeschema/tools/sch_edit_table_tool.h b/eeschema/tools/sch_edit_table_tool.h index ba5bebd360..3fca8bbe9a 100644 --- a/eeschema/tools/sch_edit_table_tool.h +++ b/eeschema/tools/sch_edit_table_tool.h @@ -21,16 +21,21 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef SCH_TABLE_TOOL_H -#define SCH_TABLE_TOOL_H +#ifndef SCH_EDIT_TABLE_TOOL_H +#define SCH_EDIT_TABLE_TOOL_H #include +#include +#include +#include +#include class SCH_EDIT_FRAME; -class SCH_EDIT_TABLE_TOOL : public EE_TOOL_BASE +class SCH_EDIT_TABLE_TOOL : public EE_TOOL_BASE, + public EDIT_TABLE_TOOL_BASE { public: SCH_EDIT_TABLE_TOOL(); @@ -39,19 +44,28 @@ public: /// @copydoc TOOL_INTERACTIVE::Init() bool Init() override; - int AddRowAbove( const TOOL_EVENT& aEvent ); - int AddRowBelow( const TOOL_EVENT& aEvent ); - int AddColumnBefore( const TOOL_EVENT& aEvent ); - int AddColumnAfter( const TOOL_EVENT& aEvent ); - int DeleteRows( const TOOL_EVENT& aEvent ); - int DeleteColumns( const TOOL_EVENT& aEvent ); + int AddRowAbove( const TOOL_EVENT& aEvent ) { return doAddRowAbove( aEvent ); } + int AddRowBelow( const TOOL_EVENT& aEvent ) { return doAddRowBelow( aEvent ); } + int AddColumnBefore( const TOOL_EVENT& aEvent ) { return doAddColumnBefore( aEvent ); } + int AddColumnAfter( const TOOL_EVENT& aEvent ) { return doAddColumnAfter( aEvent ); } + int DeleteRows( const TOOL_EVENT& aEvent ) { return doDeleteRows( aEvent ); } + int DeleteColumns( const TOOL_EVENT& aEvent ) { return doDeleteColumns( aEvent ); } - int MergeCells( const TOOL_EVENT& aEvent ); - int UnmergeCells( const TOOL_EVENT& aEvent ); + int MergeCells( const TOOL_EVENT& aEvent ) { return doMergeCells( aEvent ); } + int UnmergeCells( const TOOL_EVENT& aEvent ) { return doUnmergeCells( aEvent ); } private: ///< Set up handlers for various events. void setTransitions() override; + +private: + TOOL_MANAGER* getToolMgr() override { return m_toolMgr; } + BASE_SCREEN* getScreen() override { return m_frame->GetScreen(); } + + const SELECTION& getTableCellSelection() override; + void clearSelection() override { m_toolMgr->RunAction( EE_ACTIONS::clearSelection ); }; + + SCH_TABLECELL* copyCell( SCH_TABLECELL* aSource ) override; }; -#endif //SCH_TABLE_TOOL_H +#endif //SCH_EDIT_TABLE_TOOL_H diff --git a/eeschema/tools/sch_edit_tool.cpp b/eeschema/tools/sch_edit_tool.cpp index 6f475d6b5f..d7ab697986 100644 --- a/eeschema/tools/sch_edit_tool.cpp +++ b/eeschema/tools/sch_edit_tool.cpp @@ -1427,11 +1427,13 @@ int SCH_EDIT_TOOL::DoDelete( const TOOL_EVENT& aEvent ) } else if( sch_item->Type() == SCH_FIELD_T ) { + // Hide field commit.Modify( item, m_frame->GetScreen() ); static_cast( sch_item )->SetVisible( false ); } else if( sch_item->Type() == SCH_TABLECELL_T ) { + // Clear contents of table cell commit.Modify( item, m_frame->GetScreen() ); static_cast( sch_item )->SetText( wxEmptyString ); } diff --git a/include/core/typeinfo.h b/include/core/typeinfo.h index 2ee1398a13..c8a32e9c4e 100644 --- a/include/core/typeinfo.h +++ b/include/core/typeinfo.h @@ -91,6 +91,8 @@ enum KICAD_T PCB_GENERATOR_T, ///< class PCB_GENERATOR, generator on a layer PCB_TEXT_T, ///< class PCB_TEXT, text on a layer PCB_TEXTBOX_T, ///< class PCB_TEXTBOX, wrapped text on a layer + PCB_TABLE_T, ///< class PCB_TABLE, table of PCB_TABLECELLs + PCB_TABLECELL_T, ///< class PCB_TABLECELL, PCB_TEXTBOX for use in tables PCB_TRACE_T, ///< class PCB_TRACK, a track segment (segment on a copper layer) PCB_VIA_T, ///< class PCB_VIA, a via (like a track segment on a copper layer) PCB_ARC_T, ///< class PCB_ARC, an arc track segment on a copper layer @@ -442,6 +444,8 @@ constexpr bool IsPcbnewType( const KICAD_T aType ) case PCB_FIELD_T: case PCB_TEXT_T: case PCB_TEXTBOX_T: + case PCB_TABLE_T: + case PCB_TABLECELL_T: case PCB_TRACE_T: case PCB_VIA_T: case PCB_ARC_T: diff --git a/include/tool/actions.h b/include/tool/actions.h index 04cd63e9e1..7750bfbba9 100644 --- a/include/tool/actions.h +++ b/include/tool/actions.h @@ -78,6 +78,19 @@ public: static TOOL_ACTION centerJustify; static TOOL_ACTION rightJustify; + // Tables + static TOOL_ACTION selectRows; + static TOOL_ACTION selectColumns; + static TOOL_ACTION selectTable; + static TOOL_ACTION addRowAbove; + static TOOL_ACTION addRowBelow; + static TOOL_ACTION addColBefore; + static TOOL_ACTION addColAfter; + static TOOL_ACTION deleteRows; + static TOOL_ACTION deleteColumns; + static TOOL_ACTION mergeCells; + static TOOL_ACTION unmergeCells; + // Find and Replace static TOOL_ACTION showSearch; static TOOL_ACTION find; @@ -185,7 +198,7 @@ public: static TOOL_ACTION activatePointEditor; static TOOL_ACTION cycleArcEditMode; static TOOL_ACTION updatePreferences; - static TOOL_ACTION selectColumns; + static TOOL_ACTION selectLibTreeColumns; // Suite static TOOL_ACTION openPreferences; diff --git a/include/tool/edit_table_tool_base.h b/include/tool/edit_table_tool_base.h new file mode 100644 index 0000000000..c0208d97d2 --- /dev/null +++ b/include/tool/edit_table_tool_base.h @@ -0,0 +1,555 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2023-2024 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 EDIT_TABLE_TOOL_BASE_H +#define EDIT_TABLE_TOOL_BASE_H + +#include +#include +#include +#include + +class BASE_SCREEN; + + +/** + * SCH_TABLE_EDIT_TOOL and PCB_TABLE_EDIT_TOOL share most of their algorithms, which are + * implemented here. + */ + + +template +class EDIT_TABLE_TOOL_BASE +{ +protected: + void addMenus( CONDITIONAL_MENU& selToolMenu ) + { + auto cellSelection = SELECTION_CONDITIONS::MoreThan( 0 ) + && SELECTION_CONDITIONS::OnlyTypes( { SCH_TABLECELL_T, + PCB_TABLECELL_T } ); + + auto cellBlockSelection = + [&]( const SELECTION& sel ) + { + if( sel.Size() < 2 ) + return false; + + int colMin = std::numeric_limits::max(); + int colMax = 0; + int rowMin = std::numeric_limits::max(); + int rowMax = 0; + int selectedArea = 0; + + for( EDA_ITEM* item : sel ) + { + if( T_TABLECELL* cell = dynamic_cast( item ) ) + { + colMin = std::min( colMin, cell->GetColumn() ); + colMax = std::max( colMax, cell->GetColumn() + cell->GetColSpan() ); + rowMin = std::min( rowMin, cell->GetRow() ); + rowMax = std::max( rowMax, cell->GetRow() + cell->GetRowSpan() ); + + selectedArea += cell->GetColSpan() * cell->GetRowSpan(); + } + } + + return selectedArea == ( colMax - colMin ) * ( rowMax - rowMin ); + }; + + auto mergedCellsSelection = + [&]( const SELECTION& sel ) + { + for( EDA_ITEM* item : sel ) + { + if( T_TABLECELL* cell = dynamic_cast( item ) ) + { + if( cell->GetColSpan() > 1 || cell->GetRowSpan() > 1 ) + return true; + } + } + + return false; + }; + + // + // Add editing actions to the selection tool menu + // + selToolMenu.AddSeparator( 100 ); + selToolMenu.AddItem( ACTIONS::addRowAbove, cellSelection && SELECTION_CONDITIONS::Idle, 100 ); + selToolMenu.AddItem( ACTIONS::addRowBelow, cellSelection && SELECTION_CONDITIONS::Idle, 100 ); + selToolMenu.AddItem( ACTIONS::addColBefore, cellSelection && SELECTION_CONDITIONS::Idle, 100 ); + selToolMenu.AddItem( ACTIONS::addColAfter, cellSelection && SELECTION_CONDITIONS::Idle, 100 ); + + selToolMenu.AddSeparator( 100 ); + selToolMenu.AddItem( ACTIONS::deleteRows, cellSelection && SELECTION_CONDITIONS::Idle, 100 ); + selToolMenu.AddItem( ACTIONS::deleteColumns, cellSelection && SELECTION_CONDITIONS::Idle, 100 ); + + selToolMenu.AddSeparator( 100 ); + selToolMenu.AddItem( ACTIONS::mergeCells, cellSelection && cellBlockSelection, 100 ); + selToolMenu.AddItem( ACTIONS::unmergeCells, cellSelection && mergedCellsSelection, 100 ); + + selToolMenu.AddSeparator( 100 ); + } + + int doAddRowAbove( const TOOL_EVENT& aEvent ) + { + const SELECTION& selection = getTableCellSelection(); + T_TABLECELL* topmost = nullptr; + + for( EDA_ITEM* item : selection ) + { + T_TABLECELL* cell = static_cast( item ); + + if( !topmost || cell->GetRow() < topmost->GetRow() ) + topmost = cell; + } + + if( !topmost ) + return 0; + + int row = topmost->GetRow(); + T_TABLE* table = static_cast( topmost->GetParent() ); + T_COMMIT commit( getToolMgr() ); + + // Make a copy of the source row before things start moving around + std::vector sources; + sources.reserve( table->GetColCount() ); + + for( int col = 0; col < table->GetColCount(); ++col ) + sources.push_back( table->GetCell( row, col ) ); + + commit.Modify( table, getScreen() ); + + for( int col = 0; col < table->GetColCount(); ++col ) + { + T_TABLECELL* cell = copyCell( sources[col] ); + table->InsertCell( row * table->GetColCount(), cell ); + } + + for( int afterRow = table->GetRowCount() - 1; afterRow > row; afterRow-- ) + table->SetRowHeight( afterRow, table->GetRowHeight( afterRow - 1 ) ); + + table->Normalize(); + + commit.Push( _( "Add Row Above" ) ); + + return 0; + } + + int doAddRowBelow( const TOOL_EVENT& aEvent ) + { + const SELECTION& selection = getTableCellSelection(); + T_TABLECELL* bottommost = nullptr; + + if( selection.Empty() ) + return 0; + + for( EDA_ITEM* item : selection ) + { + T_TABLECELL* cell = static_cast( item ); + + if( !bottommost || cell->GetRow() > bottommost->GetRow() ) + bottommost = cell; + } + + if( !bottommost ) + return 0; + + int row = bottommost->GetRow(); + T_TABLE* table = static_cast( bottommost->GetParent() ); + T_COMMIT commit( getToolMgr() ); + + // Make a copy of the source row before things start moving around + std::vector sources; + sources.reserve( table->GetColCount() ); + + for( int col = 0; col < table->GetColCount(); ++col ) + sources.push_back( table->GetCell( row, col ) ); + + commit.Modify( table, getScreen() ); + + for( int col = 0; col < table->GetColCount(); ++col ) + { + T_TABLECELL* cell = copyCell( sources[col] ); + table->InsertCell( ( row + 1 ) * table->GetColCount(), cell ); + } + + for( int afterRow = table->GetRowCount() - 1; afterRow > row; afterRow-- ) + table->SetRowHeight( afterRow, table->GetRowHeight( afterRow - 1 ) ); + + table->Normalize(); + + commit.Push( _( "Add Row Below" ) ); + + return 0; + } + + int doAddColumnBefore( const TOOL_EVENT& aEvent ) + { + const SELECTION& selection = getTableCellSelection(); + T_TABLECELL* leftmost = nullptr; + + for( EDA_ITEM* item : selection ) + { + T_TABLECELL* cell = static_cast( item ); + + if( !leftmost || cell->GetColumn() < leftmost->GetColumn() ) + leftmost = cell; + } + + if( !leftmost ) + return 0; + + int col = leftmost->GetColumn(); + T_TABLE* table = static_cast( leftmost->GetParent() ); + int rowCount = table->GetRowCount(); + T_COMMIT commit( getToolMgr() ); + + // Make a copy of the source column before things start moving around + std::vector sources; + sources.reserve( rowCount ); + + for( int row = 0; row < rowCount; ++row ) + sources.push_back( table->GetCell( row, col ) ); + + commit.Modify( table, getScreen() ); + table->SetColCount( table->GetColCount() + 1 ); + + for( int row = 0; row < rowCount; ++row ) + { + T_TABLECELL* cell = copyCell( sources[row] ); + table->InsertCell( row * table->GetColCount() + col, cell ); + } + + for( int afterCol = table->GetColCount() - 1; afterCol > col; afterCol-- ) + table->SetColWidth( afterCol, table->GetColWidth( afterCol - 1 ) ); + + table->Normalize(); + + commit.Push( _( "Add Column Before" ) ); + + return 0; + } + + int doAddColumnAfter( const TOOL_EVENT& aEvent ) + { + const SELECTION& selection = getTableCellSelection(); + T_TABLECELL* rightmost = nullptr; + + for( EDA_ITEM* item : selection ) + { + T_TABLECELL* cell = static_cast( item ); + + if( !rightmost || cell->GetColumn() > rightmost->GetColumn() ) + rightmost = cell; + } + + if( !rightmost ) + return 0; + + int col = rightmost->GetColumn(); + T_TABLE* table = static_cast( rightmost->GetParent() ); + int rowCount = table->GetRowCount(); + T_COMMIT commit( getToolMgr() ); + + // Make a copy of the source column before things start moving around + std::vector sources; + sources.reserve( rowCount ); + + for( int row = 0; row < rowCount; ++row ) + sources.push_back( table->GetCell( row, col ) ); + + commit.Modify( table, getScreen() ); + table->SetColCount( table->GetColCount() + 1 ); + + for( int row = 0; row < rowCount; ++row ) + { + T_TABLECELL* cell = copyCell( sources[row] ); + table->InsertCell( row * table->GetColCount() + col + 1, cell ); + } + + for( int afterCol = table->GetColCount() - 1; afterCol > col; afterCol-- ) + table->SetColWidth( afterCol, table->GetColWidth( afterCol - 1 ) ); + + table->Normalize(); + + commit.Push( _( "Add Column After" ) ); + + return 0; + } + + int doDeleteRows( const TOOL_EVENT& aEvent ) + { + const SELECTION& selection = getTableCellSelection(); + + if( selection.Empty() ) + return 0; + + T_TABLE* table = static_cast( selection[0]->GetParent() ); + std::vector deleted; + + for( int row = 0; row < table->GetRowCount(); ++row ) + { + bool deleteRow = false; + + for( int col = 0; col < table->GetColCount(); ++col ) + { + if( table->GetCell( row, col )->IsSelected() ) + { + deleteRow = true; + break; + } + } + + if( deleteRow ) + { + for( int col = 0; col < table->GetColCount(); ++col ) + table->GetCell( row, col )->SetFlags( STRUCT_DELETED ); + + deleted.push_back( row ); + } + } + + T_COMMIT commit( getToolMgr() ); + + if( deleted.size() == (unsigned) table->GetRowCount() ) + { + commit.Remove( table ); + } + else + { + commit.Modify( table, getScreen() ); + + clearSelection(); + table->DeleteMarkedCells(); + + for( int row = 0; row < table->GetRowCount(); ++row ) + { + int offset = 0; + + for( int deletedRow : deleted ) + { + if( deletedRow >= row ) + offset++; + } + + table->SetRowHeight( row, table->GetRowHeight( row + offset ) ); + } + + table->Normalize(); + } + + if( deleted.size() > 1 ) + commit.Push( _( "Delete Rows" ) ); + else + commit.Push( _( "Delete Row" ) ); + + return 0; + } + + int doDeleteColumns( const TOOL_EVENT& aEvent ) + { + const SELECTION& selection = getTableCellSelection(); + + if( selection.Empty() ) + return 0; + + T_TABLE* table = static_cast( selection[0]->GetParent() ); + std::vector deleted; + + for( int col = 0; col < table->GetColCount(); ++col ) + { + bool deleteColumn = false; + + for( int row = 0; row < table->GetRowCount(); ++row ) + { + if( table->GetCell( row, col )->IsSelected() ) + { + deleteColumn = true; + break; + } + } + + if( deleteColumn ) + { + for( int row = 0; row < table->GetRowCount(); ++row ) + table->GetCell( row, col )->SetFlags( STRUCT_DELETED ); + + deleted.push_back( col ); + } + } + + T_COMMIT commit( getToolMgr() ); + + if( deleted.size() == (unsigned) table->GetColCount() ) + { + commit.Remove( table ); + } + else + { + commit.Modify( table, getScreen() ); + + clearSelection(); + table->DeleteMarkedCells(); + table->SetColCount( table->GetColCount() - deleted.size() ); + + for( int col = 0; col < table->GetColCount(); ++col ) + { + int offset = 0; + + for( int deletedCol : deleted ) + { + if( deletedCol >= col ) + offset++; + } + + table->SetColWidth( col, table->GetColWidth( col + offset ) ); + } + + table->Normalize(); + } + + if( deleted.size() > 1 ) + commit.Push( _( "Delete Columns" ) ); + else + commit.Push( _( "Delete Column" ) ); + + return 0; + } + + int doMergeCells( const TOOL_EVENT& aEvent ) + { + const SELECTION& sel = getTableCellSelection(); + + if( sel.Empty() ) + return 0; + + int colMin = std::numeric_limits::max(); + int colMax = 0; + int rowMin = std::numeric_limits::max(); + int rowMax = 0; + + T_COMMIT commit( getToolMgr() ); + T_TABLE* table = static_cast( sel[0]->GetParent() ); + + for( EDA_ITEM* item : sel ) + { + if( T_TABLECELL* cell = dynamic_cast( item ) ) + { + colMin = std::min( colMin, cell->GetColumn() ); + colMax = std::max( colMax, cell->GetColumn() + cell->GetColSpan() ); + rowMin = std::min( rowMin, cell->GetRow() ); + rowMax = std::max( rowMax, cell->GetRow() + cell->GetRowSpan() ); + } + } + + wxString content; + VECTOR2I extents; + + for( int row = rowMin; row < rowMax; ++row ) + { + extents.y += table->GetRowHeight( row ); + extents.x = 0; + + for( int col = colMin; col < colMax; ++col ) + { + extents.x += table->GetColWidth( col ); + + T_TABLECELL* cell = table->GetCell( row, col ); + + if( !cell->GetText().IsEmpty() ) + { + if( !content.IsEmpty() ) + content += "\n"; + + content += cell->GetText(); + } + + commit.Modify( cell, getScreen() ); + cell->SetColSpan( 0 ); + cell->SetRowSpan( 0 ); + cell->SetText( wxEmptyString ); + } + } + + T_TABLECELL* topLeft = table->GetCell( rowMin, colMin ); + topLeft->SetColSpan( colMax - colMin ); + topLeft->SetRowSpan( rowMax - rowMin ); + topLeft->SetText( content ); + topLeft->SetEnd( topLeft->GetStart() + extents ); + + table->Normalize(); + commit.Push( _( "Merge Cells" ) ); + + return 0; + } + + int doUnmergeCells( const TOOL_EVENT& aEvent ) + { + const SELECTION& sel = getTableCellSelection(); + + if( sel.Empty() ) + return 0; + + T_COMMIT commit( getToolMgr() ); + T_TABLE* table = static_cast( sel[0]->GetParent() ); + + for( EDA_ITEM* item : sel ) + { + if( T_TABLECELL* cell = dynamic_cast( item ) ) + { + int rowSpan = cell->GetRowSpan(); + int colSpan = cell->GetColSpan(); + + for( int row = cell->GetRow(); row < cell->GetRow() + rowSpan; ++row ) + { + for( int col = cell->GetColumn(); col < cell->GetColumn() + colSpan; ++col ) + { + T_TABLECELL* target = table->GetCell( row, col ); + commit.Modify( target, getScreen() ); + target->SetColSpan( 1 ); + target->SetRowSpan( 1 ); + + VECTOR2I extents( table->GetColWidth( col ), table->GetRowHeight( row ) ); + target->SetEnd( target->GetStart() + extents ); + } + } + } + } + + table->Normalize(); + commit.Push( _( "Unmerge Cells" ) ); + + return 0; + } + + virtual TOOL_MANAGER* getToolMgr() = 0; + virtual BASE_SCREEN* getScreen() = 0; + + virtual const SELECTION& getTableCellSelection() = 0; + virtual void clearSelection() = 0; + + virtual T_TABLECELL* copyCell( T_TABLECELL* aSource ) = 0; +}; + +#endif //EDIT_TABLE_TOOL_BASE_H diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index b0cb8e190e..edac0a389e 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -132,6 +132,8 @@ set( PCBNEW_DIALOGS dialogs/dialog_print_pcbnew.cpp dialogs/dialog_swap_layers.cpp dialogs/dialog_swap_layers_base.cpp + dialogs/dialog_tablecell_properties.cpp + dialogs/dialog_tablecell_properties_base.cpp dialogs/dialog_target_properties.cpp dialogs/dialog_target_properties_base.cpp dialogs/dialog_text_properties.cpp @@ -361,6 +363,7 @@ set( PCBNEW_CLASS_SRCS tools/drc_tool.cpp tools/edit_tool.cpp tools/edit_tool_move_fct.cpp + tools/pcb_edit_table_tool.cpp tools/global_edit_tool.cpp tools/group_tool.cpp tools/footprint_editor_control.cpp diff --git a/pcbnew/array_creator.cpp b/pcbnew/array_creator.cpp index b04b31ba35..9d844c9f67 100644 --- a/pcbnew/array_creator.cpp +++ b/pcbnew/array_creator.cpp @@ -142,6 +142,7 @@ void ARRAY_CREATOR::Invoke() case PCB_GENERATOR_T: case PCB_TEXT_T: case PCB_TEXTBOX_T: + case PCB_TABLE_T: case PCB_TRACE_T: case PCB_ARC_T: case PCB_VIA_T: diff --git a/pcbnew/board.cpp b/pcbnew/board.cpp index e621d9af15..e5f490a9cb 100644 --- a/pcbnew/board.cpp +++ b/pcbnew/board.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -916,6 +917,7 @@ void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode, bool aSkipConnectivity case PCB_FIELD_T: case PCB_TEXT_T: case PCB_TEXTBOX_T: + case PCB_TABLE_T: case PCB_TARGET_T: if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND ) m_drawings.push_back( aBoardItem ); @@ -1019,6 +1021,7 @@ void BOARD::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aRemoveMode ) case PCB_FIELD_T: case PCB_TEXT_T: case PCB_TEXTBOX_T: + case PCB_TABLE_T: case PCB_TARGET_T: alg::delete_matching( m_drawings, aBoardItem ); break; @@ -1170,6 +1173,15 @@ BOARD_ITEM* BOARD::GetItem( const KIID& aID ) const for( BOARD_ITEM* drawing : Drawings() ) { + if( drawing->Type() == PCB_TABLE_T ) + { + for( PCB_TABLECELL* cell : static_cast( drawing )->GetCells() ) + { + if( cell->m_Uuid == aID ) + return drawing; + } + } + if( drawing->m_Uuid == aID ) return drawing; } @@ -1505,6 +1517,8 @@ INSPECT_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, case PCB_FIELD_T: case PCB_TEXT_T: case PCB_TEXTBOX_T: + case PCB_TABLE_T: + case PCB_TABLECELL_T: case PCB_DIM_ALIGNED_T: case PCB_DIM_CENTER_T: case PCB_DIM_RADIAL_T: @@ -2524,6 +2538,13 @@ bool BOARD::cmp_drawings::operator()( const BOARD_ITEM* aFirst, return textbox->PCB_SHAPE::Compare( other ) && textbox->EDA_TEXT::Compare( other ); } + else if( aFirst->Type() == PCB_TABLE_T ) + { + const PCB_TABLE* table = static_cast( aFirst ); + const PCB_TABLE* other = static_cast( aSecond ); + + return PCB_TABLE::Compare( table, other ); + } return aFirst->m_Uuid < aSecond->m_Uuid; } @@ -2594,14 +2615,22 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, { const PCB_TEXTBOX* textbox = static_cast( item ); - // plot border + // border textbox->PCB_SHAPE::TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE ); - // plot text + // text textbox->TransformTextToPolySet( aOutlines, 0, maxError, ERROR_INSIDE ); break; } + case PCB_TABLE_T: + { + const PCB_TABLE* table = static_cast( item ); + + table->TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE ); + break; + } + case PCB_DIM_ALIGNED_T: case PCB_DIM_CENTER_T: case PCB_DIM_RADIAL_T: diff --git a/pcbnew/board_commit.cpp b/pcbnew/board_commit.cpp index 4d65e6aa10..b7c4e4e0ff 100644 --- a/pcbnew/board_commit.cpp +++ b/pcbnew/board_commit.cpp @@ -338,7 +338,8 @@ void BOARD_COMMIT::Push( const wxString& aMessage, int aCommitFlags ) case PCB_SHAPE_T: // a shape (normally not on copper layers) case PCB_REFERENCE_IMAGE_T: // a bitmap on an associated layer case PCB_GENERATOR_T: // a generator on a layer - case PCB_TEXTBOX_T: // a wrapped text on a layer + case PCB_TEXTBOX_T: // a line-wrapped (and optionally bordered) text item + case PCB_TABLE_T: // rows and columns of tablecells case PCB_TRACE_T: // a track segment (segment on a copper layer) case PCB_ARC_T: // an arced track segment (segment on a copper layer) case PCB_VIA_T: // a via (like track segment on a copper layer) diff --git a/pcbnew/collectors.cpp b/pcbnew/collectors.cpp index ec39472bd6..824eceb055 100644 --- a/pcbnew/collectors.cpp +++ b/pcbnew/collectors.cpp @@ -42,6 +42,8 @@ const std::vector GENERAL_COLLECTOR::AllBoardItems = { PCB_TEXT_T, // in m_drawings PCB_REFERENCE_IMAGE_T, // in m_drawings PCB_TEXTBOX_T, // in m_drawings + PCB_TABLE_T, // in m_drawings + PCB_TABLECELL_T, // in tables PCB_SHAPE_T, // in m_drawings PCB_DIM_ALIGNED_T, // in m_drawings PCB_DIM_CENTER_T, // in m_drawings @@ -66,6 +68,7 @@ const std::vector GENERAL_COLLECTOR::BoardLevelItems = { PCB_REFERENCE_IMAGE_T, PCB_TEXT_T, PCB_TEXTBOX_T, + PCB_TABLE_T, PCB_SHAPE_T, PCB_DIM_ALIGNED_T, PCB_DIM_ORTHOGONAL_T, @@ -101,6 +104,8 @@ const std::vector GENERAL_COLLECTOR::FootprintItems = { PCB_FIELD_T, PCB_TEXT_T, PCB_TEXTBOX_T, + PCB_TABLE_T, + PCB_TABLECELL_T, PCB_SHAPE_T, PCB_DIM_ALIGNED_T, PCB_DIM_ORTHOGONAL_T, @@ -194,6 +199,8 @@ INSPECT_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* aTestItem, void* aTestData case PCB_TEXTBOX_T: case PCB_SHAPE_T: + case PCB_TABLE_T: + case PCB_TABLECELL_T: boardItem = static_cast( aTestItem ); break; diff --git a/pcbnew/dialogs/dialog_tablecell_properties.cpp b/pcbnew/dialogs/dialog_tablecell_properties.cpp new file mode 100644 index 0000000000..0db3d90082 --- /dev/null +++ b/pcbnew/dialogs/dialog_tablecell_properties.cpp @@ -0,0 +1,477 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2024 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dialog_tablecell_properties.h" + +class TABLECELL_SCINTILLA_TRICKS : public SCINTILLA_TRICKS +{ +public: + TABLECELL_SCINTILLA_TRICKS( wxStyledTextCtrl* aScintilla, + std::function onAcceptHandler, + std::function onNextHandler ) : + SCINTILLA_TRICKS( aScintilla, wxT( "{}" ), false, std::move( onAcceptHandler ) ), + m_onNextHandler( std::move( onNextHandler ) ) + { } + +protected: + void onCharHook( wxKeyEvent& aEvent ) override + { + if( aEvent.GetKeyCode() == WXK_TAB && aEvent.AltDown() && !aEvent.ControlDown() ) + m_onNextHandler(); + else + SCINTILLA_TRICKS::onCharHook( aEvent ); + } + +private: + std::function m_onNextHandler; +}; + + +DIALOG_TABLECELL_PROPERTIES::DIALOG_TABLECELL_PROPERTIES( PCB_BASE_EDIT_FRAME* aFrame, + PCB_TABLECELL* aCell ) : + DIALOG_TABLECELL_PROPERTIES_BASE( aFrame ), + m_frame( aFrame ), + m_table( nullptr ), + m_cell( aCell ), + m_borderWidth( aFrame, m_borderWidthLabel, m_borderWidthCtrl, m_borderWidthUnits ), + m_separatorsWidth( aFrame, m_separatorsWidthLabel, m_separatorsWidthCtrl, m_separatorsWidthUnits ), + m_textHeight( aFrame, m_SizeYLabel, m_SizeYCtrl, m_SizeYUnits ), + m_textWidth( aFrame, m_SizeXLabel, m_SizeXCtrl, m_SizeXUnits ), + m_textThickness( aFrame, m_ThicknessLabel, m_ThicknessCtrl, m_ThicknessUnits ), + m_scintillaTricks( nullptr ) +{ + m_table = static_cast( m_cell->GetParent() ); + +#ifdef _WIN32 + // Without this setting, on Windows, some esoteric unicode chars create display issue + // in a wxStyledTextCtrl. + // for SetTechnology() info, see https://www.scintilla.org/ScintillaDoc.html#SCI_SETTECHNOLOGY + m_textCtrl->SetTechnology(wxSTC_TECHNOLOGY_DIRECTWRITE); +#endif + + m_scintillaTricks = new TABLECELL_SCINTILLA_TRICKS( m_textCtrl, + // onAccept handler + [this]( wxKeyEvent& aEvent ) + { + wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) ); + }, + // onNext handler + [this]() + { + wxCommandEvent dummy; + OnApply( dummy ); + } ); + + // A hack which causes Scintilla to auto-size the text editor canvas + // See: https://github.com/jacobslusser/ScintillaNET/issues/216 + m_textCtrl->SetScrollWidth( 1 ); + m_textCtrl->SetScrollWidthTracking( true ); + + SetInitialFocus( m_textCtrl ); + + if( m_table->GetParentFootprint() ) + { + // Do not allow locking items in the footprint editor + m_cbLocked->Show( false ); + } + + // Configure the layers list selector. Note that footprints are built outside the current + // board and so we may need to show all layers if the text is on an unactivated layer. + if( !m_frame->GetBoard()->IsLayerEnabled( m_table->GetLayer() ) ) + m_LayerSelectionCtrl->ShowNonActivatedLayers( true ); + + m_LayerSelectionCtrl->SetLayersHotkeys( false ); + m_LayerSelectionCtrl->SetBoardFrame( m_frame ); + m_LayerSelectionCtrl->Resync(); + + for( const auto& [lineStyle, lineStyleDesc] : lineTypeNames ) + { + m_borderStyleCombo->Append( lineStyleDesc.name, KiBitmap( lineStyleDesc.bitmap ) ); + m_separatorsStyleCombo->Append( lineStyleDesc.name, KiBitmap( lineStyleDesc.bitmap ) ); + } + + m_borderStyleCombo->Append( DEFAULT_STYLE ); + m_separatorsStyleCombo->Append( DEFAULT_STYLE ); + + m_separator1->SetIsSeparator(); + + m_bold->SetIsCheckButton(); + m_bold->SetBitmap( KiBitmapBundle( BITMAPS::text_bold ) ); + m_italic->SetIsCheckButton(); + m_italic->SetBitmap( KiBitmapBundle( BITMAPS::text_italic ) ); + + m_separator2->SetIsSeparator(); + + m_hAlignLeft->SetIsRadioButton(); + m_hAlignLeft->SetBitmap( KiBitmapBundle( BITMAPS::text_align_left ) ); + m_hAlignCenter->SetIsRadioButton(); + m_hAlignCenter->SetBitmap( KiBitmapBundle( BITMAPS::text_align_center ) ); + m_hAlignRight->SetIsRadioButton(); + m_hAlignRight->SetBitmap( KiBitmapBundle( BITMAPS::text_align_right ) ); + + m_separator3->SetIsSeparator(); + + m_vAlignTop->SetIsRadioButton(); + m_vAlignTop->SetBitmap( KiBitmapBundle( BITMAPS::text_valign_top ) ); + m_vAlignCenter->SetIsRadioButton(); + m_vAlignCenter->SetBitmap( KiBitmapBundle( BITMAPS::text_valign_center ) ); + m_vAlignBottom->SetIsRadioButton(); + m_vAlignBottom->SetBitmap( KiBitmapBundle( BITMAPS::text_valign_bottom ) ); + + m_separator4->SetIsSeparator(); + + m_hotkeyHint->SetFont( KIUI::GetInfoFont( this ) ); + m_hotkeyHint->SetLabel( wxString::Format( wxT( "(%s+%s)" ), + KeyNameFromKeyCode( WXK_ALT ), + KeyNameFromKeyCode( WXK_TAB ) ) ); + + SetupStandardButtons(); + Layout(); + + m_hAlignLeft->Bind( wxEVT_BUTTON, &DIALOG_TABLECELL_PROPERTIES::onHAlignButton, this ); + m_hAlignCenter->Bind( wxEVT_BUTTON, &DIALOG_TABLECELL_PROPERTIES::onHAlignButton, this ); + m_hAlignRight->Bind( wxEVT_BUTTON, &DIALOG_TABLECELL_PROPERTIES::onHAlignButton, this ); + m_vAlignTop->Bind( wxEVT_BUTTON, &DIALOG_TABLECELL_PROPERTIES::onVAlignButton, this ); + m_vAlignCenter->Bind( wxEVT_BUTTON, &DIALOG_TABLECELL_PROPERTIES::onVAlignButton, this ); + m_vAlignBottom->Bind( wxEVT_BUTTON, &DIALOG_TABLECELL_PROPERTIES::onVAlignButton, this ); + + // Now all widgets have the size fixed, call FinishDialogSettings + finishDialogSettings(); +} + + +DIALOG_TABLECELL_PROPERTIES::~DIALOG_TABLECELL_PROPERTIES() +{ + delete m_scintillaTricks; +} + + +bool DIALOG_TABLECELL_PROPERTIES::TransferDataToWindow() +{ + if( !wxDialog::TransferDataToWindow() ) + return false; + + m_LayerSelectionCtrl->SetLayerSelection( m_table->GetLayer() ); + m_cbLocked->SetValue( m_table->IsLocked() ); + + m_borderCheckbox->SetValue( m_table->StrokeExternal() ); + m_headerBorder->SetValue( m_table->StrokeHeader() ); + + if( m_table->GetBorderStroke().GetWidth() >= 0 ) + m_borderWidth.SetValue( m_table->GetBorderStroke().GetWidth() ); + + int style = static_cast( m_table->GetBorderStroke().GetLineStyle() ); + + if( style == -1 ) + m_borderStyleCombo->SetStringSelection( DEFAULT_STYLE ); + else if( style < (int) lineTypeNames.size() ) + m_borderStyleCombo->SetSelection( style ); + else + wxFAIL_MSG( "Line type not found in the type lookup map" ); + + m_borderWidth.Enable( m_table->StrokeExternal() || m_table->StrokeHeader() ); + m_borderStyleLabel->Enable( m_table->StrokeExternal() || m_table->StrokeHeader() ); + m_borderStyleCombo->Enable( m_table->StrokeExternal() || m_table->StrokeHeader() ); + + bool rows = m_table->StrokeRows() && m_table->GetSeparatorsStroke().GetWidth() >= 0; + bool cols = m_table->StrokeColumns() && m_table->GetSeparatorsStroke().GetWidth() >= 0; + + m_rowSeparators->SetValue( rows ); + m_colSeparators->SetValue( cols ); + + if( m_table->GetSeparatorsStroke().GetWidth() >= 0 ) + m_separatorsWidth.SetValue( m_table->GetSeparatorsStroke().GetWidth() ); + + style = static_cast( m_table->GetSeparatorsStroke().GetLineStyle() ); + + if( style == -1 ) + m_separatorsStyleCombo->SetStringSelection( DEFAULT_STYLE ); + else if( style < (int) lineTypeNames.size() ) + m_separatorsStyleCombo->SetSelection( style ); + else + wxFAIL_MSG( "Line type not found in the type lookup map" ); + + m_separatorsWidth.Enable( rows || cols ); + m_separatorsStyleLabel->Enable( rows || cols ); + m_separatorsStyleCombo->Enable( rows || cols ); + + m_textCtrl->SetValue( m_cell->GetText() ); + m_fontCtrl->SetFontSelection( m_cell->GetFont() ); + m_textWidth.SetValue( m_cell->GetTextWidth() ); + m_textHeight.SetValue( m_cell->GetTextHeight() ); + m_textThickness.SetValue( m_cell->GetTextThickness() ); + + m_bold->Check( m_cell->IsBold() ); + m_italic->Check( m_cell->IsItalic() ); + + switch( m_cell->GetHorizJustify() ) + { + case GR_TEXT_H_ALIGN_LEFT: m_hAlignLeft->Check(); break; + case GR_TEXT_H_ALIGN_CENTER: m_hAlignCenter->Check(); break; + case GR_TEXT_H_ALIGN_RIGHT: m_hAlignRight->Check(); break; + } + + switch( m_cell->GetVertJustify() ) + { + case GR_TEXT_V_ALIGN_TOP: m_vAlignTop->Check(); break; + case GR_TEXT_V_ALIGN_CENTER: m_vAlignCenter->Check(); break; + case GR_TEXT_V_ALIGN_BOTTOM: m_vAlignBottom->Check(); break; + } + + return true; +} + + +void DIALOG_TABLECELL_PROPERTIES::onHAlignButton( wxCommandEvent& aEvent ) +{ + for( BITMAP_BUTTON* btn : { m_hAlignLeft, m_hAlignCenter, m_hAlignRight } ) + { + if( btn->IsChecked() && btn != aEvent.GetEventObject() ) + btn->Check( false ); + } +} + + +void DIALOG_TABLECELL_PROPERTIES::onVAlignButton( wxCommandEvent& aEvent ) +{ + for( BITMAP_BUTTON* btn : { m_vAlignTop, m_vAlignCenter, m_vAlignBottom } ) + { + if( btn->IsChecked() && btn != aEvent.GetEventObject() ) + btn->Check( false ); + } +} + + +void DIALOG_TABLECELL_PROPERTIES::onBorderChecked( wxCommandEvent& aEvent ) +{ + BOARD_DESIGN_SETTINGS& bds = m_frame->GetDesignSettings(); + PCB_LAYER_ID currentLayer = ToLAYER_ID( m_LayerSelectionCtrl->GetLayerSelection() ); + int defaultLineThickness = bds.GetLineThickness( currentLayer ); + + bool border = m_borderCheckbox->GetValue(); + + if( border && m_borderWidth.GetValue() < 0 ) + m_borderWidth.SetValue( defaultLineThickness ); + + m_borderWidth.Enable( border ); + m_borderStyleLabel->Enable( border ); + m_borderStyleCombo->Enable( border ); + + bool row = m_rowSeparators->GetValue(); + bool col = m_colSeparators->GetValue(); + + if( ( row || col ) && m_separatorsWidth.GetValue() < 0 ) + m_separatorsWidth.SetValue( defaultLineThickness ); + + m_separatorsWidth.Enable( row || col ); + m_separatorsStyleLabel->Enable( row || col ); + m_separatorsStyleCombo->Enable( row || col ); +} + + +void DIALOG_TABLECELL_PROPERTIES::OnCharHook( wxKeyEvent& aEvt ) +{ + if( aEvt.GetKeyCode() == WXK_TAB && aEvt.AltDown() && !aEvt.ControlDown() ) + { + wxCommandEvent dummy; + OnApply( dummy ); + } + else + { + DIALOG_SHIM::OnCharHook( aEvt ); + } +} + + +void DIALOG_TABLECELL_PROPERTIES::OnApply( wxCommandEvent& aEvent ) +{ + TransferDataFromWindow(); + + for( size_t ii = 0; ii < m_table->GetCells().size(); ++ii ) + { + if( m_table->GetCells()[ii] == m_cell ) + { + ii++; + + if( ii >= m_table->GetCells().size() ) + ii = 0; + + m_cell = m_table->GetCells()[ii]; + + m_frame->GetToolManager()->RunAction( PCB_ACTIONS::selectionClear ); + m_frame->GetToolManager()->RunAction( PCB_ACTIONS::selectItem, m_cell ); + break; + } + } + + TransferDataToWindow(); + m_textCtrl->SelectAll(); +} + + +bool DIALOG_TABLECELL_PROPERTIES::TransferDataFromWindow() +{ + if( !wxDialog::TransferDataFromWindow() ) + return false; + + BOARD_COMMIT commit( m_frame ); + commit.Modify( m_table ); + + // If no other command in progress, prepare undo command + // (for a command in progress, will be made later, at the completion of command) + bool pushCommit = ( m_table->GetEditFlags() == 0 ); + + // Set IN_EDIT flag to force undo/redo/abort proper operation and avoid new calls to + // SaveCopyInUndoList for the same text if is moved, and then rotated, edited, etc.... + if( !pushCommit ) + m_table->SetFlags( IN_EDIT ); + + m_table->SetLayer( ToLAYER_ID( m_LayerSelectionCtrl->GetLayerSelection() ) ); + m_table->SetLocked( m_cbLocked->GetValue() ); + + m_table->SetStrokeExternal( m_borderCheckbox->GetValue() ); + m_table->SetStrokeHeader( m_headerBorder->GetValue() ); + { + STROKE_PARAMS stroke = m_table->GetBorderStroke(); + + if( m_borderCheckbox->GetValue() ) + stroke.SetWidth( std::max( 0, m_borderWidth.GetIntValue() ) ); + else + stroke.SetWidth( -1 ); + + auto it = lineTypeNames.begin(); + std::advance( it, m_borderStyleCombo->GetSelection() ); + + if( it == lineTypeNames.end() ) + stroke.SetLineStyle( LINE_STYLE::DEFAULT ); + else + stroke.SetLineStyle( it->first ); + + m_table->SetBorderStroke( stroke ); + } + + m_table->SetStrokeRows( m_rowSeparators->GetValue() ); + m_table->SetStrokeColumns( m_colSeparators->GetValue() ); + { + STROKE_PARAMS stroke = m_table->GetSeparatorsStroke(); + + if( m_rowSeparators->GetValue() || m_colSeparators->GetValue() ) + stroke.SetWidth( std::max( 0, m_separatorsWidth.GetIntValue() ) ); + else + stroke.SetWidth( -1 ); + + auto it = lineTypeNames.begin(); + std::advance( it, m_separatorsStyleCombo->GetSelection() ); + + if( it == lineTypeNames.end() ) + stroke.SetLineStyle( LINE_STYLE::DEFAULT ); + else + stroke.SetLineStyle( it->first ); + + m_table->SetSeparatorsStroke( stroke ); + } + + wxString txt = m_textCtrl->GetValue(); + +#ifdef __WXMAC__ + // On macOS CTRL+Enter produces '\r' instead of '\n' regardless of EOL setting. + // Replace it now. + txt.Replace( "\r", "\n" ); +#elif defined( __WINDOWS__ ) + // On Windows, a new line is coded as \r\n. We use only \n in kicad files and in + // drawing routines so strip the \r char. + txt.Replace( "\r", "" ); +#endif + + m_cell->SetText( txt ); + + if( m_fontCtrl->HaveFontSelection() ) + { + m_cell->SetFont( m_fontCtrl->GetFontSelection( m_bold->IsChecked(), + m_italic->IsChecked() ) ); + } + + m_cell->SetTextWidth( m_textWidth.GetIntValue() ); + m_cell->SetTextHeight( m_textHeight.GetIntValue() ); + m_cell->SetTextThickness( m_textThickness.GetIntValue() ); + + if( m_bold->IsChecked() != m_cell->IsBold() ) + { + if( m_bold->IsChecked() ) + { + m_cell->SetBold( true ); + m_cell->SetTextThickness( GetPenSizeForBold( m_cell->GetTextWidth() ) ); + } + else + { + m_cell->SetBold( false ); + m_cell->SetTextThickness( 0 ); // Use default pen width + } + } + + if( m_hAlignRight->IsChecked() ) + m_cell->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT ); + else if( m_hAlignCenter->IsChecked() ) + m_cell->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER ); + else + m_cell->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); + + if( m_vAlignBottom->IsChecked() ) + m_cell->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM ); + else if( m_vAlignCenter->IsChecked() ) + m_cell->SetVertJustify( GR_TEXT_V_ALIGN_CENTER ); + else + m_cell->SetVertJustify( GR_TEXT_V_ALIGN_TOP ); + + if( !commit.Empty() ) + commit.Push( _( "Edit Table Cell" ), SKIP_CONNECTIVITY ); + + return true; +} + + +void PCB_BASE_EDIT_FRAME::ShowTableCellPropertiesDialog( PCB_TABLECELL* aTableCell ) +{ + DIALOG_TABLECELL_PROPERTIES dlg( this, aTableCell ); + + // QuasiModal required for Scintilla auto-complete + dlg.ShowQuasiModal(); +} + + diff --git a/pcbnew/dialogs/dialog_tablecell_properties.h b/pcbnew/dialogs/dialog_tablecell_properties.h new file mode 100644 index 0000000000..068770d19c --- /dev/null +++ b/pcbnew/dialogs/dialog_tablecell_properties.h @@ -0,0 +1,72 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2024 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_TABLECELL_PROPERTIES_H +#define DIALOG_TABLECELL_PROPERTIES_H + +#include +#include + +#include "dialog_tablecell_properties_base.h" + + +class PCB_BASE_EDIT_FRAME; +class PCB_TABLE; +class PCB_TABLECELL; +class SCINTILLA_TRICKS; + + +class DIALOG_TABLECELL_PROPERTIES : public DIALOG_TABLECELL_PROPERTIES_BASE +{ +public: + DIALOG_TABLECELL_PROPERTIES( PCB_BASE_EDIT_FRAME* aParentFrame, PCB_TABLECELL* aCell ); + ~DIALOG_TABLECELL_PROPERTIES(); + +protected: + void OnCharHook( wxKeyEvent& aEvt ) override; + +private: + bool TransferDataToWindow() override; + bool TransferDataFromWindow() override; + + void onHAlignButton( wxCommandEvent &aEvent ); + void onVAlignButton( wxCommandEvent &aEvent ); + void onBorderChecked( wxCommandEvent& aEvent ) override; + void OnApply( wxCommandEvent& aEvent ) override; + +private: + PCB_BASE_EDIT_FRAME* m_frame; + PCB_TABLE* m_table; + PCB_TABLECELL* m_cell; + + UNIT_BINDER m_borderWidth; + UNIT_BINDER m_separatorsWidth; + UNIT_BINDER m_textHeight; + UNIT_BINDER m_textWidth; + UNIT_BINDER m_textThickness; + + SCINTILLA_TRICKS* m_scintillaTricks; +}; + + +#endif //DIALOG_TABLECELL_PROPERTIES_H diff --git a/pcbnew/dialogs/dialog_tablecell_properties_base.cpp b/pcbnew/dialogs/dialog_tablecell_properties_base.cpp new file mode 100644 index 0000000000..89797a4261 --- /dev/null +++ b/pcbnew/dialogs/dialog_tablecell_properties_base.cpp @@ -0,0 +1,382 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "pcb_layer_box_selector.h" +#include "widgets/bitmap_button.h" +#include "widgets/font_choice.h" +#include "widgets/wx_infobar.h" + +#include "dialog_tablecell_properties_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_TABLECELL_PROPERTIES_BASE::DIALOG_TABLECELL_PROPERTIES_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* bMainSizer; + bMainSizer = new wxBoxSizer( wxVERTICAL ); + + m_infoBar = new WX_INFOBAR( this ); + m_infoBar->SetShowHideEffects( wxSHOW_EFFECT_NONE, wxSHOW_EFFECT_NONE ); + m_infoBar->SetEffectDuration( 500 ); + m_infoBar->Hide(); + + bMainSizer->Add( m_infoBar, 0, wxEXPAND|wxBOTTOM, 5 ); + + wxBoxSizer* bColumns; + bColumns = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bCellContentMargins; + bCellContentMargins = new wxBoxSizer( wxVERTICAL ); + + m_textCtrl = new wxStyledTextCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN, wxEmptyString ); + m_textCtrl->SetUseTabs( true ); + m_textCtrl->SetTabWidth( 4 ); + m_textCtrl->SetIndent( 4 ); + m_textCtrl->SetTabIndents( false ); + m_textCtrl->SetBackSpaceUnIndents( false ); + m_textCtrl->SetViewEOL( false ); + m_textCtrl->SetViewWhiteSpace( false ); + m_textCtrl->SetMarginWidth( 2, 0 ); + m_textCtrl->SetIndentationGuides( false ); + m_textCtrl->SetReadOnly( false ); + m_textCtrl->SetMarginWidth( 1, 0 ); + m_textCtrl->SetMarginWidth( 0, 0 ); + m_textCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDER, wxSTC_MARK_BOXPLUS ); + m_textCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDER, wxColour( wxT("BLACK") ) ); + m_textCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDER, wxColour( wxT("WHITE") ) ); + m_textCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDEROPEN, wxSTC_MARK_BOXMINUS ); + m_textCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDEROPEN, wxColour( wxT("BLACK") ) ); + m_textCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDEROPEN, wxColour( wxT("WHITE") ) ); + m_textCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDERSUB, wxSTC_MARK_EMPTY ); + m_textCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDEREND, wxSTC_MARK_BOXPLUS ); + m_textCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDEREND, wxColour( wxT("BLACK") ) ); + m_textCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDEREND, wxColour( wxT("WHITE") ) ); + m_textCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDEROPENMID, wxSTC_MARK_BOXMINUS ); + m_textCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDEROPENMID, wxColour( wxT("BLACK") ) ); + m_textCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDEROPENMID, wxColour( wxT("WHITE") ) ); + m_textCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDERMIDTAIL, wxSTC_MARK_EMPTY ); + m_textCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDERTAIL, wxSTC_MARK_EMPTY ); + m_textCtrl->SetSelBackground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) ); + m_textCtrl->SetSelForeground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHTTEXT ) ); + m_textCtrl->SetMinSize( wxSize( 500,-1 ) ); + + bCellContentMargins->Add( m_textCtrl, 1, wxEXPAND|wxTOP|wxBOTTOM, 1 ); + + + bColumns->Add( bCellContentMargins, 1, wxEXPAND|wxTOP, 6 ); + + m_notebook = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_tablePage = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer16; + bSizer16 = new wxBoxSizer( wxVERTICAL ); + + m_textEntrySizer = new wxGridBagSizer( 3, 3 ); + m_textEntrySizer->SetFlexibleDirection( wxBOTH ); + m_textEntrySizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + m_textEntrySizer->SetEmptyCellSize( wxSize( 0,2 ) ); + + m_layerLabel = new wxStaticText( m_tablePage, wxID_ANY, _("Layer:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_layerLabel->Wrap( -1 ); + m_textEntrySizer->Add( m_layerLabel, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 ); + + m_LayerSelectionCtrl = new PCB_LAYER_BOX_SELECTOR( m_tablePage, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); + m_LayerSelectionCtrl->SetMinSize( wxSize( 175,-1 ) ); + + m_textEntrySizer->Add( m_LayerSelectionCtrl, wxGBPosition( 0, 1 ), wxGBSpan( 1, 2 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + m_cbLocked = new wxCheckBox( m_tablePage, wxID_ANY, _("Locked"), wxDefaultPosition, wxDefaultSize, 0 ); + m_textEntrySizer->Add( m_cbLocked, wxGBPosition( 1, 0 ), wxGBSpan( 1, 3 ), wxBOTTOM, 20 ); + + m_borderCheckbox = new wxCheckBox( m_tablePage, wxID_ANY, _("External border"), wxDefaultPosition, wxDefaultSize, 0 ); + m_textEntrySizer->Add( m_borderCheckbox, wxGBPosition( 2, 0 ), wxGBSpan( 1, 2 ), wxBOTTOM, 2 ); + + m_headerBorder = new wxCheckBox( m_tablePage, wxID_ANY, _("Header border"), wxDefaultPosition, wxDefaultSize, 0 ); + m_textEntrySizer->Add( m_headerBorder, wxGBPosition( 2, 2 ), wxGBSpan( 1, 1 ), wxLEFT, 20 ); + + m_borderWidthLabel = new wxStaticText( m_tablePage, wxID_ANY, _("Width:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_borderWidthLabel->Wrap( -1 ); + m_textEntrySizer->Add( m_borderWidthLabel, wxGBPosition( 4, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 ); + + wxBoxSizer* bSizer7; + bSizer7 = new wxBoxSizer( wxHORIZONTAL ); + + m_borderWidthCtrl = new wxTextCtrl( m_tablePage, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), 0 ); + bSizer7->Add( m_borderWidthCtrl, 0, wxEXPAND, 5 ); + + m_borderWidthUnits = new wxStaticText( m_tablePage, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 ); + m_borderWidthUnits->Wrap( -1 ); + bSizer7->Add( m_borderWidthUnits, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 3 ); + + + m_textEntrySizer->Add( bSizer7, wxGBPosition( 4, 1 ), wxGBSpan( 1, 2 ), wxEXPAND, 5 ); + + m_borderStyleLabel = new wxStaticText( m_tablePage, wxID_ANY, _("Style:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_borderStyleLabel->Wrap( -1 ); + m_textEntrySizer->Add( m_borderStyleLabel, wxGBPosition( 5, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 ); + + m_borderStyleCombo = new wxBitmapComboBox( m_tablePage, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY ); + m_borderStyleCombo->SetMinSize( wxSize( 200,-1 ) ); + + m_textEntrySizer->Add( m_borderStyleCombo, wxGBPosition( 5, 1 ), wxGBSpan( 1, 2 ), wxEXPAND, 5 ); + + + m_textEntrySizer->Add( 0, 15, wxGBPosition( 6, 0 ), wxGBSpan( 1, 1 ), wxEXPAND, 5 ); + + m_rowSeparators = new wxCheckBox( m_tablePage, wxID_ANY, _("Row lines"), wxDefaultPosition, wxDefaultSize, 0 ); + m_textEntrySizer->Add( m_rowSeparators, wxGBPosition( 7, 0 ), wxGBSpan( 1, 2 ), wxALIGN_CENTER_VERTICAL|wxRIGHT, 15 ); + + m_colSeparators = new wxCheckBox( m_tablePage, wxID_ANY, _("Column lines"), wxDefaultPosition, wxDefaultSize, 0 ); + m_textEntrySizer->Add( m_colSeparators, wxGBPosition( 7, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 20 ); + + m_separatorsWidthLabel = new wxStaticText( m_tablePage, wxID_ANY, _("Width:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_separatorsWidthLabel->Wrap( -1 ); + m_textEntrySizer->Add( m_separatorsWidthLabel, wxGBPosition( 9, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 ); + + wxBoxSizer* bSizer71; + bSizer71 = new wxBoxSizer( wxHORIZONTAL ); + + m_separatorsWidthCtrl = new wxTextCtrl( m_tablePage, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), 0 ); + bSizer71->Add( m_separatorsWidthCtrl, 0, wxEXPAND, 5 ); + + m_separatorsWidthUnits = new wxStaticText( m_tablePage, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 ); + m_separatorsWidthUnits->Wrap( -1 ); + bSizer71->Add( m_separatorsWidthUnits, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 3 ); + + + m_textEntrySizer->Add( bSizer71, wxGBPosition( 9, 1 ), wxGBSpan( 1, 2 ), wxEXPAND, 5 ); + + m_separatorsStyleLabel = new wxStaticText( m_tablePage, wxID_ANY, _("Style:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_separatorsStyleLabel->Wrap( -1 ); + m_textEntrySizer->Add( m_separatorsStyleLabel, wxGBPosition( 10, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 ); + + m_separatorsStyleCombo = new wxBitmapComboBox( m_tablePage, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY ); + m_separatorsStyleCombo->SetMinSize( wxSize( 200,-1 ) ); + + m_textEntrySizer->Add( m_separatorsStyleCombo, wxGBPosition( 10, 1 ), wxGBSpan( 1, 2 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + + m_textEntrySizer->AddGrowableCol( 1 ); + + bSizer16->Add( m_textEntrySizer, 1, wxEXPAND|wxALL, 5 ); + + + m_tablePage->SetSizer( bSizer16 ); + m_tablePage->Layout(); + bSizer16->Fit( m_tablePage ); + m_notebook->AddPage( m_tablePage, _("Table"), false ); + m_cellPage = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer13; + bSizer13 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bMargins; + bMargins = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizeCtrlSizer; + bSizeCtrlSizer = new wxBoxSizer( wxHORIZONTAL ); + + m_separator1 = new BITMAP_BUTTON( m_cellPage, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 21,21 ), wxBU_AUTODRAW|wxBORDER_NONE ); + m_separator1->Enable( false ); + + bSizeCtrlSizer->Add( m_separator1, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bold = new BITMAP_BUTTON( m_cellPage, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 21,21 ), wxBU_AUTODRAW|wxBORDER_NONE ); + m_bold->SetToolTip( _("Bold") ); + + bSizeCtrlSizer->Add( m_bold, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_italic = new BITMAP_BUTTON( m_cellPage, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 21,21 ), wxBU_AUTODRAW|wxBORDER_NONE ); + m_italic->SetToolTip( _("Italic") ); + + bSizeCtrlSizer->Add( m_italic, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_separator2 = new BITMAP_BUTTON( m_cellPage, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 21,21 ), wxBU_AUTODRAW|wxBORDER_NONE ); + m_separator2->Enable( false ); + + bSizeCtrlSizer->Add( m_separator2, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_hAlignLeft = new BITMAP_BUTTON( m_cellPage, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 21,21 ), wxBU_AUTODRAW|wxBORDER_NONE ); + m_hAlignLeft->SetToolTip( _("Align left") ); + + bSizeCtrlSizer->Add( m_hAlignLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_hAlignCenter = new BITMAP_BUTTON( m_cellPage, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 21,21 ), wxBU_AUTODRAW|wxBORDER_NONE ); + m_hAlignCenter->SetToolTip( _("Align horizontal center") ); + + bSizeCtrlSizer->Add( m_hAlignCenter, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_hAlignRight = new BITMAP_BUTTON( m_cellPage, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 21,21 ), wxBU_AUTODRAW|wxBORDER_NONE ); + m_hAlignRight->SetToolTip( _("Align right") ); + + bSizeCtrlSizer->Add( m_hAlignRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_separator3 = new BITMAP_BUTTON( m_cellPage, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 21,21 ), wxBU_AUTODRAW|wxBORDER_NONE ); + m_separator3->Enable( false ); + + bSizeCtrlSizer->Add( m_separator3, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_vAlignTop = new BITMAP_BUTTON( m_cellPage, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 21,21 ), wxBU_AUTODRAW|wxBORDER_NONE ); + m_vAlignTop->SetToolTip( _("Align top") ); + + bSizeCtrlSizer->Add( m_vAlignTop, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_vAlignCenter = new BITMAP_BUTTON( m_cellPage, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 21,21 ), wxBU_AUTODRAW|wxBORDER_NONE ); + m_vAlignCenter->SetToolTip( _("Align vertical center") ); + + bSizeCtrlSizer->Add( m_vAlignCenter, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_vAlignBottom = new BITMAP_BUTTON( m_cellPage, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 21,21 ), wxBU_AUTODRAW|wxBORDER_NONE ); + m_vAlignBottom->SetToolTip( _("Align bottom") ); + + bSizeCtrlSizer->Add( m_vAlignBottom, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_separator4 = new BITMAP_BUTTON( m_cellPage, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 21,21 ), wxBU_AUTODRAW|wxBORDER_NONE ); + m_separator4->Enable( false ); + + bSizeCtrlSizer->Add( m_separator4, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + + bMargins->Add( bSizeCtrlSizer, 0, wxBOTTOM, 10 ); + + wxGridBagSizer* gbSizer2; + gbSizer2 = new wxGridBagSizer( 4, 5 ); + gbSizer2->SetFlexibleDirection( wxBOTH ); + gbSizer2->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + gbSizer2->SetEmptyCellSize( wxSize( -1,5 ) ); + + m_fontLabel = new wxStaticText( m_cellPage, wxID_ANY, _("Font:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_fontLabel->Wrap( -1 ); + gbSizer2->Add( m_fontLabel, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxLEFT, 1 ); + + wxString m_fontCtrlChoices[] = { _("Default Font"), _("KiCad Font") }; + int m_fontCtrlNChoices = sizeof( m_fontCtrlChoices ) / sizeof( wxString ); + m_fontCtrl = new FONT_CHOICE( m_cellPage, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_fontCtrlNChoices, m_fontCtrlChoices, 0 ); + m_fontCtrl->SetSelection( 0 ); + gbSizer2->Add( m_fontCtrl, wxGBPosition( 0, 1 ), wxGBSpan( 1, 3 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + + gbSizer2->AddGrowableCol( 1 ); + + bMargins->Add( gbSizer2, 0, wxEXPAND|wxBOTTOM, 5 ); + + wxGridBagSizer* gbSizer1; + gbSizer1 = new wxGridBagSizer( 3, 5 ); + gbSizer1->SetFlexibleDirection( wxBOTH ); + gbSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + gbSizer1->SetEmptyCellSize( wxSize( -1,8 ) ); + + m_SizeXLabel = new wxStaticText( m_cellPage, wxID_ANY, _("Text width:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_SizeXLabel->Wrap( -1 ); + m_SizeXLabel->SetToolTip( _("Text width") ); + + gbSizer1->Add( m_SizeXLabel, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 4 ); + + m_SizeXCtrl = new wxTextCtrl( m_cellPage, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); + gbSizer1->Add( m_SizeXCtrl, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + m_SizeXUnits = new wxStaticText( m_cellPage, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 ); + m_SizeXUnits->Wrap( -1 ); + gbSizer1->Add( m_SizeXUnits, wxGBPosition( 0, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 ); + + m_SizeYLabel = new wxStaticText( m_cellPage, wxID_ANY, _("Text height:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_SizeYLabel->Wrap( -1 ); + m_SizeYLabel->SetToolTip( _("Text height") ); + + gbSizer1->Add( m_SizeYLabel, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 4 ); + + m_SizeYCtrl = new wxTextCtrl( m_cellPage, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); + gbSizer1->Add( m_SizeYCtrl, wxGBPosition( 1, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + m_SizeYUnits = new wxStaticText( m_cellPage, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 ); + m_SizeYUnits->Wrap( -1 ); + gbSizer1->Add( m_SizeYUnits, wxGBPosition( 1, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 ); + + m_ThicknessLabel = new wxStaticText( m_cellPage, wxID_ANY, _("Thickness:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_ThicknessLabel->Wrap( -1 ); + m_ThicknessLabel->SetToolTip( _("Text thickness") ); + + gbSizer1->Add( m_ThicknessLabel, wxGBPosition( 2, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 4 ); + + m_ThicknessCtrl = new wxTextCtrl( m_cellPage, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); + gbSizer1->Add( m_ThicknessCtrl, wxGBPosition( 2, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + m_ThicknessUnits = new wxStaticText( m_cellPage, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 ); + m_ThicknessUnits->Wrap( -1 ); + gbSizer1->Add( m_ThicknessUnits, wxGBPosition( 2, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 ); + + + bMargins->Add( gbSizer1, 1, wxEXPAND|wxTOP, 5 ); + + + bSizer13->Add( bMargins, 1, wxEXPAND|wxALL, 5 ); + + + m_cellPage->SetSizer( bSizer13 ); + m_cellPage->Layout(); + bSizer13->Fit( m_cellPage ); + m_notebook->AddPage( m_cellPage, _("Cell"), true ); + + bColumns->Add( m_notebook, 0, wxEXPAND|wxBOTTOM|wxLEFT, 10 ); + + + bMainSizer->Add( bColumns, 1, wxEXPAND|wxRIGHT|wxLEFT, 10 ); + + wxBoxSizer* bButtons; + bButtons = new wxBoxSizer( wxHORIZONTAL ); + + + bButtons->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_applyButton = new wxButton( this, wxID_ANY, _("Apply && Go to Next Cell"), wxDefaultPosition, wxDefaultSize, 0 ); + bButtons->Add( m_applyButton, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + m_hotkeyHint = new wxStaticText( this, wxID_ANY, _("(Option+Tab)"), wxDefaultPosition, wxDefaultSize, 0 ); + m_hotkeyHint->Wrap( -1 ); + bButtons->Add( m_hotkeyHint, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 10 ); + + m_sdbSizer1 = new wxStdDialogButtonSizer(); + m_sdbSizer1OK = new wxButton( this, wxID_OK ); + m_sdbSizer1->AddButton( m_sdbSizer1OK ); + m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL ); + m_sdbSizer1->AddButton( m_sdbSizer1Cancel ); + m_sdbSizer1->Realize(); + + bButtons->Add( m_sdbSizer1, 0, wxEXPAND|wxALL, 5 ); + + + bMainSizer->Add( bButtons, 0, wxEXPAND, 5 ); + + + this->SetSizer( bMainSizer ); + this->Layout(); + bMainSizer->Fit( this ); + + // Connect Events + m_textCtrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onMultiLineTCLostFocus ), NULL, this ); + m_borderCheckbox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onBorderChecked ), NULL, this ); + m_rowSeparators->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onBorderChecked ), NULL, this ); + m_colSeparators->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onBorderChecked ), NULL, this ); + m_SizeXCtrl->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::OnOkClick ), NULL, this ); + m_SizeYCtrl->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::OnOkClick ), NULL, this ); + m_ThicknessCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onThickness ), NULL, this ); + m_applyButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::OnApply ), NULL, this ); +} + +DIALOG_TABLECELL_PROPERTIES_BASE::~DIALOG_TABLECELL_PROPERTIES_BASE() +{ + // Disconnect Events + m_textCtrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onMultiLineTCLostFocus ), NULL, this ); + m_borderCheckbox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onBorderChecked ), NULL, this ); + m_rowSeparators->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onBorderChecked ), NULL, this ); + m_colSeparators->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onBorderChecked ), NULL, this ); + m_SizeXCtrl->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::OnOkClick ), NULL, this ); + m_SizeYCtrl->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::OnOkClick ), NULL, this ); + m_ThicknessCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onThickness ), NULL, this ); + m_applyButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::OnApply ), NULL, this ); + +} diff --git a/pcbnew/dialogs/dialog_tablecell_properties_base.fbp b/pcbnew/dialogs/dialog_tablecell_properties_base.fbp new file mode 100644 index 0000000000..7cc79feba3 --- /dev/null +++ b/pcbnew/dialogs/dialog_tablecell_properties_base.fbp @@ -0,0 +1,3445 @@ + + + + + + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + dialog_tablecell_properties_base + 1000 + none + + + 1 + dialog_tablecell_properties_base + + . + + 1 + 1 + 1 + 1 + UI + 0 + 1 + 0 + + 0 + wxAUI_MGR_DEFAULT + + + + 1 + 0 + 1 + impl_virtual + + + + 0 + wxID_ANY + + + DIALOG_TABLECELL_PROPERTIES_BASE + + -1,-1 + wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER + DIALOG_SHIM; dialog_shim.h + Table Cell Properties + + 0 + + + + + + bMainSizer + wxVERTICAL + none + + 5 + wxEXPAND|wxBOTTOM + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 500 + 1 + + 1 + + 0 + 1 + wxSHOW_EFFECT_NONE + wxID_ANY + + 0 + + + 0 + + 1 + m_infoBar + 1 + + + protected + 1 + + Resizable + 1 + wxSHOW_EFFECT_NONE + + WX_INFOBAR; widgets/wx_infobar.h; forward_declare + 0 + + + + + + + + 10 + wxEXPAND|wxRIGHT|wxLEFT + 1 + + + bColumns + wxHORIZONTAL + none + + 6 + wxEXPAND|wxTOP + 1 + + + bCellContentMargins + wxVERTICAL + none + + 1 + wxEXPAND|wxTOP|wxBOTTOM + 1 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + 0 + + 0 + 0 + wxID_ANY + 0 + 0 + + 0 + + + 0 + 500,-1 + 1 + m_textCtrl + 1 + + + protected + 1 + + 0 + Resizable + 1 + + ; forward_declare + 0 + 4 + 0 + + 1 + 0 + 0 + + + wxBORDER_SUNKEN + onMultiLineTCLostFocus + + + + + + 10 + wxEXPAND|wxBOTTOM|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_notebook + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + + + Table + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_tablePage + 1 + + + protected + 1 + + Resizable + 1 + + ; ; forward_declare + 0 + + + + wxTAB_TRAVERSAL + + + bSizer16 + wxVERTICAL + none + + 5 + wxEXPAND|wxALL + 1 + + 0,2 + wxBOTH + 1 + + 3 + + m_textEntrySizer + wxFLEX_GROWMODE_SPECIFIED + protected + 3 + + 5 + 1 + 0 + wxALIGN_CENTER_VERTICAL + 0 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Layer: + 0 + + 0 + + + 0 + + 1 + m_layerLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + 2 + 1 + wxALIGN_CENTER_VERTICAL|wxEXPAND + 0 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + 175,-1 + 1 + m_LayerSelectionCtrl + 1 + + + protected + 1 + + Resizable + -1 + 1 + + + PCB_LAYER_BOX_SELECTOR; pcb_layer_box_selector.h + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + 20 + 3 + 0 + wxBOTTOM + 1 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Locked + + 0 + + + 0 + + 1 + m_cbLocked + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 2 + 2 + 0 + wxBOTTOM + 2 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + External border + + 0 + + + 0 + + 1 + m_borderCheckbox + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + onBorderChecked + + + + 20 + 1 + 2 + wxLEFT + 2 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Header border + + 0 + + + 0 + + 1 + m_headerBorder + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + 1 + 0 + wxALIGN_CENTER_VERTICAL + 4 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Width: + 0 + + 0 + + + 0 + + 1 + m_borderWidthLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + 2 + 1 + wxEXPAND + 4 + 1 + + + bSizer7 + wxHORIZONTAL + none + + 5 + wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + -1,-1 + 0 + -1,-1 + 1 + m_borderWidthCtrl + 1 + + + protected + 1 + + Resizable + 1 + -1,-1 + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + 3 + wxALIGN_CENTER_VERTICAL|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + mm + 0 + + 0 + + + 0 + -1,-1 + 1 + m_borderWidthUnits + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + 5 + 1 + 0 + wxALIGN_CENTER_VERTICAL + 5 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Style: + 0 + + 0 + + + 0 + + 1 + m_borderStyleLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + 2 + 1 + wxEXPAND + 5 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + 200,-1 + 1 + m_borderStyleCombo + 1 + + + protected + 1 + + Resizable + -1 + 1 + + wxCB_READONLY + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + 5 + 1 + 0 + wxEXPAND + 6 + 1 + + 15 + protected + 0 + + + + 15 + 2 + 0 + wxALIGN_CENTER_VERTICAL|wxRIGHT + 7 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Row lines + + 0 + + + 0 + + 1 + m_rowSeparators + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + onBorderChecked + + + + 20 + 1 + 2 + wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT + 7 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Column lines + + 0 + + + 0 + + 1 + m_colSeparators + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + onBorderChecked + + + + 5 + 1 + 0 + wxALIGN_CENTER_VERTICAL + 9 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Width: + 0 + + 0 + + + 0 + + 1 + m_separatorsWidthLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + 2 + 1 + wxEXPAND + 9 + 1 + + + bSizer71 + wxHORIZONTAL + none + + 5 + wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + -1,-1 + 0 + -1,-1 + 1 + m_separatorsWidthCtrl + 1 + + + protected + 1 + + Resizable + 1 + -1,-1 + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + 3 + wxALIGN_CENTER_VERTICAL|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + mm + 0 + + 0 + + + 0 + -1,-1 + 1 + m_separatorsWidthUnits + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + 5 + 1 + 0 + wxALIGN_CENTER_VERTICAL + 10 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Style: + 0 + + 0 + + + 0 + + 1 + m_separatorsStyleLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + 2 + 1 + wxALIGN_CENTER_VERTICAL|wxEXPAND + 10 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + 200,-1 + 1 + m_separatorsStyleCombo + 1 + + + protected + 1 + + Resizable + -1 + 1 + + wxCB_READONLY + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + Cell + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_cellPage + 1 + + + protected + 1 + + Resizable + 1 + + ; ; forward_declare + 0 + + + + wxTAB_TRAVERSAL + + + bSizer13 + wxVERTICAL + none + + 5 + wxEXPAND|wxALL + 1 + + + bMargins + wxVERTICAL + none + + 10 + wxBOTTOM + 0 + + + bSizeCtrlSizer + wxHORIZONTAL + none + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 0 + + 1 + + + 0 + 0 + wxID_ANY + + + 0 + + 0 + + + 0 + + 1 + m_separator1 + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Bold + + 0 + + 0 + + + 0 + + 1 + m_bold + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + Bold + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Italic + + 0 + + 0 + + + 0 + + 1 + m_italic + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + Italic + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 0 + + 1 + + + 0 + 0 + wxID_ANY + + + 0 + + 0 + + + 0 + + 1 + m_separator2 + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Align left + + 0 + + 0 + + + 0 + + 1 + m_hAlignLeft + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + Align left + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Align center + + 0 + + 0 + + + 0 + + 1 + m_hAlignCenter + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + Align horizontal center + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Align right + + 0 + + 0 + + + 0 + + 1 + m_hAlignRight + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + Align right + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 0 + + 1 + + + 0 + 0 + wxID_ANY + + + 0 + + 0 + + + 0 + + 1 + m_separator3 + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Align top + + 0 + + 0 + + + 0 + + 1 + m_vAlignTop + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + Align top + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Align middle + + 0 + + 0 + + + 0 + + 1 + m_vAlignCenter + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + Align vertical center + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Align bottom + + 0 + + 0 + + + 0 + + 1 + m_vAlignBottom + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + Align bottom + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 0 + + 1 + + + 0 + 0 + wxID_ANY + + + 0 + + 0 + + + 0 + + 1 + m_separator4 + 1 + + + protected + 1 + + + + Resizable + 1 + 21,21 + wxBORDER_NONE + BITMAP_BUTTON; widgets/bitmap_button.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + 5 + wxEXPAND|wxBOTTOM + 0 + + -1,5 + wxBOTH + 1 + + 5 + + gbSizer2 + wxFLEX_GROWMODE_SPECIFIED + none + 4 + + 1 + 1 + 0 + wxALIGN_CENTER_VERTICAL|wxLEFT + 0 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Font: + 0 + + 0 + + + 0 + + 1 + m_fontLabel + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + 3 + 1 + wxALIGN_CENTER_VERTICAL|wxEXPAND + 0 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + "Default Font" "KiCad Font" + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_fontCtrl + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + FONT_CHOICE; widgets/font_choice.h; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + 5 + wxEXPAND|wxTOP + 1 + + -1,8 + wxBOTH + + + 5 + + gbSizer1 + wxFLEX_GROWMODE_SPECIFIED + none + 3 + + 4 + 1 + 0 + wxALIGN_CENTER_VERTICAL + 0 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 0 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Text width: + 0 + + 0 + + + 0 + + 1 + m_SizeXLabel + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Text width + + + + -1 + + + + 5 + 1 + 1 + wxALIGN_CENTER_VERTICAL|wxEXPAND + 0 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + + 1 + m_SizeXCtrl + 1 + + + protected + 1 + + Resizable + 1 + + wxTE_PROCESS_ENTER + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + OnOkClick + + + + 5 + 1 + 2 + wxALIGN_CENTER_VERTICAL + 0 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + unit + 0 + + 0 + + + 0 + + 1 + m_SizeXUnits + 1 + + + protected + 1 + + Resizable + 1 + + + ; forward_declare + 0 + + + + + -1 + + + + 4 + 1 + 0 + wxALIGN_CENTER_VERTICAL + 1 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 0 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Text height: + 0 + + 0 + + + 0 + + 1 + m_SizeYLabel + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Text height + + + + -1 + + + + 5 + 1 + 1 + wxALIGN_CENTER_VERTICAL|wxEXPAND + 1 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + + 1 + m_SizeYCtrl + 1 + + + protected + 1 + + Resizable + 1 + + wxTE_PROCESS_ENTER + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + OnOkClick + + + + 5 + 1 + 2 + wxALIGN_CENTER_VERTICAL + 1 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + unit + 0 + + 0 + + + 0 + + 1 + m_SizeYUnits + 1 + + + protected + 1 + + Resizable + 1 + + + ; forward_declare + 0 + + + + + -1 + + + + 4 + 1 + 0 + wxALIGN_CENTER_VERTICAL + 2 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 0 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Thickness: + 0 + + 0 + + + 0 + + 1 + m_ThicknessLabel + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Text thickness + + + + -1 + + + + 5 + 1 + 1 + wxALIGN_CENTER_VERTICAL|wxEXPAND + 2 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + + 1 + m_ThicknessCtrl + 1 + + + protected + 1 + + Resizable + 1 + + wxTE_PROCESS_ENTER + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + onThickness + + + + 5 + 1 + 2 + wxALIGN_CENTER_VERTICAL + 2 + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + unit + 0 + + 0 + + + 0 + + 1 + m_ThicknessUnits + 1 + + + protected + 1 + + Resizable + 1 + + + ; forward_declare + 0 + + + + + -1 + + + + + + + + + + + + + + + 5 + wxEXPAND + 0 + + + bButtons + wxHORIZONTAL + none + + 5 + wxEXPAND + 1 + + 0 + protected + 0 + + + + 5 + wxALIGN_CENTER_VERTICAL|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Apply && Go to Next Cell + + 0 + + 0 + + + 0 + + 1 + m_applyButton + 1 + + + protected + 1 + + + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnApply + + + + 10 + wxALIGN_CENTER_VERTICAL|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + (Option+Tab) + 0 + + 0 + + + 0 + + 1 + m_hotkeyHint + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxEXPAND|wxALL + 0 + + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + + m_sdbSizer1 + protected + + + + + + + + diff --git a/pcbnew/dialogs/dialog_tablecell_properties_base.h b/pcbnew/dialogs/dialog_tablecell_properties_base.h new file mode 100644 index 0000000000..cd71ce458c --- /dev/null +++ b/pcbnew/dialogs/dialog_tablecell_properties_base.h @@ -0,0 +1,119 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include +#include +class BITMAP_BUTTON; +class FONT_CHOICE; +class PCB_LAYER_BOX_SELECTOR; +class WX_INFOBAR; + +#include "dialog_shim.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_TABLECELL_PROPERTIES_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_TABLECELL_PROPERTIES_BASE : public DIALOG_SHIM +{ + private: + + protected: + WX_INFOBAR* m_infoBar; + wxStyledTextCtrl* m_textCtrl; + wxNotebook* m_notebook; + wxPanel* m_tablePage; + wxGridBagSizer* m_textEntrySizer; + wxStaticText* m_layerLabel; + PCB_LAYER_BOX_SELECTOR* m_LayerSelectionCtrl; + wxCheckBox* m_cbLocked; + wxCheckBox* m_borderCheckbox; + wxCheckBox* m_headerBorder; + wxStaticText* m_borderWidthLabel; + wxTextCtrl* m_borderWidthCtrl; + wxStaticText* m_borderWidthUnits; + wxStaticText* m_borderStyleLabel; + wxBitmapComboBox* m_borderStyleCombo; + wxCheckBox* m_rowSeparators; + wxCheckBox* m_colSeparators; + wxStaticText* m_separatorsWidthLabel; + wxTextCtrl* m_separatorsWidthCtrl; + wxStaticText* m_separatorsWidthUnits; + wxStaticText* m_separatorsStyleLabel; + wxBitmapComboBox* m_separatorsStyleCombo; + wxPanel* m_cellPage; + BITMAP_BUTTON* m_separator1; + BITMAP_BUTTON* m_bold; + BITMAP_BUTTON* m_italic; + BITMAP_BUTTON* m_separator2; + BITMAP_BUTTON* m_hAlignLeft; + BITMAP_BUTTON* m_hAlignCenter; + BITMAP_BUTTON* m_hAlignRight; + BITMAP_BUTTON* m_separator3; + BITMAP_BUTTON* m_vAlignTop; + BITMAP_BUTTON* m_vAlignCenter; + BITMAP_BUTTON* m_vAlignBottom; + BITMAP_BUTTON* m_separator4; + wxStaticText* m_fontLabel; + FONT_CHOICE* m_fontCtrl; + wxStaticText* m_SizeXLabel; + wxTextCtrl* m_SizeXCtrl; + wxStaticText* m_SizeXUnits; + wxStaticText* m_SizeYLabel; + wxTextCtrl* m_SizeYCtrl; + wxStaticText* m_SizeYUnits; + wxStaticText* m_ThicknessLabel; + wxTextCtrl* m_ThicknessCtrl; + wxStaticText* m_ThicknessUnits; + wxButton* m_applyButton; + wxStaticText* m_hotkeyHint; + wxStdDialogButtonSizer* m_sdbSizer1; + wxButton* m_sdbSizer1OK; + wxButton* m_sdbSizer1Cancel; + + // Virtual event handlers, override them in your derived class + virtual void onMultiLineTCLostFocus( wxFocusEvent& event ) { event.Skip(); } + virtual void onBorderChecked( wxCommandEvent& event ) { event.Skip(); } + virtual void OnOkClick( wxCommandEvent& event ) { event.Skip(); } + virtual void onThickness( wxCommandEvent& event ) { event.Skip(); } + virtual void OnApply( wxCommandEvent& event ) { event.Skip(); } + + + public: + + DIALOG_TABLECELL_PROPERTIES_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Table Cell Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + + ~DIALOG_TABLECELL_PROPERTIES_BASE(); + +}; + diff --git a/pcbnew/drc/drc_engine.cpp b/pcbnew/drc/drc_engine.cpp index deefe36584..4d8904ed16 100644 --- a/pcbnew/drc/drc_engine.cpp +++ b/pcbnew/drc/drc_engine.cpp @@ -1135,6 +1135,7 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO case PCB_FIELD_T: mask = DRC_DISALLOW_TEXTS; break; case PCB_TEXT_T: mask = DRC_DISALLOW_TEXTS; break; case PCB_TEXTBOX_T: mask = DRC_DISALLOW_TEXTS; break; + case PCB_TABLE_T: mask = DRC_DISALLOW_TEXTS; break; case PCB_ZONE_T: // Treat teardrop areas as tracks for DRC purposes diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp index f04e6d92fe..604dbcd88a 100644 --- a/pcbnew/edit.cpp +++ b/pcbnew/edit.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -136,6 +137,10 @@ void PCB_EDIT_FRAME::OnEditItemRequest( BOARD_ITEM* aItem ) ShowTextBoxPropertiesDialog( static_cast( aItem ) ); break; + case PCB_TABLECELL_T: + ShowTableCellPropertiesDialog( static_cast( aItem ) ); + break; + case PCB_PAD_T: ShowPadPropertiesDialog( static_cast( aItem ) ); break; diff --git a/pcbnew/footprint_edit_frame.cpp b/pcbnew/footprint_edit_frame.cpp index 51a70e701a..97431921d0 100644 --- a/pcbnew/footprint_edit_frame.cpp +++ b/pcbnew/footprint_edit_frame.cpp @@ -23,6 +23,7 @@ #include "tools/convert_tool.h" #include "tools/drawing_tool.h" #include "tools/edit_tool.h" +#include "tools/pcb_edit_table_tool.h" #include "tools/footprint_editor_control.h" #include "tools/pad_tool.h" #include "tools/pcb_actions.h" @@ -1119,6 +1120,7 @@ void FOOTPRINT_EDIT_FRAME::setupTools() m_toolManager->RegisterTool( new PCB_SELECTION_TOOL ); m_toolManager->RegisterTool( new ZOOM_TOOL ); m_toolManager->RegisterTool( new EDIT_TOOL ); + m_toolManager->RegisterTool( new PCB_EDIT_TABLE_TOOL ); m_toolManager->RegisterTool( new PAD_TOOL ); m_toolManager->RegisterTool( new DRAWING_TOOL ); m_toolManager->RegisterTool( new PCB_POINT_EDITOR ); diff --git a/pcbnew/menubar_pcb_editor.cpp b/pcbnew/menubar_pcb_editor.cpp index ca2d9960a2..308766f3de 100644 --- a/pcbnew/menubar_pcb_editor.cpp +++ b/pcbnew/menubar_pcb_editor.cpp @@ -312,6 +312,7 @@ void PCB_EDIT_FRAME::doReCreateMenuBar() placeMenu->Add( PCB_ACTIONS::placeReferenceImage ); placeMenu->Add( PCB_ACTIONS::placeText ); placeMenu->Add( PCB_ACTIONS::drawTextBox ); + placeMenu->Add( PCB_ACTIONS::drawTable ); placeMenu->AppendSeparator(); ACTION_MENU* dimensionSubmenu = new ACTION_MENU( false, selTool ); diff --git a/pcbnew/pcb_base_edit_frame.h b/pcbnew/pcb_base_edit_frame.h index c0db4cad9f..6b895a612b 100644 --- a/pcbnew/pcb_base_edit_frame.h +++ b/pcbnew/pcb_base_edit_frame.h @@ -33,6 +33,7 @@ class APPEARANCE_CONTROLS; class BOARD_ITEM_CONTAINER; class PANEL_SELECTION_FILTER; class PCB_TEXTBOX; +class PCB_TABLECELL; class PCB_TEXT; class PCB_SHAPE; @@ -178,6 +179,7 @@ public: void ShowReferenceImagePropertiesDialog( BOARD_ITEM* aBitmap ); void ShowTextPropertiesDialog( PCB_TEXT* aText ); int ShowTextBoxPropertiesDialog( PCB_TEXTBOX* aTextBox ); + void ShowTableCellPropertiesDialog( PCB_TABLECELL* aTableCell ); void ShowGraphicItemPropertiesDialog( PCB_SHAPE* aShape ); ///< @copydoc EDA_DRAW_FRAME::UseGalCanvas() diff --git a/pcbnew/pcb_edit_frame.cpp b/pcbnew/pcb_edit_frame.cpp index f508807a03..83a44cf936 100644 --- a/pcbnew/pcb_edit_frame.cpp +++ b/pcbnew/pcb_edit_frame.cpp @@ -68,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -650,6 +651,7 @@ void PCB_EDIT_FRAME::setupTools() m_toolManager->RegisterTool( new PCB_PICKER_TOOL ); m_toolManager->RegisterTool( new ROUTER_TOOL ); m_toolManager->RegisterTool( new EDIT_TOOL ); + m_toolManager->RegisterTool( new PCB_EDIT_TABLE_TOOL ); m_toolManager->RegisterTool( new GLOBAL_EDIT_TOOL ); m_toolManager->RegisterTool( new PAD_TOOL ); m_toolManager->RegisterTool( new DRAWING_TOOL ); @@ -968,6 +970,7 @@ void PCB_EDIT_FRAME::setupUIConditions() CURRENT_EDIT_TOOL( PCB_ACTIONS::placeReferenceImage ); CURRENT_EDIT_TOOL( PCB_ACTIONS::placeText ); CURRENT_EDIT_TOOL( PCB_ACTIONS::drawTextBox ); + CURRENT_EDIT_TOOL( PCB_ACTIONS::drawTable ); CURRENT_EDIT_TOOL( PCB_ACTIONS::drawAlignedDimension ); CURRENT_EDIT_TOOL( PCB_ACTIONS::drawOrthogonalDimension ); CURRENT_EDIT_TOOL( PCB_ACTIONS::drawCenterDimension ); diff --git a/pcbnew/pcb_group.cpp b/pcbnew/pcb_group.cpp index d25839b268..41cedaf139 100644 --- a/pcbnew/pcb_group.cpp +++ b/pcbnew/pcb_group.cpp @@ -57,6 +57,7 @@ bool PCB_GROUP::IsGroupableType( KICAD_T aType ) case PCB_FIELD_T: case PCB_TEXT_T: case PCB_TEXTBOX_T: + case PCB_TABLE_T: case PCB_GROUP_T: case PCB_GENERATOR_T: case PCB_TRACE_T: diff --git a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp index bb78d85b30..2d7676f547 100644 --- a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp +++ b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include #include #include @@ -406,6 +408,10 @@ void PCB_IO_KICAD_SEXPR::Format( const BOARD_ITEM* aItem, int aNestLevel ) const format( static_cast( aItem ), aNestLevel ); break; + case PCB_TABLE_T: + format( static_cast( aItem ), aNestLevel ); + break; + case PCB_GROUP_T: format( static_cast( aItem ), aNestLevel ); break; @@ -1448,7 +1454,7 @@ void PCB_IO_KICAD_SEXPR::format( const PAD* aPad, int aNestLevel ) const switch( aPad->GetShape() ) { case PAD_SHAPE::CIRCLE: shape = "circle"; break; - case PAD_SHAPE::RECTANGLE: shape = "rect"; break; + case PAD_SHAPE::RECTANGLE: shape = "rect"; break; case PAD_SHAPE::OVAL: shape = "oval"; break; case PAD_SHAPE::TRAPEZOID: shape = "trapezoid"; break; case PAD_SHAPE::CHAMFERED_RECT: @@ -1887,7 +1893,9 @@ void PCB_IO_KICAD_SEXPR::format( const PCB_TEXTBOX* aTextBox, int aNestLevel ) c FOOTPRINT* parentFP = aTextBox->GetParentFootprint(); m_out->Print( aNestLevel, "(%s %s\n", - parentFP ? "fp_text_box" : "gr_text_box", + aTextBox->Type() == PCB_TABLECELL_T ? "table_cell" + : parentFP ? "fp_text_box" + : "gr_text_box", m_out->Quotew( aTextBox->GetText() ).c_str() ); if( aTextBox->IsLocked() ) @@ -1911,6 +1919,9 @@ void PCB_IO_KICAD_SEXPR::format( const PCB_TEXTBOX* aTextBox, int aNestLevel ) c UNIMPLEMENTED_FOR( aTextBox->SHAPE_T_asString() ); } + if( const PCB_TABLECELL* cell = dynamic_cast( aTextBox ) ) + m_out->Print( 0, " (span %d %d)", cell->GetColSpan(), cell->GetRowSpan() ); + EDA_ANGLE angle = aTextBox->GetTextAngle(); if( parentFP ) @@ -1930,9 +1941,12 @@ void PCB_IO_KICAD_SEXPR::format( const PCB_TEXTBOX* aTextBox, int aNestLevel ) c // PCB_TEXTBOXes are never hidden, so always omit "hide" attribute aTextBox->EDA_TEXT::Format( m_out, aNestLevel, m_ctl | CTL_OMIT_HIDE ); - KICAD_FORMAT::FormatBool( m_out, aNestLevel + 1, "border", aTextBox->IsBorderEnabled() ); + if( aTextBox->Type() != PCB_TABLECELL_T ) + { + KICAD_FORMAT::FormatBool( m_out, aNestLevel + 1, "border", aTextBox->IsBorderEnabled() ); - aTextBox->GetStroke().Format( m_out, pcbIUScale, aNestLevel + 1 ); + aTextBox->GetStroke().Format( m_out, pcbIUScale, aNestLevel + 1 ); + } if( aTextBox->GetFont() && aTextBox->GetFont()->IsOutline() ) formatRenderCache( aTextBox, aNestLevel + 1 ); @@ -1941,6 +1955,66 @@ void PCB_IO_KICAD_SEXPR::format( const PCB_TEXTBOX* aTextBox, int aNestLevel ) c } +void PCB_IO_KICAD_SEXPR::format( const PCB_TABLE* aTable, int aNestLevel ) const +{ + wxCHECK_RET( aTable != nullptr && m_out != nullptr, "" ); + + m_out->Print( aNestLevel, "(table (column_count %d)\n", + aTable->GetColCount() ); + + if( aTable->IsLocked() ) + KICAD_FORMAT::FormatBool( m_out, aNestLevel, "locked", aTable->IsLocked() ); + + formatLayer( aTable->GetLayer() ); + + m_out->Print( aNestLevel + 1, "(border (external %s) (header %s)", + aTable->StrokeExternal() ? "yes" : "no", + aTable->StrokeHeader() ? "yes" : "no" ); + + if( aTable->StrokeExternal() || aTable->StrokeHeader() ) + { + m_out->Print( 0, " " ); + aTable->GetBorderStroke().Format( m_out, pcbIUScale, 0 ); + } + + m_out->Print( 0, ")\n" ); + + m_out->Print( aNestLevel + 1, "(separators (rows %s) (cols %s)", + aTable->StrokeRows() ? "yes" : "no", + aTable->StrokeColumns() ? "yes" : "no" ); + + if( aTable->StrokeRows() || aTable->StrokeColumns() ) + { + m_out->Print( 0, " " ); + aTable->GetSeparatorsStroke().Format( m_out, pcbIUScale, 0 ); + } + + m_out->Print( 0, ")\n" ); // Close `separators` token. + + m_out->Print( aNestLevel + 1, "(column_widths" ); + + for( int col = 0; col < aTable->GetColCount(); ++col ) + m_out->Print( 0, " %s", formatInternalUnits( aTable->GetColWidth( col ) ).c_str() ); + + m_out->Print( 0, ")\n" ); + + m_out->Print( aNestLevel + 1, "(row_heights" ); + + for( int row = 0; row < aTable->GetRowCount(); ++row ) + m_out->Print( 0, " %s", formatInternalUnits( aTable->GetRowHeight( row ) ).c_str() ); + + m_out->Print( 0, ")\n" ); + + m_out->Print( aNestLevel + 1, "(cells\n" ); + + for( PCB_TABLECELL* cell : aTable->GetCells() ) + format( static_cast( cell ), aNestLevel + 2 ); + + m_out->Print( aNestLevel + 1, ")\n" ); // Close `cells` token. + m_out->Print( aNestLevel, ")\n" ); // Close `table` token. +} + + void PCB_IO_KICAD_SEXPR::format( const PCB_GROUP* aGroup, int aNestLevel ) const { // Don't write empty groups diff --git a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h index 369be5c45e..5b0ef0a638 100644 --- a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h +++ b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h @@ -52,6 +52,7 @@ class PCB_TRACK; class ZONE; class PCB_TEXT; class PCB_TEXTBOX; +class PCB_TABLE; class EDA_TEXT; class SHAPE_LINE_CHAIN; class TEARDROP_PARAMETERS; @@ -148,9 +149,10 @@ class PCB_IO_KICAD_SEXPR; // forward decl //#define SEXPR_BOARD_FILE_VERSION 20231014 // V8 file format normalization //#define SEXPR_BOARD_FILE_VERSION 20231212 // Reference image locking/UUIDs, footprint boolean format //#define SEXPR_BOARD_FILE_VERSION 20231231 // Use 'uuid' rather than 'id' for generators and groups -//#define SEXPR_BOARD_FILE_VERSION 20240108 // Convert teardrop parameters to explicit bools +//#define SEXPR_BOARD_FILE_VERSION 20240108 // Convert teardrop parameters to explicit bools //----------------- Start of 9.0 development ----------------- -#define SEXPR_BOARD_FILE_VERSION 20240201 // Use nullable properties for overrides +//define SEXPR_BOARD_FILE_VERSION 20240201 // Use nullable properties for overrides +#define SEXPR_BOARD_FILE_VERSION 20240202 // Tables #define BOARD_FILE_HOST_VERSION 20200825 ///< Earlier files than this include the host tag #define LEGACY_ARC_FORMATTING 20210925 ///< These were the last to use old arc formatting @@ -159,7 +161,7 @@ class PCB_IO_KICAD_SEXPR; // forward decl #define FIRST_NORMALIZED_VERISON 20230924 ///< Earlier files did not have normalized bools #define CTL_OMIT_PAD_NETS (1 << 1) ///< Omit pads net names (useless in library) -#define CTL_OMIT_UUIDS (1 << 2) ///< Omit component unique ids (useless in library) +#define CTL_OMIT_UUIDS (1 << 2) ///< Omit component unique ids (useless in library) #define CTL_OMIT_INITIAL_COMMENTS (1 << 3) ///< omit FOOTPRINT initial comments #define CTL_OMIT_PATH (1 << 4) ///< Omit component sheet time stamp (useless in library) #define CTL_OMIT_AT (1 << 5) ///< Omit position and rotation. (always saved @@ -425,6 +427,8 @@ private: void format( const PCB_TEXT* aText, int aNestLevel = 0 ) const; void format( const PCB_TEXTBOX* aTextBox, int aNestLevel = 0 ) const; + void format( const PCB_TABLE* aTable, int aNestLevel = 0 ) const; + void format( const PCB_GENERATOR* aGenerator, int aNestLevel = 0 ) const; void format( const PCB_TRACK* aTrack, int aNestLevel = 0 ) const; diff --git a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp index 0220fcf2b6..8e33f5ce47 100644 --- a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp +++ b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -1006,6 +1007,12 @@ BOARD* PCB_IO_KICAD_SEXPR_PARSER::parseBOARD_unchecked() bulkAddedItems.push_back( item ); break; + case T_table: + item = parsePCB_TABLE( m_board ); + m_board->Add( item, ADD_MODE::BULK_APPEND, true ); + bulkAddedItems.push_back( item ); + break; + case T_dimension: item = parseDIMENSION( m_board ); m_board->Add( item, ADD_MODE::BULK_APPEND, true ); @@ -3333,19 +3340,40 @@ PCB_TEXTBOX* PCB_IO_KICAD_SEXPR_PARSER::parsePCB_TEXTBOX( BOARD_ITEM* aParent ) std::unique_ptr textbox = std::make_unique( aParent ); + parseTextBoxContent( textbox.get() ); + + return textbox.release(); +} + + +PCB_TABLECELL* PCB_IO_KICAD_SEXPR_PARSER::parsePCB_TABLECELL( BOARD_ITEM* aParent ) +{ + wxCHECK_MSG( CurTok() == T_table_cell, nullptr, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a table cell." ) ); + + std::unique_ptr cell = std::make_unique( aParent ); + + parseTextBoxContent( cell.get() ); + + return cell.release(); +} + + +void PCB_IO_KICAD_SEXPR_PARSER::parseTextBoxContent( PCB_TEXTBOX* aTextBox ) +{ STROKE_PARAMS stroke( -1, LINE_STYLE::SOLID ); T token = NextTok(); if( token == T_locked ) { - textbox->SetLocked( true ); + aTextBox->SetLocked( true ); token = NextTok(); } if( !IsSymbol( token ) && (int) token != DSN_NUMBER ) Expecting( "text value" ); - textbox->SetText( FromUTF8() ); + aTextBox->SetText( FromUTF8() ); NeedLEFT(); token = NextTok(); @@ -3354,7 +3382,7 @@ PCB_TEXTBOX* PCB_IO_KICAD_SEXPR_PARSER::parsePCB_TEXTBOX( BOARD_ITEM* aParent ) { int x = parseBoardUnits( "X coordinate" ); int y = parseBoardUnits( "Y coordinate" ); - textbox->SetStart( VECTOR2I( x, y ) ); + aTextBox->SetStart( VECTOR2I( x, y ) ); NeedRIGHT(); NeedLEFT(); @@ -3365,17 +3393,17 @@ PCB_TEXTBOX* PCB_IO_KICAD_SEXPR_PARSER::parsePCB_TEXTBOX( BOARD_ITEM* aParent ) x = parseBoardUnits( "X coordinate" ); y = parseBoardUnits( "Y coordinate" ); - textbox->SetEnd( VECTOR2I( x, y ) ); + aTextBox->SetEnd( VECTOR2I( x, y ) ); NeedRIGHT(); } else if( token == T_pts ) { - textbox->SetShape( SHAPE_T::POLY ); - textbox->GetPolyShape().RemoveAllContours(); - textbox->GetPolyShape().NewOutline(); + aTextBox->SetShape( SHAPE_T::POLY ); + aTextBox->GetPolyShape().RemoveAllContours(); + aTextBox->GetPolyShape().NewOutline(); while( (token = NextTok() ) != T_RIGHT ) - parseOutlinePoints( textbox->GetPolyShape().Outline( 0 ) ); + parseOutlinePoints( aTextBox->GetPolyShape().Outline( 0 ) ); } else { @@ -3394,7 +3422,7 @@ PCB_TEXTBOX* PCB_IO_KICAD_SEXPR_PARSER::parsePCB_TEXTBOX( BOARD_ITEM* aParent ) case T_angle: // Set the angle of the text only, the coordinates of the box (a polygon) are // already at the right position, and must not be rotated - textbox->EDA_TEXT::SetTextAngle( EDA_ANGLE( parseDouble( "text box angle" ), DEGREES_T ) ); + aTextBox->EDA_TEXT::SetTextAngle( EDA_ANGLE( parseDouble( "text box angle" ), DEGREES_T ) ); NeedRIGHT(); break; @@ -3409,48 +3437,224 @@ PCB_TEXTBOX* PCB_IO_KICAD_SEXPR_PARSER::parsePCB_TEXTBOX( BOARD_ITEM* aParent ) } case T_border: - textbox->SetBorderEnabled( parseBool() ); + aTextBox->SetBorderEnabled( parseBool() ); NeedRIGHT(); break; case T_layer: - textbox->SetLayer( parseBoardItemLayer() ); + aTextBox->SetLayer( parseBoardItemLayer() ); + NeedRIGHT(); + break; + + case T_span: + if( PCB_TABLECELL* cell = dynamic_cast( aTextBox ) ) + { + cell->SetColSpan( parseInt( "column span" ) ); + cell->SetRowSpan( parseInt( "row span" ) ); + } + else + { + Expecting( "angle, width, layer, effects, render_cache, uuid or tstamp" ); + } + NeedRIGHT(); break; case T_tstamp: case T_uuid: NextTok(); - const_cast( textbox->m_Uuid ) = CurStrToKIID(); + const_cast( aTextBox->m_Uuid ) = CurStrToKIID(); NeedRIGHT(); break; case T_effects: - parseEDA_TEXT( static_cast( textbox.get() ) ); + parseEDA_TEXT( static_cast( aTextBox ) ); break; case T_render_cache: - parseRenderCache( static_cast( textbox.get() ) ); + parseRenderCache( static_cast( aTextBox ) ); break; default: - Expecting( "angle, width, layer, effects, render_cache, uuid or tstamp" ); + if( PCB_TABLECELL* cell = dynamic_cast( aTextBox ) ) + Expecting( "angle, width, layer, effects, span, render_cache, uuid or tstamp" ); + else + Expecting( "angle, width, layer, effects, render_cache, uuid or tstamp" ); } } - textbox->SetStroke( stroke ); + aTextBox->SetStroke( stroke ); if( m_requiredVersion < 20230825 ) // compat, we move to an explicit flag - textbox->SetBorderEnabled( stroke.GetWidth() >= 0 ); + aTextBox->SetBorderEnabled( stroke.GetWidth() >= 0 ); - if( FOOTPRINT* parentFP = dynamic_cast( aParent ) ) + if( FOOTPRINT* parentFP = dynamic_cast( aTextBox->GetParent() ) ) { - textbox->Rotate( { 0, 0 }, parentFP->GetOrientation() ); - textbox->Move( parentFP->GetPosition() ); + aTextBox->Rotate( { 0, 0 }, parentFP->GetOrientation() ); + aTextBox->Move( parentFP->GetPosition() ); + } +} + + +PCB_TABLE* PCB_IO_KICAD_SEXPR_PARSER::parsePCB_TABLE( BOARD_ITEM* aParent ) +{ + wxCHECK_MSG( CurTok() == T_table, nullptr, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a table." ) ); + + T token; + STROKE_PARAMS borderStroke( -1, LINE_STYLE::SOLID ); + STROKE_PARAMS separatorsStroke( -1, LINE_STYLE::SOLID ); + std::unique_ptr table = std::make_unique( aParent, -1 ); + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token == T_locked ) + { + table->SetLocked( true ); + token = NextTok(); + } + + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_column_count: + table->SetColCount( parseInt( "column count" ) ); + NeedRIGHT(); + break; + + case T_layer: + table->SetLayer( parseBoardItemLayer() ); + NeedRIGHT(); + break; + + case T_column_widths: + { + int col = 0; + + while( ( token = NextTok() ) != T_RIGHT ) + table->SetColWidth( col++, parseBoardUnits() ); + + break; + } + + case T_row_heights: + { + int row = 0; + + while( ( token = NextTok() ) != T_RIGHT ) + table->SetRowHeight( row++, parseBoardUnits() ); + + break; + } + + case T_cells: + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + if( token != T_table_cell ) + Expecting( "table_cell" ); + + table->AddCell( parsePCB_TABLECELL( table.get() ) ); + } + + break; + + case T_border: + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_external: + table->SetStrokeExternal( parseBool() ); + NeedRIGHT(); + break; + + case T_header: + table->SetStrokeHeader( parseBool() ); + NeedRIGHT(); + break; + + case T_stroke: + { + STROKE_PARAMS_PARSER strokeParser( reader, pcbIUScale.IU_PER_MM ); + strokeParser.SyncLineReaderWith( *this ); + + strokeParser.ParseStroke( borderStroke ); + SyncLineReaderWith( strokeParser ); + + table->SetBorderStroke( borderStroke ); + break; + } + + default: + Expecting( "external, header or stroke" ); + break; + } + } + + break; + + case T_separators: + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_rows: + table->SetStrokeRows( parseBool() ); + NeedRIGHT(); + break; + + case T_cols: + table->SetStrokeColumns( parseBool() ); + NeedRIGHT(); + break; + + case T_stroke: + { + STROKE_PARAMS_PARSER strokeParser( reader, pcbIUScale.IU_PER_MM ); + strokeParser.SyncLineReaderWith( *this ); + + strokeParser.ParseStroke( separatorsStroke ); + SyncLineReaderWith( strokeParser ); + + table->SetSeparatorsStroke( separatorsStroke ); + break; + } + + default: + Expecting( "rows, cols, or stroke" ); + break; + } + } + + break; + + default: + Expecting( "columns, layer, col_widths, row_heights, border, separators, header or " + "cells" ); + } } - return textbox.release(); + return table.release(); } @@ -4324,6 +4528,13 @@ FOOTPRINT* PCB_IO_KICAD_SEXPR_PARSER::parseFOOTPRINT_unchecked( wxArrayString* a break; } + case T_table: + { + PCB_TABLE* table = parsePCB_TABLE( footprint.get() ); + footprint->Add( table, ADD_MODE::APPEND, true ); + break; + } + case T_fp_arc: case T_fp_circle: case T_fp_curve: diff --git a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.h b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.h index 7445be6de9..4dd20d60c8 100644 --- a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.h +++ b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.h @@ -52,9 +52,10 @@ class PCB_DIMENSION_BASE; class PCB_SHAPE; class PCB_REFERENCE_IMAGE; class EDA_TEXT; -class FP_SHAPE; class PCB_TEXT; class PCB_TRACK; +class PCB_TABLE; +class PCB_TABLECELL; class FOOTPRINT; class PCB_GROUP; class PCB_TARGET; @@ -207,11 +208,15 @@ private: void parseTEARDROP_PARAMETERS( TEARDROP_PARAMETERS* tdParams ); + void parseTextBoxContent( PCB_TEXTBOX* aTextBox ); + PCB_SHAPE* parsePCB_SHAPE( BOARD_ITEM* aParent ); PCB_TEXT* parsePCB_TEXT( BOARD_ITEM* aParent ); void parsePCB_TEXT_effects( PCB_TEXT* aText ); PCB_REFERENCE_IMAGE* parsePCB_REFERENCE_IMAGE( BOARD_ITEM* aParent ); PCB_TEXTBOX* parsePCB_TEXTBOX( BOARD_ITEM* aParent ); + PCB_TABLECELL* parsePCB_TABLECELL( BOARD_ITEM* aParent ); + PCB_TABLE* parsePCB_TABLE( BOARD_ITEM* aParent ); PCB_DIMENSION_BASE* parseDIMENSION( BOARD_ITEM* aParent ); // Parse a footprint, but do not replace PARSE_ERROR with FUTURE_FORMAT_ERROR automatically. diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 51f0d5e692..87165a3c4b 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include #include @@ -613,6 +615,10 @@ bool PCB_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer ) draw( static_cast( item ), aLayer ); break; + case PCB_TABLE_T: + draw( static_cast( item ), aLayer ); + break; + case PCB_FOOTPRINT_T: draw( static_cast( item ), aLayer ); break; @@ -2132,10 +2138,18 @@ void PCB_PAINTER::draw( const PCB_TEXT* aText, int aLayer ) void PCB_PAINTER::draw( const PCB_TEXTBOX* aTextBox, int aLayer ) { - const COLOR4D& color = m_pcbSettings.GetColor( aTextBox, aLayer ); - int thickness = getLineThickness( aTextBox->GetWidth() ); - LINE_STYLE lineStyle = aTextBox->GetStroke().GetLineStyle(); - wxString resolvedText( aTextBox->GetShownText( true ) ); + if( aTextBox->Type() == PCB_TABLECELL_T ) + { + const PCB_TABLECELL* cell = static_cast( aTextBox ); + + if( cell->GetColSpan() == 0 || cell->GetRowSpan() == 0 ) + return; + } + + COLOR4D color = m_pcbSettings.GetColor( aTextBox, aLayer ); + int thickness = getLineThickness( aTextBox->GetWidth() ); + LINE_STYLE lineStyle = aTextBox->GetStroke().GetLineStyle(); + wxString resolvedText( aTextBox->GetShownText( true ) ); KIFONT::FONT* font = aTextBox->GetFont(); @@ -2171,6 +2185,13 @@ void PCB_PAINTER::draw( const PCB_TEXTBOX* aTextBox, int aLayer ) m_gal->DrawPolygon( dpts ); } + if( aTextBox->Type() == PCB_TABLECELL_T ) + { + // Selection for tables is done with a background wash, so pass in nullptr to GetColor() + // so we just get the "normal" (un-selected/un-brightened) color for the borders. + color = m_pcbSettings.GetColor( nullptr, aLayer ); + } + m_gal->SetFillColor( color ); m_gal->SetStrokeColor( color ); m_gal->SetIsFill( true ); @@ -2224,14 +2245,14 @@ void PCB_PAINTER::draw( const PCB_TEXTBOX* aTextBox, int aLayer ) // so the text drawn on LAYER_LOCKED_ITEM_SHADOW with a thick width is disabled // If enabled, the thick text position must be offsetted to be exactly on the // initial text, which is not easy, depending on its rotation and justification. - #if 0 +#if 0 const COLOR4D sh_color = m_pcbSettings.GetColor( aTextBox, aLayer ); m_gal->SetFillColor( sh_color ); m_gal->SetStrokeColor( sh_color ); attrs.m_StrokeWidth += m_lockedShadowMargin; - #else +#else return; - #endif +#endif } std::vector>* cache = nullptr; @@ -2251,6 +2272,146 @@ void PCB_PAINTER::draw( const PCB_TEXTBOX* aTextBox, int aLayer ) } +void PCB_PAINTER::draw( const PCB_TABLE* aTable, int aLayer ) +{ + for( PCB_TABLECELL* cell : aTable->GetCells() ) + draw( static_cast( cell ), aLayer ); + + VECTOR2I pos = aTable->GetPosition(); + VECTOR2I end = aTable->GetEnd(); + + // Selection for tables is done with a background wash, so pass in nullptr to GetColor() + // so we just get the "normal" (un-selected/un-brightened) color for the borders. + COLOR4D color = m_pcbSettings.GetColor( nullptr, aLayer ); + int lineWidth; + LINE_STYLE lineStyle; + + auto setupStroke = + [&]( const STROKE_PARAMS& stroke ) + { + lineWidth = getLineThickness( stroke.GetWidth() ); + lineStyle = stroke.GetLineStyle(); + + m_gal->SetIsFill( false ); + m_gal->SetIsStroke( true ); + m_gal->SetStrokeColor( color ); + m_gal->SetLineWidth( lineWidth ); + }; + + auto strokeShape = + [&]( const SHAPE& shape ) + { + STROKE_PARAMS::Stroke( &shape, lineStyle, lineWidth, &m_pcbSettings, + [&]( const VECTOR2I& a, const VECTOR2I& b ) + { + // DrawLine has problem with 0 length lines so enforce minimum + if( a == b ) + m_gal->DrawLine( a+1, b ); + else + m_gal->DrawLine( a, b ); + } ); + }; + + auto strokeLine = + [&]( const VECTOR2I& ptA, const VECTOR2I& ptB ) + { + if( lineStyle <= LINE_STYLE::FIRST_TYPE ) + { + m_gal->DrawLine( ptA, ptB ); + } + else + { + SHAPE_SEGMENT seg( ptA, ptB ); + strokeShape( seg ); + } + }; + + auto strokeRect = + [&]( const VECTOR2I& ptA, const VECTOR2I& ptB ) + { + if( lineStyle <= LINE_STYLE::FIRST_TYPE ) + { + m_gal->DrawRectangle( ptA, ptB ); + } + else + { + SHAPE_RECT rect( BOX2I( ptA, ptB - ptA ) ); + strokeShape( rect ); + } + }; + + if( aTable->GetSeparatorsStroke().GetWidth() >= 0 ) + { + setupStroke( aTable->GetSeparatorsStroke() ); + + if( aTable->StrokeColumns() ) + { + for( int col = 0; col < aTable->GetColCount() - 1; ++col ) + { + for( int row = 0; row < aTable->GetRowCount(); ++row ) + { + PCB_TABLECELL* cell = aTable->GetCell( row, col ); + + if( cell->GetColSpan() > 0 && cell->GetRowSpan() > 0 ) + { + strokeLine( VECTOR2I( cell->GetEndX(), cell->GetStartY() ), + VECTOR2I( cell->GetEndX(), cell->GetEndY() ) ); + } + } + } + } + + if( aTable->StrokeRows() ) + { + for( int row = 0; row < aTable->GetRowCount() - 1; ++row ) + { + for( int col = 0; col < aTable->GetColCount(); ++col ) + { + PCB_TABLECELL* cell = aTable->GetCell( row, 0 ); + + if( cell->GetColSpan() > 0 && cell->GetRowSpan() > 0 ) + { + strokeLine( VECTOR2I( cell->GetStartX(), cell->GetEndY() ), + VECTOR2I( cell->GetEndX(), cell->GetEndY() ) ); + } + } + } + } + } + + if( aTable->GetBorderStroke().GetWidth() >= 0 ) + { + setupStroke( aTable->GetBorderStroke() ); + + if( aTable->StrokeHeader() ) + { + PCB_TABLECELL* cell = aTable->GetCell( 0, 0 ); + strokeLine( VECTOR2I( pos.x, cell->GetEndY() ), VECTOR2I( end.x, cell->GetEndY() ) ); + } + + if( aTable->StrokeExternal() ) + strokeRect( pos, end ); + } + + // Highlight selected tablecells with a background wash. + for( PCB_TABLECELL* cell : aTable->GetCells() ) + { + if( cell->IsSelected() ) + { + std::vector corners = cell->GetCorners(); + std::deque pts; + + pts.insert( pts.end(), corners.begin(), corners.end() ); + + m_gal->SetFillColor( color.WithAlpha( 0.5 ) ); + m_gal->SetIsFill( true ); + m_gal->SetIsStroke( false ); + m_gal->DrawPolygon( pts ); + } + } +} + + void PCB_PAINTER::draw( const FOOTPRINT* aFootprint, int aLayer ) { if( aLayer == LAYER_ANCHOR ) diff --git a/pcbnew/pcb_painter.h b/pcbnew/pcb_painter.h index 1f9f7699ec..b5ebde2ccd 100644 --- a/pcbnew/pcb_painter.h +++ b/pcbnew/pcb_painter.h @@ -52,6 +52,7 @@ class ZONE; class PCB_REFERENCE_IMAGE; class PCB_TEXT; class PCB_TEXTBOX; +class PCB_TABLE; class PCB_DIMENSION_BASE; class PCB_TARGET; class PCB_MARKER; @@ -185,6 +186,7 @@ protected: void draw( const PCB_REFERENCE_IMAGE* aBitmap, int aLayer ); void draw( const PCB_TEXT* aText, int aLayer ); void draw( const PCB_TEXTBOX* aText, int aLayer ); + void draw( const PCB_TABLE* aTable, int aLayer ); void draw( const FOOTPRINT* aFootprint, int aLayer ); void draw( const PCB_GROUP* aGroup, int aLayer ); void draw( const ZONE* aZone, int aLayer ); diff --git a/pcbnew/pcb_table.cpp b/pcbnew/pcb_table.cpp new file mode 100644 index 0000000000..42e42836ac --- /dev/null +++ b/pcbnew/pcb_table.cpp @@ -0,0 +1,450 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2024 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 +#include + + + +PCB_TABLE::PCB_TABLE( BOARD_ITEM* aParent, int aLineWidth ) : + BOARD_ITEM_CONTAINER( aParent, PCB_TABLE_T ), + m_strokeExternal( true ), + m_strokeHeader( true ), + m_borderStroke( aLineWidth, LINE_STYLE::DEFAULT, COLOR4D::UNSPECIFIED ), + m_strokeRows( true ), + m_strokeColumns( true ), + m_separatorsStroke( aLineWidth, LINE_STYLE::DEFAULT, COLOR4D::UNSPECIFIED ), + m_colCount( 0 ) +{ +} + + +PCB_TABLE::PCB_TABLE( const PCB_TABLE& aTable ) : + BOARD_ITEM_CONTAINER( aTable ) +{ + m_strokeExternal = aTable.m_strokeExternal; + m_strokeHeader = aTable.m_strokeHeader; + m_borderStroke = aTable.m_borderStroke; + m_strokeRows = aTable.m_strokeRows; + m_strokeColumns = aTable.m_strokeColumns; + m_separatorsStroke = aTable.m_separatorsStroke; + + m_colCount = aTable.m_colCount; + m_colWidths = aTable.m_colWidths; + m_rowHeights = aTable.m_rowHeights; + + for( PCB_TABLECELL* src : aTable.m_cells ) + AddCell( new PCB_TABLECELL( *src ) ); +} + + +PCB_TABLE::~PCB_TABLE() +{ + // We own our cells; delete them + for( PCB_TABLECELL* cell : m_cells ) + delete cell; +} + + +void PCB_TABLE::swapData( BOARD_ITEM* aImage ) +{ + wxCHECK_RET( aImage != nullptr && aImage->Type() == PCB_TABLE_T, + wxT( "Cannot swap data with invalid table." ) ); + + PCB_TABLE* table = static_cast( aImage ); + + std::swap( m_strokeExternal, table->m_strokeExternal ); + std::swap( m_strokeHeader, table->m_strokeHeader ); + std::swap( m_borderStroke, table->m_borderStroke ); + std::swap( m_strokeRows, table->m_strokeRows ); + std::swap( m_strokeColumns, table->m_strokeColumns ); + std::swap( m_separatorsStroke, table->m_separatorsStroke ); + + std::swap( m_colCount, table->m_colCount ); + std::swap( m_colWidths, table->m_colWidths ); + std::swap( m_rowHeights, table->m_rowHeights ); + + std::swap( m_cells, table->m_cells ); + + for( PCB_TABLECELL* cell : m_cells ) + cell->SetParent( this ); + + for( PCB_TABLECELL* cell : table->m_cells ) + cell->SetParent( table ); +} + + +void PCB_TABLE::SetPosition( const VECTOR2I& aPos ) +{ + Move( aPos - GetPosition() ); +} + + +VECTOR2I PCB_TABLE::GetPosition() const +{ + return m_cells[0]->GetPosition(); +} + + +VECTOR2I PCB_TABLE::GetEnd() const +{ + VECTOR2I tableSize; + + for( int ii = 0; ii < GetColCount(); ++ii ) + tableSize.x += GetColWidth( ii ); + + for( int ii = 0; ii < GetRowCount(); ++ii ) + tableSize.y += GetRowHeight( ii ); + + return GetPosition() + tableSize; +} + + +void PCB_TABLE::Normalize() +{ + // JEY TODO: pukes on rotated tables... + + int y = GetPosition().y; + + for( int row = 0; row < GetRowCount(); ++row ) + { + int x = GetPosition().x; + int rowHeight = m_rowHeights[ row ]; + + for( int col = 0; col < GetColCount(); ++col ) + { + int colWidth = m_colWidths[ col ]; + + PCB_TABLECELL* cell = GetCell( row, col ); + VECTOR2I pos( x, y ); + + if( cell->GetPosition() != pos ) + { + cell->SetPosition( pos ); + cell->ClearRenderCache(); + } + + VECTOR2I end = cell->GetStart() + VECTOR2I( colWidth, rowHeight ); + + if( cell->GetColSpan() > 1 || cell->GetRowSpan() > 1 ) + { + for( int ii = col + 1; ii < col + cell->GetColSpan(); ++ii ) + end.x += m_colWidths[ii]; + + for( int ii = row + 1; ii < row + cell->GetRowSpan(); ++ii ) + end.y += m_rowHeights[ii]; + } + + if( cell->GetEnd() != end ) + { + cell->SetEnd( end ); + cell->ClearRenderCache(); + } + + x += colWidth; + } + + y += rowHeight; + } +} + + +void PCB_TABLE::Move( const VECTOR2I& aMoveVector ) +{ + for( PCB_TABLECELL* cell : m_cells ) + cell->Move( aMoveVector ); +} + + +void PCB_TABLE::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle ) +{ + for( PCB_TABLECELL* cell : m_cells ) + cell->Rotate( aRotCentre, aAngle ); + + Normalize(); +} + + +void PCB_TABLE::Flip( const VECTOR2I& aCentre, bool aFlipLeftRight ) +{ + for( PCB_TABLECELL* cell : m_cells ) + cell->Flip( aCentre, aFlipLeftRight ); +} + + +void PCB_TABLE::RunOnChildren( const std::function& aFunction ) const +{ + for( PCB_TABLECELL* cell : m_cells ) + aFunction( cell ); +} + + +const BOX2I PCB_TABLE::GetBoundingBox() const +{ + // Note: a table with no cells is not allowed + BOX2I bbox = m_cells[0]->GetBoundingBox(); + + bbox.Merge( m_cells[ m_cells.size() - 1 ]->GetBoundingBox() ); + + return bbox; +} + + +void PCB_TABLE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, + int aClearance, int aMaxError, ERROR_LOC aErrorLoc, + bool aIgnoreLineWidth ) const +{ + for( PCB_TABLECELL* cell : m_cells ) + cell->TransformShapeToPolygon( aBuffer, aLayer, aClearance, aMaxError, aErrorLoc, false ); +} + + +INSPECT_RESULT PCB_TABLE::Visit( INSPECTOR aInspector, void* aTestData, + const std::vector& aScanTypes ) +{ + for( KICAD_T scanType : aScanTypes ) + { + if( scanType == PCB_TABLE_T ) + { + if( INSPECT_RESULT::QUIT == aInspector( this, aTestData ) ) + return INSPECT_RESULT::QUIT; + } + + if( scanType == PCB_TABLECELL_T ) + { + for( PCB_TABLECELL* cell : m_cells ) + { + if( INSPECT_RESULT::QUIT == aInspector( cell, (void*) this ) ) + return INSPECT_RESULT::QUIT; + } + } + } + + return INSPECT_RESULT::CONTINUE; +} + + +wxString PCB_TABLE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const +{ + return wxString::Format( _( "%d Column Table" ), m_colCount ); +} + + +BITMAPS PCB_TABLE::GetMenuImage() const +{ + return BITMAPS::spreadsheet; // JEY TODO +} + + +bool PCB_TABLE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const +{ + BOX2I rect = GetBoundingBox(); + + rect.Inflate( aAccuracy ); + + return rect.Contains( aPosition ); +} + + +bool PCB_TABLE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const +{ + BOX2I rect = aRect; + + rect.Inflate( aAccuracy ); + + if( aContained ) + return rect.Contains( GetBoundingBox() ); + + return rect.Intersects( GetBoundingBox() ); +} + + +void PCB_TABLE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector& aList ) +{ + // Don't use GetShownText() here; we want to show the user the variable references + aList.emplace_back( _( "Table" ), wxString::Format( _( "%d Columns" ), m_colCount ) ); +} + + +int PCB_TABLE::Compare( const PCB_TABLE* aTable, const PCB_TABLE* aOther ) +{ + int diff; + + if( ( diff = (int) aTable->GetCells().size() - (int) aOther->GetCells().size() ) != 0 ) + return diff; + + if( ( diff = aTable->GetColCount() - aOther->GetColCount() ) != 0 ) + return diff; + + for( int col = 0; col < aTable->GetColCount(); ++col ) + { + if( ( diff = aTable->GetColWidth( col ) - aOther->GetColWidth( col ) ) != 0 ) + return diff; + } + + for( int row = 0; row < aTable->GetRowCount(); ++row ) + { + if( ( diff = aTable->GetRowHeight( row ) - aOther->GetRowHeight( row ) ) != 0 ) + return diff; + } + + for( int row = 0; row < aTable->GetRowCount(); ++row ) + { + for( int col = 0; col < aTable->GetColCount(); ++col ) + { + PCB_TABLECELL* cell = aTable->GetCell( row, col ); + PCB_TABLECELL* other = aOther->GetCell( row, col ); + + if( ( diff = cell->PCB_SHAPE::Compare( other ) ) != 0 ) + return diff; + + if( ( diff = cell->EDA_TEXT::Compare( other ) ) != 0 ) + return diff; + } + } + + return 0; +} + + +bool PCB_TABLE::operator==( const BOARD_ITEM& aOther ) const +{ + if( Type() != aOther.Type() ) + return false; + + const PCB_TABLE& other = static_cast( aOther ); + + if( m_cells.size() != other.m_cells.size() ) + return false; + + if( m_colWidths != other.m_colWidths ) + return false; + + if( m_rowHeights != other.m_rowHeights ) + return false; + + for( int ii = 0; ii < (int) m_cells.size(); ++ii ) + { + if( !( *m_cells[ii] == *other.m_cells[ii] ) ) + return false; + } + + return true; +} + + +double PCB_TABLE::Similarity( const BOARD_ITEM& aOther ) const +{ + if( aOther.Type() != Type() ) + return 0.0; + + const PCB_TABLE& other = static_cast( aOther ); + + if( m_cells.size() != other.m_cells.size() ) + return 0.1; + + double similarity = 1.0; + + for( int ii = 0; ii < (int) m_cells.size(); ++ii ) + similarity *= m_cells[ii]->Similarity( *other.m_cells[ii] ); + + return similarity; +} + + +static struct PCB_TABLE_DESC +{ + PCB_TABLE_DESC() + { + ENUM_MAP& plotDashTypeEnum = ENUM_MAP::Instance(); + + if( plotDashTypeEnum.Choices().GetCount() == 0 ) + { + plotDashTypeEnum.Map( LINE_STYLE::DEFAULT, _HKI( "Default" ) ) + .Map( LINE_STYLE::SOLID, _HKI( "Solid" ) ) + .Map( LINE_STYLE::DASH, _HKI( "Dashed" ) ) + .Map( LINE_STYLE::DOT, _HKI( "Dotted" ) ) + .Map( LINE_STYLE::DASHDOT, _HKI( "Dash-Dot" ) ) + .Map( LINE_STYLE::DASHDOTDOT, _HKI( "Dash-Dot-Dot" ) ); + } + + PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance(); + REGISTER_TYPE( PCB_TABLE ); + + propMgr.AddTypeCast( new TYPE_CAST ); + propMgr.AddTypeCast( new TYPE_CAST ); + propMgr.InheritsAfter( TYPE_HASH( PCB_TABLE ), TYPE_HASH( BOARD_ITEM ) ); + propMgr.InheritsAfter( TYPE_HASH( PCB_TABLE ), TYPE_HASH( BOARD_ITEM_CONTAINER ) ); + + propMgr.AddProperty( new PROPERTY( _HKI( "Start X" ), + &PCB_TABLE::SetPositionX, &PCB_TABLE::GetPositionX, PROPERTY_DISPLAY::PT_COORD, + ORIGIN_TRANSFORMS::ABS_X_COORD ) ); + propMgr.AddProperty( new PROPERTY( _HKI( "Start Y" ), + &PCB_TABLE::SetPositionY, &PCB_TABLE::GetPositionY, PROPERTY_DISPLAY::PT_COORD, + ORIGIN_TRANSFORMS::ABS_Y_COORD ) ); + + const wxString tableProps = _( "Table Properties" ); + + propMgr.AddProperty( new PROPERTY( _HKI( "External Border" ), + &PCB_TABLE::SetStrokeExternal, &PCB_TABLE::StrokeExternal ), + tableProps ); + + propMgr.AddProperty( new PROPERTY( _HKI( "Header Border" ), + &PCB_TABLE::SetStrokeHeader, &PCB_TABLE::StrokeHeader ), + tableProps ); + + propMgr.AddProperty( new PROPERTY( _HKI( "Border Width" ), + &PCB_TABLE::SetBorderWidth, &PCB_TABLE::GetBorderWidth, + PROPERTY_DISPLAY::PT_SIZE ), + tableProps ); + + propMgr.AddProperty( new PROPERTY_ENUM( _HKI( "Border Style" ), + &PCB_TABLE::SetBorderStyle, &PCB_TABLE::GetBorderStyle ), + tableProps ); + + propMgr.AddProperty( new PROPERTY( _HKI( "Border Color" ), + &PCB_TABLE::SetBorderColor, &PCB_TABLE::GetBorderColor ), + tableProps ); + + propMgr.AddProperty( new PROPERTY( _HKI( "Row Separators" ), + &PCB_TABLE::SetStrokeRows, &PCB_TABLE::StrokeRows ), + tableProps ); + + propMgr.AddProperty( new PROPERTY( _HKI( "Cell Separators" ), + &PCB_TABLE::SetStrokeColumns, &PCB_TABLE::StrokeColumns ), + tableProps ); + + propMgr.AddProperty( new PROPERTY( _HKI( "Separators Width" ), + &PCB_TABLE::SetSeparatorsWidth, &PCB_TABLE::GetSeparatorsWidth, + PROPERTY_DISPLAY::PT_SIZE ), + tableProps ); + + propMgr.AddProperty( new PROPERTY_ENUM( _HKI( "Separators Style" ), + &PCB_TABLE::SetSeparatorsStyle, &PCB_TABLE::GetSeparatorsStyle ), + tableProps ); + + propMgr.AddProperty( new PROPERTY( _HKI( "Separators Color" ), + &PCB_TABLE::SetSeparatorsColor, &PCB_TABLE::GetSeparatorsColor ), + tableProps ); + } +} _PCB_TABLE_DESC; diff --git a/pcbnew/pcb_table.h b/pcbnew/pcb_table.h new file mode 100644 index 0000000000..66b6f2dadc --- /dev/null +++ b/pcbnew/pcb_table.h @@ -0,0 +1,250 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2024 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 PCB_TABLE_H +#define PCB_TABLE_H + + +#include +#include + + +class PCB_TABLE : public BOARD_ITEM_CONTAINER +{ +public: + PCB_TABLE( BOARD_ITEM* aParent, int aLineWidth ); + + PCB_TABLE( const PCB_TABLE& aTable ); + + ~PCB_TABLE(); + + static inline bool ClassOf( const EDA_ITEM* aItem ) + { + return aItem && PCB_TABLE_T == aItem->Type(); + } + + virtual wxString GetClass() const override + { + return wxT( "PCB_TABLE" ); + } + + void SetStrokeExternal( bool aDoStroke ) { m_strokeExternal = aDoStroke; } + bool StrokeExternal() const { return m_strokeExternal; } + + void SetStrokeHeader( bool aDoStroke ) { m_strokeHeader = aDoStroke; } + bool StrokeHeader() const { return m_strokeHeader; } + + void SetBorderStroke( const STROKE_PARAMS& aParams ) { m_borderStroke = aParams; } + const STROKE_PARAMS& GetBorderStroke() const { return m_borderStroke; } + + void SetBorderWidth( int aWidth ) { m_borderStroke.SetWidth( aWidth ); } + int GetBorderWidth() const { return m_borderStroke.GetWidth(); } + + void SetBorderStyle( const LINE_STYLE aStyle ) { m_borderStroke.SetLineStyle( aStyle ); } + LINE_STYLE GetBorderStyle() const { return m_borderStroke.GetLineStyle(); } + + void SetBorderColor( const COLOR4D& aColor ) { m_borderStroke.SetColor( aColor ); } + COLOR4D GetBorderColor() const { return m_borderStroke.GetColor(); } + + void SetSeparatorsStroke( const STROKE_PARAMS& aParams ) { m_separatorsStroke = aParams; } + const STROKE_PARAMS& GetSeparatorsStroke() const { return m_separatorsStroke; } + + void SetSeparatorsWidth( int aWidth ) { m_separatorsStroke.SetWidth( aWidth ); } + int GetSeparatorsWidth() const { return m_separatorsStroke.GetWidth(); } + + void SetSeparatorsStyle( const LINE_STYLE aStyle ) { m_separatorsStroke.SetLineStyle( aStyle ); } + LINE_STYLE GetSeparatorsStyle() const { return m_separatorsStroke.GetLineStyle(); } + + void SetSeparatorsColor( const COLOR4D& aColor ) { m_separatorsStroke.SetColor( aColor ); } + COLOR4D GetSeparatorsColor() const { return m_separatorsStroke.GetColor(); } + + void SetStrokeColumns( bool aDoStroke ) { m_strokeColumns = aDoStroke; } + bool StrokeColumns() const { return m_strokeColumns; } + + void SetStrokeRows( bool aDoStroke ) { m_strokeRows = aDoStroke; } + bool StrokeRows() const { return m_strokeRows; } + + void RunOnChildren( const std::function& aFunction ) const override; + + void SetPosition( const VECTOR2I& aPos ) override; + VECTOR2I GetPosition() const override; + VECTOR2I GetEnd() const; + + // For property manager: + void SetPositionX( int x ) { SetPosition( VECTOR2I( x, GetPosition().y ) ); } + void SetPositionY( int y ) { SetPosition( VECTOR2I( GetPosition().x, y ) ); } + int GetPositionX() const { return GetPosition().x; } + int GetPositionY() const { return GetPosition().y; } + + void SetColCount( int aCount ) { m_colCount = aCount; } + int GetColCount() const { return m_colCount; } + + int GetRowCount() const + { + return m_cells.size() / m_colCount; + } + + void SetColWidth( int aCol, int aWidth ) { m_colWidths[aCol] = aWidth; } + + int GetColWidth( int aCol ) const + { + if( m_colWidths.count( aCol ) ) + return m_colWidths.at( aCol ); + + return 0; + } + + void SetRowHeight( int aRow, int aHeight ) { m_rowHeights[aRow] = aHeight; } + + int GetRowHeight( int aRow ) const + { + if( m_rowHeights.count( aRow ) ) + return m_rowHeights.at( aRow ); + + return 0; + } + + PCB_TABLECELL* GetCell( int aRow, int aCol ) const + { + int idx = aRow * m_colCount + aCol; + + if( idx < (int) m_cells.size() ) + return m_cells[ idx ]; + else + return nullptr; + } + + std::vector GetCells() const + { + return m_cells; + } + + void AddCell( PCB_TABLECELL* aCell ) + { + m_cells.push_back( aCell ); + aCell->SetLayer( GetLayer() ); + aCell->SetParent( this ); + } + + void InsertCell( int aIdx, PCB_TABLECELL* aCell ) + { + m_cells.insert( m_cells.begin() + aIdx, aCell ); + aCell->SetLayer( GetLayer() ); + aCell->SetParent( this ); + } + + void ClearCells() + { + for( PCB_TABLECELL* cell : m_cells ) + delete cell; + + m_cells.clear(); + } + + void DeleteMarkedCells() + { + alg::delete_if( m_cells, + []( PCB_TABLECELL* cell ) + { + return ( cell->GetFlags() & STRUCT_DELETED ) > 0; + } ); + } + + void Add( BOARD_ITEM* aItem, ADD_MODE aMode = ADD_MODE::INSERT, + bool aSkipConnectivity = false ) override + { + wxFAIL_MSG( wxT( "Use AddCell()/InsertCell() instead." ) ); + } + + void Remove( BOARD_ITEM* aItem, REMOVE_MODE aMode = REMOVE_MODE::NORMAL ) override + { + wxFAIL_MSG( wxT( "Use DeleteMarkedCells() instead." ) ); + } + + void Normalize() override; + + void Move( const VECTOR2I& aMoveVector ) override; + + void Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle ) override; + + void Flip( const VECTOR2I& aCentre, bool aFlipLeftRight ) override; + + const BOX2I GetBoundingBox() const override; + + void TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance, + int aMaxError, ERROR_LOC aErrorLoc, + bool aIgnoreLineWidth = false ) const override; + + INSPECT_RESULT Visit( INSPECTOR inspector, void* testData, + const std::vector& aScanTypes ) override; + + bool Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const override + { + // Symbols are searchable via the child field and pin item text. + return false; + } + + wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const override; + + BITMAPS GetMenuImage() const override; + + bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override; + + bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override; + + EDA_ITEM* Clone() const override + { + return new PCB_TABLE( *this ); + } + + void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector& aList ) override; + + double Similarity( const BOARD_ITEM& aOther ) const override; + + bool operator==( const BOARD_ITEM& aOther ) const override; + + static int Compare( const PCB_TABLE* aTable, const PCB_TABLE* aOther ); + +#if defined(DEBUG) + void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); } +#endif + +protected: + virtual void swapData( BOARD_ITEM* aImage ) override; + +protected: + bool m_strokeExternal; + bool m_strokeHeader; + STROKE_PARAMS m_borderStroke; + bool m_strokeRows; + bool m_strokeColumns; + STROKE_PARAMS m_separatorsStroke; + + int m_colCount; + std::map m_colWidths; + std::map m_rowHeights; + std::vector m_cells; +}; + + +#endif /* PCB_TABLE_H */ diff --git a/pcbnew/pcb_tablecell.cpp b/pcbnew/pcb_tablecell.cpp new file mode 100644 index 0000000000..0754b3429b --- /dev/null +++ b/pcbnew/pcb_tablecell.cpp @@ -0,0 +1,192 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2024 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 +#include +#include +#include +#include +#include + + +PCB_TABLECELL::PCB_TABLECELL( BOARD_ITEM* aParent ) : + PCB_TEXTBOX( aParent, PCB_TABLECELL_T ), + m_colSpan( 1 ), + m_rowSpan( 1 ) +{ +} + + +void PCB_TABLECELL::swapData( BOARD_ITEM* aImage ) +{ + wxASSERT( aImage->Type() == PCB_TABLECELL_T ); + + std::swap( *((PCB_TABLECELL*) this), *((PCB_TABLECELL*) aImage) ); +} + + +wxString PCB_TABLECELL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const +{ + return wxString::Format( _( "Table Cell %s" ), GetAddr() ); +} + + +int PCB_TABLECELL::GetRow() const +{ + const PCB_TABLE* table = static_cast( GetParent() ); + + for( int row = 0; row < table->GetRowCount(); ++row ) + { + for( int col = 0; col < table->GetColCount(); ++col ) + { + if( table->GetCell( row, col ) == this ) + return row; + } + } + + return -1; +} + + +int PCB_TABLECELL::GetColumn() const +{ + const PCB_TABLE* table = static_cast( GetParent() ); + + for( int row = 0; row < table->GetRowCount(); ++row ) + { + for( int col = 0; col < table->GetColCount(); ++col ) + { + if( table->GetCell( row, col ) == this ) + return col; + } + } + + return -1; +} + + +wxString PCB_TABLECELL::GetAddr() const +{ + return wxString::Format( wxT( "%c%d" ), + 'A' + GetColumn() % 26, + GetRow() + 1 ); +} + + +void PCB_TABLECELL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector& aList ) +{ + aList.emplace_back( _( "Table Cell" ), GetAddr() ); + + // Don't use GetShownText() here; we want to show the user the variable references + aList.emplace_back( _( "Text" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) ); + + if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() ) + aList.emplace_back( _( "Status" ), _( "Locked" ) ); + + aList.emplace_back( _( "Layer" ), GetLayerName() ); + aList.emplace_back( _( "Mirror" ), IsMirrored() ? _( "Yes" ) : _( "No" ) ); + + aList.emplace_back( _( "Cell Width" ), + aFrame->MessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) ) ); + aList.emplace_back( _( "Cell Height" ), + aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) ) ); + + aList.emplace_back( _( "Font" ), GetFont() ? GetFont()->GetName() : _( "Default" ) ); + aList.emplace_back( _( "Text Thickness" ), aFrame->MessageTextFromValue( GetTextThickness() ) ); + aList.emplace_back( _( "Text Width" ), aFrame->MessageTextFromValue( GetTextWidth() ) ); + aList.emplace_back( _( "Text Height" ), aFrame->MessageTextFromValue( GetTextHeight() ) ); +} + + +double PCB_TABLECELL::Similarity( const BOARD_ITEM& aBoardItem ) const +{ + if( aBoardItem.Type() != Type() ) + return 0.0; + + const PCB_TABLECELL& other = static_cast( aBoardItem ); + + double similarity = 1.0; + + if( m_colSpan != other.m_colSpan ) + similarity *= 0.9; + + if( m_rowSpan != other.m_rowSpan ) + similarity *= 0.9; + + similarity *= PCB_TEXTBOX::Similarity( other ); + + return similarity; +} + + +bool PCB_TABLECELL::operator==( const BOARD_ITEM& aBoardItem ) const +{ + if( aBoardItem.Type() != Type() ) + return false; + + const PCB_TABLECELL& other = static_cast( aBoardItem ); + + return m_colSpan == other.m_colSpan + && m_rowSpan == other.m_rowSpan + && PCB_TEXTBOX::operator==( other ); +} + + + +static struct PCB_TABLECELL_DESC +{ + PCB_TABLECELL_DESC() + { + PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance(); + REGISTER_TYPE( PCB_TABLECELL ); + + propMgr.AddTypeCast( new TYPE_CAST ); + propMgr.AddTypeCast( new TYPE_CAST ); + propMgr.AddTypeCast( new TYPE_CAST ); + propMgr.AddTypeCast( new TYPE_CAST ); + propMgr.InheritsAfter( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( PCB_TEXTBOX ) ); + propMgr.InheritsAfter( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( PCB_SHAPE ) ); + propMgr.InheritsAfter( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_SHAPE ) ); + propMgr.InheritsAfter( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_TEXT ) ); + + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( PCB_TEXTBOX ), _HKI( "Border" ) ); + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( PCB_TEXTBOX ), _HKI( "Border Style" ) ); + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( PCB_TEXTBOX ), _HKI( "Border Width" ) ); + + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Start X" ) ); + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Start Y" ) ); + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "End X" ) ); + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "End Y" ) ); + + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Shape" ) ); + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Width" ) ); + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Style" ) ); + + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Visible" ) ); + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Width" ) ); + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Height" ) ); + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Thickness" ) ); + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Orientation" ) ); + propMgr.Mask( TYPE_HASH( PCB_TABLECELL ), TYPE_HASH( EDA_TEXT ), _HKI( "Hyperlink" ) ); + } +} _PCB_TABLECELL_DESC; diff --git a/pcbnew/pcb_tablecell.h b/pcbnew/pcb_tablecell.h new file mode 100644 index 0000000000..e98c9e4dec --- /dev/null +++ b/pcbnew/pcb_tablecell.h @@ -0,0 +1,85 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2024 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 PCB_TABLECELL_H +#define PCB_TABLECELL_H + + +#include + + +class PCB_TABLECELL : public PCB_TEXTBOX +{ +public: + PCB_TABLECELL( BOARD_ITEM* parent ); + + static inline bool ClassOf( const EDA_ITEM* aItem ) + { + return aItem && PCB_TABLECELL_T == aItem->Type(); + } + + wxString GetClass() const override + { + return wxT( "PCB_TABLECELL" ); + } + + virtual wxString GetFriendlyName() const override + { + return _( "Table Cell" ); + } + + EDA_ITEM* Clone() const override + { + return new PCB_TABLECELL( *this ); + } + + int GetRow() const; + int GetColumn() const; + + // @return the spreadsheet nomenclature for the cell (ie: B3 for 2nd column, 3rd row) + wxString GetAddr() const; + + int GetColSpan() const { return m_colSpan; } + void SetColSpan( int aSpan ) { m_colSpan = aSpan; } + + int GetRowSpan() const { return m_rowSpan; } + void SetRowSpan( int aSpan ) { m_rowSpan = aSpan; } + + wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const override; + + void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector& aList ) override; + + double Similarity( const BOARD_ITEM& aBoardItem ) const override; + + bool operator==( const BOARD_ITEM& aBoardItem ) const override; + +protected: + virtual void swapData( BOARD_ITEM* aImage ) override; + +protected: + int m_colSpan; + int m_rowSpan; +}; + + +#endif /* PCB_TABLECELL_H */ diff --git a/pcbnew/pcb_textbox.cpp b/pcbnew/pcb_textbox.cpp index 53b2e3877a..fab742ed3a 100644 --- a/pcbnew/pcb_textbox.cpp +++ b/pcbnew/pcb_textbox.cpp @@ -38,8 +38,8 @@ #include -PCB_TEXTBOX::PCB_TEXTBOX( BOARD_ITEM* parent ) : - PCB_SHAPE( parent, PCB_TEXTBOX_T, SHAPE_T::RECTANGLE ), +PCB_TEXTBOX::PCB_TEXTBOX( BOARD_ITEM* aParent, KICAD_T aType ) : + PCB_SHAPE( aParent, aType, SHAPE_T::RECTANGLE ), EDA_TEXT( pcbIUScale ), m_borderEnabled( true ) { @@ -485,7 +485,7 @@ EDA_ITEM* PCB_TEXTBOX::Clone() const void PCB_TEXTBOX::swapData( BOARD_ITEM* aImage ) { - assert( aImage->Type() == PCB_TEXTBOX_T ); + wxASSERT( aImage->Type() == PCB_TEXTBOX_T ); std::swap( *((PCB_TEXTBOX*) this), *((PCB_TEXTBOX*) aImage) ); } diff --git a/pcbnew/pcb_textbox.h b/pcbnew/pcb_textbox.h index 65424dc7e9..de5240e4c2 100644 --- a/pcbnew/pcb_textbox.h +++ b/pcbnew/pcb_textbox.h @@ -36,7 +36,7 @@ class MSG_PANEL_ITEM; class PCB_TEXTBOX : public PCB_SHAPE, public EDA_TEXT { public: - PCB_TEXTBOX( BOARD_ITEM* parent ); + PCB_TEXTBOX( BOARD_ITEM* aParent, KICAD_T aType = PCB_TEXTBOX_T ); // Do not create a copy constructor & operator=. // The ones generated by the compiler are adequate. diff --git a/pcbnew/pcb_view.cpp b/pcbnew/pcb_view.cpp index c30d7b0cfd..3107d264f5 100644 --- a/pcbnew/pcb_view.cpp +++ b/pcbnew/pcb_view.cpp @@ -76,11 +76,18 @@ void PCB_VIEW::Update( const KIGFX::VIEW_ITEM* aItem, int aUpdateFlags ) const { if( const BOARD_ITEM* boardItem = dynamic_cast( aItem ) ) { - boardItem->RunOnChildren( - [this, aUpdateFlags]( BOARD_ITEM* child ) - { - VIEW::Update( child, aUpdateFlags ); - } ); + if( boardItem->Type() == PCB_TABLECELL_T ) + { + VIEW::Update( boardItem->GetParent() ); + } + else + { + boardItem->RunOnChildren( + [this, aUpdateFlags]( BOARD_ITEM* child ) + { + VIEW::Update( child, aUpdateFlags ); + } ); + } } VIEW::Update( aItem, aUpdateFlags ); diff --git a/pcbnew/toolbars_footprint_editor.cpp b/pcbnew/toolbars_footprint_editor.cpp index 375c7e98ae..3b0f3c0f8a 100644 --- a/pcbnew/toolbars_footprint_editor.cpp +++ b/pcbnew/toolbars_footprint_editor.cpp @@ -187,6 +187,7 @@ void FOOTPRINT_EDIT_FRAME::ReCreateVToolbar() m_drawToolBar->Add( PCB_ACTIONS::placeReferenceImage, ACTION_TOOLBAR::TOGGLE ); m_drawToolBar->Add( PCB_ACTIONS::placeText, ACTION_TOOLBAR::TOGGLE ); m_drawToolBar->Add( PCB_ACTIONS::drawTextBox, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::drawTable, ACTION_TOOLBAR::TOGGLE ); m_drawToolBar->AddGroup( dimensionGroup, ACTION_TOOLBAR::TOGGLE ); m_drawToolBar->Add( ACTIONS::deleteTool, ACTION_TOOLBAR::TOGGLE ); diff --git a/pcbnew/toolbars_pcb_editor.cpp b/pcbnew/toolbars_pcb_editor.cpp index 6a1e5d836d..380192f863 100644 --- a/pcbnew/toolbars_pcb_editor.cpp +++ b/pcbnew/toolbars_pcb_editor.cpp @@ -441,6 +441,7 @@ void PCB_EDIT_FRAME::ReCreateVToolbar() m_drawToolBar->Add( PCB_ACTIONS::placeReferenceImage, ACTION_TOOLBAR::TOGGLE ); m_drawToolBar->Add( PCB_ACTIONS::placeText, ACTION_TOOLBAR::TOGGLE ); m_drawToolBar->Add( PCB_ACTIONS::drawTextBox, ACTION_TOOLBAR::TOGGLE ); + m_drawToolBar->Add( PCB_ACTIONS::drawTable, ACTION_TOOLBAR::TOGGLE ); m_drawToolBar->AddGroup( dimensionGroup, ACTION_TOOLBAR::TOGGLE ); m_drawToolBar->Add( ACTIONS::deleteTool, ACTION_TOOLBAR::TOGGLE ); diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp index 6ad79ce77d..c3717a5269 100644 --- a/pcbnew/tools/drawing_tool.cpp +++ b/pcbnew/tools/drawing_tool.cpp @@ -66,6 +66,8 @@ #include #include #include +#include +#include #include #include #include @@ -562,6 +564,7 @@ int DRAWING_TOOL::PlaceReferenceImage( const TOOL_EVENT& aEvent ) } m_frame->PushTool( aEvent ); + auto setCursor = [&]() { @@ -796,6 +799,15 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent ) SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::TEXT ); PCB_GRID_HELPER grid( m_toolMgr, m_frame->GetMagneticItemsSettings() ); + auto setCursor = + [&]() + { + if( text ) + m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::MOVING ); + else + m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::TEXT ); + }; + auto cleanup = [&]() { @@ -808,15 +820,6 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent ) text = nullptr; }; - auto setCursor = - [&]() - { - if( text ) - m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::MOVING ); - else - m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::TEXT ); - }; - m_toolMgr->RunAction( PCB_ACTIONS::selectionClear ); m_frame->PushTool( aEvent ); @@ -1026,6 +1029,218 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent ) } +int DRAWING_TOOL::DrawTable( const TOOL_EVENT& aEvent ) +{ + if( m_inDrawingTool ) + return 0; + + REENTRANCY_GUARD guard( &m_inDrawingTool ); + + COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings(); + PCB_TABLE* table = nullptr; + const BOARD_DESIGN_SETTINGS& bds = m_frame->GetDesignSettings(); + BOARD_COMMIT commit( m_frame ); + PCB_GRID_HELPER grid( m_toolMgr, m_frame->GetMagneticItemsSettings() ); + + // We might be running as the same shape in another co-routine. Make sure that one + // gets whacked. + m_toolMgr->DeactivateTool(); + + auto setCursor = + [&]() + { + if( table ) + m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::MOVING ); + else + m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL ); + }; + + auto cleanup = + [&] () + { + m_toolMgr->RunAction( PCB_ACTIONS::selectionClear ); + m_controls->ForceCursorPosition( false ); + m_controls->ShowCursor( true ); + m_controls->SetAutoPan( false ); + m_controls->CaptureCursor( false ); + delete table; + table = nullptr; + }; + + m_toolMgr->RunAction( PCB_ACTIONS::selectionClear ); + + m_frame->PushTool( aEvent ); + + Activate(); + // Must be done after Activate() so that it gets set into the correct context + getViewControls()->ShowCursor( true ); + m_controls->ForceCursorPosition( false ); + // Set initial cursor + setCursor(); + + if( aEvent.HasPosition() ) + m_toolMgr->PrimeTool( aEvent.Position() ); + else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() ) + m_toolMgr->PrimeTool( { 0, 0 } ); + + // Main loop: keep receiving events + while( TOOL_EVENT* evt = Wait() ) + { + setCursor(); + grid.SetSnap( !evt->Modifier( MD_SHIFT ) ); + grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() ); + VECTOR2I cursorPos = + GetClampedCoords( grid.BestSnapAnchor( m_controls->GetMousePosition(), + m_frame->GetActiveLayer(), GRID_TEXT ), + COORDS_PADDING ); + m_controls->ForceCursorPosition( true, cursorPos ); + + if( evt->IsCancelInteractive() || ( table && evt->IsAction( &ACTIONS::undo ) ) ) + { + if( table ) + { + cleanup(); + } + else + { + m_frame->PopTool( aEvent ); + break; + } + } + else if( evt->IsActivate() ) + { + if( table ) + cleanup(); + + if( evt->IsMoveTool() ) + { + // leave ourselves on the stack so we come back after the move + break; + } + else + { + m_frame->PopTool( aEvent ); + break; + } + } + else if( evt->IsClick( BUT_RIGHT ) ) + { + // Warp after context menu only if dragging... + if( !table ) + m_toolMgr->VetoContextMenuMouseWarp(); + + m_menu.ShowContextMenu( selection() ); + } + else if( evt->IsClick( BUT_LEFT ) ) + { + if( !table ) + { + m_toolMgr->RunAction( PCB_ACTIONS::selectionClear ); + + PCB_LAYER_ID layer = m_frame->GetActiveLayer(); + + table = new PCB_TABLE( m_frame->GetModel(), bds.GetLineThickness( layer ) ); + table->SetColCount( 1 ); + table->AddCell( new PCB_TABLECELL( table ) ); + + table->SetLayer( layer ); + table->SetPosition( cursorPos ); + + if( !m_view->IsLayerVisible( layer ) ) + { + m_frame->GetAppearancePanel()->SetLayerVisible( layer, true ); + m_frame->GetCanvas()->Refresh(); + } + + m_toolMgr->RunAction( PCB_ACTIONS::selectItem, table ); + m_view->Update( &selection() ); + + // update the cursor so it looks correct before another event + setCursor(); + } + else + { + table->ClearFlags(); + m_toolMgr->RunAction( PCB_ACTIONS::selectionClear ); + + table->Normalize(); + + commit.Add( table, m_frame->GetScreen() ); + commit.Push( _( "Draw Table" ) ); + + m_toolMgr->RunAction( PCB_ACTIONS::selectItem, table ); + table = nullptr; + + m_toolMgr->PostAction( ACTIONS::activatePointEditor ); + } + } + else if( table && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) ) + { + VECTOR2I fontSize = bds.GetTextSize( table->GetLayer() ); + VECTOR2I gridSize = grid.GetGridSize( grid.GetItemGrid( table ) ); + VECTOR2I origin( table->GetPosition() ); + VECTOR2I requestedSize( cursorPos - origin ); + + int colCount = std::max( 1, requestedSize.x / ( fontSize.x * 15 ) ); + int rowCount = std::max( 1, requestedSize.y / ( fontSize.y * 3 ) ); + + VECTOR2I cellSize( std::max( fontSize.x * 5, requestedSize.x / colCount ), + std::max( fontSize.y * 3, requestedSize.y / rowCount ) ); + + cellSize.x = KiROUND( (double) cellSize.x / gridSize.x ) * gridSize.x; + cellSize.y = KiROUND( (double) cellSize.y / gridSize.y ) * gridSize.y; + + table->ClearCells(); + table->SetColCount( colCount ); + + for( int col = 0; col < colCount; ++col ) + table->SetColWidth( col, cellSize.x ); + + for( int row = 0; row < rowCount; ++row ) + { + table->SetRowHeight( row, cellSize.y ); + + for( int col = 0; col < colCount; ++col ) + { + PCB_TABLECELL* cell = new PCB_TABLECELL( table ); + cell->SetPosition( origin + VECTOR2I( col * cellSize.x, row * cellSize.y ) ); + cell->SetEnd( cell->GetPosition() + cellSize ); + table->AddCell( cell ); + } + } + + selection().SetReferencePoint( cursorPos ); + m_view->Update( &selection() ); + m_frame->SetMsgPanel( table ); + } + else if( table && evt->IsAction( &PCB_ACTIONS::properties ) ) + { + frame()->OnEditItemRequest( table ); + m_view->Update( &selection() ); + frame()->SetMsgPanel( table ); + } + else if( table && ( ZONE_FILLER_TOOL::IsZoneFillAction( evt ) + || evt->IsAction( &ACTIONS::redo ) ) ) + { + wxBell(); + } + else + { + evt->SetPassEvent(); + } + + // Enable autopanning and cursor capture only when there is a shape being drawn + getViewControls()->SetAutoPan( table != nullptr ); + getViewControls()->CaptureCursor( table != nullptr ); + } + + getViewControls()->SetAutoPan( false ); + getViewControls()->CaptureCursor( false ); + m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW ); + return 0; +} + + void DRAWING_TOOL::constrainDimension( PCB_DIMENSION_BASE* aDim ) { const VECTOR2I lineVector{ aDim->GetEnd() - aDim->GetStart() }; @@ -3457,6 +3672,7 @@ void DRAWING_TOOL::setTransitions() Go( &DRAWING_TOOL::DrawVia, PCB_ACTIONS::drawVia.MakeEvent() ); Go( &DRAWING_TOOL::PlaceReferenceImage, PCB_ACTIONS::placeReferenceImage.MakeEvent() ); Go( &DRAWING_TOOL::PlaceText, PCB_ACTIONS::placeText.MakeEvent() ); + Go( &DRAWING_TOOL::DrawTable, PCB_ACTIONS::drawTable.MakeEvent() ); Go( &DRAWING_TOOL::DrawRectangle, PCB_ACTIONS::drawTextBox.MakeEvent() ); Go( &DRAWING_TOOL::PlaceImportedGraphics, PCB_ACTIONS::placeImportedGraphics.MakeEvent() ); Go( &DRAWING_TOOL::SetAnchor, PCB_ACTIONS::setAnchor.MakeEvent() ); diff --git a/pcbnew/tools/drawing_tool.h b/pcbnew/tools/drawing_tool.h index 2827655121..5047dce913 100644 --- a/pcbnew/tools/drawing_tool.h +++ b/pcbnew/tools/drawing_tool.h @@ -157,6 +157,11 @@ public: */ int PlaceText( const TOOL_EVENT& aEvent ); + /* + * Start interactively drawing a table (rows & columns of TEXTBOXes). + */ + int DrawTable( const TOOL_EVENT& aEvent ); + /** * Start interactively drawing a dimension. * diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index 7bf43c7a57..85469cf9f0 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -1733,6 +1734,7 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent ) { sTool->FilterCollectorForHierarchy( aCollector, true ); sTool->FilterCollectorForMarkers( aCollector ); + sTool->FilterCollectorForTableCells( aCollector ); }, // Prompt user regarding locked items if in board editor and in free-pad-mode (if // we're not in free-pad mode we delay this until the second RequestSelection()). @@ -1758,6 +1760,7 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent ) sTool->FilterCollectorForMarkers( aCollector ); sTool->FilterCollectorForHierarchy( aCollector, true ); sTool->FilterCollectorForFreePads( aCollector ); + sTool->FilterCollectorForTableCells( aCollector ); }, true /* prompt user regarding locked items */ ); } @@ -1997,6 +2000,10 @@ int EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent ) static_cast( item )->Mirror( mirrorPoint, mirrorAroundXaxis ); break; + case PCB_TABLE_T: + // JEY TODO: tables + break; + case PCB_PAD_T: if( mirrorLeftRight ) mirrorPadX( *static_cast( item ), mirrorPoint ); @@ -2129,6 +2136,7 @@ int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent ) sTool->FilterCollectorForMarkers( aCollector ); sTool->FilterCollectorForHierarchy( aCollector, true ); sTool->FilterCollectorForFreePads( aCollector ); + sTool->FilterCollectorForTableCells( aCollector ); }, !m_dragging /* prompt user regarding locked items */ ); @@ -2215,6 +2223,7 @@ void EDIT_TOOL::DeleteItems( const PCB_SELECTION& aItems, bool aIsCut ) case PCB_TEXT_T: case PCB_SHAPE_T: case PCB_TEXTBOX_T: + case PCB_TABLE_T: case PCB_REFERENCE_IMAGE_T: case PCB_DIMENSION_T: case PCB_DIM_ALIGNED_T: @@ -2225,6 +2234,12 @@ void EDIT_TOOL::DeleteItems( const PCB_SELECTION& aItems, bool aIsCut ) commit.Remove( board_item ); break; + case PCB_TABLECELL_T: + // Clear contents of table cell + commit.Modify( board_item ); + static_cast( board_item )->SetText( wxEmptyString ); + break; + case PCB_GROUP_T: board_item->RunOnDescendants( [&commit]( BOARD_ITEM* aItem ) @@ -2415,6 +2430,7 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent ) { sTool->FilterCollectorForMarkers( aCollector ); sTool->FilterCollectorForHierarchy( aCollector, true ); + sTool->FilterCollectorForTableCells( aCollector ); }, true /* prompt user regarding locked items */ ); @@ -2509,6 +2525,7 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent ) sTool->FilterCollectorForFreePads( aCollector, true ); sTool->FilterCollectorForMarkers( aCollector ); sTool->FilterCollectorForHierarchy( aCollector, true ); + sTool->FilterCollectorForTableCells( aCollector ); } ); if( selection.Empty() ) @@ -2599,6 +2616,10 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent ) commit.Add( dupe_item ); break; + case PCB_TABLE_T: + // JEY TODO: tables + break; + case PCB_GENERATOR_T: case PCB_GROUP_T: dupe_item = static_cast( orig_item )->DeepDuplicate(); diff --git a/pcbnew/tools/edit_tool_move_fct.cpp b/pcbnew/tools/edit_tool_move_fct.cpp index da911ebe06..103b731213 100644 --- a/pcbnew/tools/edit_tool_move_fct.cpp +++ b/pcbnew/tools/edit_tool_move_fct.cpp @@ -299,6 +299,7 @@ bool EDIT_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, BOARD_COMMIT* aCommit sTool->FilterCollectorForMarkers( aCollector ); sTool->FilterCollectorForHierarchy( aCollector, true ); sTool->FilterCollectorForFreePads( aCollector ); + sTool->FilterCollectorForTableCells( aCollector ); }, true /* prompt user regarding locked items */ ); diff --git a/pcbnew/tools/pcb_actions.cpp b/pcbnew/tools/pcb_actions.cpp index 299265059e..b210ed341d 100644 --- a/pcbnew/tools/pcb_actions.cpp +++ b/pcbnew/tools/pcb_actions.cpp @@ -180,10 +180,18 @@ TOOL_ACTION PCB_ACTIONS::drawTextBox( TOOL_ACTION_ARGS() .Name( "pcbnew.InteractiveDrawing.textbox" ) .Scope( AS_GLOBAL ) .FriendlyName( _( "Add Text Box" ) ) - .Tooltip( _( "Add a wrapped text item" ) ) + .Tooltip( _( "Add a line-wrapped text item" ) ) .Icon( BITMAPS::add_textbox ) .Flags( AF_ACTIVATE ) ); +TOOL_ACTION PCB_ACTIONS::drawTable( TOOL_ACTION_ARGS() + .Name( "pcbnew.InteractiveDrawing.drawTable" ) + .Scope( AS_GLOBAL ) + .FriendlyName( _( "Add Table" ) ) + .Tooltip( _( "Draw table" ) ) + .Icon( BITMAPS::spreadsheet ) // JEY TODO + .Flags( AF_ACTIVATE ) ); + TOOL_ACTION PCB_ACTIONS::spacingIncrease( TOOL_ACTION_ARGS() .Name( "pcbnew.lengthTuner.SpacingIncrease" ) .Scope( AS_GLOBAL ) diff --git a/pcbnew/tools/pcb_actions.h b/pcbnew/tools/pcb_actions.h index 5aae6634dc..b747172627 100644 --- a/pcbnew/tools/pcb_actions.h +++ b/pcbnew/tools/pcb_actions.h @@ -200,6 +200,7 @@ public: static TOOL_ACTION placeReferenceImage; static TOOL_ACTION placeText; static TOOL_ACTION drawTextBox; + static TOOL_ACTION drawTable; static TOOL_ACTION spacingIncrease; static TOOL_ACTION spacingDecrease; static TOOL_ACTION amplIncrease; diff --git a/pcbnew/tools/pcb_edit_table_tool.cpp b/pcbnew/tools/pcb_edit_table_tool.cpp new file mode 100644 index 0000000000..2eff71a4a6 --- /dev/null +++ b/pcbnew/tools/pcb_edit_table_tool.cpp @@ -0,0 +1,94 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2024 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 +#include +#include +#include +#include + + +PCB_EDIT_TABLE_TOOL::PCB_EDIT_TABLE_TOOL() : + PCB_TOOL_BASE( "pcbnew.TableEditor" ) +{ +} + + +bool PCB_EDIT_TABLE_TOOL::Init() +{ + PCB_TOOL_BASE::Init(); + + addMenus( m_toolMgr->GetTool()->GetToolMenu().GetMenu() ); + + return true; +} + + +PCB_TABLECELL* PCB_EDIT_TABLE_TOOL::copyCell( PCB_TABLECELL* aSource ) +{ + PCB_TABLECELL* cell = new PCB_TABLECELL( aSource->GetParent() ); + + cell->SetEnd( aSource->GetEnd() - aSource->GetStart() ); + + return cell; +} + + +const SELECTION& PCB_EDIT_TABLE_TOOL::getTableCellSelection() +{ + PCB_SELECTION_TOOL* selTool = m_toolMgr->GetTool(); + + return selTool->RequestSelection( + []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool ) + { + // Iterate from the back so we don't have to worry about removals. + for( int i = aCollector.GetCount() - 1; i >= 0; --i ) + { + if( !dynamic_cast( aCollector[ i ] ) ) + aCollector.Remove( aCollector[ i ] ); + } + }, + false /* prompt user regarding locked items */ ); +} + + +void PCB_EDIT_TABLE_TOOL::clearSelection() +{ + m_toolMgr->RunAction( PCB_ACTIONS::selectionClear ); +}; + + +void PCB_EDIT_TABLE_TOOL::setTransitions() +{ + Go( &PCB_EDIT_TABLE_TOOL::AddRowAbove, ACTIONS::addRowAbove.MakeEvent() ); + Go( &PCB_EDIT_TABLE_TOOL::AddRowBelow, ACTIONS::addRowBelow.MakeEvent() ); + + Go( &PCB_EDIT_TABLE_TOOL::AddColumnBefore, ACTIONS::addColBefore.MakeEvent() ); + Go( &PCB_EDIT_TABLE_TOOL::AddColumnAfter, ACTIONS::addColAfter.MakeEvent() ); + + Go( &PCB_EDIT_TABLE_TOOL::DeleteRows, ACTIONS::deleteRows.MakeEvent() ); + Go( &PCB_EDIT_TABLE_TOOL::DeleteColumns, ACTIONS::deleteColumns.MakeEvent() ); + + Go( &PCB_EDIT_TABLE_TOOL::MergeCells, ACTIONS::mergeCells.MakeEvent() ); + Go( &PCB_EDIT_TABLE_TOOL::UnmergeCells, ACTIONS::unmergeCells.MakeEvent() ); +} diff --git a/pcbnew/tools/pcb_edit_table_tool.h b/pcbnew/tools/pcb_edit_table_tool.h new file mode 100644 index 0000000000..ccb8d71749 --- /dev/null +++ b/pcbnew/tools/pcb_edit_table_tool.h @@ -0,0 +1,68 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2024 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 PCB_EDIT_TABLE_TOOL_H +#define PCB_EDIT_TABLE_TOOL_H + +#include +#include +#include +#include +#include + + +class PCB_EDIT_TABLE_TOOL : public PCB_TOOL_BASE, + public EDIT_TABLE_TOOL_BASE +{ +public: + PCB_EDIT_TABLE_TOOL(); + ~PCB_EDIT_TABLE_TOOL() override { } + + /// @copydoc TOOL_INTERACTIVE::Init() + bool Init() override; + + int AddRowAbove( const TOOL_EVENT& aEvent ) { return doAddRowAbove( aEvent ); } + int AddRowBelow( const TOOL_EVENT& aEvent ) { return doAddRowBelow( aEvent ); } + int AddColumnBefore( const TOOL_EVENT& aEvent ) { return doAddColumnBefore( aEvent ); } + int AddColumnAfter( const TOOL_EVENT& aEvent ) { return doAddColumnAfter( aEvent ); } + int DeleteRows( const TOOL_EVENT& aEvent ) { return doDeleteRows( aEvent ); } + int DeleteColumns( const TOOL_EVENT& aEvent ) { return doDeleteColumns( aEvent ); } + + int MergeCells( const TOOL_EVENT& aEvent ) { return doMergeCells( aEvent ); } + int UnmergeCells( const TOOL_EVENT& aEvent ) { return doUnmergeCells( aEvent ); } + +private: + ///< Set up handlers for various events. + void setTransitions() override; + +private: + TOOL_MANAGER* getToolMgr() override { return m_toolMgr; } + BASE_SCREEN* getScreen() override { return nullptr; } + + const SELECTION& getTableCellSelection() override; + void clearSelection() override; + + PCB_TABLECELL* copyCell( PCB_TABLECELL* aSource ) override; +}; + +#endif //PCB_EDIT_TABLE_TOOL_H diff --git a/pcbnew/tools/pcb_point_editor.cpp b/pcbnew/tools/pcb_point_editor.cpp index c9e2d4c10b..3d12419a04 100644 --- a/pcbnew/tools/pcb_point_editor.cpp +++ b/pcbnew/tools/pcb_point_editor.cpp @@ -46,6 +46,8 @@ using namespace std::placeholders; #include #include #include +#include +#include #include #include #include @@ -74,6 +76,12 @@ enum RECT_LINES }; +enum TABLECELL_POINTS +{ + COL_WIDTH, ROW_HEIGHT +}; + + enum ARC_POINTS { ARC_START, ARC_MID, ARC_END, ARC_CENTER @@ -283,6 +291,14 @@ std::shared_ptr PCB_POINT_EDITOR::makePoints( EDA_ITEM* aItem ) break; } + case PCB_TABLECELL_T: + { + PCB_TABLECELL* cell = static_cast( aItem ); + points->AddPoint( cell->GetEnd() - VECTOR2I( 0, cell->GetRectangleHeight() / 2 ) ); + points->AddPoint( cell->GetEnd() - VECTOR2I( cell->GetRectangleWidth() / 2, 0 ) ); + break; + } + case PCB_PAD_T: { const PAD* pad = static_cast( aItem ); @@ -557,9 +573,16 @@ int PCB_POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent ) m_toolMgr->RunSynchronousAction( PCB_ACTIONS::genStartEdit, &commit, static_cast( item ) ); } + else if( item->Type() == PCB_TABLECELL_T ) + { + PCB_TABLECELL* cell = static_cast( item ); + PCB_TABLE* table = static_cast( cell->GetParent() ); + + commit.Modify( table ); + } else { - commit.StageItems( selection, CHT_MODIFY ); + commit.Modify( item ); } getViewControls()->ForceCursorPosition( false ); @@ -672,9 +695,13 @@ int PCB_POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent ) m_toolMgr->RunSynchronousAction( PCB_ACTIONS::genPushEdit, &commit, static_cast( item ) ); } + else if( item->Type() == PCB_TABLECELL_T ) + { + commit.Push( _( "Resize Table Cells" ) ); + } else { - commit.Push( _( "Drag Corner" ) ); + commit.Push( _( "Move Point" ) ); } inDrag = false; @@ -1403,6 +1430,40 @@ void PCB_POINT_EDITOR::updateItem( BOARD_COMMIT* aCommit ) break; } + case PCB_TABLECELL_T: + { + PCB_TABLECELL* cell = static_cast( item ); + PCB_TABLE* table = static_cast( cell->GetParent() ); + + if( isModified( m_editPoints->Point( COL_WIDTH ) ) ) + { + cell->SetEnd( VECTOR2I( m_editPoints->Point( 0 ).GetX(), cell->GetEndY() ) ); + + int colWidth = cell->GetRectangleWidth(); + + for( int ii = 0; ii < cell->GetColSpan() - 1; ++ii ) + colWidth -= table->GetColWidth( cell->GetColumn() + ii ); + + table->SetColWidth( cell->GetColumn() + cell->GetColSpan() - 1, colWidth ); + table->Normalize(); + } + else if( isModified( m_editPoints->Point( ROW_HEIGHT ) ) ) + { + cell->SetEnd( VECTOR2I( cell->GetEndX(), m_editPoints->Point( 1 ).GetY() ) ); + + int rowHeight = cell->GetRectangleHeight(); + + for( int ii = 0; ii < cell->GetRowSpan() - 1; ++ii ) + rowHeight -= table->GetRowHeight( cell->GetRow() + ii ); + + table->SetRowHeight( cell->GetRow() + cell->GetRowSpan() - 1, rowHeight ); + table->Normalize(); + } + + getView()->Update( table ); + break; + } + case PCB_PAD_T: { PAD* pad = static_cast( item ); @@ -1933,6 +1994,17 @@ void PCB_POINT_EDITOR::updatePoints() break; } + case PCB_TABLECELL_T: + { + PCB_TABLECELL* cell = static_cast( item ); + + m_editPoints->Point( 0 ).SetPosition( cell->GetEndX(), + cell->GetEndY() - cell->GetRectangleHeight() / 2 ); + m_editPoints->Point( 1 ).SetPosition( cell->GetEndX() - cell->GetRectangleWidth() / 2, + cell->GetEndY() ); + break; + } + case PCB_PAD_T: { const PAD* pad = static_cast( item ); diff --git a/pcbnew/tools/pcb_selection_tool.cpp b/pcbnew/tools/pcb_selection_tool.cpp index 4c9e11336c..a20011f0a9 100644 --- a/pcbnew/tools/pcb_selection_tool.cpp +++ b/pcbnew/tools/pcb_selection_tool.cpp @@ -45,6 +45,8 @@ using namespace std::placeholders; #include #include #include +#include +#include #include #include #include @@ -399,7 +401,16 @@ int PCB_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent ) m_frame->FocusOnItem( nullptr ); m_toolMgr->ProcessEvent( EVENTS::InhibitSelectionEditing ); - if( hasModifier() || dragAction == MOUSE_DRAG_ACTION::SELECT ) + GENERAL_COLLECTORS_GUIDE guide = getCollectorsGuide(); + GENERAL_COLLECTOR collector; + + collector.Collect( board(), { PCB_TABLECELL_T }, evt->DragOrigin(), guide ); + + if( collector.GetCount() ) + { + selectTableCells( static_cast( collector[0]->GetParent() ) ); + } + else if( hasModifier() || dragAction == MOUSE_DRAG_ACTION::SELECT ) { selectMultiple(); } @@ -888,6 +899,112 @@ const TOOL_ACTION* allowedActions[] = { &ACTIONS::panUp, &ACTIONS::panD &ACTIONS::zoomFitObjects, nullptr }; +bool PCB_SELECTION_TOOL::selectTableCells( PCB_TABLE* aTable ) +{ + bool cancelled = false; // Was the tool canceled while it was running? + m_multiple = true; // Multiple selection mode is active + + for( PCB_TABLECELL* cell : aTable->GetCells() ) + { + if( cell->IsSelected() ) + cell->SetFlags( CANDIDATE ); + else + cell->ClearFlags( CANDIDATE ); + } + + auto wasSelected = + []( EDA_ITEM* aItem ) + { + return ( aItem->GetFlags() & CANDIDATE ) > 0; + }; + + while( TOOL_EVENT* evt = Wait() ) + { + if( evt->IsCancelInteractive() || evt->IsActivate() ) + { + cancelled = true; + break; + } + else if( evt->IsDrag( BUT_LEFT ) ) + { + getViewControls()->SetAutoPan( true ); + + BOX2I selectionRect( evt->DragOrigin(), evt->Position() - evt->DragOrigin() ); + selectionRect.Normalize(); + + for( PCB_TABLECELL* cell : aTable->GetCells() ) + { + bool doSelect = false; + + if( cell->HitTest( selectionRect, false ) ) + { + if( m_subtractive ) + doSelect = false; + else if( m_exclusive_or ) + doSelect = !wasSelected( cell ); + else + doSelect = true; + } + else if( wasSelected( cell ) ) + { + doSelect = m_additive || m_subtractive || m_exclusive_or; + } + + if( doSelect && !cell->IsSelected() ) + select( cell ); + else if( !doSelect && cell->IsSelected() ) + unselect( cell ); + } + } + else if( evt->IsMouseUp( BUT_LEFT ) ) + { + m_selection.SetIsHover( false ); + + bool anyAdded = false; + bool anySubtracted = false; + + for( PCB_TABLECELL* cell : aTable->GetCells() ) + { + if( cell->IsSelected() && !wasSelected( cell ) ) + anyAdded = true; + else if( wasSelected( cell ) && !cell->IsSelected() ) + anySubtracted = true; + } + + // Inform other potentially interested tools + if( anyAdded ) + m_toolMgr->ProcessEvent( EVENTS::SelectedEvent ); + + if( anySubtracted ) + m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent ); + + break; // Stop waiting for events + } + else + { + // Allow some actions for navigation + for( int i = 0; allowedActions[i]; ++i ) + { + if( evt->IsAction( allowedActions[i] ) ) + { + evt->SetPassEvent(); + break; + } + } + } + } + + getViewControls()->SetAutoPan( false ); + + m_multiple = false; // Multiple selection mode is inactive + + if( !cancelled ) + m_selection.ClearReferencePoint(); + + return cancelled; +} + + bool PCB_SELECTION_TOOL::selectMultiple() { bool cancelled = false; // Was the tool canceled while it was running? @@ -2322,6 +2439,8 @@ static bool itemIsIncludedByFilter( const BOARD_ITEM& aItem, const BOARD& aBoard case PCB_FIELD_T: case PCB_TEXT_T: case PCB_TEXTBOX_T: + case PCB_TABLE_T: + case PCB_TABLECELL_T: return aFilterOptions.includePcbTexts; default: @@ -2486,6 +2605,8 @@ bool PCB_SELECTION_TOOL::itemPassesFilter( BOARD_ITEM* aItem, bool aMultiSelect case PCB_FIELD_T: case PCB_TEXT_T: case PCB_TEXTBOX_T: + case PCB_TABLE_T: + case PCB_TABLECELL_T: if( !m_filter.text ) return false; @@ -2800,6 +2921,8 @@ bool PCB_SELECTION_TOOL::Selectable( const BOARD_ITEM* aItem, bool checkVisibili case PCB_SHAPE_T: case PCB_TEXTBOX_T: + case PCB_TABLE_T: + case PCB_TABLECELL_T: if( m_isFootprintEditor ) { if( !view()->IsLayerVisible( aItem->GetLayer() ) ) @@ -3042,6 +3165,7 @@ int PCB_SELECTION_TOOL::hitTestDistance( const VECTOR2I& aWhere, BOARD_ITEM* aIt } case PCB_TEXTBOX_T: + case PCB_TABLECELL_T: { PCB_TEXTBOX* textbox = static_cast( aItem ); @@ -3052,6 +3176,20 @@ int PCB_SELECTION_TOOL::hitTestDistance( const VECTOR2I& aWhere, BOARD_ITEM* aIt break; } + case PCB_TABLE_T: + { + PCB_TABLE* table = static_cast( aItem ); + + for( PCB_TABLECELL* cell : table->GetCells() ) + { + // Add a bit of slop to text-shapes + if( cell->GetEffectiveTextShape()->Collide( loc, aMaxDistance, &distance ) ) + distance = std::clamp( distance - ( aMaxDistance / 2 ), 0, distance ); + } + + break; + } + case PCB_ZONE_T: { ZONE* zone = static_cast( aItem ); @@ -3286,7 +3424,9 @@ void PCB_SELECTION_TOOL::GuessSelectionCandidates( GENERAL_COLLECTOR& aCollector { static const LSET silkLayers( 2, B_SilkS, F_SilkS ); static const LSET courtyardLayers( 2, B_CrtYd, F_CrtYd ); - static std::vector singleLayerSilkTypes = { PCB_FIELD_T, PCB_TEXT_T, PCB_TEXTBOX_T, + static std::vector singleLayerSilkTypes = { PCB_FIELD_T, + PCB_TEXT_T, PCB_TEXTBOX_T, + PCB_TABLE_T, PCB_TABLECELL_T, PCB_SHAPE_T }; if( ADVANCED_CFG::GetCfg().m_PcbSelectionVisibilityRatio != 1.0 ) @@ -3540,6 +3680,29 @@ void PCB_SELECTION_TOOL::FilterCollectorForHierarchy( GENERAL_COLLECTOR& aCollec } +void PCB_SELECTION_TOOL::FilterCollectorForTableCells( GENERAL_COLLECTOR& aCollector ) const +{ + std::set to_add; + + // Iterate from the back so we don't have to worry about removals. + for( int i = (int) aCollector.GetCount() - 1; i >= 0; --i ) + { + BOARD_ITEM* item = aCollector[i]; + + if( item->Type() == PCB_TABLECELL_T ) + { + if( !aCollector.HasItem( item->GetParent() ) ) + to_add.insert( item->GetParent() ); + + aCollector.Remove( item ); + } + } + + for( BOARD_ITEM* item : to_add ) + aCollector.Append( item ); +} + + void PCB_SELECTION_TOOL::FilterCollectorForFreePads( GENERAL_COLLECTOR& aCollector, bool aForcePromotion ) const { diff --git a/pcbnew/tools/pcb_selection_tool.h b/pcbnew/tools/pcb_selection_tool.h index 33e86566c9..526c66800e 100644 --- a/pcbnew/tools/pcb_selection_tool.h +++ b/pcbnew/tools/pcb_selection_tool.h @@ -42,6 +42,7 @@ class PCB_BASE_FRAME; class BOARD_ITEM; class GENERAL_COLLECTOR; +class PCB_TABLE; namespace KIGFX { @@ -205,6 +206,11 @@ public: void FilterCollectorForFreePads( GENERAL_COLLECTOR& aCollector, bool aForcePromotion = false ) const; + /** + * Promote any table cell selections to the whole table. + */ + void FilterCollectorForTableCells( GENERAL_COLLECTOR& aCollector ) const; + /** * Drop any PCB_MARKERs from the collector. */ @@ -293,6 +299,8 @@ private: */ bool selectMultiple(); + bool selectTableCells( PCB_TABLE* aTable ); + /** * Handle disambiguation actions including displaying the menu. */ diff --git a/pcbnew/zone_filler.cpp b/pcbnew/zone_filler.cpp index 179b6280e4..f5c621bb73 100644 --- a/pcbnew/zone_filler.cpp +++ b/pcbnew/zone_filler.cpp @@ -837,6 +837,10 @@ void ZONE_FILLER::addKnockout( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, int aGap, break; } + case PCB_TABLE_T: + // JEY TODO: tables + break; + case PCB_SHAPE_T: case PCB_TARGET_T: aItem->TransformShapeToPolygon( aHoles, aLayer, aGap, m_maxError, ERROR_OUTSIDE,