refactor(new_editor): snapshot hosted editor restructuring

This commit is contained in:
2026-04-21 00:57:14 +08:00
parent e123e584c8
commit 9b7b369007
248 changed files with 21152 additions and 14397 deletions

View File

@@ -12,8 +12,6 @@ using ::XCEngine::Input::KeyCode;
using ::XCEngine::UI::UIInputEvent;
using ::XCEngine::UI::UIInputEventType;
using ::XCEngine::UI::UIPointerButton;
using ::XCEngine::UI::Text::HandleKeyDown;
using ::XCEngine::UI::Text::InsertCharacter;
using ::XCEngine::UI::Editor::Widgets::BuildUIEditorTextFieldLayout;
using ::XCEngine::UI::Editor::Widgets::HitTestUIEditorTextField;
using ::XCEngine::UI::Editor::Widgets::IsUIEditorTextFieldPointInside;
@@ -23,37 +21,28 @@ using ::XCEngine::UI::Editor::Widgets::UIEditorTextFieldLayout;
using ::XCEngine::UI::Editor::Widgets::UIEditorTextFieldMetrics;
using ::XCEngine::UI::Editor::Widgets::UIEditorTextFieldSpec;
bool ShouldUsePointerPosition(const UIInputEvent& event) {
switch (event.type) {
case UIInputEventType::PointerMove:
case UIInputEventType::PointerEnter:
case UIInputEventType::PointerButtonDown:
case UIInputEventType::PointerButtonUp:
case UIInputEventType::PointerWheel:
return true;
default:
return false;
}
}
void SyncDisplayText(
UIEditorTextFieldInteractionState& state,
const UIEditorTextFieldSpec& spec) {
if (!state.textFieldState.editing) {
state.textFieldState.displayText = spec.value;
}
}
void SyncHoverTarget(
void SyncDisplayState(
UIEditorTextFieldInteractionState& state,
const UIEditorTextFieldSpec& spec,
const UIEditorTextFieldLayout& layout) {
if (!state.hasPointerPosition) {
state.textFieldState.hoveredTarget = UIEditorTextFieldHitTargetKind::None;
auto& fieldState = state.textFieldState;
const auto& session = state.session;
fieldState.focused = session.focused;
fieldState.editing = session.editing;
fieldState.caretBlinkStartNanoseconds = session.caretBlinkStartNanoseconds;
fieldState.displayText = session.editing
? session.textInputState.value
: spec.value;
fieldState.caretOffset = session.editing
? session.textInputState.caret
: spec.value.size();
if (!session.hasPointerPosition) {
fieldState.hoveredTarget = UIEditorTextFieldHitTargetKind::None;
return;
}
state.textFieldState.hoveredTarget =
HitTestUIEditorTextField(layout, state.pointerPosition).kind;
fieldState.hoveredTarget =
HitTestUIEditorTextField(layout, session.pointerPosition).kind;
}
bool BeginEdit(
@@ -64,44 +53,30 @@ bool BeginEdit(
return false;
}
const bool changed = state.editModel.BeginEdit(spec.fieldId, spec.value);
if (!changed &&
state.editModel.HasActiveEdit() &&
state.editModel.GetActiveFieldId() != spec.fieldId) {
return false;
}
if (!changed && state.textFieldState.editing) {
return false;
}
state.textFieldState.editing = true;
state.textInputState.value = clearText ? std::string() : spec.value;
state.textInputState.caret = state.textInputState.value.size();
state.editModel.UpdateStagedValue(state.textInputState.value);
state.textFieldState.displayText = state.textInputState.value;
return true;
return BeginUIEditorEditableFieldEdit(
state.session,
spec.fieldId,
UIEditorEditableFieldInvalidComponentIndex,
spec.value,
clearText);
}
bool CommitEdit(
UIEditorTextFieldInteractionState& state,
UIEditorTextFieldSpec& spec,
UIEditorTextFieldInteractionResult& result) {
if (!state.textFieldState.editing || !state.editModel.HasActiveEdit()) {
if (!state.session.editing) {
return false;
}
result.valueBefore = spec.value;
spec.value = state.textInputState.value;
spec.value = state.session.textInputState.value;
result.valueAfter = spec.value;
result.valueChanged = result.valueBefore != result.valueAfter;
result.editCommitted = true;
result.consumed = true;
result.committedText = spec.value;
state.editModel.CommitEdit();
state.textInputState = {};
state.textFieldState.editing = false;
state.textFieldState.displayText = spec.value;
CommitUIEditorEditableFieldEdit(state.session);
return true;
}
@@ -109,14 +84,11 @@ bool CancelEdit(
UIEditorTextFieldInteractionState& state,
const UIEditorTextFieldSpec& spec,
UIEditorTextFieldInteractionResult& result) {
if (!state.textFieldState.editing || !state.editModel.HasActiveEdit()) {
if (!state.session.editing) {
return false;
}
state.editModel.CancelEdit();
state.textInputState = {};
state.textFieldState.editing = false;
state.textFieldState.displayText = spec.value;
CancelUIEditorEditableFieldEdit(state.session);
result.consumed = true;
result.editCanceled = true;
result.valueBefore = spec.value;
@@ -132,32 +104,30 @@ UIEditorTextFieldInteractionFrame UpdateUIEditorTextFieldInteraction(
const ::XCEngine::UI::UIRect& bounds,
const std::vector<UIInputEvent>& inputEvents,
const UIEditorTextFieldMetrics& metrics) {
UIEditorTextFieldLayout layout = BuildUIEditorTextFieldLayout(bounds, spec, metrics);
SyncDisplayText(state, spec);
SyncHoverTarget(state, layout);
UIEditorTextFieldLayout layout = BuildUIEditorTextFieldLayout(
bounds,
spec,
metrics);
SyncDisplayState(state, spec, layout);
UIEditorTextFieldInteractionResult interactionResult = {};
for (const UIInputEvent& event : inputEvents) {
if (ShouldUsePointerPosition(event)) {
state.pointerPosition = event.position;
state.hasPointerPosition = true;
} else if (event.type == UIInputEventType::PointerLeave) {
state.hasPointerPosition = false;
}
UpdateUIEditorEditableFieldPointerPosition(state.session, event);
UIEditorTextFieldInteractionResult eventResult = {};
switch (event.type) {
case UIInputEventType::FocusGained:
eventResult.focusChanged = !state.textFieldState.focused;
state.textFieldState.focused = true;
eventResult.focusChanged = !state.session.focused;
state.session.focused = true;
break;
case UIInputEventType::FocusLost:
eventResult.focusChanged = state.textFieldState.focused;
state.textFieldState.focused = false;
eventResult.focusChanged = state.session.focused;
state.session.focused = false;
state.textFieldState.activeTarget = UIEditorTextFieldHitTargetKind::None;
state.hasPointerPosition = false;
if (state.textFieldState.editing) {
state.session.hasPointerPosition = false;
EndUIEditorEditableFieldDrag(state.session);
if (state.session.editing) {
CommitEdit(state, spec, eventResult);
}
break;
@@ -169,8 +139,10 @@ UIEditorTextFieldInteractionFrame UpdateUIEditorTextFieldInteraction(
case UIInputEventType::PointerButtonDown: {
const UIEditorTextFieldHitTarget hitTarget =
state.hasPointerPosition
? HitTestUIEditorTextField(layout, state.pointerPosition)
state.session.hasPointerPosition
? HitTestUIEditorTextField(
layout,
state.session.pointerPosition)
: UIEditorTextFieldHitTarget {};
eventResult.hitTarget = hitTarget;
@@ -179,24 +151,26 @@ UIEditorTextFieldInteractionFrame UpdateUIEditorTextFieldInteraction(
}
const bool insideField =
state.hasPointerPosition &&
IsUIEditorTextFieldPointInside(layout.bounds, state.pointerPosition);
state.session.hasPointerPosition &&
IsUIEditorTextFieldPointInside(
layout.bounds,
state.session.pointerPosition);
if (insideField) {
eventResult.focusChanged = !state.textFieldState.focused;
state.textFieldState.focused = true;
eventResult.focusChanged = !state.session.focused;
state.session.focused = true;
state.textFieldState.activeTarget =
hitTarget.kind == UIEditorTextFieldHitTargetKind::None
? UIEditorTextFieldHitTargetKind::Row
: hitTarget.kind;
eventResult.consumed = true;
} else {
if (state.textFieldState.editing) {
if (state.session.editing) {
CommitEdit(state, spec, eventResult);
eventResult.focusChanged = state.textFieldState.focused;
state.textFieldState.focused = false;
} else if (state.textFieldState.focused) {
eventResult.focusChanged = state.session.focused;
state.session.focused = false;
} else if (state.session.focused) {
eventResult.focusChanged = true;
state.textFieldState.focused = false;
state.session.focused = false;
}
state.textFieldState.activeTarget = UIEditorTextFieldHitTargetKind::None;
}
@@ -205,21 +179,37 @@ UIEditorTextFieldInteractionFrame UpdateUIEditorTextFieldInteraction(
case UIInputEventType::PointerButtonUp: {
const UIEditorTextFieldHitTarget hitTarget =
state.hasPointerPosition
? HitTestUIEditorTextField(layout, state.pointerPosition)
state.session.hasPointerPosition
? HitTestUIEditorTextField(
layout,
state.session.pointerPosition)
: UIEditorTextFieldHitTarget {};
eventResult.hitTarget = hitTarget;
if (event.pointerButton == UIPointerButton::Left) {
const UIEditorTextFieldHitTargetKind activeTarget = state.textFieldState.activeTarget;
const UIEditorTextFieldHitTargetKind activeTarget =
state.textFieldState.activeTarget;
state.textFieldState.activeTarget = UIEditorTextFieldHitTargetKind::None;
if (activeTarget == UIEditorTextFieldHitTargetKind::ValueBox &&
hitTarget.kind == UIEditorTextFieldHitTargetKind::ValueBox) {
if (!state.textFieldState.editing) {
if (state.session.editing) {
eventResult.consumed = true;
} else if (IsUIEditorEditableFieldDoubleClick(
state.session,
spec.fieldId,
event,
UIEditorEditableFieldInvalidComponentIndex)) {
eventResult.editStarted = BeginEdit(state, spec, false);
eventResult.consumed = true;
} else {
RecordUIEditorEditableFieldClick(
state.session,
spec.fieldId,
event,
UIEditorEditableFieldInvalidComponentIndex);
eventResult.consumed = true;
}
eventResult.consumed = true;
} else if (hitTarget.kind == UIEditorTextFieldHitTargetKind::Row) {
eventResult.consumed = true;
}
@@ -228,21 +218,21 @@ UIEditorTextFieldInteractionFrame UpdateUIEditorTextFieldInteraction(
}
case UIInputEventType::KeyDown:
if (!state.textFieldState.focused) {
if (!state.session.focused) {
break;
}
if (state.textFieldState.editing) {
if (state.session.editing) {
if (event.keyCode == static_cast<std::int32_t>(KeyCode::Escape)) {
CancelEdit(state, spec, eventResult);
break;
}
const auto textResult =
HandleKeyDown(state.textInputState, event.keyCode, event.modifiers);
const auto textResult = HandleUIEditorEditableFieldKeyDown(
state.session,
event.keyCode,
event.modifiers);
if (textResult.handled) {
state.editModel.UpdateStagedValue(state.textInputState.value);
state.textFieldState.displayText = state.textInputState.value;
eventResult.consumed = true;
eventResult.valueBefore = spec.value;
eventResult.valueAfter = spec.value;
@@ -257,7 +247,7 @@ UIEditorTextFieldInteractionFrame UpdateUIEditorTextFieldInteraction(
break;
case UIInputEventType::Character:
if (!state.textFieldState.focused ||
if (!state.session.focused ||
spec.readOnly ||
event.modifiers.control ||
event.modifiers.alt ||
@@ -265,13 +255,13 @@ UIEditorTextFieldInteractionFrame UpdateUIEditorTextFieldInteraction(
break;
}
if (!state.textFieldState.editing) {
if (!state.session.editing) {
eventResult.editStarted = BeginEdit(state, spec, true);
}
if (InsertCharacter(state.textInputState, event.character)) {
state.editModel.UpdateStagedValue(state.textInputState.value);
state.textFieldState.displayText = state.textInputState.value;
if (InsertUIEditorEditableFieldCharacter(
state.session,
event.character)) {
eventResult.consumed = true;
}
break;
@@ -281,11 +271,12 @@ UIEditorTextFieldInteractionFrame UpdateUIEditorTextFieldInteraction(
}
layout = BuildUIEditorTextFieldLayout(bounds, spec, metrics);
SyncDisplayText(state, spec);
SyncHoverTarget(state, layout);
SyncDisplayState(state, spec, layout);
if (eventResult.hitTarget.kind == UIEditorTextFieldHitTargetKind::None &&
state.hasPointerPosition) {
eventResult.hitTarget = HitTestUIEditorTextField(layout, state.pointerPosition);
state.session.hasPointerPosition) {
eventResult.hitTarget = HitTestUIEditorTextField(
layout,
state.session.pointerPosition);
}
if (eventResult.consumed ||
@@ -300,11 +291,12 @@ UIEditorTextFieldInteractionFrame UpdateUIEditorTextFieldInteraction(
}
layout = BuildUIEditorTextFieldLayout(bounds, spec, metrics);
SyncDisplayText(state, spec);
SyncHoverTarget(state, layout);
SyncDisplayState(state, spec, layout);
if (interactionResult.hitTarget.kind == UIEditorTextFieldHitTargetKind::None &&
state.hasPointerPosition) {
interactionResult.hitTarget = HitTestUIEditorTextField(layout, state.pointerPosition);
state.session.hasPointerPosition) {
interactionResult.hitTarget = HitTestUIEditorTextField(
layout,
state.session.pointerPosition);
}
return {