Я предлагаю разделить логику для отображения входов пользовательского интерфейса для конкретной операции на выделенные объекты. Давайте назовем их сенсорным объектом. Не зная вашего языка реализации, я буду в общих чертах с этим, но вы должны понять.
OperationSensor
+ OnKeyDown
+ OnKeyPress
+ OnKeyUp
+ OnLeftMouseDown
+ OnLeftMouseUp
+ OnNodeSelect
+ OnNodeDeselect
+ OnDragStart
+ OnDragStop
Допустим, у вас есть центральный класс, который объединяет все входы пользовательского интерфейса UiInputManager
. Он использует специфичные для языка механизмы для прослушивания ввода с клавиатуры и мыши. Он также обнаруживает основные операции, такие как обнаружение того, что если мышь нажать и затем переместить, это логическое «перетаскивание».
UiInputManager
// event listeners
+ keyboard_keydownHandler
+ keyboard_keyupHandler
+ mouse_leftdownHandler
+ mouse_rightdownHandler
// active sensor list, can be added to or removed from
+ Sensors
UiInputManager НЕ несет ответственности за знание того, какие операции вызывают эти входные данные. Он просто уведомляет свои датчики определенным языком.
foreach sensor in Sensors
sensor.OnDragStarted
или, если датчики прослушивают логические события, выданные UiInputManager
RaiseEvent DragStarted
Теперь у вас есть соединение для маршрутизации ввода в подклассы OperationSensor. Каждый OperationSensor имеет логику, относящуюся только к одной операции. Если он обнаруживает, что критерии операции выполнены, он создает соответствующий объект Command и передает его обратно.
// Ctrl + zooms in, Ctrl - zooms out
ZoomSensor : OperationSensor
override OnKeyDown
{
if keyDown.Char = '+' && keyDown.IsCtrlDepressed
base.IssueCommand(new ZoomCommand(changeZoomBy:=10)
elseif keyDown.Char = '-' && keyDown.IsCtrlDepressed
base.IssueCommand(new ZoomCommand(changeZoomBy:=-10)
}
Я бы порекомендовал передавать объекты команд из датчиков в UiInputManager. Затем менеджер может передать их в вашу подсистему обработки команд. Это дает менеджеру возможность, возможно, уведомить датчики о завершении операции, что позволяет им при необходимости сбросить свое внутреннее состояние.
Многошаговые операции могут выполняться двумя различными способами. Вы можете реализовать внутренние конечные автоматы внутри SensorOperation, или вы можете заставить датчик «шаг 1» создать датчик «шаг 2» и добавить его в список активных датчиков, возможно, даже удалив себя из списка. По завершении «шага 2» он может повторно добавить датчик «шага 1» и удалить себя.