Fixed scrollbar thumb dragging and ALT-SPACE.
This commit is contained in:
parent
1a60fdcf54
commit
8550fbbbf2
10 changed files with 492 additions and 4 deletions
|
|
@ -2936,7 +2936,8 @@ static void pollKeyboard(AppContextT *ctx) {
|
|||
|
||||
// Alt+Space — open/close system menu
|
||||
// Enhanced INT 16h: Alt+Space returns scancode 0x39, ascii 0x20
|
||||
if (scancode == 0x39 && ascii == 0x20) {
|
||||
// Must check Alt modifier (bit 3) to distinguish from plain Space
|
||||
if (scancode == 0x39 && ascii == 0x20 && (shiftFlags & 0x08)) {
|
||||
if (ctx->sysMenu.active) {
|
||||
closeSysMenu(ctx);
|
||||
} else if (ctx->stack.focusedIdx >= 0) {
|
||||
|
|
|
|||
|
|
@ -52,6 +52,9 @@ int32_t sResizeOrigW = 0; // column width at resize start
|
|||
WidgetT *sDragSplitter = NULL; // splitter being dragged
|
||||
int32_t sDragSplitStart = 0; // mouse offset from splitter edge at drag start
|
||||
WidgetT *sDragReorder = NULL; // list/tree widget in drag-reorder mode
|
||||
WidgetT *sDragScrollbar = NULL; // widget whose scrollbar thumb is being dragged
|
||||
int32_t sDragScrollbarOff = 0; // mouse offset within thumb at drag start
|
||||
int32_t sDragScrollbarOrient = 0; // 0=vertical, 1=horizontal
|
||||
|
||||
|
||||
// ============================================================
|
||||
|
|
@ -201,6 +204,10 @@ void widgetDestroyChildren(WidgetT *w) {
|
|||
sResizeCol = -1;
|
||||
}
|
||||
|
||||
if (sDragScrollbar == child) {
|
||||
sDragScrollbar = NULL;
|
||||
}
|
||||
|
||||
free(child);
|
||||
child = next;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -388,6 +388,20 @@ void widgetOnMouse(WindowT *win, int32_t x, int32_t y, int32_t buttons) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Handle scrollbar thumb drag release
|
||||
if (sDragScrollbar && !(buttons & MOUSE_LEFT)) {
|
||||
sDragScrollbar = NULL;
|
||||
wgtInvalidatePaint(root);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle scrollbar thumb drag (mouse move while pressed)
|
||||
if (sDragScrollbar && (buttons & MOUSE_LEFT)) {
|
||||
widgetScrollbarDragUpdate(sDragScrollbar, sDragScrollbarOrient, sDragScrollbarOff, x, y);
|
||||
wgtInvalidatePaint(root);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle button press release
|
||||
if (sPressedButton && !(buttons & MOUSE_LEFT)) {
|
||||
if (sPressedButton->type == WidgetImageButtonE) {
|
||||
|
|
|
|||
|
|
@ -191,6 +191,9 @@ extern int32_t sResizeOrigW; // original column width at start of resize
|
|||
extern WidgetT *sDragSplitter; // splitter being dragged
|
||||
extern int32_t sDragSplitStart; // mouse position at start of splitter drag
|
||||
extern WidgetT *sDragReorder; // listbox/treeview item being drag-reordered
|
||||
extern WidgetT *sDragScrollbar; // widget whose scrollbar thumb is being dragged
|
||||
extern int32_t sDragScrollbarOff; // mouse offset within thumb at drag start
|
||||
extern int32_t sDragScrollbarOrient; // 0=vertical, 1=horizontal
|
||||
|
||||
// ============================================================
|
||||
// Core functions (widgetCore.c)
|
||||
|
|
@ -260,6 +263,7 @@ typedef enum {
|
|||
|
||||
void widgetDrawScrollbarH(DisplayT *d, const BlitOpsT *ops, const ColorSchemeT *colors, int32_t sbX, int32_t sbY, int32_t sbW, int32_t totalSize, int32_t visibleSize, int32_t scrollPos);
|
||||
void widgetDrawScrollbarV(DisplayT *d, const BlitOpsT *ops, const ColorSchemeT *colors, int32_t sbX, int32_t sbY, int32_t sbH, int32_t totalSize, int32_t visibleSize, int32_t scrollPos);
|
||||
void widgetScrollbarDragUpdate(WidgetT *w, int32_t orient, int32_t dragOff, int32_t mouseX, int32_t mouseY);
|
||||
ScrollHitE widgetScrollbarHitTest(int32_t sbLen, int32_t relPos, int32_t totalSize, int32_t visibleSize, int32_t scrollPos);
|
||||
|
||||
// ============================================================
|
||||
|
|
|
|||
|
|
@ -471,6 +471,15 @@ void widgetListBoxOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy) {
|
|||
} else if (sh == ScrollHitPageIncE) {
|
||||
hit->as.listBox.scrollPos += visibleRows;
|
||||
hit->as.listBox.scrollPos = clampInt(hit->as.listBox.scrollPos, 0, maxScroll);
|
||||
} else if (sh == ScrollHitThumbE) {
|
||||
int32_t trackLen = innerH - WGT_SB_W * 2;
|
||||
int32_t thumbPos;
|
||||
int32_t thumbSize;
|
||||
widgetScrollbarThumb(trackLen, hit->as.listBox.itemCount, visibleRows, hit->as.listBox.scrollPos, &thumbPos, &thumbSize);
|
||||
|
||||
sDragScrollbar = hit;
|
||||
sDragScrollbarOrient = 0;
|
||||
sDragScrollbarOff = relY - WGT_SB_W - thumbPos;
|
||||
}
|
||||
|
||||
hit->focused = true;
|
||||
|
|
|
|||
|
|
@ -817,6 +817,15 @@ void widgetListViewOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy)
|
|||
} else if (sh == ScrollHitPageIncE) {
|
||||
hit->as.listView->scrollPos += visibleRows;
|
||||
hit->as.listView->scrollPos = clampInt(hit->as.listView->scrollPos, 0, maxScrollV);
|
||||
} else if (sh == ScrollHitThumbE) {
|
||||
int32_t trackLen = innerH - WGT_SB_W * 2;
|
||||
int32_t thumbPos;
|
||||
int32_t thumbSize;
|
||||
widgetScrollbarThumb(trackLen, hit->as.listView->rowCount, visibleRows, hit->as.listView->scrollPos, &thumbPos, &thumbSize);
|
||||
|
||||
sDragScrollbar = hit;
|
||||
sDragScrollbarOrient = 0;
|
||||
sDragScrollbarOff = relY - WGT_SB_W - thumbPos;
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
@ -846,6 +855,15 @@ void widgetListViewOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy)
|
|||
hit->as.listView->scrollPosH -= pageSize;
|
||||
} else if (sh == ScrollHitPageIncE) {
|
||||
hit->as.listView->scrollPosH += pageSize;
|
||||
} else if (sh == ScrollHitThumbE) {
|
||||
int32_t trackLen = innerW - WGT_SB_W * 2;
|
||||
int32_t thumbPos;
|
||||
int32_t thumbSize;
|
||||
widgetScrollbarThumb(trackLen, totalColW, innerW, hit->as.listView->scrollPosH, &thumbPos, &thumbSize);
|
||||
|
||||
sDragScrollbar = hit;
|
||||
sDragScrollbarOrient = 1;
|
||||
sDragScrollbarOff = relX - WGT_SB_W - thumbPos;
|
||||
}
|
||||
|
||||
hit->as.listView->scrollPosH = clampInt(hit->as.listView->scrollPosH, 0, maxScrollH);
|
||||
|
|
|
|||
|
|
@ -499,6 +499,11 @@ void widgetScrollPaneOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy
|
|||
hit->as.scrollPane.scrollPosV -= pageSize;
|
||||
} else if (trackRelY >= thumbPos + thumbSize) {
|
||||
hit->as.scrollPane.scrollPosV += pageSize;
|
||||
} else {
|
||||
sDragScrollbar = hit;
|
||||
sDragScrollbarOrient = 0;
|
||||
sDragScrollbarOff = trackRelY - thumbPos;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -538,6 +543,11 @@ void widgetScrollPaneOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy
|
|||
hit->as.scrollPane.scrollPosH -= pageSize;
|
||||
} else if (trackRelX >= thumbPos + thumbSize) {
|
||||
hit->as.scrollPane.scrollPosH += pageSize;
|
||||
} else {
|
||||
sDragScrollbar = hit;
|
||||
sDragScrollbarOrient = 1;
|
||||
sDragScrollbarOff = trackRelX - thumbPos;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,16 @@
|
|||
|
||||
#include "widgetInternal.h"
|
||||
|
||||
// Constants duplicated from widgetTextInput.c and widgetScrollPane.c
|
||||
// for use in widgetScrollbarDragUpdate. These are file-local in their
|
||||
// source files, so we repeat the values here to avoid cross-file
|
||||
// coupling. They must stay in sync with the originals.
|
||||
#define TEXTAREA_BORDER 2
|
||||
#define TEXTAREA_PAD 2
|
||||
#define TEXTAREA_SB_W 14
|
||||
#define SP_BORDER 2
|
||||
#define SP_SB_W 14
|
||||
|
||||
|
||||
// ============================================================
|
||||
// widgetDrawScrollbarH
|
||||
|
|
@ -135,6 +145,393 @@ void widgetDrawScrollbarV(DisplayT *d, const BlitOpsT *ops, const ColorSchemeT *
|
|||
}
|
||||
|
||||
|
||||
// ============================================================
|
||||
// widgetScrollbarDragUpdate
|
||||
// ============================================================
|
||||
|
||||
// Handles ongoing scrollbar thumb drag for widget-internal scrollbars.
|
||||
// Converts the mouse pixel position into a scroll value using linear
|
||||
// interpolation, matching the WM-level wmScrollbarDrag logic.
|
||||
// orient: 0=vertical, 1=horizontal.
|
||||
// dragOff: mouse offset within thumb captured at drag start.
|
||||
//
|
||||
// Each widget type stores scroll state differently (row counts vs
|
||||
// pixel offsets, different struct fields), so this function switches
|
||||
// on widget type to extract the scrollbar geometry and update the
|
||||
// correct scroll field.
|
||||
void widgetScrollbarDragUpdate(WidgetT *w, int32_t orient, int32_t dragOff, int32_t mouseX, int32_t mouseY) {
|
||||
// Determine scrollbar geometry per widget type.
|
||||
// sbOrigin: screen coordinate of the scrollbar's top/left edge
|
||||
// sbLen: total length of the scrollbar (including arrow buttons)
|
||||
// totalSize: total content size (items, pixels, or columns)
|
||||
// visibleSize: visible portion of content
|
||||
// scrollPos: current scroll position (pointer to update)
|
||||
// maxScroll: maximum scroll value
|
||||
int32_t sbOrigin = 0;
|
||||
int32_t sbLen = 0;
|
||||
int32_t totalSize = 0;
|
||||
int32_t visibleSize = 0;
|
||||
int32_t maxScroll = 0;
|
||||
int32_t sbWidth = WGT_SB_W;
|
||||
|
||||
if (w->type == WidgetTextAreaE) {
|
||||
sbWidth = TEXTAREA_SB_W;
|
||||
|
||||
if (orient == 0) {
|
||||
// Vertical scrollbar
|
||||
AppContextT *ctx = (AppContextT *)w->window->widgetRoot->userData;
|
||||
const BitmapFontT *font = &ctx->font;
|
||||
|
||||
int32_t innerW = w->w - TEXTAREA_BORDER * 2 - TEXTAREA_PAD * 2 - TEXTAREA_SB_W;
|
||||
int32_t visCols = innerW / font->charWidth;
|
||||
int32_t maxLL = 0;
|
||||
|
||||
// Compute max line length by scanning lines
|
||||
const char *buf = w->as.textArea.buf;
|
||||
int32_t len = w->as.textArea.len;
|
||||
int32_t lineStart = 0;
|
||||
|
||||
for (int32_t i = 0; i <= len; i++) {
|
||||
if (i == len || buf[i] == '\n') {
|
||||
int32_t ll = i - lineStart;
|
||||
|
||||
if (ll > maxLL) {
|
||||
maxLL = ll;
|
||||
}
|
||||
|
||||
lineStart = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool needHSb = (maxLL > visCols);
|
||||
int32_t innerH = w->h - TEXTAREA_BORDER * 2 - (needHSb ? TEXTAREA_SB_W : 0);
|
||||
int32_t visRows = innerH / font->charHeight;
|
||||
|
||||
if (visRows < 1) {
|
||||
visRows = 1;
|
||||
}
|
||||
|
||||
// Count total lines
|
||||
int32_t totalLines = 1;
|
||||
|
||||
for (int32_t i = 0; i < len; i++) {
|
||||
if (buf[i] == '\n') {
|
||||
totalLines++;
|
||||
}
|
||||
}
|
||||
|
||||
sbOrigin = w->y + TEXTAREA_BORDER;
|
||||
sbLen = innerH;
|
||||
totalSize = totalLines;
|
||||
visibleSize = visRows;
|
||||
maxScroll = totalLines - visRows;
|
||||
} else {
|
||||
// Horizontal scrollbar
|
||||
AppContextT *ctx = (AppContextT *)w->window->widgetRoot->userData;
|
||||
const BitmapFontT *font = &ctx->font;
|
||||
|
||||
int32_t innerW = w->w - TEXTAREA_BORDER * 2 - TEXTAREA_PAD * 2 - TEXTAREA_SB_W;
|
||||
int32_t visCols = innerW / font->charWidth;
|
||||
int32_t maxLL = 0;
|
||||
|
||||
const char *buf = w->as.textArea.buf;
|
||||
int32_t len = w->as.textArea.len;
|
||||
int32_t lineStart = 0;
|
||||
|
||||
for (int32_t i = 0; i <= len; i++) {
|
||||
if (i == len || buf[i] == '\n') {
|
||||
int32_t ll = i - lineStart;
|
||||
|
||||
if (ll > maxLL) {
|
||||
maxLL = ll;
|
||||
}
|
||||
|
||||
lineStart = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t hsbW = w->w - TEXTAREA_BORDER * 2 - TEXTAREA_SB_W;
|
||||
|
||||
sbOrigin = w->x + TEXTAREA_BORDER;
|
||||
sbLen = hsbW;
|
||||
totalSize = maxLL;
|
||||
visibleSize = visCols;
|
||||
maxScroll = maxLL - visCols;
|
||||
}
|
||||
} else if (w->type == WidgetListBoxE) {
|
||||
// Vertical only
|
||||
AppContextT *ctx = (AppContextT *)w->window->widgetRoot->userData;
|
||||
const BitmapFontT *font = &ctx->font;
|
||||
|
||||
int32_t innerH = w->h - LISTBOX_BORDER * 2;
|
||||
int32_t visibleRows = innerH / font->charHeight;
|
||||
|
||||
sbOrigin = w->y + LISTBOX_BORDER;
|
||||
sbLen = innerH;
|
||||
totalSize = w->as.listBox.itemCount;
|
||||
visibleSize = visibleRows;
|
||||
maxScroll = totalSize - visibleSize;
|
||||
} else if (w->type == WidgetListViewE) {
|
||||
AppContextT *ctx = (AppContextT *)w->window->widgetRoot->userData;
|
||||
const BitmapFontT *font = &ctx->font;
|
||||
|
||||
int32_t headerH = font->charHeight + 4;
|
||||
int32_t innerH = w->h - LISTVIEW_BORDER * 2 - headerH;
|
||||
int32_t innerW = w->w - LISTVIEW_BORDER * 2;
|
||||
int32_t visibleRows = innerH / font->charHeight;
|
||||
int32_t totalColW = w->as.listView->totalColW;
|
||||
bool needVSb = (w->as.listView->rowCount > visibleRows);
|
||||
|
||||
if (needVSb) {
|
||||
innerW -= WGT_SB_W;
|
||||
}
|
||||
|
||||
if (totalColW > innerW) {
|
||||
innerH -= WGT_SB_W;
|
||||
visibleRows = innerH / font->charHeight;
|
||||
|
||||
if (!needVSb && w->as.listView->rowCount > visibleRows) {
|
||||
innerW -= WGT_SB_W;
|
||||
}
|
||||
}
|
||||
|
||||
if (visibleRows < 1) {
|
||||
visibleRows = 1;
|
||||
}
|
||||
|
||||
if (orient == 0) {
|
||||
// Vertical
|
||||
sbOrigin = w->y + LISTVIEW_BORDER + headerH;
|
||||
sbLen = innerH;
|
||||
totalSize = w->as.listView->rowCount;
|
||||
visibleSize = visibleRows;
|
||||
maxScroll = totalSize - visibleSize;
|
||||
} else {
|
||||
// Horizontal
|
||||
sbOrigin = w->x + LISTVIEW_BORDER;
|
||||
sbLen = innerW;
|
||||
totalSize = totalColW;
|
||||
visibleSize = innerW;
|
||||
maxScroll = totalColW - innerW;
|
||||
}
|
||||
} else if (w->type == WidgetTreeViewE) {
|
||||
AppContextT *ctx = (AppContextT *)w->window->widgetRoot->userData;
|
||||
const BitmapFontT *font = &ctx->font;
|
||||
|
||||
int32_t totalH;
|
||||
int32_t totalW;
|
||||
int32_t innerH;
|
||||
int32_t innerW;
|
||||
bool needVSb;
|
||||
|
||||
// Walk the visible tree to compute total content dimensions.
|
||||
// This duplicates treeCalcScrollbarNeeds which is file-static,
|
||||
// so we compute it inline using the same logic.
|
||||
int32_t treeH = 0;
|
||||
int32_t treeW = 0;
|
||||
|
||||
// Count visible items and max width
|
||||
for (WidgetT *c = w->firstChild; c; c = c->nextSibling) {
|
||||
if (c->type == WidgetTreeItemE && c->visible) {
|
||||
// Walk visible items
|
||||
WidgetT *item = c;
|
||||
|
||||
while (item) {
|
||||
treeH += font->charHeight;
|
||||
|
||||
// Compute depth
|
||||
int32_t depth = 0;
|
||||
WidgetT *p = item->parent;
|
||||
|
||||
while (p && p != w) {
|
||||
depth++;
|
||||
p = p->parent;
|
||||
}
|
||||
|
||||
int32_t itemW = depth * TREE_INDENT + TREE_EXPAND_SIZE + TREE_ICON_GAP;
|
||||
|
||||
if (item->as.treeItem.text) {
|
||||
itemW += (int32_t)strlen(item->as.treeItem.text) * font->charWidth;
|
||||
}
|
||||
|
||||
if (itemW > treeW) {
|
||||
treeW = itemW;
|
||||
}
|
||||
|
||||
item = widgetTreeViewNextVisible(item, w);
|
||||
}
|
||||
|
||||
break; // Only process first top-level visible chain
|
||||
}
|
||||
}
|
||||
|
||||
totalH = treeH;
|
||||
totalW = treeW;
|
||||
innerH = w->h - TREE_BORDER * 2;
|
||||
innerW = w->w - TREE_BORDER * 2;
|
||||
needVSb = (totalH > innerH);
|
||||
|
||||
if (needVSb) {
|
||||
innerW -= WGT_SB_W;
|
||||
}
|
||||
|
||||
if (totalW > innerW) {
|
||||
innerH -= WGT_SB_W;
|
||||
|
||||
if (!needVSb && totalH > innerH) {
|
||||
needVSb = true;
|
||||
innerW -= WGT_SB_W;
|
||||
}
|
||||
}
|
||||
|
||||
if (orient == 0) {
|
||||
// Vertical (pixel-based scroll)
|
||||
sbOrigin = w->y + TREE_BORDER;
|
||||
sbLen = innerH;
|
||||
totalSize = totalH;
|
||||
visibleSize = innerH;
|
||||
maxScroll = totalH - innerH;
|
||||
} else {
|
||||
// Horizontal (pixel-based scroll)
|
||||
sbOrigin = w->x + TREE_BORDER;
|
||||
sbLen = innerW;
|
||||
totalSize = totalW;
|
||||
visibleSize = innerW;
|
||||
maxScroll = totalW - innerW;
|
||||
}
|
||||
} else if (w->type == WidgetScrollPaneE) {
|
||||
sbWidth = SP_SB_W;
|
||||
|
||||
AppContextT *ctx = (AppContextT *)w->window->widgetRoot->userData;
|
||||
const BitmapFontT *font = &ctx->font;
|
||||
|
||||
// Compute content min size by measuring children
|
||||
int32_t contentMinW = 0;
|
||||
int32_t contentMinH = 0;
|
||||
|
||||
for (WidgetT *c = w->firstChild; c; c = c->nextSibling) {
|
||||
if (c->visible) {
|
||||
if (c->wclass && c->wclass->calcMinSize) {
|
||||
c->wclass->calcMinSize(c, font);
|
||||
}
|
||||
|
||||
if (c->calcMinW > contentMinW) {
|
||||
contentMinW = c->calcMinW;
|
||||
}
|
||||
|
||||
contentMinH += c->calcMinH;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t innerH = w->h - SP_BORDER * 2;
|
||||
int32_t innerW = w->w - SP_BORDER * 2;
|
||||
bool needVSb = (contentMinH > innerH);
|
||||
|
||||
if (needVSb) {
|
||||
innerW -= SP_SB_W;
|
||||
}
|
||||
|
||||
if (contentMinW > innerW) {
|
||||
innerH -= SP_SB_W;
|
||||
|
||||
if (!needVSb && contentMinH > innerH) {
|
||||
needVSb = true;
|
||||
innerW -= SP_SB_W;
|
||||
}
|
||||
}
|
||||
|
||||
if (orient == 0) {
|
||||
// Vertical
|
||||
sbOrigin = w->y + SP_BORDER;
|
||||
sbLen = innerH;
|
||||
totalSize = contentMinH;
|
||||
visibleSize = innerH;
|
||||
maxScroll = contentMinH - innerH;
|
||||
} else {
|
||||
// Horizontal
|
||||
sbOrigin = w->x + SP_BORDER;
|
||||
sbLen = innerW;
|
||||
totalSize = contentMinW;
|
||||
visibleSize = innerW;
|
||||
maxScroll = contentMinW - innerW;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (maxScroll < 0) {
|
||||
maxScroll = 0;
|
||||
}
|
||||
|
||||
if (maxScroll == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute thumb geometry
|
||||
int32_t trackLen = sbLen - sbWidth * 2;
|
||||
|
||||
if (trackLen <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t thumbPos;
|
||||
int32_t thumbSize;
|
||||
widgetScrollbarThumb(trackLen, totalSize, visibleSize, 0, &thumbPos, &thumbSize);
|
||||
|
||||
if (trackLen <= thumbSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert mouse position to scroll value
|
||||
int32_t mousePos;
|
||||
|
||||
if (orient == 0) {
|
||||
mousePos = mouseY - sbOrigin - sbWidth - dragOff;
|
||||
} else {
|
||||
mousePos = mouseX - sbOrigin - sbWidth - dragOff;
|
||||
}
|
||||
|
||||
int32_t newScroll = (mousePos * maxScroll) / (trackLen - thumbSize);
|
||||
|
||||
if (newScroll < 0) {
|
||||
newScroll = 0;
|
||||
}
|
||||
|
||||
if (newScroll > maxScroll) {
|
||||
newScroll = maxScroll;
|
||||
}
|
||||
|
||||
// Update the widget's scroll position
|
||||
if (w->type == WidgetTextAreaE) {
|
||||
if (orient == 0) {
|
||||
w->as.textArea.scrollRow = newScroll;
|
||||
} else {
|
||||
w->as.textArea.scrollCol = newScroll;
|
||||
}
|
||||
} else if (w->type == WidgetListBoxE) {
|
||||
w->as.listBox.scrollPos = newScroll;
|
||||
} else if (w->type == WidgetListViewE) {
|
||||
if (orient == 0) {
|
||||
w->as.listView->scrollPos = newScroll;
|
||||
} else {
|
||||
w->as.listView->scrollPosH = newScroll;
|
||||
}
|
||||
} else if (w->type == WidgetTreeViewE) {
|
||||
if (orient == 0) {
|
||||
w->as.treeView.scrollPos = newScroll;
|
||||
} else {
|
||||
w->as.treeView.scrollPosH = newScroll;
|
||||
}
|
||||
} else if (w->type == WidgetScrollPaneE) {
|
||||
if (orient == 0) {
|
||||
w->as.scrollPane.scrollPosV = newScroll;
|
||||
} else {
|
||||
w->as.scrollPane.scrollPosH = newScroll;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ============================================================
|
||||
// widgetScrollbarHitTest
|
||||
// ============================================================
|
||||
|
|
|
|||
|
|
@ -1850,6 +1850,11 @@ void widgetTextAreaOnMouse(WidgetT *w, WidgetT *root, int32_t vx, int32_t vy) {
|
|||
} else if (trackRelX >= thumbPos + thumbSize) {
|
||||
w->as.textArea.scrollCol += visCols;
|
||||
w->as.textArea.scrollCol = clampInt(w->as.textArea.scrollCol, 0, maxHScroll);
|
||||
} else {
|
||||
sDragScrollbar = w;
|
||||
sDragScrollbarOrient = 1;
|
||||
sDragScrollbarOff = trackRelX - thumbPos;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1889,6 +1894,11 @@ void widgetTextAreaOnMouse(WidgetT *w, WidgetT *root, int32_t vx, int32_t vy) {
|
|||
} else if (trackRelY >= thumbPos + thumbSize) {
|
||||
w->as.textArea.scrollRow += visRows;
|
||||
w->as.textArea.scrollRow = clampInt(w->as.textArea.scrollRow, 0, maxScroll);
|
||||
} else {
|
||||
sDragScrollbar = w;
|
||||
sDragScrollbarOrient = 0;
|
||||
sDragScrollbarOff = trackRelY - thumbPos;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1056,6 +1056,15 @@ void widgetTreeViewOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy)
|
|||
hit->as.treeView.scrollPos -= pageSize;
|
||||
} else if (sh == ScrollHitPageIncE) {
|
||||
hit->as.treeView.scrollPos += pageSize;
|
||||
} else if (sh == ScrollHitThumbE) {
|
||||
int32_t trackLen = innerH - WGT_SB_W * 2;
|
||||
int32_t thumbPos;
|
||||
int32_t thumbSize;
|
||||
widgetScrollbarThumb(trackLen, totalH, innerH, hit->as.treeView.scrollPos, &thumbPos, &thumbSize);
|
||||
|
||||
sDragScrollbar = hit;
|
||||
sDragScrollbarOrient = 0;
|
||||
sDragScrollbarOff = relY - WGT_SB_W - thumbPos;
|
||||
}
|
||||
|
||||
hit->as.treeView.scrollPos = clampInt(hit->as.treeView.scrollPos, 0, maxScrollV);
|
||||
|
|
@ -1085,6 +1094,15 @@ void widgetTreeViewOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy)
|
|||
hit->as.treeView.scrollPosH -= pageSize;
|
||||
} else if (sh == ScrollHitPageIncE) {
|
||||
hit->as.treeView.scrollPosH += pageSize;
|
||||
} else if (sh == ScrollHitThumbE) {
|
||||
int32_t trackLen = innerW - WGT_SB_W * 2;
|
||||
int32_t thumbPos;
|
||||
int32_t thumbSize;
|
||||
widgetScrollbarThumb(trackLen, totalW, innerW, hit->as.treeView.scrollPosH, &thumbPos, &thumbSize);
|
||||
|
||||
sDragScrollbar = hit;
|
||||
sDragScrollbarOrient = 1;
|
||||
sDragScrollbarOff = relX - WGT_SB_W - thumbPos;
|
||||
}
|
||||
|
||||
hit->as.treeView.scrollPosH = clampInt(hit->as.treeView.scrollPosH, 0, maxScrollH);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue