21#include <magic_enum.hpp>
47#include <api/common/types/base_types.pb.h>
50using namespace kiapi::common::commands;
51using types::CommandStatus;
52using types::DocumentType;
53using types::ItemRequestStatus;
60 registerHandler<GetOpenDocuments, GetOpenDocumentsResponse>(
72 registerHandler<RemoveFromSelection, SelectionResponse>(
76 registerHandler<GetGraphicsDefaults, GraphicsDefaultsResponse>(
78 registerHandler<GetBoundingBox, GetBoundingBoxResponse>(
80 registerHandler<GetPadShapeAsPolygon, PadShapeAsPolygonResponse>(
82 registerHandler<CheckPadstackPresenceOnLayers, PadstackPresenceResponse>(
84 registerHandler<GetTitleBlockInfo, types::TitleBlockInfo>(
86 registerHandler<ExpandTextVariables, ExpandTextVariablesResponse>(
93 registerHandler<GetNetClassForNets, NetClassForNetsResponse>(
97 registerHandler<SaveDocumentToString, SavedDocumentResponse>(
99 registerHandler<SaveSelectionToString, SavedSelectionResponse>(
101 registerHandler<ParseAndCreateItemsFromString, CreateItemsResponse>(
107 registerHandler<GetBoardEditorAppearanceSettings, BoardEditorAppearanceSettings>(
109 registerHandler<SetBoardEditorAppearanceSettings, Empty>(
123 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
124 return tl::unexpected( *busy );
126 RunActionResponse response;
128 if(
frame()->GetToolManager()->RunAction( aCtx.
Request.action(),
true ) )
129 response.set_status( RunActionStatus::RAS_OK );
131 response.set_status( RunActionStatus::RAS_INVALID );
140 if( aCtx.
Request.type() != DocumentType::DOCTYPE_PCB )
144 e.set_status( ApiStatusCode::AS_UNHANDLED );
145 return tl::unexpected( e );
148 GetOpenDocumentsResponse response;
149 common::types::DocumentSpecifier doc;
151 wxFileName fn(
frame()->GetCurrentFileName() );
153 doc.set_type( DocumentType::DOCTYPE_PCB );
154 doc.set_board_filename( fn.GetFullName() );
156 doc.mutable_project()->set_name(
frame()->
Prj().GetProjectName().ToStdString() );
157 doc.mutable_project()->set_path(
frame()->
Prj().GetProjectDirectory().ToStdString() );
159 response.mutable_documents()->Add( std::move( doc ) );
167 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
168 return tl::unexpected( *busy );
172 if( !documentValidation )
173 return tl::unexpected( documentValidation.error() );
183 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
184 return tl::unexpected( *busy );
188 if( !documentValidation )
189 return tl::unexpected( documentValidation.error() );
191 wxFileName boardPath(
frame()->
Prj().AbsolutePath( wxString::FromUTF8( aCtx.
Request.path() ) ) );
193 if( !boardPath.IsOk() || !boardPath.IsDirWritable() )
196 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
197 e.set_error_message( fmt::format(
"save path '{}' could not be opened",
198 boardPath.GetFullPath().ToStdString() ) );
199 return tl::unexpected( e );
202 if( boardPath.FileExists()
203 && ( !boardPath.IsFileWritable() || !aCtx.
Request.options().overwrite() ) )
206 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
207 e.set_error_message( fmt::format(
"save path '{}' exists and cannot be overwritten",
208 boardPath.GetFullPath().ToStdString() ) );
209 return tl::unexpected( e );
215 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
216 e.set_error_message( fmt::format(
"save path '{}' must have a kicad_pcb extension",
217 boardPath.GetFullPath().ToStdString() ) );
218 return tl::unexpected( e );
223 if( board->
GetFileName().Matches( boardPath.GetFullPath() ) )
229 bool includeProject =
true;
231 if( aCtx.
Request.has_options() )
232 includeProject = aCtx.
Request.options().include_project();
243 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
244 return tl::unexpected( *busy );
248 if( !documentValidation )
249 return tl::unexpected( documentValidation.error() );
270 return std::make_unique<BOARD_COMMIT>(
frame() );
287 if( aDocument.type() != DocumentType::DOCTYPE_PCB )
290 wxFileName fn(
frame()->GetCurrentFileName() );
291 return 0 == aDocument.board_filename().compare( fn.GetFullName() );
301 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
302 e.set_error_message(
"Tried to create an item in a null container" );
303 return tl::unexpected( e );
309 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
310 e.set_error_message( fmt::format(
"Tried to create a pad in {}, which is not a footprint",
312 return tl::unexpected( e );
317 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
318 e.set_error_message( fmt::format(
"Tried to create a footprint in {}, which is not a board",
320 return tl::unexpected( e );
328 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
329 e.set_error_message( fmt::format(
"Tried to create an item of type {}, which is unhandled",
330 magic_enum::enum_name( aType ) ) );
331 return tl::unexpected( e );
339 const std::string& aClientName,
340 const types::ItemHeader &aHeader,
341 const google::protobuf::RepeatedPtrField<google::protobuf::Any>& aItems,
342 std::function<
void( ItemStatus, google::protobuf::Any )> aItemHandler )
348 if( !containerResult && containerResult.error().status() == ApiStatusCode::AS_UNHANDLED )
351 e.set_status( ApiStatusCode::AS_UNHANDLED );
352 return tl::unexpected( e );
354 else if( !containerResult )
356 e.CopyFrom( containerResult.error() );
357 return tl::unexpected( e );
363 if( containerResult->has_value() )
365 const KIID& containerId = **containerResult;
366 std::optional<BOARD_ITEM*> optItem =
getItemById( containerId );
374 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
375 e.set_error_message( fmt::format(
376 "The requested container {} is not a valid board item container",
378 return tl::unexpected( e );
383 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
384 e.set_error_message( fmt::format(
385 "The requested container {} does not exist in this document",
387 return tl::unexpected( e );
393 for(
const google::protobuf::Any& anyItem : aItems )
400 status.set_code( ItemStatusCode::ISC_INVALID_TYPE );
401 status.set_error_message( fmt::format(
"Could not decode a valid type from {}",
402 anyItem.type_url() ) );
403 aItemHandler( status, anyItem );
409 board::types::Dimension dimension;
410 anyItem.UnpackTo( &dimension );
412 switch( dimension.dimension_style_case() )
419 case board::types::Dimension::DIMENSION_STYLE_NOT_SET:
break;
426 if( !creationResult )
428 status.set_code( ItemStatusCode::ISC_INVALID_TYPE );
429 status.set_error_message( creationResult.error().error_message() );
430 aItemHandler( status, anyItem );
434 std::unique_ptr<BOARD_ITEM> item( std::move( *creationResult ) );
436 if( !item->Deserialize( anyItem ) )
438 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
439 e.set_error_message( fmt::format(
"could not unpack {} from request",
440 item->GetClass().ToStdString() ) );
441 return tl::unexpected( e );
444 std::optional<BOARD_ITEM*> optItem =
getItemById( item->m_Uuid );
446 if( aCreate && optItem )
448 status.set_code( ItemStatusCode::ISC_EXISTING );
449 status.set_error_message( fmt::format(
"an item with UUID {} already exists",
450 item->m_Uuid.AsStdString() ) );
451 aItemHandler( status, anyItem );
454 else if( !aCreate && !optItem )
456 status.set_code( ItemStatusCode::ISC_NONEXISTENT );
457 status.set_error_message( fmt::format(
"an item with UUID {} does not exist",
458 item->m_Uuid.AsStdString() ) );
459 aItemHandler( status, anyItem );
465 status.set_code( ItemStatusCode::ISC_INVALID_DATA );
466 status.set_error_message(
467 "attempted to add item with no overlapping layers with the board" );
468 aItemHandler( status, anyItem );
472 status.set_code( ItemStatusCode::ISC_OK );
473 google::protobuf::Any newItem;
477 item->Serialize( newItem );
478 commit->
Add( item.release() );
492 commit->
Remove( boardItem );
493 item->Serialize( newItem );
494 commit->
Add( item.release() );
498 commit->
Modify( boardItem );
504 aItemHandler( status, newItem );
510 :
_(
"Modified items via API" ) );
514 return ItemRequestStatus::IRS_OK;
521 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
522 return tl::unexpected( *busy );
528 e.set_status( ApiStatusCode::AS_UNHANDLED );
529 return tl::unexpected( e );
532 GetItemsResponse response;
535 std::vector<BOARD_ITEM*> items;
536 std::set<KICAD_T> typesRequested, typesInserted;
537 bool handledAnything =
false;
539 for(
int typeRaw : aCtx.
Request.types() )
541 auto typeMessage =
static_cast<common::types::KiCadObjectType
>( typeRaw );
542 KICAD_T type = FromProtoEnum<KICAD_T>( typeMessage );
547 typesRequested.emplace( type );
549 if( typesInserted.count( type ) )
557 handledAnything =
true;
558 std::copy( board->
Tracks().begin(), board->
Tracks().end(),
559 std::back_inserter( items ) );
565 handledAnything =
true;
569 std::copy( fp->Pads().begin(), fp->Pads().end(),
570 std::back_inserter( items ) );
579 handledAnything =
true;
582 std::back_inserter( items ) );
592 handledAnything =
true;
593 bool inserted =
false;
597 if( item->Type() == type )
599 items.emplace_back( item );
612 handledAnything =
true;
614 std::copy( board->
Zones().begin(), board->
Zones().end(),
615 std::back_inserter( items ) );
623 handledAnything =
true;
625 std::copy( board->
Groups().begin(), board->
Groups().end(),
626 std::back_inserter( items ) );
636 if( !handledAnything )
639 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
640 e.set_error_message(
"none of the requested types are valid for a Board object" );
641 return tl::unexpected( e );
646 if( !typesRequested.count( item->Type() ) )
649 google::protobuf::Any itemBuf;
650 item->Serialize( itemBuf );
651 response.mutable_items()->Add( std::move( itemBuf ) );
654 response.set_status( ItemRequestStatus::IRS_OK );
662 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
663 return tl::unexpected( *busy );
668 e.set_status( ApiStatusCode::AS_UNHANDLED );
669 return tl::unexpected( e );
672 GetItemsResponse response;
674 std::vector<BOARD_ITEM*> items;
676 for(
const kiapi::common::types::KIID&
id : aCtx.
Request.items() )
678 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
679 items.emplace_back( *item );
685 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
686 e.set_error_message(
"none of the requested IDs were found or valid" );
687 return tl::unexpected( e );
692 google::protobuf::Any itemBuf;
693 item->Serialize( itemBuf );
694 response.mutable_items()->Add( std::move( itemBuf ) );
697 response.set_status( ItemRequestStatus::IRS_OK );
702 const std::string& aClientName )
705 std::vector<BOARD_ITEM*> validatedItems;
707 for( std::pair<const KIID, ItemDeletionStatus> pair : aItemsToDelete )
711 validatedItems.push_back( item );
712 aItemsToDelete[pair.first] = ItemDeletionStatus::IDS_OK;
746 e.set_status( ApiStatusCode::AS_UNHANDLED );
747 return tl::unexpected( e );
752 for(
int typeRaw : aCtx.
Request.types() )
754 auto typeMessage =
static_cast<types::KiCadObjectType
>( typeRaw );
755 KICAD_T type = FromProtoEnum<KICAD_T>( typeMessage );
766 SelectionResponse response;
771 item->Serialize( *response.add_items() );
781 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
782 return tl::unexpected( *busy );
788 e.set_status( ApiStatusCode::AS_UNHANDLED );
789 return tl::unexpected( e );
803 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
804 return tl::unexpected( *busy );
810 e.set_status( ApiStatusCode::AS_UNHANDLED );
811 return tl::unexpected( e );
817 std::vector<EDA_ITEM*> toAdd;
819 for(
const types::KIID&
id : aCtx.
Request.items() )
821 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
822 toAdd.emplace_back( *item );
828 SelectionResponse response;
831 item->Serialize( *response.add_items() );
840 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
841 return tl::unexpected( *busy );
847 e.set_status( ApiStatusCode::AS_UNHANDLED );
848 return tl::unexpected( e );
854 std::vector<EDA_ITEM*> toRemove;
856 for(
const types::KIID&
id : aCtx.
Request.items() )
858 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
859 toRemove.emplace_back( *item );
865 SelectionResponse response;
868 item->Serialize( *response.add_items() );
879 if( !documentValidation )
880 return tl::unexpected( documentValidation.error() );
882 BoardStackupResponse response;
883 google::protobuf::Any any;
887 any.UnpackTo( response.mutable_stackup() );
890 for( board::BoardStackupLayer& layer : *response.mutable_stackup()->mutable_layers() )
892 if( layer.type() == board::BoardStackupLayerType::BSLT_DIELECTRIC )
895 PCB_LAYER_ID id = FromProtoEnum<PCB_LAYER_ID>( layer.layer() );
898 layer.set_user_name(
frame()->
GetBoard()->GetLayerName(
id ) );
910 if( !documentValidation )
911 return tl::unexpected( documentValidation.error() );
914 GraphicsDefaultsResponse response;
917 constexpr std::array<kiapi::board::BoardLayerClass, LAYER_CLASS_COUNT> classOrder = {
918 kiapi::board::BLC_SILKSCREEN,
919 kiapi::board::BLC_COPPER,
920 kiapi::board::BLC_EDGES,
921 kiapi::board::BLC_COURTYARD,
922 kiapi::board::BLC_FABRICATION,
923 kiapi::board::BLC_OTHER
928 kiapi::board::BoardLayerGraphicsDefaults* l = response.mutable_defaults()->add_layers();
930 l->set_layer( classOrder[i] );
933 kiapi::common::types::TextAttributes*
text = l->mutable_text();
949 !documentValidation )
951 return tl::unexpected( documentValidation.error() );
971 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
972 e.set_error_message(
"Unexpected origin type" );
973 return tl::unexpected( e );
977 types::Vector2 reply;
985 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
986 return tl::unexpected( *busy );
989 !documentValidation )
991 return tl::unexpected( documentValidation.error() );
1002 frame()->CallAfter( [f, origin]()
1017 frame()->CallAfter( [f, origin]()
1029 ApiResponseStatus e;
1030 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1031 e.set_error_message(
"Unexpected origin type" );
1032 return tl::unexpected( e );
1043 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1044 return tl::unexpected( *busy );
1048 ApiResponseStatus e;
1050 e.set_status( ApiStatusCode::AS_UNHANDLED );
1051 return tl::unexpected( e );
1054 GetBoundingBoxResponse response;
1055 bool includeText = aCtx.
Request.mode() == BoundingBoxMode::BBM_ITEM_AND_CHILD_TEXT;
1057 for(
const types::KIID& idMsg : aCtx.
Request.items() )
1059 KIID id( idMsg.value() );
1060 std::optional<BOARD_ITEM*> optItem =
getItemById(
id );
1069 bbox =
static_cast<FOOTPRINT*
>( item )->GetBoundingBox( includeText );
1073 response.add_items()->set_value( idMsg.value() );
1074 PackBox2( *response.add_boxes(), bbox );
1085 !documentValidation )
1087 return tl::unexpected( documentValidation.error() );
1090 PadShapeAsPolygonResponse response;
1091 PCB_LAYER_ID layer = FromProtoEnum<PCB_LAYER_ID, board::types::BoardLayer>( aCtx.
Request.layer() );
1093 for(
const types::KIID& padRequest : aCtx.
Request.pads() )
1095 KIID id( padRequest.value() );
1096 std::optional<BOARD_ITEM*> optPad =
getItemById(
id );
1098 if( !optPad || ( *optPad )->Type() !=
PCB_PAD_T )
1101 response.add_pads()->set_value( padRequest.value() );
1103 PAD*
pad =
static_cast<PAD*
>( *optPad );
1105 pad->TransformShapeToPolygon( poly,
pad->Padstack().EffectiveLayerFor( layer ), 0,
1108 types::PolygonWithHoles* polyMsg = response.mutable_polygons()->Add();
1119 using board::types::BoardLayer;
1122 !documentValidation )
1124 return tl::unexpected( documentValidation.error() );
1127 PadstackPresenceResponse response;
1131 for(
const int layer : aCtx.
Request.layers() )
1132 layers.
set( FromProtoEnum<PCB_LAYER_ID, BoardLayer>(
static_cast<BoardLayer
>( layer ) ) );
1134 for(
const types::KIID& padRequest : aCtx.
Request.items() )
1136 KIID id( padRequest.value() );
1137 std::optional<BOARD_ITEM*> optItem =
getItemById(
id );
1142 switch( ( *optItem )->Type() )
1146 PAD*
pad =
static_cast<PAD*
>( *optItem );
1150 PadstackPresenceEntry* entry = response.add_entries();
1151 entry->mutable_item()->set_value(
pad->m_Uuid.AsStdString() );
1152 entry->set_layer( ToProtoEnum<PCB_LAYER_ID, BoardLayer>( layer ) );
1153 entry->set_presence(
pad->FlashLayer( layer ) ? PSP_PRESENT : PSP_NOT_PRESENT );
1165 PadstackPresenceEntry* entry = response.add_entries();
1166 entry->mutable_item()->set_value(
via->m_Uuid.AsStdString() );
1167 entry->set_layer( ToProtoEnum<PCB_LAYER_ID, BoardLayer>( layer ) );
1168 entry->set_presence(
via->FlashLayer( layer ) ? PSP_PRESENT : PSP_NOT_PRESENT );
1188 if( !documentValidation )
1189 return tl::unexpected( documentValidation.error() );
1194 types::TitleBlockInfo response;
1196 response.set_title( block.
GetTitle().ToUTF8() );
1197 response.set_date( block.
GetDate().ToUTF8() );
1198 response.set_revision( block.
GetRevision().ToUTF8() );
1199 response.set_company( block.
GetCompany().ToUTF8() );
1200 response.set_comment1( block.
GetComment( 0 ).ToUTF8() );
1201 response.set_comment2( block.
GetComment( 1 ).ToUTF8() );
1202 response.set_comment3( block.
GetComment( 2 ).ToUTF8() );
1203 response.set_comment4( block.
GetComment( 3 ).ToUTF8() );
1204 response.set_comment5( block.
GetComment( 4 ).ToUTF8() );
1205 response.set_comment6( block.
GetComment( 5 ).ToUTF8() );
1206 response.set_comment7( block.
GetComment( 6 ).ToUTF8() );
1207 response.set_comment8( block.
GetComment( 7 ).ToUTF8() );
1208 response.set_comment9( block.
GetComment( 8 ).ToUTF8() );
1219 if( !documentValidation )
1220 return tl::unexpected( documentValidation.error() );
1222 ExpandTextVariablesResponse reply;
1225 std::function<bool( wxString* )> textResolver =
1226 [&]( wxString* token ) ->
bool
1232 for(
const std::string& textMsg : aCtx.
Request.text() )
1235 reply.add_text(
text.ToUTF8() );
1245 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1246 return tl::unexpected( *busy );
1250 if( !documentValidation )
1251 return tl::unexpected( documentValidation.error() );
1254 std::vector<EDA_ITEM*> toSelect;
1256 for(
const kiapi::common::types::KIID&
id : aCtx.
Request.items() )
1258 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
1259 toSelect.emplace_back(
static_cast<EDA_ITEM*
>( *item ) );
1262 if( toSelect.empty() )
1264 ApiResponseStatus e;
1265 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1266 e.set_error_message( fmt::format(
"None of the given items exist on the board",
1267 aCtx.
Request.board().board_filename() ) );
1268 return tl::unexpected( e );
1288 if( !documentValidation )
1289 return tl::unexpected( documentValidation.error() );
1291 NetsResponse response;
1294 std::set<wxString> netclassFilter;
1296 for(
const std::string& nc : aCtx.
Request.netclass_filter() )
1297 netclassFilter.insert( wxString( nc.c_str(), wxConvUTF8 ) );
1303 if( !netclassFilter.empty() && nc && !netclassFilter.count( nc->
GetName() ) )
1306 board::types::Net* netProto = response.add_nets();
1307 netProto->set_name( net->GetNetname() );
1308 netProto->mutable_code()->set_value( net->GetNetCode() );
1318 NetClassForNetsResponse response;
1322 google::protobuf::Any any;
1324 for(
const board::types::Net& net : aCtx.
Request.net() )
1332 auto [pair, rc] = response.mutable_classes()->insert( { net.name(), {} } );
1333 any.UnpackTo( &pair->second );
1342 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1343 return tl::unexpected( *busy );
1347 if( !documentValidation )
1348 return tl::unexpected( documentValidation.error() );
1350 if( aCtx.
Request.zones().empty() )
1353 frame()->CallAfter( [mgr]()
1361 ApiResponseStatus e;
1362 e.set_status( ApiStatusCode::AS_UNIMPLEMENTED );
1363 return tl::unexpected( e );
1375 if( !documentValidation )
1376 return tl::unexpected( documentValidation.error() );
1378 SavedDocumentResponse response;
1379 response.mutable_document()->CopyFrom( aCtx.
Request.document() );
1383 [&](
const wxString& aData )
1385 response.set_contents( aData.ToUTF8() );
1397 SavedSelectionResponse response;
1405 [&](
const wxString& aData )
1407 response.set_contents( aData.ToUTF8() );
1420 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1421 return tl::unexpected( *busy );
1425 if( !documentValidation )
1426 return tl::unexpected( documentValidation.error() );
1428 CreateItemsResponse response;
1438 if( !documentValidation )
1439 return tl::unexpected( documentValidation.error() );
1441 BoardLayers response;
1444 response.add_layers( ToProtoEnum<PCB_LAYER_ID, board::types::BoardLayer>( layer ) );
1453 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1454 return tl::unexpected( *busy );
1458 if( !documentValidation )
1459 return tl::unexpected( documentValidation.error() );
1464 for(
int layerIdx : aCtx.
Request.layers() )
1467 FromProtoEnum<PCB_LAYER_ID>(
static_cast<board::types::BoardLayer
>( layerIdx ) );
1470 visible.
set( layer );
1486 if( !documentValidation )
1487 return tl::unexpected( documentValidation.error() );
1489 BoardLayerResponse response;
1491 ToProtoEnum<PCB_LAYER_ID, board::types::BoardLayer>(
frame()->GetActiveLayer() ) );
1500 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1501 return tl::unexpected( *busy );
1505 if( !documentValidation )
1506 return tl::unexpected( documentValidation.error() );
1510 if( !
frame()->
GetBoard()->GetEnabledLayers().Contains( layer ) )
1512 ApiResponseStatus err;
1513 err.set_status( ApiStatusCode::AS_BAD_REQUEST );
1514 err.set_error_message( fmt::format(
"Layer {} is not a valid layer for the given board",
1515 magic_enum::enum_name( layer ) ) );
1516 return tl::unexpected( err );
1527 BoardEditorAppearanceSettings reply;
1533 reply.set_inactive_layer_display( ToProtoEnum<HIGH_CONTRAST_MODE, InactiveLayerDisplayMode>(
1535 reply.set_net_color_display(
1536 ToProtoEnum<NET_COLOR_MODE, NetColorDisplayMode>( displayOptions.
m_NetColorMode ) );
1538 reply.set_board_flip(
frame()->GetCanvas()->GetView()->IsMirroredX()
1539 ? BoardFlipMode::BFM_FLIPPED_X
1540 : BoardFlipMode::BFM_NORMAL );
1544 reply.set_ratsnest_display( ToProtoEnum<RATSNEST_MODE, RatsnestDisplayMode>(
1554 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1555 return tl::unexpected( *busy );
1560 const BoardEditorAppearanceSettings& newSettings = aCtx.
Request.settings();
1563 FromProtoEnum<HIGH_CONTRAST_MODE>( newSettings.inactive_layer_display() );
1565 FromProtoEnum<NET_COLOR_MODE>( newSettings.net_color_display() );
1567 bool flip = newSettings.board_flip() == BoardFlipMode::BFM_FLIPPED_X;
1576 FromProtoEnum<RATSNEST_MODE>( newSettings.ratsnest_display() );
tl::expected< T, ApiResponseStatus > HANDLER_RESULT
std::unique_ptr< EDA_ITEM > CreateItemForType(KICAD_T aType, EDA_ITEM *aContainer)
static TOOL_ACTION selectionClear
Clear the current selection.
static TOOL_ACTION gridSetOrigin
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Base class for API handlers related to editor frames.
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.
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.
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 > handleInteractiveMoveItems(const HANDLER_CONTEXT< InteractiveMoveItems > &aCtx)
bool validateDocumentInternal(const DocumentSpecifier &aDocument) const override
HANDLER_RESULT< Empty > handleSetActiveLayer(const HANDLER_CONTEXT< SetActiveLayer > &aCtx)
API_HANDLER_PCB(PCB_EDIT_FRAME *aFrame)
static HANDLER_RESULT< std::unique_ptr< BOARD_ITEM > > createItemForType(KICAD_T aType, BOARD_ITEM_CONTAINER *aContainer)
std::optional< BOARD_ITEM * > getItemById(const KIID &aId) const
HANDLER_RESULT< types::Vector2 > handleGetBoardOrigin(const HANDLER_CONTEXT< GetBoardOrigin > &aCtx)
std::unique_ptr< COMMIT > createCommit() override
Override this to create an appropriate COMMIT subclass for the frame in question.
HANDLER_RESULT< BoardStackupResponse > handleGetStackup(const HANDLER_CONTEXT< GetBoardStackup > &aCtx)
HANDLER_RESULT< types::TitleBlockInfo > handleGetTitleBlockInfo(const HANDLER_CONTEXT< commands::GetTitleBlockInfo > &aCtx)
HANDLER_RESULT< commands::SelectionResponse > handleGetSelection(const HANDLER_CONTEXT< commands::GetSelection > &aCtx)
HANDLER_RESULT< NetClassForNetsResponse > handleGetNetClassForNets(const HANDLER_CONTEXT< GetNetClassForNets > &aCtx)
std::optional< EDA_ITEM * > getItemFromDocument(const DocumentSpecifier &aDocument, const KIID &aId) override
HANDLER_RESULT< commands::ExpandTextVariablesResponse > handleExpandTextVariables(const HANDLER_CONTEXT< commands::ExpandTextVariables > &aCtx)
HANDLER_RESULT< Empty > handleSetVisibleLayers(const HANDLER_CONTEXT< SetVisibleLayers > &aCtx)
HANDLER_RESULT< Empty > handleSaveCopyOfDocument(const HANDLER_CONTEXT< commands::SaveCopyOfDocument > &aCtx)
HANDLER_RESULT< GraphicsDefaultsResponse > handleGetGraphicsDefaults(const HANDLER_CONTEXT< GetGraphicsDefaults > &aCtx)
HANDLER_RESULT< commands::GetItemsResponse > handleGetItemsById(const HANDLER_CONTEXT< commands::GetItemsById > &aCtx)
HANDLER_RESULT< Empty > handleSetBoardOrigin(const HANDLER_CONTEXT< SetBoardOrigin > &aCtx)
HANDLER_RESULT< Empty > handleClearSelection(const HANDLER_CONTEXT< commands::ClearSelection > &aCtx)
HANDLER_RESULT< commands::RunActionResponse > handleRunAction(const HANDLER_CONTEXT< commands::RunAction > &aCtx)
HANDLER_RESULT< BoardLayers > handleGetVisibleLayers(const HANDLER_CONTEXT< GetVisibleLayers > &aCtx)
HANDLER_RESULT< PadstackPresenceResponse > handleCheckPadstackPresenceOnLayers(const HANDLER_CONTEXT< CheckPadstackPresenceOnLayers > &aCtx)
HANDLER_RESULT< commands::SelectionResponse > handleRemoveFromSelection(const HANDLER_CONTEXT< commands::RemoveFromSelection > &aCtx)
HANDLER_RESULT< commands::GetOpenDocumentsResponse > handleGetOpenDocuments(const HANDLER_CONTEXT< commands::GetOpenDocuments > &aCtx)
HANDLER_RESULT< BoardEditorAppearanceSettings > handleGetBoardEditorAppearanceSettings(const HANDLER_CONTEXT< GetBoardEditorAppearanceSettings > &aCtx)
HANDLER_RESULT< NetsResponse > handleGetNets(const HANDLER_CONTEXT< GetNets > &aCtx)
HANDLER_RESULT< commands::SavedDocumentResponse > handleSaveDocumentToString(const HANDLER_CONTEXT< commands::SaveDocumentToString > &aCtx)
HANDLER_RESULT< commands::GetBoundingBoxResponse > handleGetBoundingBox(const HANDLER_CONTEXT< commands::GetBoundingBox > &aCtx)
HANDLER_RESULT< Empty > handleSaveDocument(const HANDLER_CONTEXT< commands::SaveDocument > &aCtx)
void deleteItemsInternal(std::map< KIID, ItemDeletionStatus > &aItemsToDelete, const std::string &aClientName) override
HANDLER_RESULT< commands::GetItemsResponse > handleGetItems(const HANDLER_CONTEXT< commands::GetItems > &aCtx)
HANDLER_RESULT< PadShapeAsPolygonResponse > handleGetPadShapeAsPolygon(const HANDLER_CONTEXT< GetPadShapeAsPolygon > &aCtx)
PCB_EDIT_FRAME * frame() const
HANDLER_RESULT< Empty > handleSetBoardEditorAppearanceSettings(const HANDLER_CONTEXT< SetBoardEditorAppearanceSettings > &aCtx)
HANDLER_RESULT< Empty > handleRefillZones(const HANDLER_CONTEXT< RefillZones > &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< BoardLayerResponse > handleGetActiveLayer(const HANDLER_CONTEXT< GetActiveLayer > &aCtx)
HANDLER_RESULT< Empty > handleRevertDocument(const HANDLER_CONTEXT< commands::RevertDocument > &aCtx)
HANDLER_RESULT< commands::SavedSelectionResponse > handleSaveSelectionToString(const HANDLER_CONTEXT< commands::SaveSelectionToString > &aCtx)
void pushCurrentCommit(const std::string &aClientName, const wxString &aMessage) override
void SetContentModified(bool aModified=true)
BASE_SET & set(size_t pos)
Container for design settings for a BOARD object.
bool m_TextUpright[LAYER_CLASS_COUNT]
const VECTOR2I & GetGridOrigin() const
const VECTOR2I & GetAuxOrigin() const
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)
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Information pertinent to a Pcbnew printed circuit board.
BOARD_STACKUP GetStackupOrDefault() const
const NETINFO_LIST & GetNetInfo() const
void SetVisibleLayers(const LSET &aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings changes the bit-mask of vis...
const ZONES & Zones() const
const GROUPS & Groups() const
The groups must maintain the following invariants.
bool ResolveTextVar(wxString *token, int aDepth) const
TITLE_BLOCK & GetTitleBlock()
const FOOTPRINTS & Footprints() const
const TRACKS & Tracks() const
const wxString & GetFileName() const
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
BOARD_ITEM * ResolveItem(const KIID &aID, bool aAllowNullptrReturn=false) const
const DRAWINGS & Drawings() const
void SaveSelection(const PCB_SELECTION &selected, bool isFootprintEditor)
void SetWriter(std::function< void(const wxString &)> aWriter)
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 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.
void ReleaseFile()
Release the current file marked in use.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
A base class for most all the KiCad significant classes used in schematics and boards.
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
KICAD_T Type() const
Returns the type of object.
virtual wxString GetFriendlyName() const
void SetMirror(bool aMirrorX, bool aMirrorY)
Control the mirroring of the VIEW.
void UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
bool IsMirroredX() const
Return true if view is flipped across the X axis.
void RecacheAllItems()
Rebuild GAL display lists.
bool IsMirroredY() const
Return true if view is flipped across the Y axis.
std::string AsStdString() const
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
LSET is a set of PCB_LAYER_IDs.
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
A collection of nets and the parameters used to route or test these nets.
const wxString GetName() const
Gets the name of this (maybe aggregate) netclass in a format for internal usage or for export to exte...
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Handle the data for a net.
Container for NETINFO_ITEM elements, which are the nets.
NETINFO_ITEM * GetNetItem(int aNetCode) const
DISPLAY_OPTIONS m_Display
static TOOL_ACTION zoneFillAll
static TOOL_ACTION move
move or drag an item
static TOOL_ACTION drillSetOrigin
APPEARANCE_CONTROLS * GetAppearancePanel()
const PCB_DISPLAY_OPTIONS & GetDisplayOptions() const
Display options control the way tracks, vias, outlines and other things are shown (for instance solid...
PCBNEW_SETTINGS * GetPcbNewSettings() const
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
void SetDisplayOptions(const PCB_DISPLAY_OPTIONS &aOptions, bool aRefresh=true)
Update the current display options.
HIGH_CONTRAST_MODE m_ContrastModeDisplay
How inactive layers are displayed.
NET_COLOR_MODE m_NetColorMode
How to use color overrides on specific nets and netclasses.
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
void SyncLayersVisibility(const BOARD *aBoard)
Update "visibility" property of each layer of a given BOARD.
The main frame for Pcbnew.
void SetActiveLayer(PCB_LAYER_ID aLayer) override
Change the currently active layer to aLayer and also update the APPEARANCE_CONTROLS.
bool SaveBoard(bool aSaveAs=false, bool aSaveCopy=false)
bool OpenProjectFiles(const std::vector< wxString > &aFileSet, int aCtl=0) override
Load a KiCad board (.kicad_pcb) from aFileName.
bool SavePcbCopy(const wxString &aFileName, bool aCreateProject=false, bool aHeadless=false)
Write the board data structures to aFileName.
virtual const wxString AbsolutePath(const wxString &aFileName) const
Fix up aFileName if it is relative to the project's directory to be an absolute path and filename.
void SetReferencePoint(const VECTOR2I &aP)
virtual void Serialize(google::protobuf::Any &aContainer) const
Serializes this object to the given Any message.
Represent a set of closed polygons.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
Hold the information shown in the lower right corner of a plot, printout, or editing view.
const wxString & GetCompany() const
const wxString & GetRevision() const
const wxString & GetDate() const
const wxString & GetComment(int aIdx) const
const wxString & GetTitle() const
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
static const std::string KiCadPcbFileExtension
#define KICTL_REVERT
reverting to a previously-saved (KiCad) file.
PCB_LAYER_ID
A quick note on layer IDs:
KICOMMON_API void PackBox2(types::Box2 &aOutput, const BOX2I &aInput)
KICOMMON_API std::optional< KICAD_T > TypeNameFromAny(const google::protobuf::Any &aMessage)
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput)
KICOMMON_API void PackVector2(types::Vector2 &aOutput, const VECTOR2I &aInput)
KICOMMON_API void PackPolyLine(types::PolyLine &aOutput, const SHAPE_LINE_CHAIN &aSlc)
Class to handle a set of BOARD_ITEMs.
RequestMessageType Request
RATSNEST_MODE m_RatsnestMode
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
@ 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_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_FOOTPRINT_T
class FOOTPRINT, a footprint
@ 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_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
VECTOR2< double > VECTOR2D