Currently all editing tools in pcbnew reside in a single, enormous class
(PCB_EDIT_FRAME) entangled with numerous editing methods in the model
& a bunch of global/static functions and variables. Such code is very
difficult to maintain and extend.
Each tool belongs to one of following categories:
- interactive, such as a PCB router - that once activated take a
group of keyboard/mouse events and process them until an exit event
is received. Only one interactive tool can be active at a time.
- batch, which are run once in response to a UI/Scripting command
(such as DRC)
Interactive tools are implemented as (hierarchical) state machines.
An interactive tool can call another interactive or batch tool (for
example, drag tool internally calls selection tool to know what to
Each tool has a predefined activation event, and accepts a
predefined range of keyboard/mouse events, assigned on-the-fly.
Tools can exit when they want or when application-wide exit event is
received (i.e. pressing Esc).
In general, tools are not allowed to draw anything that doesn't go
through the View, unless there exists a very good reason for doing
so (an example is drawing transparent selection boxes or moving
large groups of items)
One tool = one class. Tools must not use non-trivial static methods
and must never, ever, have any global states. Main tool interface
must not have any wx dependencies. If the tool needs special GUI
other than a menu entry, shortcut and button in a toolbar or the
right-click menu (e.g. a settings dialog/docker window), it must be
handled by a separate, non-public class.
Tools are registered within an application-wide tool manager via a
factory class/function. This allows for adding tools as DLL/DSO
Tools use KiCad-internal event format, that works with native board
units and follows gestures & shortcuts set in application
preferences. A big advantage of this approach is the ability to
drive a tool with a series of events from a script. For instance, an
automatic BGA fanouter script could simply run the P&S tool with a
click-move-click series of events for each pad instead of
calculating every breakout trace itself.
All the tools are already ported to the Tool Framework. Some of them
lack minor functionality (e.g. context menus).
Tools can be invoked using hotkeys, menu, toolbar or by calling
InvokeTool() function from another tool.
It is possible to have a few interactive tools active at the same
time. In such case, the most recently activated tool gets all events
as first. Then it may choose to pass received events further to
other tools, or stop them.