diff --git a/common/controlsigs.h b/common/controlsigs.h index 944afa9b3..5881a786d 100644 --- a/common/controlsigs.h +++ b/common/controlsigs.h @@ -19,6 +19,7 @@ #define uiMultilineEntrySignature 0x4D6C6E45 #define uiProgressBarSignature 0x50426172 #define uiRadioButtonsSignature 0x5264696F +#define uiScrollSignature 0x5dcd9b83 #define uiSeparatorSignature 0x53657061 #define uiSliderSignature 0x536C6964 #define uiSpinboxSignature 0x5370696E diff --git a/darwin/scrollview.m b/darwin/scrollview.m index 1b5cc8d93..ea3ba004b 100644 --- a/darwin/scrollview.m +++ b/darwin/scrollview.m @@ -2,7 +2,7 @@ #include "uipriv_darwin.h" // see http://stackoverflow.com/questions/37979445/how-do-i-properly-set-up-a-scrolling-nstableview-using-auto-layout-what-ive-tr for why we don't use auto layout -// TODO do the same with uiGroup and uiTab? +// TODO do the same with uiScrollView and uiTab? struct uiprivScrollViewData { BOOL hscroll; @@ -38,8 +38,10 @@ [sv setVerticalScrollElasticity:NSScrollElasticityAutomatic]; [sv setAllowsMagnification:NO]; - [sv setDocumentView:p->DocumentView]; - d = uiprivNew(uiprivScrollViewData); + if (p->DocumentView != nil) + [sv setDocumentView:p->DocumentView]; + + d = uiprivNew(uiprivScrollViewData); uiprivScrollViewSetScrolling(sv, d, p->HScroll, p->VScroll); *dout = d; @@ -59,3 +61,65 @@ void uiprivScrollViewFreeData(NSScrollView *sv, uiprivScrollViewData *d) { uiprivFree(d); } + +struct uiScroll { + uiDarwinControl c; + NSScrollView *sv; + uiprivScrollViewData *d; + uiControl *child; +}; + +static void uiScrollDestroy(uiControl *c) +{ + uiScroll *g = uiScroll(c); + + if (g->child != NULL) { + uiControlSetParent(g->child, NULL); + uiDarwinControlSetSuperview(uiDarwinControl(g->child), nil); + uiControlDestroy(g->child); + } + [g->sv release]; + uiFreeControl(uiControl(g)); +} + +uiDarwinControlAllDefaultsExceptDestroy(uiScroll, sv) + +void uiScrollSetChild(uiScroll *g, uiControl *child) +{ + if (g->child != NULL) { + uiControlSetParent(g->child, NULL); + uiDarwinControlSetSuperview(uiDarwinControl(g->child), nil); + } + g->child = child; + + if (g->child != NULL) { + NSView *childView = (NSView *) uiControlHandle(g->child); + uiControlSetParent(g->child, uiControl(g)); + uiDarwinControlSetSuperview(uiDarwinControl(g->child), [g->sv contentView]); + [childView removeFromSuperview]; + [childView setTranslatesAutoresizingMaskIntoConstraints:NO]; + [g->sv setDocumentView:childView]; + uiDarwinControlSyncEnableState(uiDarwinControl(g->child), uiControlEnabledToUser(uiControl(g))); + } +} + + +uiScroll *uiNewScroll(void) +{ + uiScroll *g; + + uiDarwinNewControl(uiScroll, g); + + uiprivScrollViewCreateParams params = { + nil, + nil, + NO, + YES, + YES, + YES + }; + + g->sv = uiprivMkScrollView(¶ms, &g->d); + + return g; +} diff --git a/examples/meson.build b/examples/meson.build index 3b9ab82a0..fbd0843f1 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -48,6 +48,9 @@ libui_examples = { 'datetime': { 'sources': ['datetime/main.c'], }, + 'scrolling': { + 'sources': ['scrolling/main.c'], + }, } foreach name, args : libui_examples # TODO once we upgrade to 0.49.0, add pie: true diff --git a/examples/scrolling/main.c b/examples/scrolling/main.c new file mode 100644 index 000000000..312605cf3 --- /dev/null +++ b/examples/scrolling/main.c @@ -0,0 +1,38 @@ +#include "../../ui.h" +#include +#include + +int onClosing(uiWindow *w, void *data) +{ + uiQuit(); + return 1; +} + +int main(void) +{ + uiInitOptions o; + uiWindow *w; + uiScroll *s; + uiBox *box; + + memset(&o, 0, sizeof (uiInitOptions)); + if (uiInit(&o) != NULL) + abort(); + + w = uiNewWindow("Scrolling", 320, 240, 0); + s = uiNewScroll(); + box = uiNewVerticalBox(); + uiScrollSetChild(s, uiControl(box)); + uiBoxSetPadded(box, 1); + + for (int i = 0; i < 32; i++) { + uiButton *btn = uiNewButton("Button"); + uiBoxAppend(box, uiControl(btn), 0); + } + + uiWindowOnClosing(w, onClosing, NULL); + uiWindowSetChild(w, uiControl(s)); + uiControlShow(uiControl(w)); + uiMain(); + return 0; +} diff --git a/examples/scrolling/unix.png b/examples/scrolling/unix.png new file mode 100644 index 000000000..11de3705e Binary files /dev/null and b/examples/scrolling/unix.png differ diff --git a/ui.h b/ui.h index 40aea9498..8c6d070f4 100644 --- a/ui.h +++ b/ui.h @@ -297,6 +297,11 @@ _UI_EXTERN char *uiSaveFile(uiWindow *parent); _UI_EXTERN void uiMsgBox(uiWindow *parent, const char *title, const char *description); _UI_EXTERN void uiMsgBoxError(uiWindow *parent, const char *title, const char *description); +typedef struct uiScroll uiScroll; +#define uiScroll(this) ((uiScroll *) (this)) +_UI_EXTERN uiScroll *uiNewScroll(void); +_UI_EXTERN void uiScrollSetChild(uiScroll *scroll, uiControl *ctl); + typedef struct uiArea uiArea; typedef struct uiAreaHandler uiAreaHandler; typedef struct uiAreaDrawParams uiAreaDrawParams; diff --git a/unix/meson.build b/unix/meson.build index f8004fbd2..a3f3eb019 100644 --- a/unix/meson.build +++ b/unix/meson.build @@ -35,6 +35,7 @@ libui_sources += [ 'unix/opentype.c', 'unix/progressbar.c', 'unix/radiobuttons.c', + 'unix/scrollview.c', 'unix/separator.c', 'unix/slider.c', 'unix/spinbox.c', diff --git a/unix/scrollview.c b/unix/scrollview.c new file mode 100644 index 000000000..d8054e93e --- /dev/null +++ b/unix/scrollview.c @@ -0,0 +1,45 @@ +// 9 september 2021 + +#include "uipriv_unix.h" + +struct uiScroll { + uiUnixControl c; + GtkWidget *widget; + GtkScrolledWindow *scroll; + GtkContainer *container; + + uiprivChild *child; + + int margined; +}; + +uiUnixControlAllDefaultsExceptDestroy(uiScroll) + +void uiScrollDestroy(uiControl *c) +{ + uiScroll *v = uiScroll(c); + + if (v->child != NULL) + uiprivChildDestroy(v->child); + g_object_unref(v->widget); + uiFreeControl(c); +} + +void uiScrollSetChild(uiScroll *v, uiControl *child) +{ + if (v->child != NULL) + uiprivChildRemove(v->child); + v->child = uiprivNewChildWithBox(child, uiControl(v), v->container, v->margined); +} + +uiScroll *uiNewScroll(void) +{ + uiScroll *v; + + uiUnixNewControl(uiScroll, v); + v->widget = gtk_scrolled_window_new(NULL, NULL); + v->scroll = GTK_SCROLLED_WINDOW(v->widget); + v->container = GTK_CONTAINER(v->widget); + + return v; +}