1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 04:20:27 +01:00
Files
wmaker/WINGs/wscrollview.c
Christophe CURIS 708bc27e3f WINGs: Added explicit parameter list to function prototypes (Simple cases)
It is dangerous to let the compiler know about a function without
letting him know the arguments because he won't be able to report
invalid calls.

This patch concern the cases where adding the arguments did not
need other code change.
2013-05-12 01:01:20 +01:00

562 lines
12 KiB
C

#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(W_ViewDelegate *self, WMView *view);
static void updateScrollerProportion(ScrollView *sPtr);
W_ViewDelegate _ScrollViewViewDelegate = {
NULL,
NULL,
resizeScrollView,
NULL,
NULL
};
WMScrollView *WMCreateScrollView(WMWidget * parent)
{
ScrollView *sPtr;
sPtr = wmalloc(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 = (prop * oldV) / oldP;
else
value = 0;
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 = (prop * oldV) / oldP;
else
value = 0;
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);
}