X-Git-Url: https://repo.or.cz/w/wmaker-crm.git/blobdiff_plain/59fc927dc9f183802621138534fa6eaafe5593ba..688a56e8ab67b56550e2874d9d7423f0d435bfd9:/WINGs/wscrollview.c diff --git a/WINGs/wscrollview.c b/WINGs/wscrollview.c dissimilarity index 97% index 0285a237..7733e27c 100644 --- a/WINGs/wscrollview.c +++ b/WINGs/wscrollview.c @@ -1,634 +1,563 @@ - - - - -#include "WINGsP.h" - - -typedef struct W_ScrollView { - W_Class widgetClass; - WMView *view; - - WMView *contentView; - WMView *viewport; - - WMScroller *vScroller; - WMScroller *hScroller; - - short lineScroll; - short pageScroll; - - struct { - WMReliefType relief:3; - unsigned int hasVScroller:1; - unsigned int hasHScroller:1; - - } flags; - -} ScrollView; - - - - -static void destroyScrollView(ScrollView *sPtr); - -static void paintScrollView(ScrollView *sPtr); -static void handleEvents(XEvent *event, void *data); -static void handleViewportEvents(XEvent *event, void *data); -static void resizeScrollView(); -static void updateScrollerProportion(); - -W_ViewDelegate _ScrollViewViewDelegate = { - NULL, - NULL, - resizeScrollView, - NULL, - NULL -}; - - - -WMScrollView* -WMCreateScrollView(WMWidget *parent) -{ - ScrollView *sPtr; - - sPtr = wmalloc(sizeof(ScrollView)); - memset(sPtr, 0, sizeof(ScrollView)); - - sPtr->widgetClass = WC_ScrollView; - - sPtr->view = W_CreateView(W_VIEW(parent)); - if (!sPtr->view) { - wfree(sPtr); - return NULL; - } - sPtr->viewport = W_CreateView(sPtr->view); - if (!sPtr->viewport) { - W_DestroyView(sPtr->view); - wfree(sPtr); - return NULL; - } - sPtr->view->self = sPtr; - sPtr->viewport->self = sPtr; - - sPtr->view->delegate = &_ScrollViewViewDelegate; - - sPtr->viewport->flags.mapWhenRealized = 1; - - WMCreateEventHandler(sPtr->view, StructureNotifyMask|ExposureMask, - handleEvents, sPtr); - WMCreateEventHandler(sPtr->viewport, SubstructureNotifyMask, - handleViewportEvents, sPtr); - - sPtr->lineScroll = 4; - - sPtr->pageScroll = 0; - - return sPtr; -} - - -static void -applyScrollerValues(WMScrollView *sPtr) -{ - int x, y; - - if (sPtr->contentView == NULL) - return; - - if (sPtr->flags.hasHScroller) { - float v = WMGetScrollerValue(sPtr->hScroller); - int size; - - size = sPtr->contentView->size.width-sPtr->viewport->size.width; - - x = v * size; - } else { - x = 0; - } - - if (sPtr->flags.hasVScroller) { - float v = WMGetScrollerValue(sPtr->vScroller); - - int size; - - size = sPtr->contentView->size.height-sPtr->viewport->size.height; - - y = v * size; - } else { - y = 0; - } - - - - x = WMAX(0, x); - y = WMAX(0, y); - - W_MoveView(sPtr->contentView, -x, -y); - - W_RaiseView(sPtr->viewport); -} - - -static void -reorganizeInterior(WMScrollView *sPtr) -{ - int hx, hy, hw; - int vx, vy, vh; - int cx, cy, cw, ch; - - - cw = hw = sPtr->view->size.width; - vh = ch = sPtr->view->size.height; - - if (sPtr->flags.relief == WRSimple) { - cw -= 2; - ch -= 2; - cx = 1; - cy = 1; - } else if (sPtr->flags.relief != WRFlat) { - cw -= 3; - ch -= 3; - cx = 2; - cy = 2; - } else { - cx = 0; - cy = 0; - } - - if (sPtr->flags.hasHScroller) { - int h = 20; - - ch -= h; - - if (sPtr->flags.relief == WRSimple) { - hx = 0; - hy = sPtr->view->size.height - h; - } else if (sPtr->flags.relief != WRFlat) { - hx = 1; - hy = sPtr->view->size.height - h - 1; - hw -= 2; - } else { - hx = 0; - hy = sPtr->view->size.height - h; - } - } else { - /* make compiler shutup */ - hx = 0; - hy = 0; - } - - if (sPtr->flags.hasVScroller) { - int w = 20; - cw -= w; - cx += w; - hx += w - 1; - hw -= w - 1; - - if (sPtr->flags.relief == WRSimple) { - vx = 0; - vy = 0; - } else if (sPtr->flags.relief != WRFlat) { - vx = 1; - vy = 1; - vh -= 2; - } else { - vx = 0; - vy = 0; - } - } else { - /* make compiler shutup */ - vx = 0; - vy = 0; - } - - W_ResizeView(sPtr->viewport, cw, ch); - W_MoveView(sPtr->viewport, cx, cy); - - if (sPtr->flags.hasHScroller) { - WMResizeWidget(sPtr->hScroller, hw, 20); - WMMoveWidget(sPtr->hScroller, hx, hy); - } - if (sPtr->flags.hasVScroller) { - WMResizeWidget(sPtr->vScroller, 20, vh); - WMMoveWidget(sPtr->vScroller, vx, vy); - } - - applyScrollerValues(sPtr); -} - - -static void -resizeScrollView(W_ViewDelegate *self, WMView *view) -{ - reorganizeInterior(view->self); - updateScrollerProportion(view->self); -} - - - -void -WMResizeScrollViewContent(WMScrollView *sPtr, unsigned int width, - unsigned int height) -{ - int w, h, x; - - w = width; - h = height; - - x = 0; - if (sPtr->flags.relief == WRSimple) { - w += 2; - h += 2; - } else if (sPtr->flags.relief != WRFlat) { - w += 4; - h += 4; - x = 1; - } - - if (sPtr->flags.hasVScroller) { - WMResizeWidget(sPtr->vScroller, 20, h); - width -= W_VIEW(sPtr->vScroller)->size.width; - } - - if (sPtr->flags.hasHScroller) { - WMResizeWidget(sPtr->hScroller, w, 20); - WMMoveWidget(sPtr->hScroller, x, h); - height -= W_VIEW(sPtr->hScroller)->size.height; - } - - W_ResizeView(sPtr->view, w, h); - - W_ResizeView(sPtr->viewport, width, height); -} - - -void -WMSetScrollViewLineScroll(WMScrollView *sPtr, int amount) -{ - assert(amount > 0); - - sPtr->lineScroll = amount; -} - - -void -WMSetScrollViewPageScroll(WMScrollView *sPtr, int amount) -{ - assert(amount >= 0); - - sPtr->pageScroll = amount; -} - - -WMRect -WMGetScrollViewVisibleRect(WMScrollView *sPtr) -{ - WMRect rect; - - rect.pos.x = -sPtr->contentView->pos.x; - rect.pos.y = -sPtr->contentView->pos.y; - rect.size = sPtr->viewport->size; - - return rect; -} - - -void -WMScrollViewScrollPoint(WMScrollView *sPtr, WMPoint point) -{ - float xsize, ysize; - float xpos, ypos; - - xsize = sPtr->contentView->size.width-sPtr->viewport->size.width; - ysize = sPtr->contentView->size.height-sPtr->viewport->size.height; - - xpos = point.x / xsize; - ypos = point.y / ysize; - - if (sPtr->hScroller) - WMSetScrollerParameters(sPtr->hScroller, xpos, - WMGetScrollerKnobProportion(sPtr->hScroller)); - if (sPtr->vScroller) - WMSetScrollerParameters(sPtr->vScroller, ypos, - WMGetScrollerKnobProportion(sPtr->vScroller)); - - W_MoveView(sPtr->contentView, -point.x, -point.y); -} - - -static void -doScrolling(WMWidget *self, void *data) -{ - ScrollView *sPtr = (ScrollView*)data; - float value; - int pos; - int vpsize; - float size; - - if (sPtr->hScroller == (WMScroller *)self) { - pos = -sPtr->contentView->pos.x; - size = sPtr->contentView->size.width-sPtr->viewport->size.width; - vpsize = sPtr->viewport->size.width - sPtr->pageScroll; - } else { - pos = -sPtr->contentView->pos.y; - size = sPtr->contentView->size.height-sPtr->viewport->size.height; - vpsize = sPtr->viewport->size.height - sPtr->pageScroll; - } - if (vpsize <= 0) - vpsize = 1; - - switch (WMGetScrollerHitPart(self)) { - case WSDecrementLine: - if (pos > 0) { - pos-=sPtr->lineScroll; - if (pos < 0) - pos = 0; - value = (float)pos / size; - WMSetScrollerParameters(self, value, - WMGetScrollerKnobProportion(self)); - } - break; - case WSIncrementLine: - if (pos < size) { - pos+=sPtr->lineScroll; - if (pos > size) - pos = size; - value = (float)pos / size; - WMSetScrollerParameters(self, value, - WMGetScrollerKnobProportion(self)); - } - break; - - case WSKnob: - value = WMGetScrollerValue(self); - pos = value*size; - break; - - case WSDecrementPage: - if (pos > 0) { - pos -= vpsize; - if (pos < 0) - pos = 0; - value = (float)pos / size; - WMSetScrollerParameters(self, value, - WMGetScrollerKnobProportion(self)); - } - break; - - case WSDecrementWheel: - if (pos > 0) { - pos -= vpsize/3; - if (pos < 0) - pos = 0; - value = (float)pos / size; - WMSetScrollerParameters(self, value, - WMGetScrollerKnobProportion(self)); - } - break; - - case WSIncrementPage: - if (pos < size) { - pos += vpsize; - if (pos > size) - pos = size; - value = (float)pos / size; - WMSetScrollerParameters(self, value, - WMGetScrollerKnobProportion(self)); - } - break; - - case WSIncrementWheel: - if (pos < size) { - pos += vpsize/3; - if (pos > size) - pos = size; - value = (float)pos / size; - WMSetScrollerParameters(self, value, - WMGetScrollerKnobProportion(self)); - } - break; - - case WSNoPart: - case WSKnobSlot: - break; - } - - if (sPtr->hScroller == (WMScroller *)self) { - W_MoveView(sPtr->contentView, -pos, sPtr->contentView->pos.y); - } else { - W_MoveView(sPtr->contentView, sPtr->contentView->pos.x, -pos); - } -} - - -WMScroller* -WMGetScrollViewHorizontalScroller(WMScrollView *sPtr) -{ - return sPtr->hScroller; -} - - - -WMScroller* -WMGetScrollViewVerticalScroller(WMScrollView *sPtr) -{ - return sPtr->vScroller; -} - - -void -WMSetScrollViewHasHorizontalScroller(WMScrollView *sPtr, Bool flag) -{ - if (flag) { - if (sPtr->flags.hasHScroller) - return; - sPtr->flags.hasHScroller = 1; - - sPtr->hScroller = WMCreateScroller(sPtr); - WMSetScrollerAction(sPtr->hScroller, doScrolling, sPtr); - /* make it a horiz. scroller */ - WMResizeWidget(sPtr->hScroller, 2, 1); - - if (W_VIEW_REALIZED(sPtr->view)) { - WMRealizeWidget(sPtr->hScroller); - } - - reorganizeInterior(sPtr); - - WMMapWidget(sPtr->hScroller); - } else { - if (!sPtr->flags.hasHScroller) - return; - - WMUnmapWidget(sPtr->hScroller); - WMDestroyWidget(sPtr->hScroller); - sPtr->hScroller = NULL; - sPtr->flags.hasHScroller = 0; - - reorganizeInterior(sPtr); - } -} - - -void -WMSetScrollViewHasVerticalScroller(WMScrollView *sPtr, Bool flag) -{ - if (flag) { - if (sPtr->flags.hasVScroller) - return; - sPtr->flags.hasVScroller = 1; - - sPtr->vScroller = WMCreateScroller(sPtr); - WMSetScrollerAction(sPtr->vScroller, doScrolling, sPtr); - WMSetScrollerArrowsPosition(sPtr->vScroller, WSAMaxEnd); - /* make it a vert. scroller */ - WMResizeWidget(sPtr->vScroller, 1, 2); - - if (W_VIEW_REALIZED(sPtr->view)) { - WMRealizeWidget(sPtr->vScroller); - } - - reorganizeInterior(sPtr); - - WMMapWidget(sPtr->vScroller); - } else { - if (!sPtr->flags.hasVScroller) - return; - sPtr->flags.hasVScroller = 0; - - WMUnmapWidget(sPtr->vScroller); - WMDestroyWidget(sPtr->vScroller); - sPtr->vScroller = NULL; - - reorganizeInterior(sPtr); - } -} - - -void -WMSetScrollViewContentView(WMScrollView *sPtr, WMView *view) -{ - assert(sPtr->contentView == NULL); - - sPtr->contentView = view; - - W_ReparentView(sPtr->contentView, sPtr->viewport, 0, 0); - - if (sPtr->flags.hasHScroller) { - float prop; - - prop = (float)sPtr->viewport->size.width/sPtr->contentView->size.width; - WMSetScrollerParameters(sPtr->hScroller, 0, prop); - } - if (sPtr->flags.hasVScroller) { - float prop; - - prop = (float)sPtr->viewport->size.height/sPtr->contentView->size.height; - - WMSetScrollerParameters(sPtr->vScroller, 0, prop); - } -} - - -void -WMSetScrollViewRelief(WMScrollView *sPtr, WMReliefType type) -{ - sPtr->flags.relief = type; - - reorganizeInterior(sPtr); - - if (sPtr->view->flags.mapped) - paintScrollView(sPtr); - - -} - - - -static void -paintScrollView(ScrollView *sPtr) -{ - W_DrawRelief(sPtr->view->screen, sPtr->view->window, 0, 0, - sPtr->view->size.width, sPtr->view->size.height, - sPtr->flags.relief); -} - - -static void -updateScrollerProportion(ScrollView *sPtr) -{ - float prop, value; - float oldV, oldP; - - if (sPtr->flags.hasHScroller) { - oldV = WMGetScrollerValue(sPtr->hScroller); - oldP = WMGetScrollerKnobProportion(sPtr->hScroller); - - prop = (float)sPtr->viewport->size.width/(float)sPtr->contentView->size.width; - - if (oldP == 1.0) - value = 0; - else - value = (prop * oldV) / oldP; - WMSetScrollerParameters(sPtr->hScroller, value, prop); - } - if (sPtr->flags.hasVScroller) { - oldV = WMGetScrollerValue(sPtr->vScroller); - oldP = WMGetScrollerKnobProportion(sPtr->vScroller); - - prop = (float)sPtr->viewport->size.height/(float)sPtr->contentView->size.height; - - if (oldP == 1.0) - value = 0; - else - value = (prop * oldV) / oldP; - WMSetScrollerParameters(sPtr->vScroller, value, prop); - } - applyScrollerValues(sPtr); -} - - -static void -handleViewportEvents(XEvent *event, void *data) -{ - ScrollView *sPtr = (ScrollView*)data; - - if (sPtr->contentView - && event->xconfigure.window == sPtr->contentView->window) - updateScrollerProportion(sPtr); -} - - -static void -handleEvents(XEvent *event, void *data) -{ - ScrollView *sPtr = (ScrollView*)data; - - CHECK_CLASS(data, WC_ScrollView); - - switch (event->type) { - case Expose: - if (event->xexpose.count!=0) - break; - if (event->xexpose.serial == 0) /* means it's artificial */ - W_RedisplayView(sPtr->contentView); - else - paintScrollView(sPtr); - break; - - case DestroyNotify: - destroyScrollView(sPtr); - break; - - } -} - - -static void -destroyScrollView(ScrollView *sPtr) -{ - wfree(sPtr); -} - + +#include "WINGsP.h" + +typedef struct W_ScrollView { + W_Class widgetClass; + WMView *view; + + WMView *contentView; + WMView *viewport; + + WMScroller *vScroller; + WMScroller *hScroller; + + short lineScroll; + short pageScroll; + + struct { + WMReliefType relief:3; + unsigned int hasVScroller:1; + unsigned int hasHScroller:1; + + } flags; + +} ScrollView; + +static void destroyScrollView(ScrollView * sPtr); + +static void paintScrollView(ScrollView * sPtr); +static void handleEvents(XEvent * event, void *data); +static void handleViewportEvents(XEvent * event, void *data); +static void resizeScrollView(); +static void updateScrollerProportion(); + +W_ViewDelegate _ScrollViewViewDelegate = { + NULL, + NULL, + resizeScrollView, + NULL, + NULL +}; + +WMScrollView *WMCreateScrollView(WMWidget * parent) +{ + ScrollView *sPtr; + + sPtr = wmalloc(sizeof(ScrollView)); + memset(sPtr, 0, sizeof(ScrollView)); + + sPtr->widgetClass = WC_ScrollView; + + sPtr->view = W_CreateView(W_VIEW(parent)); + if (!sPtr->view) { + wfree(sPtr); + return NULL; + } + sPtr->viewport = W_CreateView(sPtr->view); + if (!sPtr->viewport) { + W_DestroyView(sPtr->view); + wfree(sPtr); + return NULL; + } + sPtr->view->self = sPtr; + sPtr->viewport->self = sPtr; + + sPtr->view->delegate = &_ScrollViewViewDelegate; + + sPtr->viewport->flags.mapWhenRealized = 1; + + WMCreateEventHandler(sPtr->view, StructureNotifyMask | ExposureMask, handleEvents, sPtr); + WMCreateEventHandler(sPtr->viewport, SubstructureNotifyMask, handleViewportEvents, sPtr); + + sPtr->lineScroll = 4; + + sPtr->pageScroll = 0; + + return sPtr; +} + +static void applyScrollerValues(WMScrollView * sPtr) +{ + int x, y; + + if (sPtr->contentView == NULL) + return; + + if (sPtr->flags.hasHScroller) { + float v = WMGetScrollerValue(sPtr->hScroller); + int size; + + size = sPtr->contentView->size.width - sPtr->viewport->size.width; + + x = v * size; + } else { + x = 0; + } + + if (sPtr->flags.hasVScroller) { + float v = WMGetScrollerValue(sPtr->vScroller); + + int size; + + size = sPtr->contentView->size.height - sPtr->viewport->size.height; + + y = v * size; + } else { + y = 0; + } + + x = WMAX(0, x); + y = WMAX(0, y); + + W_MoveView(sPtr->contentView, -x, -y); + + W_RaiseView(sPtr->viewport); +} + +static void reorganizeInterior(WMScrollView * sPtr) +{ + int hx, hy, hw; + int vx, vy, vh; + int cx, cy, cw, ch; + + cw = hw = sPtr->view->size.width; + vh = ch = sPtr->view->size.height; + + if (sPtr->flags.relief == WRSimple) { + cw -= 2; + ch -= 2; + cx = 1; + cy = 1; + } else if (sPtr->flags.relief != WRFlat) { + cw -= 3; + ch -= 3; + cx = 2; + cy = 2; + } else { + cx = 0; + cy = 0; + } + + if (sPtr->flags.hasHScroller) { + int h = 20; + + ch -= h; + + if (sPtr->flags.relief == WRSimple) { + hx = 0; + hy = sPtr->view->size.height - h; + } else if (sPtr->flags.relief != WRFlat) { + hx = 1; + hy = sPtr->view->size.height - h - 1; + hw -= 2; + } else { + hx = 0; + hy = sPtr->view->size.height - h; + } + } else { + /* make compiler shutup */ + hx = 0; + hy = 0; + } + + if (sPtr->flags.hasVScroller) { + int w = 20; + cw -= w; + cx += w; + hx += w - 1; + hw -= w - 1; + + if (sPtr->flags.relief == WRSimple) { + vx = 0; + vy = 0; + } else if (sPtr->flags.relief != WRFlat) { + vx = 1; + vy = 1; + vh -= 2; + } else { + vx = 0; + vy = 0; + } + } else { + /* make compiler shutup */ + vx = 0; + vy = 0; + } + + W_ResizeView(sPtr->viewport, cw, ch); + W_MoveView(sPtr->viewport, cx, cy); + + if (sPtr->flags.hasHScroller) { + WMResizeWidget(sPtr->hScroller, hw, 20); + WMMoveWidget(sPtr->hScroller, hx, hy); + } + if (sPtr->flags.hasVScroller) { + WMResizeWidget(sPtr->vScroller, 20, vh); + WMMoveWidget(sPtr->vScroller, vx, vy); + } + + applyScrollerValues(sPtr); +} + +static void resizeScrollView(W_ViewDelegate * self, WMView * view) +{ + reorganizeInterior(view->self); + updateScrollerProportion(view->self); +} + +void WMResizeScrollViewContent(WMScrollView * sPtr, unsigned int width, unsigned int height) +{ + int w, h, x; + + w = width; + h = height; + + x = 0; + if (sPtr->flags.relief == WRSimple) { + w += 2; + h += 2; + } else if (sPtr->flags.relief != WRFlat) { + w += 4; + h += 4; + x = 1; + } + + if (sPtr->flags.hasVScroller) { + WMResizeWidget(sPtr->vScroller, 20, h); + width -= W_VIEW(sPtr->vScroller)->size.width; + } + + if (sPtr->flags.hasHScroller) { + WMResizeWidget(sPtr->hScroller, w, 20); + WMMoveWidget(sPtr->hScroller, x, h); + height -= W_VIEW(sPtr->hScroller)->size.height; + } + + W_ResizeView(sPtr->view, w, h); + + W_ResizeView(sPtr->viewport, width, height); +} + +void WMSetScrollViewLineScroll(WMScrollView * sPtr, int amount) +{ + assert(amount > 0); + + sPtr->lineScroll = amount; +} + +void WMSetScrollViewPageScroll(WMScrollView * sPtr, int amount) +{ + assert(amount >= 0); + + sPtr->pageScroll = amount; +} + +WMRect WMGetScrollViewVisibleRect(WMScrollView * sPtr) +{ + WMRect rect; + + rect.pos.x = -sPtr->contentView->pos.x; + rect.pos.y = -sPtr->contentView->pos.y; + rect.size = sPtr->viewport->size; + + return rect; +} + +void WMScrollViewScrollPoint(WMScrollView * sPtr, WMPoint point) +{ + float xsize, ysize; + float xpos, ypos; + + xsize = sPtr->contentView->size.width - sPtr->viewport->size.width; + ysize = sPtr->contentView->size.height - sPtr->viewport->size.height; + + xpos = point.x / xsize; + ypos = point.y / ysize; + + if (sPtr->hScroller) + WMSetScrollerParameters(sPtr->hScroller, xpos, WMGetScrollerKnobProportion(sPtr->hScroller)); + if (sPtr->vScroller) + WMSetScrollerParameters(sPtr->vScroller, ypos, WMGetScrollerKnobProportion(sPtr->vScroller)); + + W_MoveView(sPtr->contentView, -point.x, -point.y); +} + +static void doScrolling(WMWidget * self, void *data) +{ + ScrollView *sPtr = (ScrollView *) data; + float value; + int pos; + int vpsize; + float size; + + if (sPtr->hScroller == (WMScroller *) self) { + pos = -sPtr->contentView->pos.x; + size = sPtr->contentView->size.width - sPtr->viewport->size.width; + vpsize = sPtr->viewport->size.width - sPtr->pageScroll; + } else { + pos = -sPtr->contentView->pos.y; + size = sPtr->contentView->size.height - sPtr->viewport->size.height; + vpsize = sPtr->viewport->size.height - sPtr->pageScroll; + } + if (vpsize <= 0) + vpsize = 1; + + switch (WMGetScrollerHitPart(self)) { + case WSDecrementLine: + if (pos > 0) { + pos -= sPtr->lineScroll; + if (pos < 0) + pos = 0; + value = (float)pos / size; + WMSetScrollerParameters(self, value, WMGetScrollerKnobProportion(self)); + } + break; + case WSIncrementLine: + if (pos < size) { + pos += sPtr->lineScroll; + if (pos > size) + pos = size; + value = (float)pos / size; + WMSetScrollerParameters(self, value, WMGetScrollerKnobProportion(self)); + } + break; + + case WSKnob: + value = WMGetScrollerValue(self); + pos = value * size; + break; + + case WSDecrementPage: + if (pos > 0) { + pos -= vpsize; + if (pos < 0) + pos = 0; + value = (float)pos / size; + WMSetScrollerParameters(self, value, WMGetScrollerKnobProportion(self)); + } + break; + + case WSDecrementWheel: + if (pos > 0) { + pos -= vpsize / 3; + if (pos < 0) + pos = 0; + value = (float)pos / size; + WMSetScrollerParameters(self, value, WMGetScrollerKnobProportion(self)); + } + break; + + case WSIncrementPage: + if (pos < size) { + pos += vpsize; + if (pos > size) + pos = size; + value = (float)pos / size; + WMSetScrollerParameters(self, value, WMGetScrollerKnobProportion(self)); + } + break; + + case WSIncrementWheel: + if (pos < size) { + pos += vpsize / 3; + if (pos > size) + pos = size; + value = (float)pos / size; + WMSetScrollerParameters(self, value, WMGetScrollerKnobProportion(self)); + } + break; + + case WSNoPart: + case WSKnobSlot: + break; + } + + if (sPtr->hScroller == (WMScroller *) self) { + W_MoveView(sPtr->contentView, -pos, sPtr->contentView->pos.y); + } else { + W_MoveView(sPtr->contentView, sPtr->contentView->pos.x, -pos); + } +} + +WMScroller *WMGetScrollViewHorizontalScroller(WMScrollView * sPtr) +{ + return sPtr->hScroller; +} + +WMScroller *WMGetScrollViewVerticalScroller(WMScrollView * sPtr) +{ + return sPtr->vScroller; +} + +void WMSetScrollViewHasHorizontalScroller(WMScrollView * sPtr, Bool flag) +{ + if (flag) { + if (sPtr->flags.hasHScroller) + return; + sPtr->flags.hasHScroller = 1; + + sPtr->hScroller = WMCreateScroller(sPtr); + WMSetScrollerAction(sPtr->hScroller, doScrolling, sPtr); + /* make it a horiz. scroller */ + WMResizeWidget(sPtr->hScroller, 2, 1); + + if (W_VIEW_REALIZED(sPtr->view)) { + WMRealizeWidget(sPtr->hScroller); + } + + reorganizeInterior(sPtr); + + WMMapWidget(sPtr->hScroller); + } else { + if (!sPtr->flags.hasHScroller) + return; + + WMUnmapWidget(sPtr->hScroller); + WMDestroyWidget(sPtr->hScroller); + sPtr->hScroller = NULL; + sPtr->flags.hasHScroller = 0; + + reorganizeInterior(sPtr); + } +} + +void WMSetScrollViewHasVerticalScroller(WMScrollView * sPtr, Bool flag) +{ + if (flag) { + if (sPtr->flags.hasVScroller) + return; + sPtr->flags.hasVScroller = 1; + + sPtr->vScroller = WMCreateScroller(sPtr); + WMSetScrollerAction(sPtr->vScroller, doScrolling, sPtr); + WMSetScrollerArrowsPosition(sPtr->vScroller, WSAMaxEnd); + /* make it a vert. scroller */ + WMResizeWidget(sPtr->vScroller, 1, 2); + + if (W_VIEW_REALIZED(sPtr->view)) { + WMRealizeWidget(sPtr->vScroller); + } + + reorganizeInterior(sPtr); + + WMMapWidget(sPtr->vScroller); + } else { + if (!sPtr->flags.hasVScroller) + return; + sPtr->flags.hasVScroller = 0; + + WMUnmapWidget(sPtr->vScroller); + WMDestroyWidget(sPtr->vScroller); + sPtr->vScroller = NULL; + + reorganizeInterior(sPtr); + } +} + +void WMSetScrollViewContentView(WMScrollView * sPtr, WMView * view) +{ + assert(sPtr->contentView == NULL); + + sPtr->contentView = view; + + W_ReparentView(sPtr->contentView, sPtr->viewport, 0, 0); + + if (sPtr->flags.hasHScroller) { + float prop; + + prop = (float)sPtr->viewport->size.width / sPtr->contentView->size.width; + WMSetScrollerParameters(sPtr->hScroller, 0, prop); + } + if (sPtr->flags.hasVScroller) { + float prop; + + prop = (float)sPtr->viewport->size.height / sPtr->contentView->size.height; + + WMSetScrollerParameters(sPtr->vScroller, 0, prop); + } +} + +void WMSetScrollViewRelief(WMScrollView * sPtr, WMReliefType type) +{ + sPtr->flags.relief = type; + + reorganizeInterior(sPtr); + + if (sPtr->view->flags.mapped) + paintScrollView(sPtr); + +} + +static void paintScrollView(ScrollView * sPtr) +{ + W_DrawRelief(sPtr->view->screen, sPtr->view->window, 0, 0, + sPtr->view->size.width, sPtr->view->size.height, sPtr->flags.relief); +} + +static void updateScrollerProportion(ScrollView * sPtr) +{ + float prop, value; + float oldV, oldP; + + if (sPtr->flags.hasHScroller) { + oldV = WMGetScrollerValue(sPtr->hScroller); + oldP = WMGetScrollerKnobProportion(sPtr->hScroller); + + prop = (float)sPtr->viewport->size.width / (float)sPtr->contentView->size.width; + + if (oldP == 1.0) + value = 0; + else + value = (prop * oldV) / oldP; + WMSetScrollerParameters(sPtr->hScroller, value, prop); + } + if (sPtr->flags.hasVScroller) { + oldV = WMGetScrollerValue(sPtr->vScroller); + oldP = WMGetScrollerKnobProportion(sPtr->vScroller); + + prop = (float)sPtr->viewport->size.height / (float)sPtr->contentView->size.height; + + if (oldP == 1.0) + value = 0; + else + value = (prop * oldV) / oldP; + WMSetScrollerParameters(sPtr->vScroller, value, prop); + } + applyScrollerValues(sPtr); +} + +static void handleViewportEvents(XEvent * event, void *data) +{ + ScrollView *sPtr = (ScrollView *) data; + + if (sPtr->contentView && event->xconfigure.window == sPtr->contentView->window) + updateScrollerProportion(sPtr); +} + +static void handleEvents(XEvent * event, void *data) +{ + ScrollView *sPtr = (ScrollView *) data; + + CHECK_CLASS(data, WC_ScrollView); + + switch (event->type) { + case Expose: + if (event->xexpose.count != 0) + break; + if (event->xexpose.serial == 0) /* means it's artificial */ + W_RedisplayView(sPtr->contentView); + else + paintScrollView(sPtr); + break; + + case DestroyNotify: + destroyScrollView(sPtr); + break; + + } +} + +static void destroyScrollView(ScrollView * sPtr) +{ + wfree(sPtr); +}