Selection drag support

This commit is contained in:
elasota
2020-03-09 01:40:47 -04:00
parent 424a09ccc8
commit 699c3cf13c
2 changed files with 102 additions and 10 deletions

View File

@@ -29,6 +29,8 @@ namespace PortabilityLayer
, m_hasFocus(false)
, m_caratTimer(0)
, m_isMultiLine(false)
, m_isDraggingSelection(false)
, m_dragSelectionStartChar(false)
{
}
@@ -163,12 +165,15 @@ namespace PortabilityLayer
WidgetHandleState_t EditboxWidget::ProcessEvent(const TimeTaggedVOSEvent &evt)
{
if (m_isDraggingSelection)
return HandleDragSelection(evt);
if (!m_visible || !m_enabled)
return WidgetHandleStates::kIgnored;
if (evt.m_vosEvent.m_eventType == GpVOSEventTypes::kKeyboardInput)
{
if (!m_hasFocus)
if (!m_hasFocus || m_isDraggingSelection)
return WidgetHandleStates::kIgnored;
const GpKeyboardInputEvent &keyEvent = evt.m_vosEvent.m_event.m_keyboardInputEvent;
@@ -245,6 +250,21 @@ namespace PortabilityLayer
}
else if (evt.m_vosEvent.m_eventType == GpVOSEventTypes::kMouseInput)
{
const GpMouseInputEvent &mouseEvent = evt.m_vosEvent.m_event.m_mouseInputEvent;
if (evt.IsLMouseDownEvent())
{
const Point pt = m_window->MouseToLocal(evt.m_vosEvent.m_event.m_mouseInputEvent);
if (m_rect.Contains(pt))
{
m_window->FocusWidget(this);
m_isDraggingSelection = true;
return HandleDragSelection(evt);
}
else
return WidgetHandleStates::kIgnored;
}
}
return WidgetHandleStates::kIgnored;
@@ -489,15 +509,13 @@ namespace PortabilityLayer
Redraw();
}
size_t EditboxWidget::FindVerticalMovementCaratPos(const Vec2i &desiredPos, bool &outShouldUnlock) const
size_t EditboxWidget::FindVerticalMovementCaratPos(const Vec2i &desiredPos, bool &isOutOfRange) const
{
assert(m_isMultiLine);
Vec2i basePoint = Vec2i(0, 0);
if (desiredPos.m_y < basePoint.m_y)
{
outShouldUnlock = true;
isOutOfRange = true;
return 0;
}
@@ -514,11 +532,16 @@ namespace PortabilityLayer
if (characteristics.m_glyphStartPos.m_y == desiredPos.m_y)
{
caratChar = characteristics.m_characterIndex;
if (characteristics.m_character == '\r')
caratChar--;
foundLine = true;
caratChar = characteristics.m_characterIndex;
if (desiredPos.m_x <= 0)
break;
if (characteristics.m_character != '\r')
caratChar++;
if (characteristics.m_glyphStartPos.m_x <= desiredPos.m_x && characteristics.m_glyphEndPos.m_x > desiredPos.m_x)
{
int32_t distanceToEnd = characteristics.m_glyphEndPos.m_x - desiredPos.m_x;
@@ -536,11 +559,11 @@ namespace PortabilityLayer
if (foundLine)
{
outShouldUnlock = false;
isOutOfRange = false;
return caratChar;
}
outShouldUnlock = true;
isOutOfRange = true;
return m_length;
}
@@ -567,6 +590,70 @@ namespace PortabilityLayer
}
}
WidgetHandleState_t EditboxWidget::HandleDragSelection(const TimeTaggedVOSEvent &evt)
{
if (evt.m_vosEvent.m_eventType == GpVOSEventTypes::kMouseInput)
{
const GpMouseInputEvent &mouseEvent = evt.m_vosEvent.m_event.m_mouseInputEvent;
const Point pt = m_window->MouseToLocal(evt.m_vosEvent.m_event.m_mouseInputEvent);
RenderedFont *rfont = GetRenderedFont();
const int32_t linegap = rfont->GetMetrics().m_linegap;
const Vec2i basePoint = ResolveBasePoint();
const Vec2i relativePoint = Vec2i(pt.h, pt.v) - basePoint;
int32_t relativeY = relativePoint.m_y;
int32_t paragraph = 0;
if (relativeY >= 0)
paragraph = relativeY / linegap;
else
paragraph = -((-relativeY + (linegap - 1)) / linegap);
bool isOutOfRange = false;
const size_t caratPos = FindVerticalMovementCaratPos(Vec2i(relativePoint.m_x, paragraph * linegap), isOutOfRange);
if (mouseEvent.m_eventType == GpMouseEventTypes::kDown)
{
m_dragSelectionStartChar = caratPos;
m_selStartChar = caratPos;
m_selEndChar = caratPos;
m_caratSelectionAnchor = CaratSelectionAnchor_End;
m_caratTimer = 0;
Redraw();
}
else
{
if (caratPos < m_dragSelectionStartChar)
{
m_caratSelectionAnchor = CaratSelectionAnchor_Start;
m_selStartChar = caratPos;
m_selEndChar = m_dragSelectionStartChar;
}
else
{
m_caratSelectionAnchor = CaratSelectionAnchor_End;
m_selEndChar = caratPos;
m_selStartChar = m_dragSelectionStartChar;
}
m_caratTimer = 0;
Redraw();
if (mouseEvent.m_eventType == GpMouseEventTypes::kUp)
{
m_caratScrollLocked = false;
m_isDraggingSelection = false;
return WidgetHandleStates::kDigested;
}
}
}
return WidgetHandleStates::kCaptured;
}
void EditboxWidget::DrawSelection(DrawSurface *surface, const Vec2i &basePoint) const
{
PortabilityLayer::RenderedFont *rfont = surface->ResolveFont(true);

View File

@@ -57,6 +57,8 @@ namespace PortabilityLayer
size_t FindVerticalMovementCaratPos(const Vec2i &desiredPos, bool &isOutOfRange) const;
void HandleKeyMoveCarat(size_t newPos, bool shiftHeld);
WidgetHandleState_t HandleDragSelection(const TimeTaggedVOSEvent &evt);
void DrawSelection(DrawSurface *surface, const Vec2i &basePoint) const;
Vec2i ResolveCaratPos(const Vec2i &basePoint, PortabilityLayer::RenderedFont *rfont) const;
@@ -78,6 +80,9 @@ namespace PortabilityLayer
bool m_hasFocus;
bool m_isMultiLine;
bool m_isDraggingSelection;
size_t m_dragSelectionStartChar;
uint16_t m_caratTimer;
};
}