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;
127 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
128 return tl::unexpected( *busy );
130 RunActionResponse response;
132 if(
frame()->GetToolManager()->RunAction( aCtx.
Request.action(),
true ) )
133 response.set_status( RunActionStatus::RAS_OK );
135 response.set_status( RunActionStatus::RAS_INVALID );
144 if( aCtx.
Request.type() != DocumentType::DOCTYPE_PCB )
148 e.set_status( ApiStatusCode::AS_UNHANDLED );
149 return tl::unexpected( e );
152 GetOpenDocumentsResponse response;
153 common::types::DocumentSpecifier doc;
155 wxFileName fn(
frame()->GetCurrentFileName() );
157 doc.set_type( DocumentType::DOCTYPE_PCB );
158 doc.set_board_filename( fn.GetFullName() );
160 doc.mutable_project()->set_name(
frame()->
Prj().GetProjectName().ToStdString() );
161 doc.mutable_project()->set_path(
frame()->
Prj().GetProjectDirectory().ToStdString() );
163 response.mutable_documents()->Add( std::move( doc ) );
171 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
172 return tl::unexpected( *busy );
176 if( !documentValidation )
177 return tl::unexpected( documentValidation.error() );
187 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
188 return tl::unexpected( *busy );
192 if( !documentValidation )
193 return tl::unexpected( documentValidation.error() );
195 wxFileName boardPath(
frame()->
Prj().AbsolutePath( wxString::FromUTF8( aCtx.
Request.path() ) ) );
197 if( !boardPath.IsOk() || !boardPath.IsDirWritable() )
200 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
201 e.set_error_message( fmt::format(
"save path '{}' could not be opened",
202 boardPath.GetFullPath().ToStdString() ) );
203 return tl::unexpected( e );
206 if( boardPath.FileExists()
207 && ( !boardPath.IsFileWritable() || !aCtx.
Request.options().overwrite() ) )
210 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
211 e.set_error_message( fmt::format(
"save path '{}' exists and cannot be overwritten",
212 boardPath.GetFullPath().ToStdString() ) );
213 return tl::unexpected( e );
219 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
220 e.set_error_message( fmt::format(
"save path '{}' must have a kicad_pcb extension",
221 boardPath.GetFullPath().ToStdString() ) );
222 return tl::unexpected( e );
227 if(
board->GetFileName().Matches( boardPath.GetFullPath() ) )
233 bool includeProject =
true;
235 if( aCtx.
Request.has_options() )
236 includeProject = aCtx.
Request.options().include_project();
247 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
248 return tl::unexpected( *busy );
252 if( !documentValidation )
253 return tl::unexpected( documentValidation.error() );
274 return std::make_unique<BOARD_COMMIT>(
frame() );
291 if( aDocument.type() != DocumentType::DOCTYPE_PCB )
294 wxFileName fn(
frame()->GetCurrentFileName() );
295 return 0 == aDocument.board_filename().compare( fn.GetFullName() );
305 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
306 e.set_error_message(
"Tried to create an item in a null container" );
307 return tl::unexpected( e );
313 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
314 e.set_error_message( fmt::format(
"Tried to create a pad in {}, which is not a footprint",
316 return tl::unexpected( e );
321 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
322 e.set_error_message( fmt::format(
"Tried to create a footprint in {}, which is not a board",
324 return tl::unexpected( e );
332 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
333 e.set_error_message( fmt::format(
"Tried to create an item of type {}, which is unhandled",
334 magic_enum::enum_name( aType ) ) );
335 return tl::unexpected( e );
343 const std::string& aClientName,
344 const types::ItemHeader &aHeader,
345 const google::protobuf::RepeatedPtrField<google::protobuf::Any>& aItems,
346 std::function<
void( ItemStatus, google::protobuf::Any )> aItemHandler )
352 if( !containerResult && containerResult.error().status() == ApiStatusCode::AS_UNHANDLED )
355 e.set_status( ApiStatusCode::AS_UNHANDLED );
356 return tl::unexpected( e );
358 else if( !containerResult )
360 e.CopyFrom( containerResult.error() );
361 return tl::unexpected( e );
367 if( containerResult->has_value() )
369 const KIID& containerId = **containerResult;
370 std::optional<BOARD_ITEM*> optItem =
getItemById( containerId );
378 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
379 e.set_error_message( fmt::format(
380 "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(
389 "The requested container {} does not exist in this document",
391 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 {}",
406 anyItem.type_url() ) );
407 aItemHandler( status, anyItem );
413 board::types::Dimension dimension;
414 anyItem.UnpackTo( &dimension );
416 switch( dimension.dimension_style_case() )
423 case board::types::Dimension::DIMENSION_STYLE_NOT_SET:
break;
430 if( !creationResult )
432 status.set_code( ItemStatusCode::ISC_INVALID_TYPE );
433 status.set_error_message( creationResult.error().error_message() );
434 aItemHandler( status, anyItem );
438 std::unique_ptr<BOARD_ITEM> item( std::move( *creationResult ) );
440 if( !item->Deserialize( anyItem ) )
442 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
443 e.set_error_message( fmt::format(
"could not unpack {} from request",
444 item->GetClass().ToStdString() ) );
445 return tl::unexpected( e );
448 std::optional<BOARD_ITEM*> optItem =
getItemById( item->m_Uuid );
450 if( aCreate && optItem )
452 status.set_code( ItemStatusCode::ISC_EXISTING );
453 status.set_error_message( fmt::format(
"an item with UUID {} already exists",
454 item->m_Uuid.AsStdString() ) );
455 aItemHandler( status, anyItem );
458 else if( !aCreate && !optItem )
460 status.set_code( ItemStatusCode::ISC_NONEXISTENT );
461 status.set_error_message( fmt::format(
"an item with UUID {} does not exist",
462 item->m_Uuid.AsStdString() ) );
463 aItemHandler( status, anyItem );
467 if( aCreate && !(
board->GetEnabledLayers() & item->GetLayerSet() ).any() )
469 status.set_code( ItemStatusCode::ISC_INVALID_DATA );
470 status.set_error_message(
471 "attempted to add item with no overlapping layers with the board" );
472 aItemHandler( status, anyItem );
476 status.set_code( ItemStatusCode::ISC_OK );
477 google::protobuf::Any newItem;
481 item->Serialize( newItem );
482 commit->
Add( item.release() );
496 commit->
Remove( boardItem );
497 item->Serialize( newItem );
498 commit->
Add( item.release() );
502 commit->
Modify( boardItem );
508 aItemHandler( status, newItem );
514 :
_(
"Modified items via API" ) );
518 return ItemRequestStatus::IRS_OK;
524 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
525 return tl::unexpected( *busy );
531 e.set_status( ApiStatusCode::AS_UNHANDLED );
532 return tl::unexpected( e );
535 GetItemsResponse response;
538 std::vector<BOARD_ITEM*> items;
539 std::set<KICAD_T> typesRequested, typesInserted;
540 bool handledAnything =
false;
542 for(
int typeRaw : aCtx.
Request.types() )
544 auto typeMessage =
static_cast<common::types::KiCadObjectType
>( typeRaw );
550 typesRequested.emplace( type );
552 if( typesInserted.count( type ) )
560 handledAnything =
true;
561 std::copy(
board->Tracks().begin(),
board->Tracks().end(),
562 std::back_inserter( items ) );
568 handledAnything =
true;
572 std::copy( fp->Pads().begin(), fp->Pads().end(),
573 std::back_inserter( items ) );
582 handledAnything =
true;
584 std::copy(
board->Footprints().begin(),
board->Footprints().end(),
585 std::back_inserter( items ) );
596 handledAnything =
true;
597 bool inserted =
false;
601 if( item->Type() == type )
603 items.emplace_back( item );
609 typesInserted.insert( type );
616 handledAnything =
true;
618 std::copy(
board->Zones().begin(),
board->Zones().end(),
619 std::back_inserter( items ) );
627 handledAnything =
true;
629 std::copy(
board->Groups().begin(),
board->Groups().end(),
630 std::back_inserter( items ) );
640 if( !handledAnything )
643 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
644 e.set_error_message(
"none of the requested types are valid for a Board object" );
645 return tl::unexpected( e );
650 if( !typesRequested.count( item->Type() ) )
653 google::protobuf::Any itemBuf;
654 item->Serialize( itemBuf );
655 response.mutable_items()->Add( std::move( itemBuf ) );
658 response.set_status( ItemRequestStatus::IRS_OK );
666 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
667 return tl::unexpected( *busy );
672 e.set_status( ApiStatusCode::AS_UNHANDLED );
673 return tl::unexpected( e );
676 GetItemsResponse response;
678 std::vector<BOARD_ITEM*> items;
680 for(
const kiapi::common::types::KIID&
id : aCtx.
Request.items() )
682 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
683 items.emplace_back( *item );
689 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
690 e.set_error_message(
"none of the requested IDs were found or valid" );
691 return tl::unexpected( e );
696 google::protobuf::Any itemBuf;
697 item->Serialize( itemBuf );
698 response.mutable_items()->Add( std::move( itemBuf ) );
701 response.set_status( ItemRequestStatus::IRS_OK );
706 const std::string& aClientName )
709 std::vector<BOARD_ITEM*> validatedItems;
711 for( std::pair<const KIID, ItemDeletionStatus> pair : aItemsToDelete )
715 validatedItems.push_back( item );
716 aItemsToDelete[pair.first] = ItemDeletionStatus::IDS_OK;
750 e.set_status( ApiStatusCode::AS_UNHANDLED );
751 return tl::unexpected( e );
756 for(
int typeRaw : aCtx.
Request.types() )
758 auto typeMessage =
static_cast<types::KiCadObjectType
>( typeRaw );
770 SelectionResponse response;
775 item->Serialize( *response.add_items() );
785 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
786 return tl::unexpected( *busy );
792 e.set_status( ApiStatusCode::AS_UNHANDLED );
793 return tl::unexpected( e );
807 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
808 return tl::unexpected( *busy );
814 e.set_status( ApiStatusCode::AS_UNHANDLED );
815 return tl::unexpected( e );
821 std::vector<EDA_ITEM*> toAdd;
823 for(
const types::KIID&
id : aCtx.
Request.items() )
825 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
826 toAdd.emplace_back( *item );
832 SelectionResponse response;
835 item->Serialize( *response.add_items() );
844 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
845 return tl::unexpected( *busy );
851 e.set_status( ApiStatusCode::AS_UNHANDLED );
852 return tl::unexpected( e );
858 std::vector<EDA_ITEM*> toRemove;
860 for(
const types::KIID&
id : aCtx.
Request.items() )
862 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
863 toRemove.emplace_back( *item );
869 SelectionResponse response;
872 item->Serialize( *response.add_items() );
883 if( !documentValidation )
884 return tl::unexpected( documentValidation.error() );
886 BoardStackupResponse response;
887 google::protobuf::Any
any;
891 any.UnpackTo( response.mutable_stackup() );
894 for( board::BoardStackupLayer& layer : *response.mutable_stackup()->mutable_layers() )
896 if( layer.type() == board::BoardStackupLayerType::BSLT_DIELECTRIC )
902 layer.set_user_name(
frame()->
GetBoard()->GetLayerName(
id ) );
914 if( !documentValidation )
915 return tl::unexpected( documentValidation.error() );
917 BoardEnabledLayersResponse response;
920 int copperLayerCount =
board->GetCopperLayerCount();
922 response.set_copper_layer_count( copperLayerCount );
924 LSET enabled =
board->GetEnabledLayers();
943 if( !documentValidation )
944 return tl::unexpected( documentValidation.error() );
946 if( aCtx.
Request.copper_layer_count() % 2 != 0 )
949 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
950 e.set_error_message(
"copper_layer_count must be an even number" );
951 return tl::unexpected( e );
957 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
958 e.set_error_message( fmt::format(
"copper_layer_count must be below %d",
MAX_CU_LAYERS ) );
959 return tl::unexpected( e );
962 int copperLayerCount =
static_cast<int>( aCtx.
Request.copper_layer_count() );
967 enabled &=
~LSET::AllCuMask();
972 LSET previousEnabled =
board->GetEnabledLayers();
973 LSET changedLayers = enabled ^ previousEnabled;
975 board->SetEnabledLayers( enabled );
976 board->SetVisibleLayers(
board->GetVisibleLayers() | changedLayers );
982 if( !enabled[layer_id] &&
board->HasItemsOnLayer( layer_id ) )
983 removedLayers.push_back( layer_id );
986 bool modified =
false;
988 if( !removedLayers.empty() )
993 modified |=
board->RemoveAllItemsOnLayer( layer_id );
996 if( enabled != previousEnabled )
1002 BoardEnabledLayersResponse response;
1004 response.set_copper_layer_count( copperLayerCount );
1016 if( !documentValidation )
1017 return tl::unexpected( documentValidation.error() );
1020 GraphicsDefaultsResponse response;
1023 constexpr std::array<kiapi::board::BoardLayerClass, LAYER_CLASS_COUNT> classOrder = {
1024 kiapi::board::BLC_SILKSCREEN,
1025 kiapi::board::BLC_COPPER,
1026 kiapi::board::BLC_EDGES,
1027 kiapi::board::BLC_COURTYARD,
1028 kiapi::board::BLC_FABRICATION,
1029 kiapi::board::BLC_OTHER
1034 kiapi::board::BoardLayerGraphicsDefaults* l = response.mutable_defaults()->add_layers();
1036 l->set_layer( classOrder[i] );
1039 kiapi::common::types::TextAttributes*
text = l->mutable_text();
1055 !documentValidation )
1057 return tl::unexpected( documentValidation.error() );
1076 ApiResponseStatus e;
1077 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1078 e.set_error_message(
"Unexpected origin type" );
1079 return tl::unexpected( e );
1083 types::Vector2 reply;
1091 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1092 return tl::unexpected( *busy );
1095 !documentValidation )
1097 return tl::unexpected( documentValidation.error() );
1108 frame()->CallAfter( [f, origin]()
1123 frame()->CallAfter( [f, origin]()
1135 ApiResponseStatus e;
1136 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1137 e.set_error_message(
"Unexpected origin type" );
1138 return tl::unexpected( e );
1149 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1150 return tl::unexpected( *busy );
1154 ApiResponseStatus e;
1156 e.set_status( ApiStatusCode::AS_UNHANDLED );
1157 return tl::unexpected( e );
1160 GetBoundingBoxResponse response;
1161 bool includeText = aCtx.
Request.mode() == BoundingBoxMode::BBM_ITEM_AND_CHILD_TEXT;
1163 for(
const types::KIID& idMsg : aCtx.
Request.items() )
1165 KIID id( idMsg.value() );
1166 std::optional<BOARD_ITEM*> optItem =
getItemById(
id );
1175 bbox =
static_cast<FOOTPRINT*
>( item )->GetBoundingBox( includeText );
1179 response.add_items()->set_value( idMsg.value() );
1180 PackBox2( *response.add_boxes(), bbox );
1191 !documentValidation )
1193 return tl::unexpected( documentValidation.error() );
1196 PadShapeAsPolygonResponse response;
1199 for(
const types::KIID& padRequest : aCtx.
Request.pads() )
1201 KIID id( padRequest.value() );
1202 std::optional<BOARD_ITEM*> optPad =
getItemById(
id );
1204 if( !optPad || ( *optPad )->Type() !=
PCB_PAD_T )
1207 response.add_pads()->set_value( padRequest.value() );
1209 PAD*
pad =
static_cast<PAD*
>( *optPad );
1211 pad->TransformShapeToPolygon( poly,
pad->Padstack().EffectiveLayerFor( layer ), 0,
1214 types::PolygonWithHoles* polyMsg = response.mutable_polygons()->Add();
1225 using board::types::BoardLayer;
1228 !documentValidation )
1230 return tl::unexpected( documentValidation.error() );
1233 PadstackPresenceResponse response;
1237 for(
const int layer : aCtx.
Request.layers() )
1240 for(
const types::KIID& padRequest : aCtx.
Request.items() )
1242 KIID id( padRequest.value() );
1243 std::optional<BOARD_ITEM*> optItem =
getItemById(
id );
1248 switch( ( *optItem )->Type() )
1252 PAD*
pad =
static_cast<PAD*
>( *optItem );
1256 PadstackPresenceEntry* entry = response.add_entries();
1257 entry->mutable_item()->set_value(
pad->m_Uuid.AsStdString() );
1259 entry->set_presence(
pad->FlashLayer( layer ) ? PSP_PRESENT : PSP_NOT_PRESENT );
1271 PadstackPresenceEntry* entry = response.add_entries();
1272 entry->mutable_item()->set_value(
via->m_Uuid.AsStdString() );
1274 entry->set_presence(
via->FlashLayer( layer ) ? PSP_PRESENT : PSP_NOT_PRESENT );
1294 if( !documentValidation )
1295 return tl::unexpected( documentValidation.error() );
1300 types::TitleBlockInfo response;
1302 response.set_title( block.
GetTitle().ToUTF8() );
1303 response.set_date( block.
GetDate().ToUTF8() );
1304 response.set_revision( block.
GetRevision().ToUTF8() );
1305 response.set_company( block.
GetCompany().ToUTF8() );
1306 response.set_comment1( block.
GetComment( 0 ).ToUTF8() );
1307 response.set_comment2( block.
GetComment( 1 ).ToUTF8() );
1308 response.set_comment3( block.
GetComment( 2 ).ToUTF8() );
1309 response.set_comment4( block.
GetComment( 3 ).ToUTF8() );
1310 response.set_comment5( block.
GetComment( 4 ).ToUTF8() );
1311 response.set_comment6( block.
GetComment( 5 ).ToUTF8() );
1312 response.set_comment7( block.
GetComment( 6 ).ToUTF8() );
1313 response.set_comment8( block.
GetComment( 7 ).ToUTF8() );
1314 response.set_comment9( block.
GetComment( 8 ).ToUTF8() );
1325 if( !documentValidation )
1326 return tl::unexpected( documentValidation.error() );
1328 ExpandTextVariablesResponse reply;
1331 std::function<bool( wxString* )> textResolver =
1332 [&]( wxString* token ) ->
bool
1335 return board->ResolveTextVar( token, 0 );
1338 for(
const std::string& textMsg : aCtx.
Request.text() )
1341 reply.add_text(
text.ToUTF8() );
1351 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1352 return tl::unexpected( *busy );
1356 if( !documentValidation )
1357 return tl::unexpected( documentValidation.error() );
1360 std::vector<EDA_ITEM*> toSelect;
1362 for(
const kiapi::common::types::KIID&
id : aCtx.
Request.items() )
1364 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
1365 toSelect.emplace_back(
static_cast<EDA_ITEM*
>( *item ) );
1368 if( toSelect.empty() )
1370 ApiResponseStatus e;
1371 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1372 e.set_error_message( fmt::format(
"None of the given items exist on the board",
1373 aCtx.
Request.board().board_filename() ) );
1374 return tl::unexpected( e );
1394 if( !documentValidation )
1395 return tl::unexpected( documentValidation.error() );
1397 NetsResponse response;
1400 std::set<wxString> netclassFilter;
1402 for(
const std::string& nc : aCtx.
Request.netclass_filter() )
1403 netclassFilter.insert( wxString( nc.c_str(), wxConvUTF8 ) );
1409 if( !netclassFilter.empty() && nc && !netclassFilter.count( nc->
GetName() ) )
1412 board::types::Net* netProto = response.add_nets();
1413 netProto->set_name( net->GetNetname() );
1414 netProto->mutable_code()->set_value( net->GetNetCode() );
1424 NetClassForNetsResponse response;
1428 google::protobuf::Any
any;
1430 for(
const board::types::Net& net : aCtx.
Request.net() )
1438 auto [pair, rc] = response.mutable_classes()->insert( { net.name(), {} } );
1439 any.UnpackTo( &pair->second );
1448 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1449 return tl::unexpected( *busy );
1453 if( !documentValidation )
1454 return tl::unexpected( documentValidation.error() );
1456 if( aCtx.
Request.zones().empty() )
1459 frame()->CallAfter( [mgr]()
1467 ApiResponseStatus e;
1468 e.set_status( ApiStatusCode::AS_UNIMPLEMENTED );
1469 return tl::unexpected( e );
1481 if( !documentValidation )
1482 return tl::unexpected( documentValidation.error() );
1484 SavedDocumentResponse response;
1485 response.mutable_document()->CopyFrom( aCtx.
Request.document() );
1489 [&](
const wxString& aData )
1491 response.set_contents( aData.ToUTF8() );
1503 SavedSelectionResponse response;
1511 [&](
const wxString& aData )
1513 response.set_contents( aData.ToUTF8() );
1526 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1527 return tl::unexpected( *busy );
1531 if( !documentValidation )
1532 return tl::unexpected( documentValidation.error() );
1534 CreateItemsResponse response;
1544 if( !documentValidation )
1545 return tl::unexpected( documentValidation.error() );
1547 BoardLayers response;
1559 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1560 return tl::unexpected( *busy );
1564 if( !documentValidation )
1565 return tl::unexpected( documentValidation.error() );
1570 for(
int layerIdx : aCtx.
Request.layers() )
1576 visible.
set( layer );
1592 if( !documentValidation )
1593 return tl::unexpected( documentValidation.error() );
1595 BoardLayerResponse response;
1606 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1607 return tl::unexpected( *busy );
1611 if( !documentValidation )
1612 return tl::unexpected( documentValidation.error() );
1616 if( !
frame()->
GetBoard()->GetEnabledLayers().Contains( layer ) )
1618 ApiResponseStatus err;
1619 err.set_status( ApiStatusCode::AS_BAD_REQUEST );
1620 err.set_error_message( fmt::format(
"Layer {} is not a valid layer for the given board",
1621 magic_enum::enum_name( layer ) ) );
1622 return tl::unexpected( err );
1633 BoardEditorAppearanceSettings reply;
1641 reply.set_net_color_display(
1644 reply.set_board_flip(
frame()->GetCanvas()->GetView()->IsMirroredX()
1645 ? BoardFlipMode::BFM_FLIPPED_X
1646 : BoardFlipMode::BFM_NORMAL );
1660 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1661 return tl::unexpected( *busy );
1666 const BoardEditorAppearanceSettings& newSettings = aCtx.
Request.settings();
1673 bool flip = newSettings.board_flip() == BoardFlipMode::BFM_FLIPPED_X;
types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
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)
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.
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< BoardEnabledLayersResponse > handleGetBoardEnabledLayers(const HANDLER_CONTEXT< GetBoardEnabledLayers > &aCtx)
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< BoardEnabledLayersResponse > handleSetBoardEnabledLayers(const HANDLER_CONTEXT< SetBoardEnabledLayers > &aCtx)
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 registerHandler(HANDLER_RESULT< ResponseType >(HandlerType::*aHandler)(const HANDLER_CONTEXT< RequestType > &))
Registers an API command handler for the given message types.
void SetContentModified(bool aModified=true)
BASE_SET & reset(size_t pos)
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
void SetVisibleLayers(const LSET &aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings changes the bit-mask of vis...
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
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.
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
LSET is a set of PCB_LAYER_IDs.
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
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.
void OnModify() override
Must be called after a board change to set the modified flag.
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.
void UpdateUserInterface()
Update the layer manager and other widgets from the board setup (layer and items visibility,...
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
A type-safe container of any type.
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:
void PackLayerSet(google::protobuf::RepeatedField< int > &aOutput, const LSET &aLayerSet)
LSET UnpackLayerSet(const google::protobuf::RepeatedField< int > &aProtoLayerSet)
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_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
@ 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< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D