#include static void vscroll_changed(MwWidget handle, void* user, void* call) { MwViewport vp = user; (void)handle; (void)call; vp->vchanged = 1; } static void hscroll_changed(MwWidget handle, void* user, void* call) { MwViewport vp = user; (void)handle; (void)call; vp->hchanged = 1; } static void resize(MwWidget handle) { MwViewport vp = handle->internal; int w = MwGetInteger(handle, MwNwidth); int h = MwGetInteger(handle, MwNheight); int iw; int ih; if(vp->vscroll == NULL) { vp->vscroll = MwVaCreateWidget(MwScrollBarClass, "vscroll", handle, w - 16, 0, 16, h - 16, NULL); MwAddUserHandler(vp->vscroll, MwNchangedHandler, vscroll_changed, vp); } else { MwVaApply(vp->vscroll, MwNx, w - 16, MwNy, 0, MwNwidth, 16, MwNheight, h - 16, NULL); } if(vp->hscroll == NULL) { vp->hscroll = MwVaCreateWidget(MwScrollBarClass, "hscroll", handle, 0, h - 16, w - 16, 16, MwNorientation, MwHORIZONTAL, NULL); MwAddUserHandler(vp->hscroll, MwNchangedHandler, hscroll_changed, vp); } else { MwVaApply(vp->hscroll, MwNx, 0, MwNy, h - 16, MwNwidth, w - 16, MwNheight, 16, NULL); } if(vp->frame == NULL) { vp->frame = MwCreateWidget(MwFrameClass, "frame", handle, 0, 0, w - 16, h - 16); } else { MwVaApply(vp->frame, MwNx, 0, MwNy, 0, MwNwidth, w - 16, MwNheight, h - 16, NULL); } if(vp->inframe == NULL) { vp->inframe = MwCreateWidget(MwFrameClass, "inframe", vp->frame, 0, 0, w - 16, h - 16); } iw = MwGetInteger(vp->inframe, MwNwidth); ih = MwGetInteger(vp->inframe, MwNheight); MwVaApply(vp->vscroll, MwNareaShown, h - 16, MwNmaxValue, ih, NULL); MwVaApply(vp->hscroll, MwNareaShown, w - 16, MwNmaxValue, iw, NULL); } static int create(MwWidget handle) { MwViewport vp = malloc(sizeof(*vp)); memset(vp, 0, sizeof(*vp)); handle->internal = vp; MwSetDefault(handle); vp->vchanged = 0; vp->hchanged = 0; resize(handle); return 0; } static void destroy(MwWidget handle) { free(handle->internal); } static void draw(MwWidget handle) { MwRect r; MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); r.x = 0; r.y = 0; r.width = MwGetInteger(handle, MwNwidth); r.height = MwGetInteger(handle, MwNheight); MwDrawRect(handle, &r, base); MwLLFreeColor(base); } static void prop_change(MwWidget handle, const char* prop) { if(strcmp(prop, MwNwidth) == 0 || strcmp(prop, MwNheight) == 0) resize(handle); } static MwWidget mwViewportGetViewportImpl(MwWidget handle) { MwViewport vp = handle->internal; return vp->inframe; } static void mwViewportSetSizeImpl(MwWidget handle, int w, int h) { MwViewport vp = handle->internal; MwVaApply(vp->inframe, MwNwidth, w, MwNheight, h, NULL); resize(handle); } static void func_handler(MwWidget handle, const char* name, void* out, va_list va) { if(strcmp(name, "mwViewportGetViewport") == 0) { *(MwWidget*)out = mwViewportGetViewportImpl(handle); } if(strcmp(name, "mwViewportSetSize") == 0) { int w = va_arg(va, int); int h = va_arg(va, int); mwViewportSetSizeImpl(handle, w, h); } } static void tick(MwWidget handle) { MwViewport vp = handle->internal; if(vp->vchanged) { int v, mv, l; vp->vchanged = 0; v = MwGetInteger(vp->vscroll, MwNvalue); mv = MwGetInteger(vp->vscroll, MwNmaxValue); l = MwGetInteger(vp->frame, MwNheight); v = (mv - l) * (double)v / mv; if(v < 0) v = 0; MwVaApply(vp->inframe, MwNy, -v, NULL); } if(vp->hchanged) { int v, mv, l; vp->vchanged = 0; v = MwGetInteger(vp->hscroll, MwNvalue); mv = MwGetInteger(vp->hscroll, MwNmaxValue); l = MwGetInteger(vp->frame, MwNwidth); v = (mv - l) * (double)v / mv; if(v < 0) v = 0; MwVaApply(vp->inframe, MwNx, -v, NULL); } } MwClassRec MwViewportClassRec = { create, /* create */ destroy, /* destroy */ draw, /* draw */ NULL, /* click */ NULL, /* parent_resize */ prop_change, /* prop_change */ NULL, /* mouse_move */ NULL, /* mouse_up */ NULL, /* mouse_down */ NULL, /* key */ func_handler, /* execute */ tick, /* tick */ NULL, /* resize */ NULL, /* children_update */ NULL, /* children_prop_change */ NULL, /* clipboard */ NULL, NULL, NULL, NULL}; MwClass MwViewportClass = &MwViewportClassRec;