EsScrollView

This commit is contained in:
nakst 2021-10-05 12:00:46 +01:00
parent 4d1c7ace98
commit 8ce9eddea3
5 changed files with 72 additions and 27 deletions

View File

@ -323,14 +323,7 @@ struct ScrollPane {
bool enabled[2];
bool dragScrolling;
#define SCROLL_MODE_NONE (0) // No scrolling takes place on this axis.
#define SCROLL_MODE_HIDDEN (1) // Scrolling takes place, but there is no visible scrollbar.
#define SCROLL_MODE_FIXED (2) // The scrollbar is always visible.
#define SCROLL_MODE_AUTO (3) // The scrollbar is only visible if the content is larger than the viewport.
uint8_t mode[2];
#define SCROLL_X_DRAG (1 << 0)
#define SCROLL_Y_DRAG (1 << 1)
#define SCROLL_MANUAL (1 << 2) // The parent is responsible for updating the position of the scroll bars.
uint16_t flags;
void Setup(EsElement *parent, uint8_t xMode, uint8_t yMode, uint16_t flags);
@ -2790,11 +2783,11 @@ void ScrollPane::Setup(EsElement *_parent, uint8_t _xMode, uint8_t _yMode, uint1
mode[1] = _yMode;
flags = _flags;
if (mode[0] == SCROLL_MODE_NONE) flags &= ~SCROLL_X_DRAG;
if (mode[1] == SCROLL_MODE_NONE) flags &= ~SCROLL_Y_DRAG;
if (mode[0] == ES_SCROLL_MODE_NONE) flags &= ~SCROLL_X_DRAG;
if (mode[1] == ES_SCROLL_MODE_NONE) flags &= ~SCROLL_Y_DRAG;
for (int axis = 0; axis < 2; axis++) {
if (mode[axis] == SCROLL_MODE_FIXED || mode[axis] == SCROLL_MODE_AUTO) {
if (mode[axis] == ES_SCROLL_MODE_FIXED || mode[axis] == ES_SCROLL_MODE_AUTO) {
uint64_t flags = ES_CELL_FILL | ES_ELEMENT_NON_CLIENT | (axis ? ES_SCROLLBAR_VERTICAL : ES_SCROLLBAR_HORIZONTAL);
if (!bar[axis]) {
@ -2870,7 +2863,7 @@ void ScrollPane::ReceivedMessage(EsMessage *message) {
message->animate.complete = false;
}
} else if (message->type == ES_MSG_GET_HEIGHT) {
if (message->measure.width && (mode[0] == SCROLL_MODE_AUTO) && (mode[1] != SCROLL_MODE_AUTO)) {
if (message->measure.width && (mode[0] == ES_SCROLL_MODE_AUTO) && (mode[1] != ES_SCROLL_MODE_AUTO)) {
// To accurately measure the height of the element for this width,
// we need to determine whether the horizontal scrollbar will be present.
// TODO This assumes that the element will be send a LAYOUT message after measurements are complete,
@ -2881,7 +2874,7 @@ void ScrollPane::ReceivedMessage(EsMessage *message) {
parent->internalOffsetBottom = (m.measure.width + fixedViewport[0] > message->measure.width) ? bar[0]->currentStyle->preferredHeight : 0;
}
} else if (message->type == ES_MSG_GET_WIDTH) {
if (message->measure.width && (mode[1] == SCROLL_MODE_AUTO) && (mode[0] != SCROLL_MODE_AUTO)) {
if (message->measure.width && (mode[1] == ES_SCROLL_MODE_AUTO) && (mode[0] != ES_SCROLL_MODE_AUTO)) {
// As above.
EsMessage m = {};
m.type = ES_MSG_GET_HEIGHT;
@ -2895,7 +2888,7 @@ void ScrollPane::ReceivedMessage(EsMessage *message) {
}
void ScrollPane::SetPosition(int axis, double newScroll, bool sendMovedMessage) {
if (mode[axis] == SCROLL_MODE_NONE) return;
if (mode[axis] == ES_SCROLL_MODE_NONE) return;
if (newScroll < 0) newScroll = 0;
else if (newScroll > limit[axis]) newScroll = limit[axis];
if (newScroll == position[axis]) return;
@ -2917,7 +2910,7 @@ void ScrollPane::SetPosition(int axis, double newScroll, bool sendMovedMessage)
}
bool ScrollPane::RefreshLimit(int axis, int64_t *contentSize) {
if (mode[axis] != SCROLL_MODE_NONE) {
if (mode[axis] != ES_SCROLL_MODE_NONE) {
uint8_t *internalOffset = axis ? &parent->internalOffsetRight : &parent->internalOffsetBottom;
EsRectangle bounds = parent->GetBounds();
@ -2936,7 +2929,7 @@ bool ScrollPane::RefreshLimit(int axis, int64_t *contentSize) {
axis + 'X', limit[axis], *contentSize, axis ? bounds.r : bounds.b);
}
if (mode[axis] == SCROLL_MODE_AUTO && limit[axis] > 0 && !(*internalOffset)) {
if (mode[axis] == ES_SCROLL_MODE_AUTO && limit[axis] > 0 && !(*internalOffset)) {
*internalOffset = axis ? bar[axis]->currentStyle->preferredWidth : bar[axis]->currentStyle->preferredHeight;
return true;
}
@ -2950,8 +2943,8 @@ void ScrollPane::Refresh() {
InspectorNotifyElementEvent(parent, "scroll", "Refreshing scroll pane...\n");
}
parent->internalOffsetRight = mode[1] == SCROLL_MODE_FIXED ? bar[1]->currentStyle->preferredWidth : 0;
parent->internalOffsetBottom = mode[0] == SCROLL_MODE_FIXED ? bar[0]->currentStyle->preferredHeight : 0;
parent->internalOffsetRight = mode[1] == ES_SCROLL_MODE_FIXED ? bar[1]->currentStyle->preferredWidth : 0;
parent->internalOffsetBottom = mode[0] == ES_SCROLL_MODE_FIXED ? bar[0]->currentStyle->preferredHeight : 0;
int64_t contentWidth = 0, contentHeight = 0;
@ -2993,6 +2986,25 @@ void ScrollPane::Refresh() {
}
}
struct EsScrollView : EsElement { ScrollPane scroll; };
void EsScrollViewSetup(EsScrollView *view, uint8_t xMode, uint8_t yMode, uint16_t flags) { view->scroll.Setup(view, xMode, yMode, flags); }
void EsScrollViewSetPosition(EsScrollView *view, int axis, double newPosition, bool notify) { view->scroll.SetPosition(axis, newPosition, notify); }
void EsScrollViewRefresh(EsScrollView *view) { view->scroll.Refresh(); }
void EsScrollViewReceivedMessage(EsScrollView *view, EsMessage *message) { view->scroll.ReceivedMessage(message); }
int64_t EsScrollViewGetPosition(EsScrollView *view, int axis) { return view->scroll.position[axis]; }
int64_t EsScrollViewGetLimit(EsScrollView *view, int axis) { return view->scroll.limit[axis]; }
void EsScrollViewSetFixedViewport(EsScrollView *view, int axis, int32_t value) { view->scroll.fixedViewport[axis] = value; }
bool EsScrollViewIsBarEnabled(EsScrollView *view, int axis) { return view->scroll.enabled[axis]; }
bool EsScrollViewIsInDragScroll(EsScrollView *view) { return view->scroll.dragScrolling; }
EsScrollView *EsCustomScrollViewCreate(EsElement *parent, uint64_t flags, const EsStyle *style) {
EsScrollView *element = (EsScrollView *) EsHeapAllocate(sizeof(EsScrollView), true);
if (!element) return nullptr;
element->Initialise(parent, flags, nullptr, style);
element->cName = "custom scroll view";
return element;
}
// --------------------------------- Panels.
void PanelSwitcherTransitionComplete(EsPanel *panel) {
@ -3386,8 +3398,8 @@ EsPanel *EsPanelCreate(EsElement *parent, uint64_t flags, const EsStyle *style)
if (flags & ES_PANEL_REVERSE) panel->flags |= ES_ELEMENT_LAYOUT_HINT_REVERSE;
panel->scroll.Setup(panel,
((flags & ES_PANEL_H_SCROLL_FIXED) ? SCROLL_MODE_FIXED : (flags & ES_PANEL_H_SCROLL_AUTO) ? SCROLL_MODE_AUTO : SCROLL_MODE_NONE),
((flags & ES_PANEL_V_SCROLL_FIXED) ? SCROLL_MODE_FIXED : (flags & ES_PANEL_V_SCROLL_AUTO) ? SCROLL_MODE_AUTO : SCROLL_MODE_NONE),
((flags & ES_PANEL_H_SCROLL_FIXED) ? ES_SCROLL_MODE_FIXED : (flags & ES_PANEL_H_SCROLL_AUTO) ? ES_SCROLL_MODE_AUTO : ES_SCROLL_MODE_NONE),
((flags & ES_PANEL_V_SCROLL_FIXED) ? ES_SCROLL_MODE_FIXED : (flags & ES_PANEL_V_SCROLL_AUTO) ? ES_SCROLL_MODE_AUTO : ES_SCROLL_MODE_NONE),
ES_FLAGS_DEFAULT);
return panel;
@ -3824,7 +3836,7 @@ EsCanvasPane *EsCanvasPaneCreate(EsElement *parent, uint64_t flags, const EsStyl
pane->Initialise(parent, flags, ProcessCanvasPaneMessage, style);
pane->cName = "canvas pane";
pane->zoom = 1.0;
pane->scroll.Setup(pane, SCROLL_MODE_AUTO, SCROLL_MODE_AUTO, SCROLL_MANUAL);
pane->scroll.Setup(pane, ES_SCROLL_MODE_AUTO, ES_SCROLL_MODE_AUTO, SCROLL_MANUAL);
return pane;
}

View File

@ -1925,18 +1925,18 @@ void EsListViewChangeStyles(EsListView *view, const EsStyle *style, const EsStyl
view->scroll.fixedViewport[1] = 0;
}
// It's safe to use SCROLL_MODE_AUTO even in tiled mode,
// It's safe to use ES_SCROLL_MODE_AUTO even in tiled mode,
// because decreasing the secondary axis can only increase the primary axis.
uint8_t scrollXMode = 0, scrollYMode = 0;
if (view->flags & ES_LIST_VIEW_COLUMNS) {
scrollXMode = SCROLL_MODE_AUTO;
scrollYMode = SCROLL_MODE_AUTO;
scrollXMode = ES_SCROLL_MODE_AUTO;
scrollYMode = ES_SCROLL_MODE_AUTO;
} else if (view->flags & ES_LIST_VIEW_HORIZONTAL) {
scrollXMode = SCROLL_MODE_AUTO;
scrollXMode = ES_SCROLL_MODE_AUTO;
} else {
scrollYMode = SCROLL_MODE_AUTO;
scrollYMode = ES_SCROLL_MODE_AUTO;
}
view->scroll.Setup(view, scrollXMode, scrollYMode, SCROLL_X_DRAG | SCROLL_Y_DRAG);

View File

@ -14,6 +14,7 @@ opaque_type EsImageDisplay EsElement;
opaque_type EsListDisplay EsElement;
opaque_type EsCanvasPane EsElement;
opaque_type EsSlider EsElement;
opaque_type EsScrollView EsElement;
opaque_type EsTextPlan none;
opaque_type EsPaintTarget none;
opaque_type EsUndoManager none;
@ -735,6 +736,16 @@ define ES_CLIPBOARD_ADD_LAZY_CUT (1 << 0) // Only perform the deletion after pas
define ES_SCROLL_WHEEL_NOTCH (0x100)
// Scroll view modes.
define ES_SCROLL_MODE_NONE (0) // No scrolling takes place on this axis.
define ES_SCROLL_MODE_HIDDEN (1) // Scrolling takes place, but there is no visible scrollbar.
define ES_SCROLL_MODE_FIXED (2) // The scrollbar is always visible.
define ES_SCROLL_MODE_AUTO (3) // The scrollbar is only visible if the content is larger than the viewport.
// Scroll view flags.
define SCROLL_X_DRAG (1 << 0)
define SCROLL_Y_DRAG (1 << 1)
private define SCROLL_MANUAL (1 << 2) // The parent is responsible for updating the position of the scroll bars.
include desktop/icons.header
enum EsFatalError {
@ -2378,7 +2389,19 @@ function void EsElementGetTextStyle(EsElement *element, EsTextStyle *style);
function EsRectangle EsElementGetWindowBounds(EsElement *element, bool client = true);
function EsRectangle EsElementGetScreenBounds(EsElement *element, bool client = true);
// TODO Rename these functions?
function EsElement *EsCustomElementCreate(EsElement *parent, uint64_t flags = ES_FLAGS_DEFAULT, const EsStyle *style = ES_NULL);
function EsScrollView *EsCustomScrollViewCreate(EsElement *parent, uint64_t flags = ES_FLAGS_DEFAULT, const EsStyle *style = ES_NULL);
function void EsScrollViewReceivedMessage(EsScrollView *view, EsMessage *message); // You *must* call this *before* handling any messages.
function void EsScrollViewSetup(EsScrollView *view, uint8_t xMode, uint8_t yMode, uint16_t flags);
function void EsScrollViewSetPosition(EsScrollView *view, int axis, double newPosition, bool sendMovedMessage = true);
function void EsScrollViewRefresh(EsScrollView *view);
function int64_t EsScrollViewGetPosition(EsScrollView *view, int axis);
function int64_t EsScrollViewGetLimit(EsScrollView *view, int axis);
function void EsScrollViewSetFixedViewport(EsScrollView *view, int axis, int32_t value);
function bool EsScrollViewIsBarEnabled(EsScrollView *view, int axis);
function bool EsScrollViewIsInDragScroll(EsScrollView *view);
// Windows, menus, popups, toolbars and dialogs.

View File

@ -4714,8 +4714,8 @@ EsTextbox *EsTextboxCreate(EsElement *parent, uint64_t flags, const EsStyle *sty
textbox->cName = "textbox";
textbox->scroll.Setup(textbox,
(flags & ES_TEXTBOX_MULTILINE) ? SCROLL_MODE_AUTO : SCROLL_MODE_HIDDEN,
(flags & ES_TEXTBOX_MULTILINE) ? SCROLL_MODE_AUTO : SCROLL_MODE_NONE,
(flags & ES_TEXTBOX_MULTILINE) ? ES_SCROLL_MODE_AUTO : ES_SCROLL_MODE_HIDDEN,
(flags & ES_TEXTBOX_MULTILINE) ? ES_SCROLL_MODE_AUTO : ES_SCROLL_MODE_NONE,
SCROLL_X_DRAG | SCROLL_Y_DRAG);
textbox->undo = &textbox->localUndo;

View File

@ -477,3 +477,13 @@ EsCRTstrtod=475
EsCRTstrtof=476
EsOpenDocumentQueryInformation=477
EsDrawTextThemed=478
EsCustomScrollViewCreate=479
EsScrollViewSetup=480
EsScrollViewSetPosition=481
EsScrollViewRefresh=482
EsScrollViewReceivedMessage=483
EsScrollViewGetPosition=484
EsScrollViewGetLimit=485
EsScrollViewSetFixedViewport=486
EsScrollViewIsBarEnabled=487
EsScrollViewIsInDragScroll=488