From d394975336a606429b0c9387afeaf1dde987f767 Mon Sep 17 00:00:00 2001 From: elasota Date: Sat, 14 Mar 2020 04:29:47 -0400 Subject: [PATCH] Finish scroll bars --- GpApp/Map.cpp | 92 +++++++------- PortabilityLayer/PLScrollBarWidget.cpp | 162 ++++++++++++++++++++++++- PortabilityLayer/PLScrollBarWidget.h | 7 ++ PortabilityLayer/PLWidgets.h | 2 +- 4 files changed, 205 insertions(+), 58 deletions(-) diff --git a/GpApp/Map.cpp b/GpApp/Map.cpp index a566f03..4b3692c 100644 --- a/GpApp/Map.cpp +++ b/GpApp/Map.cpp @@ -248,6 +248,9 @@ void RedrawMapContents (void) } else { + surface->SetForeColor(StdColors::White()); + surface->FillRect(aRoom); + if (i >= groundLevel) surface->SetForeColor(StdColors::Green()); else @@ -464,50 +467,50 @@ void ToggleMapWindow (void) //-------------------------------------------------------------- LiveHScrollAction #ifndef COMPILEDEMO -void LiveHScrollAction (ControlHandle theControl, short thePart) +void LiveHScrollAction (PortabilityLayer::Widget *theControl, int thePart) { short wasValue, newValue; switch (thePart) { case kControlUpButtonPart: - wasValue = GetControlValue(theControl); - SetControlValue(theControl, wasValue - 1); - if (GetControlValue(theControl) != wasValue) + wasValue = theControl->GetState(); + theControl->SetState(wasValue - 1); + if (theControl->GetState() != wasValue) { - mapLeftRoom = GetControlValue(theControl); + mapLeftRoom = theControl->GetState(); RedrawMapContents(); } break; case kControlDownButtonPart: - wasValue = GetControlValue(theControl); - SetControlValue(theControl, wasValue + 1); - if (GetControlValue(theControl) != wasValue) + wasValue = theControl->GetState(); + theControl->SetState(wasValue + 1); + if (theControl->GetState() != wasValue) { - mapLeftRoom = GetControlValue(theControl); + mapLeftRoom = theControl->GetState(); RedrawMapContents(); } break; case kControlPageUpPart: - wasValue = GetControlValue(theControl); + wasValue = theControl->GetState(); newValue = wasValue - (mapRoomsWide / 2); - SetControlValue(theControl, newValue); - if (GetControlValue(theControl) != wasValue) + theControl->SetState(newValue); + if (theControl->GetState() != wasValue) { - mapLeftRoom = GetControlValue(theControl); + mapLeftRoom = theControl->GetState(); RedrawMapContents(); } break; case kControlPageDownPart: - wasValue = GetControlValue(theControl); + wasValue = theControl->GetState(); newValue = wasValue + (mapRoomsWide / 2); - SetControlValue(theControl, newValue); - if (GetControlValue(theControl) != wasValue) + theControl->SetState(newValue); + if (theControl->GetState() != wasValue) { - mapLeftRoom = GetControlValue(theControl); + mapLeftRoom = theControl->GetState(); RedrawMapContents(); } break; @@ -521,50 +524,50 @@ void LiveHScrollAction (ControlHandle theControl, short thePart) //-------------------------------------------------------------- LiveVScrollAction #ifndef COMPILEDEMO -void LiveVScrollAction (ControlHandle theControl, short thePart) +void LiveVScrollAction (PortabilityLayer::Widget *theControl, int thePart) { short wasValue, newValue; switch (thePart) { case kControlUpButtonPart: - wasValue = GetControlValue(theControl); - SetControlValue(theControl, wasValue - 1); - if (GetControlValue(theControl) != wasValue) + wasValue = theControl->GetState(); + theControl->SetState(wasValue - 1); + if (theControl->GetState() != wasValue) { - mapTopRoom = GetControlValue(theControl); + mapTopRoom = theControl->GetState(); RedrawMapContents(); } break; case kControlDownButtonPart: - wasValue = GetControlValue(theControl); - SetControlValue(theControl, wasValue + 1); - if (GetControlValue(theControl) != wasValue) + wasValue = theControl->GetState(); + theControl->SetState(wasValue + 1); + if (theControl->GetState() != wasValue) { - mapTopRoom = GetControlValue(theControl); + mapTopRoom = theControl->GetState(); RedrawMapContents(); } break; case kControlPageUpPart: - wasValue = GetControlValue(theControl); + wasValue = theControl->GetState(); newValue = wasValue - (mapRoomsHigh / 2); - SetControlValue(theControl, newValue); - if (GetControlValue(theControl) != wasValue) + theControl->SetState(newValue); + if (theControl->GetState() != wasValue) { - mapTopRoom = GetControlValue(theControl); + mapTopRoom = theControl->GetState(); RedrawMapContents(); } break; case kControlPageDownPart: - wasValue = GetControlValue(theControl); + wasValue = theControl->GetState(); newValue = wasValue + (mapRoomsHigh / 2); - SetControlValue(theControl, newValue); - if (GetControlValue(theControl) != wasValue) + theControl->SetState(newValue); + if (theControl->GetState() != wasValue) { - mapTopRoom = GetControlValue(theControl); + mapTopRoom = theControl->GetState(); RedrawMapContents(); } break; @@ -586,13 +589,9 @@ void HandleMapClick (const GpMouseInputEvent &theEvent) long controlRef; short whichPart, localH, localV; short roomH, roomV, itsNumber; - ControlActionUPP scrollHActionUPP, scrollVActionUPP; wherePt = Point::Create(theEvent.m_x, theEvent.m_y); - scrollHActionUPP = NewControlActionUPP(LiveHScrollAction); - scrollVActionUPP = NewControlActionUPP(LiveVScrollAction); - if (mapWindow == nil) return; @@ -676,14 +675,11 @@ void HandleMapClick (const GpMouseInputEvent &theEvent) case kControlDownButtonPart: case kControlPageUpPart: case kControlPageDownPart: - if (TrackControl(whichControl, wherePt, scrollHActionUPP)) - { - - } + whichControl->Capture(wherePt, LiveHScrollAction); break; case kControlIndicatorPart: - if (TrackControl(whichControl, wherePt, nil)) + if (whichControl->Capture(wherePt, nil)) { mapLeftRoom = whichControl->GetState(); RedrawMapContents(); @@ -699,14 +695,11 @@ void HandleMapClick (const GpMouseInputEvent &theEvent) case kControlDownButtonPart: case kControlPageUpPart: case kControlPageDownPart: - if (TrackControl(whichControl, wherePt, scrollVActionUPP)) - { - - } + whichControl->Capture(wherePt, LiveVScrollAction); break; case kControlIndicatorPart: - if (TrackControl(whichControl, wherePt, nil)) + if (whichControl->Capture(wherePt, nil)) { mapTopRoom = whichControl->GetState(); RedrawMapContents(); @@ -715,9 +708,6 @@ void HandleMapClick (const GpMouseInputEvent &theEvent) } } } - - DisposeControlActionUPP(scrollHActionUPP); - DisposeControlActionUPP(scrollVActionUPP); #endif } diff --git a/PortabilityLayer/PLScrollBarWidget.cpp b/PortabilityLayer/PLScrollBarWidget.cpp index af34b76..e4d6018 100644 --- a/PortabilityLayer/PLScrollBarWidget.cpp +++ b/PortabilityLayer/PLScrollBarWidget.cpp @@ -1,6 +1,7 @@ #include "PLScrollBarWidget.h" #include "PLControlDefinitions.h" #include "PLStandardColors.h" +#include "PLTimeTaggedVOSEvent.h" namespace PortabilityLayer { @@ -196,12 +197,161 @@ namespace PortabilityLayer } } + void ScrollBarWidget::SetState(int16_t state) + { + if (state < m_min) + WidgetSpec::SetState(m_min); + else if (state > m_max) + WidgetSpec::SetState(m_max); + else + WidgetSpec::SetState(state); + } + void ScrollBarWidget::OnStateChanged() { RefreshGrip(); DrawControl(m_window->GetDrawSurface()); } + int16_t ScrollBarWidget::Capture(const Point &pos, WidgetUpdateCallback_t callback) + { + int part = ResolvePart(pos); + if (!part) + return 0; + + if (part == kControlIndicatorPart) + return CaptureIndicator(pos, callback); + else + return CaptureScrollSegment(pos, part, callback); + } + + int16_t ScrollBarWidget::CaptureScrollSegment(const Point &pos, int part, WidgetUpdateCallback_t callback) + { + int tickDelay = 15; + + Point currentPos = pos; + bool wasInBounds = false; + bool isInBounds = (ResolvePart(pos) == part); + + int ticksUntilIterate = 0; + for (;;) + { + if (ticksUntilIterate == 0) + { + if (isInBounds) + { + IterateScrollSegment(part, callback); + isInBounds = (ResolvePart(currentPos) == part); // Update in-bounds since the scroll may invalidate it + } + + ticksUntilIterate = tickDelay; + } + + TimeTaggedVOSEvent evt; + if (WaitForEvent(&evt, 1)) + { + if (evt.m_vosEvent.m_eventType == GpVOSEventTypes::kMouseInput) + { + const GpMouseInputEvent &mouseEvt = evt.m_vosEvent.m_event.m_mouseInputEvent; + if (mouseEvt.m_button == GpMouseButtons::kLeft && mouseEvt.m_eventType == GpMouseEventTypes::kUp) + return part; + else + { + currentPos = m_window->MouseToLocal(mouseEvt); + isInBounds = (ResolvePart(currentPos) == part); + } + } + } + else + ticksUntilIterate--; + } + } + + int16_t ScrollBarWidget::CaptureIndicator(const Point &pos, WidgetUpdateCallback_t callback) + { + const bool isHorizontal = IsHorizontal(); + + const int32_t startCoordinate = isHorizontal ? pos.h : pos.v; + int32_t currentGripPos = m_gripPos; + + Rect currentHandle; + if (isHorizontal) + currentHandle = Rect::Create(m_rect.top, m_rect.left + 16 + m_gripPos, m_rect.bottom, m_rect.left + 16 + m_gripPos + m_gripSize); + else + currentHandle = Rect::Create(m_rect.top + 16 + m_gripPos, m_rect.left, m_rect.top + 16 + m_gripPos + m_gripSize, m_rect.right); + + DrawSurface *surface = this->m_window->GetDrawSurface(); + + uint8_t solidPattern[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + surface->InvertFillRect(currentHandle, solidPattern); + + for (;;) + { + TimeTaggedVOSEvent evt; + if (WaitForEvent(&evt, 1)) + { + if (evt.m_vosEvent.m_eventType == GpVOSEventTypes::kMouseInput) + { + const GpMouseInputEvent &mouseEvt = evt.m_vosEvent.m_event.m_mouseInputEvent; + if (mouseEvt.m_eventType == GpMouseEventTypes::kUp || mouseEvt.m_eventType == GpMouseEventTypes::kMove) + { + const Point localPoint = m_window->MouseToLocal(mouseEvt); + int32_t desiredCoordinate = isHorizontal ? localPoint.h : localPoint.v; + int32_t desiredGripPos = m_gripPos + (desiredCoordinate - startCoordinate); + + if (desiredGripPos < 0) + desiredGripPos = 0; + else if (desiredGripPos > m_laneCapacity) + desiredGripPos = m_laneCapacity; + + if (desiredGripPos != currentGripPos) + { + surface->InvertFillRect(currentHandle, solidPattern); + + if (isHorizontal) + currentHandle = Rect::Create(m_rect.top, m_rect.left + 16 + desiredGripPos, m_rect.bottom, m_rect.left + 16 + desiredGripPos + m_gripSize); + else + currentHandle = Rect::Create(m_rect.top + 16 + desiredGripPos, m_rect.left, m_rect.top + 16 + desiredGripPos + m_gripSize, m_rect.right); + + surface->InvertFillRect(currentHandle, solidPattern); + + currentGripPos = desiredGripPos; + } + } + + if (mouseEvt.m_eventType == GpMouseEventTypes::kUp && mouseEvt.m_button == GpMouseButtons::kLeft) + { + surface->InvertFillRect(currentHandle, solidPattern); + + //int32_t desiredState = (currentGripPos / m_laneCapacity) * (m_max - m_min); + int32_t desiredState = m_min; + + if (m_laneCapacity > 0) + { + desiredState = ((currentGripPos * (m_max - m_min)) * 2 + m_laneCapacity) / (m_laneCapacity * 2); + + // This shouldn't happen unless something weird happens like an int overflow + if (desiredState < m_min) + desiredState = m_min; + else if (desiredState > m_max) + desiredState = m_max; + + SetState(desiredState); + } + + return kControlIndicatorPart; + } + } + } + } + } + + void ScrollBarWidget::IterateScrollSegment(int part, WidgetUpdateCallback_t callback) + { + if (callback != nullptr) + callback(this, part); + } + int ScrollBarWidget::ResolvePart(const Point &point) const { if (!m_rect.Contains(point)) @@ -222,17 +372,17 @@ namespace PortabilityLayer } if (coord < 16) - return isHorizontal ? kControlDownButtonPart : kControlUpButtonPart; + return kControlUpButtonPart; - if (coord < m_gripPos) - return isHorizontal ? kControlPageDownPart : kControlPageUpPart; + if (coord - 16 < m_gripPos) + return kControlPageUpPart; - if (coord - m_gripPos < m_gripSize) + if (coord - 16 - m_gripPos < m_gripSize) return kControlIndicatorPart; if (coord < span - 16) - return isHorizontal ? kControlPageUpPart : kControlPageDownPart; + return kControlPageDownPart; - return isHorizontal ? kControlUpButtonPart : kControlDownButtonPart; + return kControlDownButtonPart; } } diff --git a/PortabilityLayer/PLScrollBarWidget.h b/PortabilityLayer/PLScrollBarWidget.h index d10361f..5a5bbef 100644 --- a/PortabilityLayer/PLScrollBarWidget.h +++ b/PortabilityLayer/PLScrollBarWidget.h @@ -18,8 +18,11 @@ namespace PortabilityLayer WidgetHandleState_t ProcessEvent(const TimeTaggedVOSEvent &evt) override; void DrawControl(DrawSurface *surface) override; + void SetState(int16_t state) override; void OnStateChanged() override; + int16_t Capture(const Point &pos, WidgetUpdateCallback_t callback) override; + int ResolvePart(const Point &point) const override; private: @@ -33,6 +36,10 @@ namespace PortabilityLayer static void DrawBeveledBox(DrawSurface *surface, const Rect &rect); + int16_t CaptureScrollSegment(const Point &pos, int part, WidgetUpdateCallback_t callback); + int16_t CaptureIndicator(const Point &pos, WidgetUpdateCallback_t callback); + void IterateScrollSegment(int part, WidgetUpdateCallback_t callback); + int32_t m_min; int32_t m_max; int32_t m_gripSize; diff --git a/PortabilityLayer/PLWidgets.h b/PortabilityLayer/PLWidgets.h index 46e5eb9..9713cc8 100644 --- a/PortabilityLayer/PLWidgets.h +++ b/PortabilityLayer/PLWidgets.h @@ -58,7 +58,7 @@ namespace PortabilityLayer void Resize(uint16_t width, uint16_t height); void SetEnabled(bool enabled); - void SetState(int16_t state); + virtual void SetState(int16_t state); int16_t GetState() const; void SetVisible(bool visible);