7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-04 23:05:30 +00:00

API: Add selection handling

This commit is contained in:
Jon Evans 2025-01-21 19:52:38 -05:00
parent 71353b11f1
commit 4118c14d97
3 changed files with 196 additions and 1 deletions

View File

@ -326,6 +326,47 @@ message GetBoundingBoxResponse
repeated kiapi.common.types.Box2 boxes = 2;
}
// Retrieves a list of items. Returns SelectionResponse
message GetSelection
{
// Specifies which document to query for selected items.
kiapi.common.types.ItemHeader header = 1;
// An optional list of types to filter on.
// If none are provided, all selected items will be returned.
repeated kiapi.common.types.KiCadObjectType types = 2;
}
// The set of currently selected items
message SelectionResponse
{
repeated google.protobuf.Any items = 1;
}
// Adds the given items to the selection. Returns SelectionResponse
message AddToSelection
{
kiapi.common.types.ItemHeader header = 1;
// The items to select
repeated kiapi.common.types.KIID items = 2;
}
// Removes the given items to the selection. Returns SelectionResponse
message RemoveFromSelection
{
kiapi.common.types.ItemHeader header = 1;
// The items to deselect
repeated kiapi.common.types.KIID items = 2;
}
// Removes all items from selection
message ClearSelection
{
kiapi.common.types.ItemHeader header = 1;
}
// Tests if a certain point falls within tolerance of an item's geometry
message HitTest
{

View File

@ -65,6 +65,12 @@ API_HANDLER_PCB::API_HANDLER_PCB( PCB_EDIT_FRAME* aFrame ) :
registerHandler<GetItems, GetItemsResponse>( &API_HANDLER_PCB::handleGetItems );
registerHandler<GetSelection, SelectionResponse>( &API_HANDLER_PCB::handleGetSelection );
registerHandler<ClearSelection, Empty>( &API_HANDLER_PCB::handleClearSelection );
registerHandler<AddToSelection, SelectionResponse>( &API_HANDLER_PCB::handleAddToSelection );
registerHandler<RemoveFromSelection, SelectionResponse>(
&API_HANDLER_PCB::handleRemoveFromSelection );
registerHandler<GetBoardStackup, BoardStackupResponse>( &API_HANDLER_PCB::handleGetStackup );
registerHandler<GetGraphicsDefaults, GraphicsDefaultsResponse>(
&API_HANDLER_PCB::handleGetGraphicsDefaults );
@ -657,6 +663,141 @@ std::optional<EDA_ITEM*> API_HANDLER_PCB::getItemFromDocument( const DocumentSpe
}
HANDLER_RESULT<SelectionResponse> API_HANDLER_PCB::handleGetSelection(
const HANDLER_CONTEXT<GetSelection>& aCtx )
{
if( std::optional<ApiResponseStatus> busy = checkForBusy() )
return tl::unexpected( *busy );
if( !validateItemHeaderDocument( aCtx.Request.header() ) )
{
ApiResponseStatus e;
// No message needed for AS_UNHANDLED; this is an internal flag for the API server
e.set_status( ApiStatusCode::AS_UNHANDLED );
return tl::unexpected( e );
}
std::set<KICAD_T> filter;
for( int typeRaw : aCtx.Request.types() )
{
auto typeMessage = static_cast<types::KiCadObjectType>( typeRaw );
KICAD_T type = FromProtoEnum<KICAD_T>( typeMessage );
if( type == TYPE_NOT_INIT )
continue;
filter.insert( type );
}
TOOL_MANAGER* mgr = frame()->GetToolManager();
PCB_SELECTION_TOOL* selectionTool = mgr->GetTool<PCB_SELECTION_TOOL>();
SelectionResponse response;
for( EDA_ITEM* item : selectionTool->GetSelection() )
{
if( filter.empty() || filter.contains( item->Type() ) )
item->Serialize( *response.add_items() );
}
return response;
}
HANDLER_RESULT<Empty> API_HANDLER_PCB::handleClearSelection(
const HANDLER_CONTEXT<ClearSelection>& aCtx )
{
if( std::optional<ApiResponseStatus> busy = checkForBusy() )
return tl::unexpected( *busy );
if( !validateItemHeaderDocument( aCtx.Request.header() ) )
{
ApiResponseStatus e;
// No message needed for AS_UNHANDLED; this is an internal flag for the API server
e.set_status( ApiStatusCode::AS_UNHANDLED );
return tl::unexpected( e );
}
TOOL_MANAGER* mgr = frame()->GetToolManager();
mgr->RunAction( PCB_ACTIONS::selectionClear );
return Empty();
}
HANDLER_RESULT<SelectionResponse> API_HANDLER_PCB::handleAddToSelection(
const HANDLER_CONTEXT<AddToSelection>& aCtx )
{
if( std::optional<ApiResponseStatus> busy = checkForBusy() )
return tl::unexpected( *busy );
if( !validateItemHeaderDocument( aCtx.Request.header() ) )
{
ApiResponseStatus e;
// No message needed for AS_UNHANDLED; this is an internal flag for the API server
e.set_status( ApiStatusCode::AS_UNHANDLED );
return tl::unexpected( e );
}
TOOL_MANAGER* mgr = frame()->GetToolManager();
PCB_SELECTION_TOOL* selectionTool = mgr->GetTool<PCB_SELECTION_TOOL>();
std::vector<EDA_ITEM*> toAdd;
for( const types::KIID& id : aCtx.Request.items() )
{
if( std::optional<BOARD_ITEM*> item = getItemById( KIID( id.value() ) ) )
toAdd.emplace_back( *item );
}
selectionTool->AddItemsToSel( &toAdd );
SelectionResponse response;
for( EDA_ITEM* item : selectionTool->GetSelection() )
item->Serialize( *response.add_items() );
return response;
}
HANDLER_RESULT<SelectionResponse> API_HANDLER_PCB::handleRemoveFromSelection(
const HANDLER_CONTEXT<RemoveFromSelection>& aCtx )
{
if( std::optional<ApiResponseStatus> busy = checkForBusy() )
return tl::unexpected( *busy );
if( !validateItemHeaderDocument( aCtx.Request.header() ) )
{
ApiResponseStatus e;
// No message needed for AS_UNHANDLED; this is an internal flag for the API server
e.set_status( ApiStatusCode::AS_UNHANDLED );
return tl::unexpected( e );
}
TOOL_MANAGER* mgr = frame()->GetToolManager();
PCB_SELECTION_TOOL* selectionTool = mgr->GetTool<PCB_SELECTION_TOOL>();
std::vector<EDA_ITEM*> toRemove;
for( const types::KIID& id : aCtx.Request.items() )
{
if( std::optional<BOARD_ITEM*> item = getItemById( KIID( id.value() ) ) )
toRemove.emplace_back( *item );
}
selectionTool->RemoveItemsFromSel( &toRemove );
SelectionResponse response;
for( EDA_ITEM* item : selectionTool->GetSelection() )
item->Serialize( *response.add_items() );
return response;
}
HANDLER_RESULT<BoardStackupResponse> API_HANDLER_PCB::handleGetStackup(
const HANDLER_CONTEXT<GetBoardStackup>& aCtx )
{

View File

@ -74,7 +74,20 @@ private:
HANDLER_RESULT<commands::GetItemsResponse> handleGetItems(
const HANDLER_CONTEXT<commands::GetItems>& aCtx );
HANDLER_RESULT<BoardStackupResponse> handleGetStackup( const HANDLER_CONTEXT<GetBoardStackup>& aCtx );
HANDLER_RESULT<commands::SelectionResponse> handleGetSelection(
const HANDLER_CONTEXT<commands::GetSelection>& aCtx );
HANDLER_RESULT<Empty> handleClearSelection(
const HANDLER_CONTEXT<commands::ClearSelection>& aCtx );
HANDLER_RESULT<commands::SelectionResponse> handleAddToSelection(
const HANDLER_CONTEXT<commands::AddToSelection>& aCtx );
HANDLER_RESULT<commands::SelectionResponse> handleRemoveFromSelection(
const HANDLER_CONTEXT<commands::RemoveFromSelection>& aCtx );
HANDLER_RESULT<BoardStackupResponse> handleGetStackup(
const HANDLER_CONTEXT<GetBoardStackup>& aCtx );
HANDLER_RESULT<GraphicsDefaultsResponse> handleGetGraphicsDefaults(
const HANDLER_CONTEXT<GetGraphicsDefaults>& aCtx );