105 lines
2.5 KiB
C++
105 lines
2.5 KiB
C++
#pragma once
|
|
|
|
#include "UIInputPath.h"
|
|
|
|
#include <XCEngine/UI/Types.h>
|
|
|
|
#include <cstdint>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
namespace XCEngine {
|
|
namespace UI {
|
|
|
|
enum class UIInputRoutingPhase : std::uint8_t {
|
|
Capture = 0,
|
|
Target,
|
|
Bubble
|
|
};
|
|
|
|
enum class UIInputTargetKind : std::uint8_t {
|
|
None = 0,
|
|
Hovered,
|
|
Focused,
|
|
Captured
|
|
};
|
|
|
|
struct UIInputRouteContext {
|
|
UIInputPath hoveredPath = {};
|
|
UIInputPath focusedPath = {};
|
|
UIInputPath capturePath = {};
|
|
};
|
|
|
|
struct UIInputRoutingStep {
|
|
UIElementId elementId = 0;
|
|
UIInputRoutingPhase phase = UIInputRoutingPhase::Target;
|
|
bool isTargetElement = false;
|
|
};
|
|
|
|
struct UIInputRoutingPlan {
|
|
UIInputTargetKind targetKind = UIInputTargetKind::None;
|
|
UIInputPath targetPath = {};
|
|
std::vector<UIInputRoutingStep> steps = {};
|
|
|
|
bool HasTargetPath() const {
|
|
return !targetPath.Empty();
|
|
}
|
|
};
|
|
|
|
struct UIInputDispatchRequest {
|
|
const UIInputEvent* event = nullptr;
|
|
UIElementId elementId = 0;
|
|
UIInputRoutingPhase phase = UIInputRoutingPhase::Target;
|
|
UIInputTargetKind targetKind = UIInputTargetKind::None;
|
|
bool isTargetElement = false;
|
|
};
|
|
|
|
struct UIInputDispatchDecision {
|
|
bool handled = false;
|
|
bool stopPropagation = false;
|
|
};
|
|
|
|
struct UIInputDispatchResult {
|
|
UIInputRoutingPlan plan = {};
|
|
bool handled = false;
|
|
};
|
|
|
|
class UIInputRouter {
|
|
public:
|
|
static bool IsPointerEvent(UIInputEventType type);
|
|
static bool IsKeyboardEvent(UIInputEventType type);
|
|
|
|
static UIInputRoutingPlan BuildRoutingPlan(
|
|
const UIInputEvent& event,
|
|
const UIInputRouteContext& context);
|
|
|
|
template <typename HandlerFn>
|
|
static UIInputDispatchResult Dispatch(
|
|
const UIInputEvent& event,
|
|
const UIInputRouteContext& context,
|
|
HandlerFn&& handler) {
|
|
UIInputDispatchResult result = {};
|
|
result.plan = BuildRoutingPlan(event, context);
|
|
|
|
for (const UIInputRoutingStep& step : result.plan.steps) {
|
|
UIInputDispatchRequest request = {};
|
|
request.event = &event;
|
|
request.elementId = step.elementId;
|
|
request.phase = step.phase;
|
|
request.targetKind = result.plan.targetKind;
|
|
request.isTargetElement = step.isTargetElement;
|
|
|
|
const UIInputDispatchDecision decision = handler(request);
|
|
result.handled = result.handled || decision.handled;
|
|
if (decision.stopPropagation) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
};
|
|
|
|
} // namespace UI
|
|
} // namespace XCEngine
|