23#include <fmt/ranges.h>
24#include <magic_enum.hpp>
52#include <api/common/types/base_types.pb.h>
54using namespace kiapi::common::commands;
55using types::CommandStatus;
57using types::DocumentType;
58using types::ItemRequestStatus;
111 const std::string& aCommandName )
const
117 e.set_status( ApiStatusCode::AS_UNIMPLEMENTED );
118 e.set_error_message( fmt::format(
"{} is not available in headless mode", aCommandName ) );
130 const wxString& aMessage )
142 bool isFootprintEditor =
thisDocumentType() == kiapi::common::types::DOCTYPE_FOOTPRINT;
144 return std::make_unique<BOARD_COMMIT>(
toolManager(), !isFootprintEditor, isFootprintEditor );
165 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
166 e.set_error_message(
"Tried to create an item in a null container" );
167 return tl::unexpected( e );
173 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
174 e.set_error_message( fmt::format(
"Tried to create a pad in {}, which is not a footprint",
176 return tl::unexpected( e );
181 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
182 e.set_error_message( fmt::format(
"Tried to create a footprint in {}, which is not a board",
184 return tl::unexpected( e );
187 if(
dynamic_cast<FOOTPRINT*
>( aContainer ) )
189 static const std::set<KICAD_T> s_footprintItemTypes = {
196 if( !s_footprintItemTypes.contains( aType ) )
199 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
200 e.set_error_message( fmt::format(
"items of type {} cannot be created in a footprint",
201 magic_enum::enum_name( aType ) ) );
202 return tl::unexpected( e );
211 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
212 e.set_error_message( fmt::format(
"Tried to create an item of type {}, which is unhandled",
213 magic_enum::enum_name( aType ) ) );
214 return tl::unexpected( e );
222 const std::string& aClientName )
225 std::vector<BOARD_ITEM*> validatedItems;
227 for( std::pair<const KIID, ItemDeletionStatus> pair : aItemsToDelete )
235 aItemsToDelete[pair.first] = ItemDeletionStatus::IDS_IMMUTABLE;
239 validatedItems.push_back( item );
240 aItemsToDelete[pair.first] = ItemDeletionStatus::IDS_OK;
259 static_cast<PCB_TABLECELL*
>( item )->SetText( wxEmptyString );
301 const std::vector<PCB_GENERATOR*>& aGenerators,
302 std::function<
void(
const KIID&, ItemStatus )> aResultHandler )
const
312 generator->EditStart( aTool,
board, aCommit );
313 bool ok = generator->Update( aTool,
board, aCommit );
314 generator->EditFinish( aTool,
board, aCommit );
316 status.set_code( ok ? ItemStatusCode::ISC_OK : ItemStatusCode::ISC_INVALID_DATA );
319 status.set_error_message(
"the generator reported an update failure" );
321 catch(
const std::exception& exc )
323 status.set_code( ItemStatusCode::ISC_INVALID_DATA );
324 status.set_error_message( fmt::format(
"regeneration exception: {}", exc.what() ) );
328 aResultHandler( generator->m_Uuid, status );
334 const DocumentSpecifier& aDocument,
const KIID& aId )
344 const std::string& aClientName,
345 const types::ItemHeader &aHeader,
346 const google::protobuf::RepeatedPtrField<google::protobuf::Any>& aItems,
347 std::function<
void( ItemStatus, google::protobuf::Any )> aItemHandler )
353 if( !containerResult && containerResult.error().status() == ApiStatusCode::AS_UNHANDLED )
356 e.set_status( ApiStatusCode::AS_UNHANDLED );
357 return tl::unexpected( e );
359 else if( !containerResult )
361 e.CopyFrom( containerResult.error() );
362 return tl::unexpected( e );
368 if( containerResult->has_value() )
370 const KIID& containerId = **containerResult;
371 std::optional<BOARD_ITEM*> optItem =
getItemById( containerId );
379 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
380 e.set_error_message( fmt::format(
"The requested container {} is not a valid board item container",
382 return tl::unexpected( e );
387 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
388 e.set_error_message( fmt::format(
"The requested container {} does not exist in this document",
390 return tl::unexpected( e );
397 for(
const google::protobuf::Any& anyItem : aItems )
404 status.set_code( ItemStatusCode::ISC_INVALID_TYPE );
405 status.set_error_message( fmt::format(
"Could not decode a valid type from {}", anyItem.type_url() ) );
406 aItemHandler( status, anyItem );
412 board::types::Dimension dimension;
413 anyItem.UnpackTo( &dimension );
415 switch( dimension.dimension_style_case() )
422 case board::types::Dimension::DIMENSION_STYLE_NOT_SET:
break;
428 board::types::BoardGraphicShape shape;
429 anyItem.UnpackTo( &shape );
431 if( shape.has_pad_custom_shape_options() )
433 status.set_code( ItemStatusCode::ISC_INVALID_DATA );
434 status.set_error_message(
"pad_custom_shape_options are only valid on shapes inside a pad's "
435 "padstack custom shapes" );
436 aItemHandler( status, anyItem );
450 ItemStatus genStatus;
451 genStatus.set_code( ItemStatusCode::ISC_INVALID_TYPE );
452 genStatus.set_error_message( fmt::format(
"could not decode a generator from {}",
453 anyItem.type_url() ) );
454 aItemHandler( genStatus, anyItem );
462 ItemStatus genStatus;
463 genStatus.set_code( ItemStatusCode::ISC_INVALID_TYPE );
464 genStatus.set_error_message( fmt::format(
"generator type {} is not registered",
465 generatorType->ToStdString() ) );
466 aItemHandler( genStatus, anyItem );
476 if( !creationResult || !creationResult.value() )
478 if( !creationResult )
480 status.set_code( ItemStatusCode::ISC_INVALID_TYPE );
481 status.set_error_message( creationResult.error().error_message() );
482 aItemHandler( status, anyItem );
488 std::unique_ptr<BOARD_ITEM> item( std::move( *creationResult ) );
490 bool unpacked =
false;
493 unpacked = item->Deserialize( anyItem );
495 unpacked =
group->DeserializeGroup( anyItem, commit );
497 unpacked = item->Deserialize( anyItem );
503 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
504 e.set_error_message( fmt::format(
"could not unpack {} from request",
505 item->GetClass().ToStdString() ) );
506 return tl::unexpected( e );
509 if( std::vector<wxString> removed = item->RemoveConflictingCustomProperties(); !removed.empty() )
512 [](
const wxString& aIn )
514 return std::string( aIn.ToUTF8() );
517 status.set_code( ItemStatusCode::ISC_INVALID_DATA );
518 status.set_error_message( fmt::format(
"Invalid custom properties for item {}: property name(s) '{}' "
520 item->m_Uuid.AsStdString(),
521 fmt::join( std::views::transform( removed, as_str ),
", " ) ) );
523 aItemHandler( status, anyItem );
527 std::optional<BOARD_ITEM*> optItem =
getItemById( item->m_Uuid );
529 if( aCreate && optItem )
531 status.set_code( ItemStatusCode::ISC_EXISTING );
532 status.set_error_message( fmt::format(
"an item with UUID {} already exists",
533 item->m_Uuid.AsStdString() ) );
534 aItemHandler( status, anyItem );
537 else if( !aCreate && !optItem )
539 status.set_code( ItemStatusCode::ISC_NONEXISTENT );
540 status.set_error_message( fmt::format(
"an item with UUID {} does not exist",
541 item->m_Uuid.AsStdString() ) );
542 aItemHandler( status, anyItem );
546 if( !aCreate && ( *optItem )->Type() != item->Type() )
548 status.set_code( ItemStatusCode::ISC_INVALID_TYPE );
549 status.set_error_message( fmt::format(
"item {} is of type {}, not {}",
550 item->m_Uuid.AsStdString(),
551 magic_enum::enum_name( ( *optItem )->Type() ),
552 magic_enum::enum_name( item->Type() ) ) );
553 aItemHandler( status, anyItem );
558 && !item->FitsEnabledLayers(
board->GetEnabledLayers(),
board->GetCopperLayerCount() ) )
560 status.set_code( ItemStatusCode::ISC_INVALID_DATA );
561 status.set_error_message(
"attempted to add item with no overlapping layers with the board" );
562 aItemHandler( status, anyItem );
566 status.set_code( ItemStatusCode::ISC_OK );
567 google::protobuf::Any newItem;
580 status.set_code( ItemStatusCode::ISC_INVALID_DATA );
581 status.set_error_message(
"a table cell must target a table container" );
582 aItemHandler( status, anyItem );
588 table->AddCell( cell );
606 item->Serialize( newItem );
607 commit->
Add( item.release() );
625 commit->
Modify( boardItem );
628 static_cast<PCB_GROUP*
>( boardItem )->FinalizeGroupDeserialization();
647 commit->
Remove( boardItem );
648 item->Serialize( newItem );
651 commit->
Add( newBoardItem );
655 parentGroup->
AddItem( newBoardItem );
662 commit->
Modify( boardItem );
675 aItemHandler( status, newItem );
681 :
_(
"Modified items via API" ) );
684 return ItemRequestStatus::IRS_OK;
689 const google::protobuf::RepeatedField<int>& aTypes )
691 std::vector<KICAD_T>
types;
693 for(
int typeRaw : aTypes )
695 auto typeMessage =
static_cast<common::types::KiCadObjectType
>( typeRaw );
699 types.emplace_back( type );
709 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"RunAction" ) )
710 return tl::unexpected( *headless );
712 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
713 return tl::unexpected( *busy );
715 RunActionResponse response;
718 response.set_status( RunActionStatus::RAS_OK );
720 response.set_status( RunActionStatus::RAS_INVALID );
732 e.set_status( ApiStatusCode::AS_UNHANDLED );
733 return tl::unexpected( e );
736 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
737 return tl::unexpected( *busy );
739 GetItemsResponse response;
741 std::vector<BOARD_ITEM*> items;
743 for(
const kiapi::common::types::KIID&
id : aCtx.
Request.items() )
745 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
746 items.emplace_back( *item );
752 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
753 e.set_error_message(
"none of the requested IDs were found or valid" );
754 return tl::unexpected( e );
759 google::protobuf::Any itemBuf;
760 item->Serialize( itemBuf );
761 response.mutable_items()->Add( std::move( itemBuf ) );
764 response.set_status( ItemRequestStatus::IRS_OK );
772 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"GetSelection" ) )
773 return tl::unexpected( *headless );
779 e.set_status( ApiStatusCode::AS_UNHANDLED );
780 return tl::unexpected( e );
802 SelectionResponse response;
807 item->Serialize( *response.add_items() );
817 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"ClearSelection" ) )
818 return tl::unexpected( *headless );
824 e.set_status( ApiStatusCode::AS_UNHANDLED );
825 return tl::unexpected( e );
828 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
829 return tl::unexpected( *busy );
842 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"AddToSelection" ) )
843 return tl::unexpected( *headless );
849 e.set_status( ApiStatusCode::AS_UNHANDLED );
850 return tl::unexpected( e );
853 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
854 return tl::unexpected( *busy );
859 std::vector<EDA_ITEM*> toAdd;
861 for(
const types::KIID&
id : aCtx.
Request.items() )
863 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
864 toAdd.emplace_back( *item );
870 SelectionResponse response;
873 item->Serialize( *response.add_items() );
881 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"FocusOnItems" ) )
882 return tl::unexpected( *headless );
885 return tl::unexpected( documentValidation.error() );
887 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
888 return tl::unexpected( *busy );
890 if( aCtx.
Request.items().empty() )
891 return tl::unexpected(
MakeResponseStatus( AS_BAD_REQUEST,
"no items were given to focus on" ) );
893 std::optional<BOX2I> bbox;
894 std::vector<std::string> missing;
896 for(
const types::KIID& idMsg : aCtx.
Request.items() )
898 std::optional<BOARD_ITEM*> item =
getItemById(
KIID( idMsg.value() ) );
902 missing.push_back( idMsg.value() );
907 bbox->Merge( ( *item )->GetBoundingBox() );
909 bbox = ( *item )->GetBoundingBox();
912 if( !missing.empty() )
914 return tl::unexpected(
915 MakeResponseStatus( AS_BAD_REQUEST, fmt::format(
"the items {} are not in the requested document",
916 fmt::join( missing,
", " ) ) ) );
919 if( aCtx.
Request.has_margin() )
931 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"RemoveFromSelection" ) )
932 return tl::unexpected( *headless );
938 e.set_status( ApiStatusCode::AS_UNHANDLED );
939 return tl::unexpected( e );
942 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
943 return tl::unexpected( *busy );
948 std::vector<EDA_ITEM*> toRemove;
950 for(
const types::KIID&
id : aCtx.
Request.items() )
952 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
953 toRemove.emplace_back( *item );
959 SelectionResponse response;
962 item->Serialize( *response.add_items() );
973 if( !documentValidation )
974 return tl::unexpected( documentValidation.error() );
976 BoardStackupResponse response;
989 if( !documentValidation )
990 return tl::unexpected( documentValidation.error() );
992 BoardEnabledLayersResponse response;
995 int copperLayerCount =
board->GetCopperLayerCount();
997 response.set_copper_layer_count( copperLayerCount );
999 LSET enabled =
board->GetEnabledLayers();
1018 if( !documentValidation )
1019 return tl::unexpected( documentValidation.error() );
1022 GraphicsDefaultsResponse response;
1025 constexpr std::array<kiapi::board::BoardLayerClass, LAYER_CLASS_COUNT> classOrder = {
1026 kiapi::board::BLC_SILKSCREEN,
1027 kiapi::board::BLC_COPPER,
1028 kiapi::board::BLC_EDGES,
1029 kiapi::board::BLC_COURTYARD,
1030 kiapi::board::BLC_FABRICATION,
1031 kiapi::board::BLC_OTHER
1036 kiapi::board::BoardLayerGraphicsDefaults* l = response.mutable_defaults()->add_layers();
1038 l->set_layer( classOrder[i] );
1041 kiapi::common::types::TextAttributes*
text = l->mutable_text();
1058 ApiResponseStatus e;
1060 e.set_status( ApiStatusCode::AS_UNHANDLED );
1061 return tl::unexpected( e );
1064 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1065 return tl::unexpected( *busy );
1067 GetBoundingBoxResponse response;
1068 bool includeText = aCtx.
Request.mode() == BoundingBoxMode::BBM_ITEM_AND_CHILD_TEXT;
1070 for(
const types::KIID& idMsg : aCtx.
Request.items() )
1072 KIID id( idMsg.value() );
1073 std::optional<BOARD_ITEM*> optItem =
getItemById(
id );
1082 bbox =
static_cast<FOOTPRINT*
>( item )->GetBoundingBox( includeText );
1086 response.add_items()->set_value( idMsg.value() );
1087 PackBox2( *response.add_boxes(), bbox );
1098 return tl::unexpected( documentValidation.error() );
1100 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1101 return tl::unexpected( *busy );
1103 BoardBoundingBoxResponse response;
1109 case BoardBoundingBoxMode::BBBM_PHYSICAL_LAYERS_ONLY: bbox =
board()->
ComputeBoundingBox(
false,
true );
break;
1112 return tl::unexpected(
MakeResponseStatus( AS_BAD_REQUEST,
"invalid bounding box mode requested" ) );
1115 PackBox2( *response.mutable_box(), bbox );
1125 !documentValidation )
1127 return tl::unexpected( documentValidation.error() );
1130 PadShapeAsPolygonResponse response;
1133 for(
const types::KIID& padRequest : aCtx.
Request.pads() )
1135 KIID id( padRequest.value() );
1136 std::optional<BOARD_ITEM*> optPad =
getItemById(
id );
1138 if( !optPad || ( *optPad )->Type() !=
PCB_PAD_T )
1141 response.add_pads()->set_value( padRequest.value() );
1143 PAD*
pad =
static_cast<PAD*
>( *optPad );
1145 pad->TransformShapeToPolygon( poly,
pad->Padstack().EffectiveLayerFor( layer ), 0,
1148 types::PolygonWithHoles* polyMsg = response.mutable_polygons()->Add();
1159 using board::types::BoardLayer;
1162 !documentValidation )
1164 return tl::unexpected( documentValidation.error() );
1167 PadstackPresenceResponse response;
1171 for(
const int layer : aCtx.
Request.layers() )
1178 layers.
set( pcbLayer );
1181 for(
const types::KIID& padRequest : aCtx.
Request.items() )
1183 KIID id( padRequest.value() );
1184 std::optional<BOARD_ITEM*> optItem =
getItemById(
id );
1189 switch( ( *optItem )->Type() )
1193 PAD*
pad =
static_cast<PAD*
>( *optItem );
1197 PadstackPresenceEntry* entry = response.add_entries();
1198 entry->mutable_item()->set_value(
pad->m_Uuid.AsStdString() );
1200 entry->set_presence(
pad->FlashLayer( layer ) ? PSP_PRESENT : PSP_NOT_PRESENT );
1212 PadstackPresenceEntry* entry = response.add_entries();
1213 entry->mutable_item()->set_value(
via->m_Uuid.AsStdString() );
1215 entry->set_presence(
via->FlashLayer( layer ) ? PSP_PRESENT : PSP_NOT_PRESENT );
1235 if( !documentValidation )
1236 return tl::unexpected( documentValidation.error() );
1238 ExpandTextVariablesResponse reply;
1241 std::function<bool( wxString* )> textResolver =
1242 [&]( wxString* token ) ->
bool
1245 return board->ResolveTextVar( token, 0 );
1248 for(
const std::string& textMsg : aCtx.
Request.text() )
1252 if( aCtx.
Request.expand_env_vars() )
1255 reply.add_text(
text.ToUTF8() );
1265 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"InteractiveMoveItems" ) )
1266 return tl::unexpected( *headless );
1270 if( !documentValidation )
1271 return tl::unexpected( documentValidation.error() );
1273 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1274 return tl::unexpected( *busy );
1277 std::vector<EDA_ITEM*> toSelect;
1279 for(
const kiapi::common::types::KIID&
id : aCtx.
Request.items() )
1281 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
1282 toSelect.emplace_back(
static_cast<EDA_ITEM*
>( *item ) );
1285 if( toSelect.empty() )
1287 ApiResponseStatus e;
1288 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1289 e.set_error_message( fmt::format(
"None of the given items exist on the board",
1290 aCtx.
Request.board().board_filename() ) );
1291 return tl::unexpected( e );
1312 if( !containerResult && containerResult.error().status() == ApiStatusCode::AS_UNHANDLED )
1315 ApiResponseStatus e;
1316 e.set_status( ApiStatusCode::AS_UNHANDLED );
1317 return tl::unexpected( e );
1319 else if( !containerResult )
1321 return tl::unexpected( containerResult.error() );
1324 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1325 return tl::unexpected( *busy );
1330 FlipItemsResponse response;
1331 response.mutable_header()->CopyFrom( aCtx.
Request.header() );
1335 bool anyModified =
false;
1337 for(
const types::KIID&
id : aCtx.
Request.items() )
1339 ItemFlipResult*
result = response.add_flipped_items();
1341 std::optional<BOARD_ITEM*> optItem =
getItemById(
KIID(
id.value() ) );
1345 result->mutable_status()->set_code( ItemStatusCode::ISC_NONEXISTENT );
1346 result->mutable_status()->set_error_message(
1347 fmt::format(
"an item with UUID {} does not exist",
id.value() ) );
1353 static const std::set<KICAD_T> flippableTypes = {
1382 if( !flippableTypes.contains( itemType ) )
1384 result->mutable_status()->set_code( ItemStatusCode::ISC_INVALID_TYPE );
1385 result->mutable_status()->set_error_message(
1386 fmt::format(
"items of type {} cannot be flipped",
1387 magic_enum::enum_name( itemType ) ) );
1397 static_cast<FOOTPRINT*
>( boardItem )->InvalidateComponentClassCache();
1401 google::protobuf::Any itemBuf;
1403 *
result->mutable_item() = std::move( itemBuf );
1405 result->mutable_status()->set_code( ItemStatusCode::ISC_OK );
1408 response.set_status( ItemRequestStatus::IRS_OK );
1422 if( !documentValidation )
1423 return tl::unexpected( documentValidation.error() );
1425 SavedDocumentResponse response;
1426 response.mutable_document()->CopyFrom( aCtx.
Request.document() );
1430 [&](
const wxString& aData )
1432 response.set_contents( aData.ToUTF8() );
1444 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"SaveSelectionToString" ) )
1445 return tl::unexpected( *headless );
1447 SavedSelectionResponse response;
1455 [&](
const wxString& aData )
1457 response.set_contents( aData.ToUTF8() );
1472 if( !documentValidation )
1473 return tl::unexpected( documentValidation.error() );
1475 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1476 return tl::unexpected( *busy );
1478 CreateItemsResponse response;
1486 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"GetVisibleLayers" ) )
1487 return tl::unexpected( *headless );
1491 if( !documentValidation )
1492 return tl::unexpected( documentValidation.error() );
1494 BoardLayers response;
1506 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"SetVisibleLayers" ) )
1507 return tl::unexpected( *headless );
1511 if( !documentValidation )
1512 return tl::unexpected( documentValidation.error() );
1514 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1515 return tl::unexpected( *busy );
1520 for(
int layerIdx : aCtx.
Request.layers() )
1526 visible.
set( layer );
1534 editFrame->Refresh();
1542 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"GetActiveLayer" ) )
1543 return tl::unexpected( *headless );
1547 if( !documentValidation )
1548 return tl::unexpected( documentValidation.error() );
1552 BoardLayerResponse response;
1563 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"SetActiveLayer" ) )
1564 return tl::unexpected( *headless );
1568 if( !documentValidation )
1569 return tl::unexpected( documentValidation.error() );
1571 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1572 return tl::unexpected( *busy );
1576 if( !
board()->GetEnabledLayers().Contains( layer ) )
1578 ApiResponseStatus err;
1579 err.set_status( ApiStatusCode::AS_BAD_REQUEST );
1580 err.set_error_message( fmt::format(
"Layer {} is not a valid layer for the given board",
1581 magic_enum::enum_name( layer ) ) );
1582 return tl::unexpected( err );
KICOMMON_API types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICOMMON_API KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
tl::expected< T, ApiResponseStatus > HANDLER_RESULT
std::unique_ptr< BOARD_ITEM > CreateGeneratorForType(const wxString &aGeneratorType, BOARD_ITEM_CONTAINER *aContainer)
std::unique_ptr< EDA_ITEM > CreateItemForType(KICAD_T aType, EDA_ITEM *aContainer)
static TOOL_ACTION selectionClear
Clear the current selection.
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
API_HANDLER_BOARD(std::shared_ptr< BOARD_CONTEXT > aContext, EDA_BASE_FRAME *aFrame=nullptr)
HANDLER_RESULT< commands::ExpandTextVariablesResponse > handleExpandTextVariables(const HANDLER_CONTEXT< commands::ExpandTextVariables > &aCtx)
HANDLER_RESULT< BoardEnabledLayersResponse > handleGetBoardEnabledLayers(const HANDLER_CONTEXT< GetBoardEnabledLayers > &aCtx)
std::unique_ptr< COMMIT > createCommit() override
Override this to create an appropriate COMMIT subclass for the frame in question.
HANDLER_RESULT< commands::SelectionResponse > handleGetSelection(const HANDLER_CONTEXT< commands::GetSelection > &aCtx)
HANDLER_RESULT< commands::SavedSelectionResponse > handleSaveSelectionToString(const HANDLER_CONTEXT< commands::SaveSelectionToString > &aCtx)
HANDLER_RESULT< Empty > handleSetActiveLayer(const HANDLER_CONTEXT< SetActiveLayer > &aCtx)
HANDLER_RESULT< BoardLayers > handleGetVisibleLayers(const HANDLER_CONTEXT< GetVisibleLayers > &aCtx)
TOOL_MANAGER * toolManager() const
GENERATOR_TOOL * ensureGeneratorTool() const
Creates the generator tool if needed (e.g. in headless mode); returns it if available.
HANDLER_RESULT< commands::SelectionResponse > handleAddToSelection(const HANDLER_CONTEXT< commands::AddToSelection > &aCtx)
HANDLER_RESULT< commands::CreateItemsResponse > handleParseAndCreateItemsFromString(const HANDLER_CONTEXT< commands::ParseAndCreateItemsFromString > &aCtx)
HANDLER_RESULT< Empty > handleClearSelection(const HANDLER_CONTEXT< commands::ClearSelection > &aCtx)
std::vector< KICAD_T > parseRequestedItemTypes(const google::protobuf::RepeatedField< int > &aTypes)
HANDLER_RESULT< Empty > handleInteractiveMoveItems(const HANDLER_CONTEXT< InteractiveMoveItems > &aCtx)
HANDLER_RESULT< BoardBoundingBoxResponse > handleGetBoardBoundingBox(const HANDLER_CONTEXT< GetBoardBoundingBox > &aCtx)
HANDLER_RESULT< types::ItemRequestStatus > handleCreateUpdateItemsInternal(bool aCreate, const std::string &aClientName, const types::ItemHeader &aHeader, const google::protobuf::RepeatedPtrField< google::protobuf::Any > &aItems, std::function< void(commands::ItemStatus, google::protobuf::Any)> aItemHandler) override
HANDLER_RESULT< BoardStackupResponse > handleGetStackup(const HANDLER_CONTEXT< GetBoardStackup > &aCtx)
void pushCurrentCommit(const std::string &aClientName, const wxString &aMessage) override
HANDLER_RESULT< commands::GetItemsResponse > handleGetItemsById(const HANDLER_CONTEXT< commands::GetItemsById > &aCtx)
std::optional< EDA_ITEM * > getItemFromDocument(const DocumentSpecifier &aDocument, const KIID &aId) override
void deleteItemsInternal(std::map< KIID, ItemDeletionStatus > &aItemsToDelete, const std::string &aClientName) override
HANDLER_RESULT< commands::SelectionResponse > handleRemoveFromSelection(const HANDLER_CONTEXT< commands::RemoveFromSelection > &aCtx)
HANDLER_RESULT< GraphicsDefaultsResponse > handleGetGraphicsDefaults(const HANDLER_CONTEXT< GetGraphicsDefaults > &aCtx)
HANDLER_RESULT< BoardLayerResponse > handleGetActiveLayer(const HANDLER_CONTEXT< GetActiveLayer > &aCtx)
HANDLER_RESULT< commands::GetBoundingBoxResponse > handleGetBoundingBox(const HANDLER_CONTEXT< commands::GetBoundingBox > &aCtx)
static HANDLER_RESULT< std::unique_ptr< BOARD_ITEM > > createItemForType(KICAD_T aType, BOARD_ITEM_CONTAINER *aContainer)
HANDLER_RESULT< commands::RunActionResponse > handleRunAction(const HANDLER_CONTEXT< commands::RunAction > &aCtx)
std::optional< ApiResponseStatus > checkForHeadless(const std::string &aCommandName) const
HANDLER_RESULT< commands::SavedDocumentResponse > handleSaveDocumentToString(const HANDLER_CONTEXT< commands::SaveDocumentToString > &aCtx)
HANDLER_RESULT< PadShapeAsPolygonResponse > handleGetPadShapeAsPolygon(const HANDLER_CONTEXT< GetPadShapeAsPolygon > &aCtx)
HANDLER_RESULT< Empty > handleFocusOnItems(const HANDLER_CONTEXT< commands::FocusOnItems > &aCtx)
std::shared_ptr< BOARD_CONTEXT > m_context
HANDLER_RESULT< PadstackPresenceResponse > handleCheckPadstackPresenceOnLayers(const HANDLER_CONTEXT< CheckPadstackPresenceOnLayers > &aCtx)
virtual BOARD_ITEM_CONTAINER * getDefaultContainer()
HANDLER_RESULT< Empty > handleSetVisibleLayers(const HANDLER_CONTEXT< SetVisibleLayers > &aCtx)
void regenerateGenerators(GENERATOR_TOOL *aTool, BOARD_COMMIT *aCommit, const std::vector< PCB_GENERATOR * > &aGenerators, std::function< void(const KIID &, commands::ItemStatus)> aResultHandler) const
std::optional< BOARD_ITEM * > getItemById(const KIID &aId) const
HANDLER_RESULT< FlipItemsResponse > handleFlipItems(const HANDLER_CONTEXT< FlipItems > &aCtx)
HANDLER_RESULT< bool > validateDocument(const DocumentSpecifier &aDocument)
HANDLER_RESULT< std::optional< KIID > > validateItemHeaderDocument(const kiapi::common::types::ItemHeader &aHeader)
If the header is valid, returns the item container.
API_HANDLER_EDITOR(EDA_BASE_FRAME *aFrame=nullptr)
COMMIT * getCurrentCommit(const std::string &aClientName)
virtual void pushCurrentCommit(const std::string &aClientName, const wxString &aMessage)
std::set< std::string > m_activeClients
virtual std::optional< ApiResponseStatus > checkForBusy()
Checks if the editor can accept commands.
virtual types::DocumentType thisDocumentType() const =0
Override this to specify which document type this editor handles.
virtual void onModified()
void registerHandler(HANDLER_RESULT< ResponseType >(HandlerType::*aHandler)(const HANDLER_CONTEXT< RequestType > &))
Registers an API command handler for the given message types.
void OnBoardChanged()
Update the panel contents from the application and board models.
BASE_SET & reset(size_t pos)
BASE_SET & set(size_t pos)
void RevertToCheckpoint(int aCheckpoint) override
Container for design settings for a BOARD object.
bool m_TextUpright[LAYER_CLASS_COUNT]
int m_TextThickness[LAYER_CLASS_COUNT]
int m_LineThickness[LAYER_CLASS_COUNT]
VECTOR2I m_TextSize[LAYER_CLASS_COUNT]
bool m_TextItalic[LAYER_CLASS_COUNT]
Abstract interface for BOARD_ITEMs capable of storing other items inside.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual void CopyFrom(const BOARD_ITEM *aOther)
BOARD_ITEM_CONTAINER * GetParent() const
virtual void Normalize()
Perform any normalization required after a user rotate and/or flip.
virtual void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection)
Flip this object, i.e.
Information pertinent to a Pcbnew printed circuit board.
void SetVisibleLayers(const LSET &aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings changes the bit-mask of vis...
const BOX2I GetBoardEdgesBoundingBox() const
Return the board bounding box calculated using exclusively the board edges (graphics on Edge....
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false, bool aPhysicalLayersOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
BOARD_ITEM * ResolveItem(const KIID &aID, bool aAllowNullptrReturn=false) const
void SaveBoard(const wxString &aFileName, BOARD &aBoard, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Write aBoard to a storage file in a format that this PCB_IO implementation knows about or it can be u...
void SaveSelection(const PCB_SELECTION &selected, bool isFootprintEditor)
void SetWriter(std::function< void(const wxString &)> aWriter)
void SetBoard(BOARD *aBoard)
Represent a set of changes (additions, deletions or modifications) of a data model (e....
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
The base frame for deriving all KiCad main window classes.
The base class for create windows for drawing purpose.
A set of EDA_ITEMs (i.e., without duplicates).
virtual void FinalizeGroupDeserialization()
void AddItem(EDA_ITEM *aItem)
Add item to group.
A base class for most all the KiCad significant classes used in schematics and boards.
virtual VECTOR2I GetPosition() const
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
virtual EDA_GROUP * GetParentGroup() const
KICAD_T Type() const
Returns the type of object.
virtual void SetParentGroup(EDA_GROUP *aGroup)
virtual wxString GetFriendlyName() const
virtual void SetParent(EDA_ITEM *aParent)
std::string AsStdString() const
LSET is a set of PCB_LAYER_IDs.
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
static TOOL_ACTION genRemove
static TOOL_ACTION move
move or drag an item
Common, abstract interface for edit frames.
APPEARANCE_CONTROLS * GetAppearancePanel()
virtual void SetActiveLayer(PCB_LAYER_ID aLayer)
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
virtual PCB_LAYER_ID GetActiveLayer() const
void SyncLayersVisibility(const BOARD *aBoard)
Update "visibility" property of each layer of a given BOARD.
A set of BOARD_ITEMs (i.e., without duplicates).
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
void SetReferencePoint(const VECTOR2I &aP)
virtual void Serialize(google::protobuf::Any &aContainer) const
Serializes this object to the given Any message.
virtual bool Deserialize(const google::protobuf::Any &aContainer)
Deserializes the given protobuf message into this object.
Represent a set of closed polygons.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, RESOLUTION_CONTEXT aContext)
PCB_LAYER_ID
A quick note on layer IDs:
void PackLayerSet(google::protobuf::RepeatedField< int > &aOutput, const LSET &aLayerSet)
void PackBoardStackup(const BOARD &aBoard, BoardStackup &aOut)
KICOMMON_API int UnpackDistance(const types::Distance &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API std::optional< KICAD_T > TypeNameFromAny(const google::protobuf::Any &aMessage)
KICOMMON_API ApiResponseStatus MakeResponseStatus(ApiStatusCode aCode, const std::string &aMessage)
KICOMMON_API void PackBox2(types::Box2 &aOutput, const BOX2I &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API std::optional< wxString > GeneratorTypeFromAny(const google::protobuf::Any &aMessage)
KICOMMON_API void PackPolyLine(types::PolyLine &aOutput, const SHAPE_LINE_CHAIN &aSlc, const EDA_IU_SCALE &aScale)
Class to handle a set of BOARD_ITEMs.
bool IsGeneratedTableCell(const EDA_ITEM *aItem)
True for a cell whose text is generated from the board, so only its formatting is the user's.
std::vector< EDA_ITEM * > EDA_ITEMS
RequestMessageType Request
wxString result
Test unit parsing edge cases and error handling.
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
@ PCB_CONSTRAINT_T
a geometric constraint between board items
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
@ PCB_GENERATOR_T
class PCB_GENERATOR, generator on a layer
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
@ PCB_ZONE_T
class ZONE, a copper pour area
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_REFERENCE_IMAGE_T
class PCB_REFERENCE_IMAGE, bitmap on a layer
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
@ PCB_MARKER_T
class PCB_MARKER, a marker used to show something
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
@ PCB_GRID_ITEM_T
a subgrid placed on a board
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
@ PCB_PAD_T
class PAD, a pad in a footprint
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
@ PCB_POINT_T
class PCB_POINT, a 0-dimensional point
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension