diff --git a/roo-e/roo-e.pro b/roo-e/roo-e.pro
index 45d2adf..1150cfa 100644
--- a/roo-e/roo-e.pro
+++ b/roo-e/roo-e.pro
@@ -59,6 +59,7 @@ HEADERS += \
src/gui/widgets/picture.h \
src/gui/widgets/radio.h \
src/gui/widgets/hscroll.h \
+ src/gui/widgets/scroll.h \
src/gui/widgets/vscroll.h \
src/gui/wmwindow.h \
src/os.h \
@@ -81,6 +82,7 @@ SOURCES += \
src/gui/widgets/picture.c \
src/gui/widgets/radio.c \
src/gui/widgets/hscroll.c \
+ src/gui/widgets/scroll.c \
src/gui/widgets/vscroll.c \
src/gui/wmwindow.c \
src/main.c \
diff --git a/roo-e/src/gui/gui-all.h b/roo-e/src/gui/gui-all.h
index b67eef2..63db501 100644
--- a/roo-e/src/gui/gui-all.h
+++ b/roo-e/src/gui/gui-all.h
@@ -38,6 +38,7 @@
#include "widgets/radio.h"
#include "widgets/vscroll.h"
#include "widgets/hscroll.h"
+#include "widgets/scroll.h"
#endif // GUIALL_H
diff --git a/roo-e/src/gui/gui.c b/roo-e/src/gui/gui.c
index afb6453..5128491 100644
--- a/roo-e/src/gui/gui.c
+++ b/roo-e/src/gui/gui.c
@@ -199,6 +199,7 @@ uint8_t guiStartup(int16_t width, int16_t height, int16_t depth) {
guiRegister(radioRegister);
guiRegister(vscrollRegister);
guiRegister(hscrollRegister);
+ guiRegister(scrollableRegister); // After hscroll and vscroll.
return SUCCESS;
}
diff --git a/roo-e/src/gui/widgets/scroll.c b/roo-e/src/gui/widgets/scroll.c
new file mode 100644
index 0000000..9a7287c
--- /dev/null
+++ b/roo-e/src/gui/widgets/scroll.c
@@ -0,0 +1,130 @@
+/*
+ * Roo/E, the Kangaroo Punch Portable GUI Toolkit
+ * Copyright (C) 2022 Scott Duensing
+ *
+ * http://kangaroopunch.com
+ *
+ *
+ * This file is part of Roo/E.
+ *
+ * Roo/E is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Affero General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Roo/E is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Roo/E. If not, see .
+ *
+ */
+
+
+#include "../image.h"
+
+#include "scroll.h"
+
+
+uint8_t __MAGIC_SCROLLABLE = 0;
+
+
+static void scrollableClickHandler(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event, void *data);
+static void scrollableDestroy(struct WidgetS *widget, ...);
+static void scrollablePaint(struct WidgetS *widget, ...);
+
+
+static void scrollableClickHandler(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event, void *data) {
+}
+
+
+// Passing "flags" as a default int provides proper alignment for the following va_args list.
+ScrollableT *scrollableCreate(int16_t width, int16_t height, int16_t totalWidth, int16_t totalHeight, int flags, ...) {
+ ScrollableT *s = NULL;
+ SurfaceT *t = surfaceGet();
+ int16_t w = 0;
+
+ NEW(ScrollableT, s);
+ memset(s, 0, sizeof(ScrollableT));
+
+ // Set up desired scroll bars.
+ s->flags = flags;
+ if (s->flags & SCROLLABLE_SCROLL_V) {
+ s->scrollv = vscrollCreate(height, scrollableClickHandler, NULL);
+ vscrollRangeSet(s->scrollv, 0, totalHeight- 1);
+ w = s->scrollv->base.r.w;
+ }
+ if (s->flags & SCROLLABLE_SCROLL_H) {
+ s->scrollh = hscrollCreate(width - w, scrollableClickHandler, NULL);
+ hscrollRangeSet(s->scrollh, 0, totalWidth - 1);
+ }
+
+ // Create scrollable surface.
+ s->area = surfaceCreate(totalWidth, totalHeight);
+ if (!s->area) {
+ DEL(s);
+ return NULL;
+ }
+ surfaceSet(s->area);
+ surfaceClear(GUI_LIGHTBLUE);
+ surfaceSet(t);
+
+ widgetBaseSet(W(s), __MAGIC_SCROLLABLE, width, height);
+
+ return s;
+}
+
+
+static void scrollableDestroy(struct WidgetS *widget, ...) {
+ ScrollableT *s = (ScrollableT *)widget;
+
+ if (s->scrollh) widgetDestroy(W(s->scrollh));
+ if (s->scrollv) widgetDestroy(W(s->scrollv));
+ if (s->area) surfaceDestroy(&s->area);
+
+ DEL(s);
+}
+
+
+static void scrollablePaint(struct WidgetS *widget, ...) {
+ ScrollableT *s = (ScrollableT *)widget;
+ int16_t width;
+ int16_t height;
+
+ if (widgetDirtyGet(widget)) {
+ widgetDirtySet(widget, 0);
+ // Find height and width of blittable area, based on presence of scrollbars.
+ if (s->scrollh) {
+ height = s->base.r.h - s->scrollh->base.r.h;
+ widgetPaintManually(W(s->scrollh), s->base.r.x, s->base.r.y + height);
+ } else {
+ height = s->base.r.h;
+ }
+ if (s->scrollv) {
+ width = s->base.r.w - s->scrollv->base.r.w;
+ widgetPaintManually(W(s->scrollv), s->base.r.x + width, s->base.r.y);
+ } else {
+ width = s->base.r.w;
+ }
+ // Blit.
+ surfaceBlit(s->base.r.x, s->base.r.y, s->offset.x, s->offset.y, width, height, s->area);
+ }
+}
+
+
+RegisterT *scrollableRegister(uint8_t magic) {
+ static RegisterT reg = {
+ "Scrollable",
+ NULL, // No default on-click handler.
+ scrollableDestroy,
+ scrollablePaint,
+ NULL // No unregister handler.
+ };
+
+ // One-time widget startup code.
+ __MAGIC_SCROLLABLE = magic;
+
+ return ®
+}
diff --git a/roo-e/src/gui/widgets/scroll.h b/roo-e/src/gui/widgets/scroll.h
new file mode 100644
index 0000000..fadd216
--- /dev/null
+++ b/roo-e/src/gui/widgets/scroll.h
@@ -0,0 +1,59 @@
+/*
+ * Roo/E, the Kangaroo Punch Portable GUI Toolkit
+ * Copyright (C) 2022 Scott Duensing
+ *
+ * http://kangaroopunch.com
+ *
+ *
+ * This file is part of Roo/E.
+ *
+ * Roo/E is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Affero General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Roo/E is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Roo/E. If not, see .
+ *
+ */
+
+
+#ifndef SCROLL_H
+#define SCROLL_H
+
+
+#include "../gui.h"
+#include "hscroll.h"
+#include "vscroll.h"
+
+
+#define SCROLLABLE_NONE 0
+#define SCROLLABLE_SCROLL_V 1
+#define SCROLLABLE_SCROLL_H 2
+
+#define SCROLLABLE_STANDARD (SCROLLABLE_SCROLL_V | SCROLLABLE_SCROLL_H)
+
+
+typedef struct ScrollableS {
+ WidgetT base; // Required by all widgets.
+ PointT offset; // View offset.
+ SurfaceT *area; // Scrollable area buffer.
+ HscrollT *scrollh; // Horizontal scroll bar.
+ VscrollT *scrollv; // Vertical scroll bar.
+ uint8_t flags; // Flag bits.
+} ScrollableT;
+
+
+extern uint8_t __MAGIC_SCROLLABLE; // Magic ID assigned to us from the GUI.
+
+
+ScrollableT *scrollableCreate(int16_t width, int16_t height, int16_t totalWidth, int16_t totalHeight, int flags, ...);
+RegisterT *scrollableRegister(uint8_t magic);
+
+
+#endif // SCROLL_H
diff --git a/roo-e/src/main.c b/roo-e/src/main.c
index 9f239e3..37b8a49 100644
--- a/roo-e/src/main.c
+++ b/roo-e/src/main.c
@@ -27,7 +27,7 @@
VscrollT *_v = NULL;
-VscrollT *_h = NULL;
+HscrollT *_h = NULL;
void clickHandler(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event, void *data) {
@@ -37,20 +37,19 @@ void clickHandler(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event, void *
int main(int argc, char *argv[]) {
- char title[256];
- uint16_t i;
- WindowT *w = NULL;
- LabelT *l = NULL;
- ButtonT *b = NULL;
- CheckboxT *c = NULL;
- RadioT *r = NULL;
+ char title[256];
+ uint16_t i;
+ WindowT *w = NULL;
+ LabelT *l = NULL;
+ ButtonT *b = NULL;
+ CheckboxT *c = NULL;
+ RadioT *r = NULL;
+ ScrollableT *s = NULL;
// frame
// scrollarea
- // vscroll
- // hscroll
// listbox
// textbox
// up/down
@@ -69,7 +68,7 @@ int main(int argc, char *argv[]) {
for (i=1; i<4; i++) {
sprintf(title, "Testing %d", i);
- w = windowCreate(i * 50, i * 50, 300, 200, title, WIN_STANDARD, 640, 480);
+ w = windowCreate(i * 50, i * 50, 600, 400, title, WIN_STANDARD, 640, 480);
l = labelCreate(LABEL_ALIGN_LEFT, __guiFontVGA8x16, "Label");
labelColorSet(l, __guiBaseColors[i], GUI_BLACK);
@@ -102,7 +101,10 @@ int main(int argc, char *argv[]) {
_h = hscrollCreate(100, clickHandler, NULL);
hscrollRangeSet(_h, 0, 640);
- windowWidgetAdd(w, 70, 5, W(_h));
+ windowWidgetAdd(w, 100, 5, W(_h));
+
+ s = scrollableCreate(300, 200, 648, 480, SCROLLABLE_STANDARD);
+ windowWidgetAdd(w, 20, 170, W(s));
}
guiRun();
guiShutdown();