Finish scroll bars

This commit is contained in:
elasota
2020-03-14 04:29:47 -04:00
parent dd78b08a5f
commit d394975336
4 changed files with 205 additions and 58 deletions

View File

@@ -248,6 +248,9 @@ void RedrawMapContents (void)
} }
else else
{ {
surface->SetForeColor(StdColors::White());
surface->FillRect(aRoom);
if (i >= groundLevel) if (i >= groundLevel)
surface->SetForeColor(StdColors::Green()); surface->SetForeColor(StdColors::Green());
else else
@@ -464,50 +467,50 @@ void ToggleMapWindow (void)
//-------------------------------------------------------------- LiveHScrollAction //-------------------------------------------------------------- LiveHScrollAction
#ifndef COMPILEDEMO #ifndef COMPILEDEMO
void LiveHScrollAction (ControlHandle theControl, short thePart) void LiveHScrollAction (PortabilityLayer::Widget *theControl, int thePart)
{ {
short wasValue, newValue; short wasValue, newValue;
switch (thePart) switch (thePart)
{ {
case kControlUpButtonPart: case kControlUpButtonPart:
wasValue = GetControlValue(theControl); wasValue = theControl->GetState();
SetControlValue(theControl, wasValue - 1); theControl->SetState(wasValue - 1);
if (GetControlValue(theControl) != wasValue) if (theControl->GetState() != wasValue)
{ {
mapLeftRoom = GetControlValue(theControl); mapLeftRoom = theControl->GetState();
RedrawMapContents(); RedrawMapContents();
} }
break; break;
case kControlDownButtonPart: case kControlDownButtonPart:
wasValue = GetControlValue(theControl); wasValue = theControl->GetState();
SetControlValue(theControl, wasValue + 1); theControl->SetState(wasValue + 1);
if (GetControlValue(theControl) != wasValue) if (theControl->GetState() != wasValue)
{ {
mapLeftRoom = GetControlValue(theControl); mapLeftRoom = theControl->GetState();
RedrawMapContents(); RedrawMapContents();
} }
break; break;
case kControlPageUpPart: case kControlPageUpPart:
wasValue = GetControlValue(theControl); wasValue = theControl->GetState();
newValue = wasValue - (mapRoomsWide / 2); newValue = wasValue - (mapRoomsWide / 2);
SetControlValue(theControl, newValue); theControl->SetState(newValue);
if (GetControlValue(theControl) != wasValue) if (theControl->GetState() != wasValue)
{ {
mapLeftRoom = GetControlValue(theControl); mapLeftRoom = theControl->GetState();
RedrawMapContents(); RedrawMapContents();
} }
break; break;
case kControlPageDownPart: case kControlPageDownPart:
wasValue = GetControlValue(theControl); wasValue = theControl->GetState();
newValue = wasValue + (mapRoomsWide / 2); newValue = wasValue + (mapRoomsWide / 2);
SetControlValue(theControl, newValue); theControl->SetState(newValue);
if (GetControlValue(theControl) != wasValue) if (theControl->GetState() != wasValue)
{ {
mapLeftRoom = GetControlValue(theControl); mapLeftRoom = theControl->GetState();
RedrawMapContents(); RedrawMapContents();
} }
break; break;
@@ -521,50 +524,50 @@ void LiveHScrollAction (ControlHandle theControl, short thePart)
//-------------------------------------------------------------- LiveVScrollAction //-------------------------------------------------------------- LiveVScrollAction
#ifndef COMPILEDEMO #ifndef COMPILEDEMO
void LiveVScrollAction (ControlHandle theControl, short thePart) void LiveVScrollAction (PortabilityLayer::Widget *theControl, int thePart)
{ {
short wasValue, newValue; short wasValue, newValue;
switch (thePart) switch (thePart)
{ {
case kControlUpButtonPart: case kControlUpButtonPart:
wasValue = GetControlValue(theControl); wasValue = theControl->GetState();
SetControlValue(theControl, wasValue - 1); theControl->SetState(wasValue - 1);
if (GetControlValue(theControl) != wasValue) if (theControl->GetState() != wasValue)
{ {
mapTopRoom = GetControlValue(theControl); mapTopRoom = theControl->GetState();
RedrawMapContents(); RedrawMapContents();
} }
break; break;
case kControlDownButtonPart: case kControlDownButtonPart:
wasValue = GetControlValue(theControl); wasValue = theControl->GetState();
SetControlValue(theControl, wasValue + 1); theControl->SetState(wasValue + 1);
if (GetControlValue(theControl) != wasValue) if (theControl->GetState() != wasValue)
{ {
mapTopRoom = GetControlValue(theControl); mapTopRoom = theControl->GetState();
RedrawMapContents(); RedrawMapContents();
} }
break; break;
case kControlPageUpPart: case kControlPageUpPart:
wasValue = GetControlValue(theControl); wasValue = theControl->GetState();
newValue = wasValue - (mapRoomsHigh / 2); newValue = wasValue - (mapRoomsHigh / 2);
SetControlValue(theControl, newValue); theControl->SetState(newValue);
if (GetControlValue(theControl) != wasValue) if (theControl->GetState() != wasValue)
{ {
mapTopRoom = GetControlValue(theControl); mapTopRoom = theControl->GetState();
RedrawMapContents(); RedrawMapContents();
} }
break; break;
case kControlPageDownPart: case kControlPageDownPart:
wasValue = GetControlValue(theControl); wasValue = theControl->GetState();
newValue = wasValue + (mapRoomsHigh / 2); newValue = wasValue + (mapRoomsHigh / 2);
SetControlValue(theControl, newValue); theControl->SetState(newValue);
if (GetControlValue(theControl) != wasValue) if (theControl->GetState() != wasValue)
{ {
mapTopRoom = GetControlValue(theControl); mapTopRoom = theControl->GetState();
RedrawMapContents(); RedrawMapContents();
} }
break; break;
@@ -586,13 +589,9 @@ void HandleMapClick (const GpMouseInputEvent &theEvent)
long controlRef; long controlRef;
short whichPart, localH, localV; short whichPart, localH, localV;
short roomH, roomV, itsNumber; short roomH, roomV, itsNumber;
ControlActionUPP scrollHActionUPP, scrollVActionUPP;
wherePt = Point::Create(theEvent.m_x, theEvent.m_y); wherePt = Point::Create(theEvent.m_x, theEvent.m_y);
scrollHActionUPP = NewControlActionUPP(LiveHScrollAction);
scrollVActionUPP = NewControlActionUPP(LiveVScrollAction);
if (mapWindow == nil) if (mapWindow == nil)
return; return;
@@ -676,14 +675,11 @@ void HandleMapClick (const GpMouseInputEvent &theEvent)
case kControlDownButtonPart: case kControlDownButtonPart:
case kControlPageUpPart: case kControlPageUpPart:
case kControlPageDownPart: case kControlPageDownPart:
if (TrackControl(whichControl, wherePt, scrollHActionUPP)) whichControl->Capture(wherePt, LiveHScrollAction);
{
}
break; break;
case kControlIndicatorPart: case kControlIndicatorPart:
if (TrackControl(whichControl, wherePt, nil)) if (whichControl->Capture(wherePt, nil))
{ {
mapLeftRoom = whichControl->GetState(); mapLeftRoom = whichControl->GetState();
RedrawMapContents(); RedrawMapContents();
@@ -699,14 +695,11 @@ void HandleMapClick (const GpMouseInputEvent &theEvent)
case kControlDownButtonPart: case kControlDownButtonPart:
case kControlPageUpPart: case kControlPageUpPart:
case kControlPageDownPart: case kControlPageDownPart:
if (TrackControl(whichControl, wherePt, scrollVActionUPP)) whichControl->Capture(wherePt, LiveVScrollAction);
{
}
break; break;
case kControlIndicatorPart: case kControlIndicatorPart:
if (TrackControl(whichControl, wherePt, nil)) if (whichControl->Capture(wherePt, nil))
{ {
mapTopRoom = whichControl->GetState(); mapTopRoom = whichControl->GetState();
RedrawMapContents(); RedrawMapContents();
@@ -715,9 +708,6 @@ void HandleMapClick (const GpMouseInputEvent &theEvent)
} }
} }
} }
DisposeControlActionUPP(scrollHActionUPP);
DisposeControlActionUPP(scrollVActionUPP);
#endif #endif
} }

View File

@@ -1,6 +1,7 @@
#include "PLScrollBarWidget.h" #include "PLScrollBarWidget.h"
#include "PLControlDefinitions.h" #include "PLControlDefinitions.h"
#include "PLStandardColors.h" #include "PLStandardColors.h"
#include "PLTimeTaggedVOSEvent.h"
namespace PortabilityLayer namespace PortabilityLayer
{ {
@@ -196,12 +197,161 @@ namespace PortabilityLayer
} }
} }
void ScrollBarWidget::SetState(int16_t state)
{
if (state < m_min)
WidgetSpec<ScrollBarWidget>::SetState(m_min);
else if (state > m_max)
WidgetSpec<ScrollBarWidget>::SetState(m_max);
else
WidgetSpec<ScrollBarWidget>::SetState(state);
}
void ScrollBarWidget::OnStateChanged() void ScrollBarWidget::OnStateChanged()
{ {
RefreshGrip(); RefreshGrip();
DrawControl(m_window->GetDrawSurface()); 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 int ScrollBarWidget::ResolvePart(const Point &point) const
{ {
if (!m_rect.Contains(point)) if (!m_rect.Contains(point))
@@ -222,17 +372,17 @@ namespace PortabilityLayer
} }
if (coord < 16) if (coord < 16)
return isHorizontal ? kControlDownButtonPart : kControlUpButtonPart; return kControlUpButtonPart;
if (coord < m_gripPos) if (coord - 16 < m_gripPos)
return isHorizontal ? kControlPageDownPart : kControlPageUpPart; return kControlPageUpPart;
if (coord - m_gripPos < m_gripSize) if (coord - 16 - m_gripPos < m_gripSize)
return kControlIndicatorPart; return kControlIndicatorPart;
if (coord < span - 16) if (coord < span - 16)
return isHorizontal ? kControlPageUpPart : kControlPageDownPart; return kControlPageDownPart;
return isHorizontal ? kControlUpButtonPart : kControlDownButtonPart; return kControlDownButtonPart;
} }
} }

View File

@@ -18,8 +18,11 @@ namespace PortabilityLayer
WidgetHandleState_t ProcessEvent(const TimeTaggedVOSEvent &evt) override; WidgetHandleState_t ProcessEvent(const TimeTaggedVOSEvent &evt) override;
void DrawControl(DrawSurface *surface) override; void DrawControl(DrawSurface *surface) override;
void SetState(int16_t state) override;
void OnStateChanged() override; void OnStateChanged() override;
int16_t Capture(const Point &pos, WidgetUpdateCallback_t callback) override;
int ResolvePart(const Point &point) const override; int ResolvePart(const Point &point) const override;
private: private:
@@ -33,6 +36,10 @@ namespace PortabilityLayer
static void DrawBeveledBox(DrawSurface *surface, const Rect &rect); 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_min;
int32_t m_max; int32_t m_max;
int32_t m_gripSize; int32_t m_gripSize;

View File

@@ -58,7 +58,7 @@ namespace PortabilityLayer
void Resize(uint16_t width, uint16_t height); void Resize(uint16_t width, uint16_t height);
void SetEnabled(bool enabled); void SetEnabled(bool enabled);
void SetState(int16_t state); virtual void SetState(int16_t state);
int16_t GetState() const; int16_t GetState() const;
void SetVisible(bool visible); void SetVisible(bool visible);