1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 04:20:27 +01:00
Files
wmaker/WINGs/wscrollview.c
kojima 80fb09a74e replaced free() with wfree() everywhere
fixed bug in wlist that caused colorpanel to crash
1999-10-09 20:07:23 +00:00

505 lines
9.5 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 _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->view) {
W_DestroyView(sPtr->view);
wfree(sPtr);
return NULL;
}
sPtr->view->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
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 = W_VIEW(sPtr->hScroller)->size.height;
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 = W_VIEW(sPtr->vScroller)->size.width;
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);
}
}
static void
resizeScrollView(W_ViewDelegate *self, WMView *view)
{
reorganizeInterior(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) {
w -= W_VIEW(sPtr->hScroller)->size.width;
WMResizeWidget(sPtr->vScroller, 20, h);
}
if (sPtr->flags.hasHScroller) {
h -= W_VIEW(sPtr->hScroller)->size.height;
WMResizeWidget(sPtr->hScroller, w, 20);
WMMoveWidget(sPtr->hScroller, x, h);
}
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;
}
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 WSIncrementPage:
if (pos < size) {
pos += vpsize;
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);
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);
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;
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;
if (sPtr->flags.hasHScroller) {
prop = (float)sPtr->viewport->size.width/sPtr->contentView->size.width;
value = WMGetScrollerValue(sPtr->hScroller);
WMSetScrollerParameters(sPtr->hScroller, value, prop);
}
if (sPtr->flags.hasVScroller) {
prop = (float)sPtr->viewport->size.height/sPtr->contentView->size.height;
value = WMGetScrollerValue(sPtr->vScroller);
WMSetScrollerParameters(sPtr->vScroller, value, prop);
}
}
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;
paintScrollView(sPtr);
break;
case DestroyNotify:
destroyScrollView(sPtr);
break;
}
}
static void
destroyScrollView(ScrollView *sPtr)
{
wfree(sPtr);
}