コンテンツにスキップ

@tool() デコレーター

クラスを LinkCAD のツールとして登録し、自動生成されるオプションダイアログとともにアプリケーションメニューに表示します。

シグネチャ

@tool(
name: str,
menu: str,
tooltip: str = "",
shortcut: str = "",
icon: str = "",
requires_drawing: bool = True,
)
class MyTool(Tool):
...

パラメーター

パラメーター既定値説明
namestr必須メニューでの表示名
menustr必須メニューパス(サブメニューは / 区切り)。例: "Tools/Analysis"
tooltipstr""ホバー時に表示されるツールチップ
shortcutstr""キーボードショートカット(例: "Ctrl+Shift+M"
iconstr""res/ からの相対アイコンファイル名
requires_drawingboolTrue図面が読み込まれていないときにツールを無効化するかどうか

Tool 基底クラス

すべてのツールプラグインは Tool を継承し、run() を実装しなければなりません。

class Tool:
def run(self, drawing) -> dict:
"""Override to implement the tool logic. Return a result dictionary."""
...
def format_result(self, result: dict) -> str:
"""Override to control how the result is displayed."""
...

drawing 引数は linkcad.v1.db.Drawing——アプリケーションが所有するライブデータベースなので、決して破棄しないでください。requires_drawing=False の場合は None になることがあります。

run() は結果の辞書を返します。既定の format_result()result["summary"] があればそれを表示するので、そのキーを含めてください。より充実した表示が必要な場合は format_result() をオーバーライドします。

run() の実行中、フレームワークは読み取りロックを保持しています。変更を取り消し可能にするには Transaction で包んでください。

ToolInfo

デコレーターはクラスに ToolInfo オブジェクトを付与します。

フィールド説明
nameツールの表示名
menuメニューパス
tooltipツールチップのテキスト
shortcutキーボードショートカット
iconアイコンのファイル名
requires_drawing図面が必要かどうか
optionsクラスから収集された Option 属性

メニューパス

menu パラメーターは、ツールが LinkCAD のメニューのどこに表示されるかを決めます。

"Edit/Analyze" → Edit → Analyze → <tool name>
"Tools/Analysis" → Tools → Analysis → <tool name>
"Tools/Drawing/Custom" → Tools → Drawing → Custom → <tool name>

完全な例

from typing import Any, Dict
from linkcad.v1.plugin import tool, Tool, Option
@tool(
name="Shape Counter",
menu="Tools/Analysis",
tooltip="Count shapes per layer",
shortcut="Ctrl+Shift+C",
requires_drawing=True,
)
class ShapeCounter(Tool):
closed_only = Option.boolean("Closed shapes only", default=False)
def run(self, drawing) -> Dict[str, Any]:
counts: Dict[str, int] = {}
for cell in drawing.cells:
for shape in cell.shapes:
if self.closed_only and not shape.closed:
continue
layer = shape.layer
if layer is not None:
counts[layer.name] = counts.get(layer.name, 0) + 1
return {
"layers": counts,
"summary": f"{sum(counts.values())} shapes on {len(counts)} layers",
}
def format_result(self, result: Dict[str, Any]) -> str:
lines = [f"{name}: {n}" for name, n in sorted(result["layers"].items())]
lines += ["", result["summary"]]
return "\n".join(lines)