Files
wmaker/WINGs/wsplitview.c
T

792 lines
17 KiB
C
Raw Normal View History

1998-09-29 22:36:29 +00:00
#include "WINGsP.h"
1999-10-27 22:32:12 +00:00
/*
2004-10-12 21:28:27 +00:00
char *WMSplitViewDidResizeSubviewsNotification
= "WMSplitViewDidResizeSubviewsNotification";
char *WMSplitViewWillResizeSubviewsNotification
= "WMSplitViewWillResizeSubviewsNotification";
*/
1999-10-27 22:32:12 +00:00
typedef struct W_SplitViewSubview {
2009-08-20 00:59:40 +02:00
WMView *view;
int minSize;
int maxSize;
int size;
int pos;
} W_SplitViewSubview;
1998-09-29 22:36:29 +00:00
typedef struct W_SplitView {
2009-08-20 00:59:40 +02:00
W_Class widgetClass;
W_View *view;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
WMArray *subviews;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
WMSplitViewConstrainProc *constrainProc;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
struct {
unsigned int vertical:1;
unsigned int adjustOnPaint:1;
unsigned int subviewsWereManuallyMoved:1;
} flags;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
/* WMSplitViewResizeSubviewsProc *resizeSubviewsProc; */
1999-10-27 22:32:12 +00:00
} W_SplitView;
1998-09-29 22:36:29 +00:00
1999-10-27 22:32:12 +00:00
#define DIVIDER_THICKNESS 8
#define MIN_SUBVIEW_SIZE 4
#define MAX_SUBVIEW_SIZE -1
/* TODO: rewrite --Dan */
#define _GetSubviewsCount() WMGetArrayItemCount(sPtr->subviews)
1999-10-27 22:32:12 +00:00
#define _GetPSubviewStructAt(i) \
2004-10-12 21:28:27 +00:00
((W_SplitViewSubview*)WMGetFromArray(sPtr->subviews,(i)))
1999-10-27 22:32:12 +00:00
#define _GetSubviewAt(i) \
2004-10-12 21:28:27 +00:00
(((W_SplitViewSubview*)WMGetFromArray(sPtr->subviews,(i)))->view)
1999-10-27 22:32:12 +00:00
#define _GetMinSizeAt(i) \
2004-10-12 21:28:27 +00:00
(((W_SplitViewSubview*)WMGetFromArray(sPtr->subviews,(i)))->minSize)
1999-10-27 22:32:12 +00:00
#define _GetMaxSizeAt(i) \
2004-10-12 21:28:27 +00:00
(((W_SplitViewSubview*)WMGetFromArray(sPtr->subviews,(i)))->maxSize)
1998-09-29 22:36:29 +00:00
1999-10-27 22:32:12 +00:00
#define _GetSizeAt(i) \
2004-10-12 21:28:27 +00:00
(((W_SplitViewSubview*)WMGetFromArray(sPtr->subviews,(i)))->size)
1998-09-29 22:36:29 +00:00
1999-10-27 22:32:12 +00:00
#define _GetPosAt(i) \
2004-10-12 21:28:27 +00:00
(((W_SplitViewSubview*)WMGetFromArray(sPtr->subviews,(i)))->pos)
1999-10-27 22:32:12 +00:00
#define _GetSplitViewSize() \
2004-10-12 21:28:27 +00:00
((sPtr->flags.vertical) ? sPtr->view->size.width : sPtr->view->size.height)
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
static void destroySplitView(WMSplitView * sPtr);
static void paintSplitView(WMSplitView * sPtr);
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
static void handleEvents(XEvent * event, void *data);
static void handleActionEvents(XEvent * event, void *data);
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
static void getConstraints(WMSplitView * sPtr, int index, int *minSize, int *maxSize)
1998-09-29 22:36:29 +00:00
{
2009-08-20 00:59:40 +02:00
*minSize = MIN_SUBVIEW_SIZE;
*maxSize = MAX_SUBVIEW_SIZE;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
if (sPtr->constrainProc)
(*sPtr->constrainProc) (sPtr, index, minSize, maxSize);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
if (*minSize < MIN_SUBVIEW_SIZE)
*minSize = MIN_SUBVIEW_SIZE;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
if (*maxSize < MIN_SUBVIEW_SIZE)
*maxSize = MAX_SUBVIEW_SIZE;
else if (*maxSize < *minSize)
*maxSize = *minSize;
1998-09-29 22:36:29 +00:00
}
2009-08-20 00:59:40 +02:00
static void updateConstraints(WMSplitView * sPtr)
1998-09-29 22:36:29 +00:00
{
2009-08-20 00:59:40 +02:00
W_SplitViewSubview *p;
int i, count;
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
count = _GetSubviewsCount();
for (i = 0; i < count; i++) {
p = _GetPSubviewStructAt(i);
getConstraints(sPtr, i, &(p->minSize), &(p->maxSize));
}
1998-09-29 22:36:29 +00:00
}
2009-08-20 00:59:40 +02:00
static void resizeView(WMSplitView * sPtr, WMView * view, int size)
1998-09-29 22:36:29 +00:00
{
2009-08-20 00:59:40 +02:00
int width, height;
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
if (sPtr->flags.vertical) {
width = size;
height = sPtr->view->size.height;
} else {
width = sPtr->view->size.width;
height = size;
}
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
if (view->self)
WMResizeWidget(view->self, width, height);
else
W_ResizeView(view, width, height);
1999-10-27 22:32:12 +00:00
}
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
static void reparentView(WMSplitView * sPtr, WMView * view, int pos)
1999-10-27 22:32:12 +00:00
{
2009-08-20 00:59:40 +02:00
int x, y;
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
if (sPtr->flags.vertical) {
x = pos;
y = 0;
} else {
x = 0;
y = pos;
}
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
W_ReparentView(view, sPtr->view, x, y);
1998-09-29 22:36:29 +00:00
}
2009-08-20 00:59:40 +02:00
static void moveView(WMSplitView * sPtr, WMView * view, int pos)
1998-09-29 22:36:29 +00:00
{
2009-08-20 00:59:40 +02:00
int x, y;
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
if (sPtr->flags.vertical) {
x = pos;
y = 0;
} else {
x = 0;
y = pos;
}
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
if (view->self)
WMMoveWidget(view->self, x, y);
else
W_MoveView(view, x, y);
1999-10-27 22:32:12 +00:00
}
2009-08-20 00:59:40 +02:00
static int checkSizes(WMSplitView * sPtr)
1999-10-27 22:32:12 +00:00
{
2009-08-20 00:59:40 +02:00
int i, count, offset;
W_SplitViewSubview *p;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
count = _GetSubviewsCount();
offset = 0;
for (i = 0; i < count; i++) {
p = _GetPSubviewStructAt(i);
if (p->size < p->minSize) {
offset += p->minSize - p->size;
p->size = p->minSize;
} else if (p->maxSize != MAX_SUBVIEW_SIZE && p->size > p->maxSize) {
offset += p->maxSize - p->size;
p->size = p->maxSize;
}
}
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
return (offset);
1999-10-27 22:32:12 +00:00
}
2009-08-20 00:59:40 +02:00
static void checkPositions(WMSplitView * sPtr)
1999-10-27 22:32:12 +00:00
{
2009-08-20 00:59:40 +02:00
int i, count, pos;
W_SplitViewSubview *p;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
count = _GetSubviewsCount();
pos = 0;
for (i = 0; i < count; i++) {
p = _GetPSubviewStructAt(i);
p->pos = pos;
pos += p->size + DIVIDER_THICKNESS;
}
1998-09-29 22:36:29 +00:00
}
2009-08-20 00:59:40 +02:00
static void updateSubviewsGeom(WMSplitView * sPtr)
1998-09-29 22:36:29 +00:00
{
2009-08-20 00:59:40 +02:00
int i, count;
W_SplitViewSubview *p;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
count = _GetSubviewsCount();
for (i = 0; i < count; i++) {
p = _GetPSubviewStructAt(i);
resizeView(sPtr, p->view, p->size);
moveView(sPtr, p->view, p->pos);
}
1998-09-29 22:36:29 +00:00
}
2009-08-20 00:59:40 +02:00
static int getTotalSize(WMSplitView * sPtr)
1998-09-29 22:36:29 +00:00
{
2009-08-20 00:59:40 +02:00
int i, count, totSize;
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
count = _GetSubviewsCount();
if (!count)
return (0);
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
totSize = 0;
for (i = 0; i < count; i++)
totSize += _GetSizeAt(i) + DIVIDER_THICKNESS;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
return (totSize - DIVIDER_THICKNESS);
1999-10-27 22:32:12 +00:00
}
2009-08-20 00:59:40 +02:00
static Bool distributeOffsetEqually(WMSplitView * sPtr, int offset)
1999-10-27 22:32:12 +00:00
{
2009-08-20 00:59:40 +02:00
W_SplitViewSubview *p;
int i, count, sizeChanged, forced;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
if ((count = _GetSubviewsCount()) < 1)
return (True);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
forced = False;
while (offset != 0) {
sizeChanged = 0;
for (i = 0; i < count && offset != 0; i++) {
p = _GetPSubviewStructAt(i);
if (offset < 0) {
if (p->size > p->minSize) {
offset++;
p->size--;
sizeChanged = 1;
}
} else if (p->maxSize == MAX_SUBVIEW_SIZE || p->size < p->maxSize) {
offset--;
p->size++;
sizeChanged = 1;
}
}
if (offset != 0 && !sizeChanged) {
p = _GetPSubviewStructAt(count - 1);
if (offset > 0) {
p->size += offset;
p->maxSize = MAX_SUBVIEW_SIZE;
}
offset = 0;
forced = True;
}
}
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
return (forced);
1999-10-27 22:32:12 +00:00
}
2009-08-20 00:59:40 +02:00
static Bool distributeOffsetFormEnd(WMSplitView * sPtr, int offset)
1999-10-27 22:32:12 +00:00
{
2009-08-20 00:59:40 +02:00
W_SplitViewSubview *p;
int i, count, sizeTmp;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
if ((count = _GetSubviewsCount()) < 1)
return (True);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
for (i = count - 1; i >= 0 && offset != 0; i--) {
p = _GetPSubviewStructAt(i);
sizeTmp = p->size;
if (offset > 0) {
if (p->maxSize == MAX_SUBVIEW_SIZE || p->size + offset < p->maxSize)
p->size += offset;
else
p->size = p->maxSize;
} else {
if (p->size + offset >= p->minSize)
p->size += offset;
else
p->size = p->minSize;
}
offset -= p->size - sizeTmp;
}
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
return (offset == 0);
1998-09-29 22:36:29 +00:00
}
2009-08-20 00:59:40 +02:00
static void adjustSplitViewSubviews(WMSplitView * sPtr)
1999-10-27 22:32:12 +00:00
{
2009-08-20 00:59:40 +02:00
W_SplitViewSubview *p;
int i, count, adjSize, adjPad;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
CHECK_CLASS(sPtr, WC_SplitView);
1999-10-27 22:32:12 +00:00
1998-09-29 22:36:29 +00:00
#if 0
2009-08-20 00:59:40 +02:00
printf("---- (adjustSplitViewSubviews - 1) ----\n");
dumpSubviews(sPtr);
1999-10-27 22:32:12 +00:00
#endif
2009-08-20 00:59:40 +02:00
if ((count = _GetSubviewsCount()) < 1)
return;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
adjSize = (_GetSplitViewSize() - ((count - 1) * DIVIDER_THICKNESS)) / count;
adjPad = (_GetSplitViewSize() - ((count - 1) * DIVIDER_THICKNESS)) % count;
for (i = 0; i < count; i++) {
p = _GetPSubviewStructAt(i);
p->size = adjSize;
}
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
distributeOffsetEqually(sPtr, adjPad - checkSizes(sPtr));
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
checkPositions(sPtr);
updateSubviewsGeom(sPtr);
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
sPtr->flags.subviewsWereManuallyMoved = 0;
1999-10-27 22:32:12 +00:00
2004-10-12 21:28:27 +00:00
#if 0
2009-08-20 00:59:40 +02:00
printf("---- (adjustSplitViewSubviews - 2) ----\n");
dumpSubviews(sPtr);
1999-10-27 22:32:12 +00:00
#endif
}
#if 0
2009-08-20 00:59:40 +02:00
static void handleSubviewResized(void *self, WMNotification * notif)
{
WMSplitView *sPtr = (WMSplitView *) self;
CHECK_CLASS(sPtr, WC_SplitView);
if (WMGetNotificationName(notif) == WMViewSizeDidChangeNotification) {
W_SplitViewSubview *p;
int i, count, done;
WMView *view = WMGetNotificationObject(notif);
count = _GetSubviewsCount();
done = 0;
for (i = 0; i < count; i++) {
p = _GetPSubviewStructAt(i);
if (p->view == view) {
done = 1;
break;
}
}
if (done) {
/* TODO !!! */
resizeView(sPtr, p->view, p->size);
moveView(sPtr, p->view, p->pos);
}
}
1998-09-29 22:36:29 +00:00
}
#endif
2009-08-20 00:59:40 +02:00
static void handleViewResized(void *self, WMNotification * notification)
1998-09-29 22:36:29 +00:00
{
2009-08-20 00:59:40 +02:00
WMSplitView *sPtr = (WMSplitView *) self;
1999-10-27 22:32:12 +00:00
/* Parameter not used, but tell the compiler that it is ok */
(void) notification;
1999-10-27 22:32:12 +00:00
#if 0
2009-08-20 00:59:40 +02:00
printf("---- (handleViewResized - 1) ----\n");
dumpSubviews(sPtr);
1999-10-27 22:32:12 +00:00
#endif
2009-08-20 00:59:40 +02:00
updateConstraints(sPtr);
checkSizes(sPtr);
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
if (sPtr->constrainProc || sPtr->flags.subviewsWereManuallyMoved) {
distributeOffsetFormEnd(sPtr, _GetSplitViewSize() - getTotalSize(sPtr));
checkPositions(sPtr);
updateSubviewsGeom(sPtr);
} else
adjustSplitViewSubviews(sPtr);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
assert(checkSizes(sPtr) == 0);
1999-10-27 22:32:12 +00:00
#if 0
2009-08-20 00:59:40 +02:00
printf("---- (handleViewResized - 2) ----\n");
dumpSubviews(sPtr);
1999-10-27 22:32:12 +00:00
#endif
1998-09-29 22:36:29 +00:00
}
2009-08-20 00:59:40 +02:00
static void paintSplitView(WMSplitView * sPtr)
1998-09-29 22:36:29 +00:00
{
2009-08-20 00:59:40 +02:00
W_SplitViewSubview *p;
W_Screen *scr = sPtr->view->screen;
int x, y, i, count;
WMPixmap *dimple = scr->scrollerDimple;
1998-09-29 22:36:29 +00:00
1999-10-27 22:32:12 +00:00
#if 0
2009-08-20 00:59:40 +02:00
printf("---- (paintSplitView - 1) ----\n");
dumpSubviews(sPtr);
1999-10-27 22:32:12 +00:00
#endif
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
if (!sPtr->view->flags.mapped || !sPtr->view->flags.realized)
return;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
XClearWindow(scr->display, sPtr->view->window);
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
count = _GetSubviewsCount();
if (count == 0)
return;
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
if (sPtr->flags.adjustOnPaint) {
handleViewResized(sPtr, NULL);
sPtr->flags.adjustOnPaint = 0;
}
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
XSetClipMask(scr->display, scr->clipGC, dimple->mask);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
if (sPtr->flags.vertical) {
x = ((DIVIDER_THICKNESS - dimple->width) / 2);
y = (sPtr->view->size.height - dimple->height) / 2;
} else {
x = (sPtr->view->size.width - dimple->width) / 2;
y = ((DIVIDER_THICKNESS - dimple->height) / 2);
}
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
for (i = 0; i < count - 1; i++) {
p = _GetPSubviewStructAt(i);
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
if (sPtr->flags.vertical)
x += p->size;
else
y += p->size;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
XSetClipOrigin(scr->display, scr->clipGC, x, y);
XCopyArea(scr->display, dimple->pixmap, sPtr->view->window,
scr->clipGC, 0, 0, dimple->width, dimple->height, x, y);
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
if (sPtr->flags.vertical)
x += DIVIDER_THICKNESS;
else
y += DIVIDER_THICKNESS;
}
1998-09-29 22:36:29 +00:00
1999-10-27 22:32:12 +00:00
#if 0
2009-08-20 00:59:40 +02:00
printf("---- (paintSplitView - 2) ----\n");
dumpSubviews(sPtr);
1999-10-27 22:32:12 +00:00
#endif
}
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
static void drawDragingRectangle(WMSplitView * sPtr, int pos)
{
int x, y, w, h;
if (sPtr->flags.vertical) {
x = pos;
y = 0;
w = DIVIDER_THICKNESS;
h = sPtr->view->size.height;
} else {
x = 0;
y = pos;
w = sPtr->view->size.width;
h = DIVIDER_THICKNESS;
}
XFillRectangle(sPtr->view->screen->display, sPtr->view->window, sPtr->view->screen->ixorGC, x, y, w, h);
}
static void getMinMaxDividerCoord(WMSplitView * sPtr, int divider, int *minC, int *maxC)
{
int relMinC, relMaxC;
int totSize = _GetSizeAt(divider) + _GetSizeAt(divider + 1);
relMinC = _GetMinSizeAt(divider);
if (_GetMaxSizeAt(divider + 1) != MAX_SUBVIEW_SIZE && relMinC < totSize - _GetMaxSizeAt(divider + 1))
relMinC = totSize - _GetMaxSizeAt(divider + 1);
relMaxC = totSize - _GetMinSizeAt(divider + 1);
if (_GetMaxSizeAt(divider) != MAX_SUBVIEW_SIZE && relMaxC > _GetMaxSizeAt(divider))
relMaxC = _GetMaxSizeAt(divider);
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
*minC = _GetPosAt(divider) + relMinC;
*maxC = _GetPosAt(divider) + relMaxC;
1998-09-29 22:36:29 +00:00
}
2009-08-20 00:59:40 +02:00
static void dragDivider(WMSplitView * sPtr, int clickX, int clickY)
{
int divider, pos, ofs, done, dragging;
int i, count;
XEvent ev;
WMScreen *scr;
int minCoord, maxCoord, coord;
if (sPtr->constrainProc) {
updateConstraints(sPtr);
checkSizes(sPtr);
distributeOffsetFormEnd(sPtr, _GetSplitViewSize() - getTotalSize(sPtr));
checkPositions(sPtr);
updateSubviewsGeom(sPtr);
}
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
scr = sPtr->view->screen;
divider = ofs = pos = done = 0;
coord = (sPtr->flags.vertical) ? clickX : clickY;
count = _GetSubviewsCount();
if (count < 2)
return;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
for (i = 0; i < count - 1; i++) {
pos += _GetSizeAt(i) + DIVIDER_THICKNESS;
if (coord < pos) {
ofs = coord - pos + DIVIDER_THICKNESS;
done = 1;
break;
}
divider++;
}
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
if (!done)
return;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
getMinMaxDividerCoord(sPtr, divider, &minCoord, &maxCoord);
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
done = 0;
dragging = 0;
while (!done) {
WMMaskEvent(scr->display, ButtonMotionMask | ButtonReleaseMask | ExposureMask, &ev);
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
coord = (sPtr->flags.vertical) ? ev.xmotion.x : ev.xmotion.y;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
switch (ev.type) {
case ButtonRelease:
done = 1;
if (dragging)
drawDragingRectangle(sPtr, pos);
break;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
case MotionNotify:
if (dragging)
drawDragingRectangle(sPtr, pos);
if (coord - ofs < minCoord)
pos = minCoord;
else if (coord - ofs > maxCoord)
pos = maxCoord;
else
pos = coord - ofs;
drawDragingRectangle(sPtr, pos);
dragging = 1;
break;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
default:
WMHandleEvent(&ev);
break;
}
}
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
if (dragging) {
W_SplitViewSubview *p1, *p2;
int totSize;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
p1 = _GetPSubviewStructAt(divider);
p2 = _GetPSubviewStructAt(divider + 1);
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
totSize = p1->size + DIVIDER_THICKNESS + p2->size;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
p1->size = pos - p1->pos;
p2->size = totSize - p1->size - DIVIDER_THICKNESS;
p2->pos = p1->pos + p1->size + DIVIDER_THICKNESS;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
resizeView(sPtr, p1->view, p1->size);
moveView(sPtr, p2->view, p2->pos);
resizeView(sPtr, p2->view, p2->size);
sPtr->flags.subviewsWereManuallyMoved = 1;
}
1999-10-27 22:32:12 +00:00
}
2009-08-20 00:59:40 +02:00
static void handleEvents(XEvent * event, void *data)
1999-10-27 22:32:12 +00:00
{
2009-08-20 00:59:40 +02:00
WMSplitView *sPtr = (WMSplitView *) data;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
CHECK_CLASS(data, WC_SplitView);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
switch (event->type) {
case Expose:
if (event->xexpose.count != 0)
break;
paintSplitView(sPtr);
break;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
case DestroyNotify:
destroySplitView(sPtr);
break;
}
1998-09-29 22:36:29 +00:00
}
2009-08-20 00:59:40 +02:00
static void handleActionEvents(XEvent * event, void *data)
1998-09-29 22:36:29 +00:00
{
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
CHECK_CLASS(data, WC_SplitView);
1998-09-29 22:36:29 +00:00
2009-08-20 00:59:40 +02:00
switch (event->type) {
case ButtonPress:
if (event->xbutton.button == Button1)
dragDivider(data, event->xbutton.x, event->xbutton.y);
break;
}
1998-09-29 22:36:29 +00:00
}
2009-08-20 00:59:40 +02:00
static void destroySplitView(WMSplitView * sPtr)
1998-09-29 22:36:29 +00:00
{
2009-08-20 00:59:40 +02:00
WMFreeArray(sPtr->subviews);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
WMRemoveNotificationObserver(sPtr);
2009-08-20 00:59:40 +02:00
wfree(sPtr);
1998-09-29 22:36:29 +00:00
}
2009-08-20 00:59:40 +02:00
WMSplitView *WMCreateSplitView(WMWidget * parent)
1999-10-27 22:32:12 +00:00
{
2009-08-20 00:59:40 +02:00
WMSplitView *sPtr;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
sPtr = wmalloc(sizeof(WMSplitView));
sPtr->widgetClass = WC_SplitView;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
sPtr->view = W_CreateView(W_VIEW(parent));
if (!sPtr->view) {
wfree(sPtr);
return NULL;
}
sPtr->view->self = sPtr;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
WMSetViewNotifySizeChanges(sPtr->view, True);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
WMCreateEventHandler(sPtr->view, ExposureMask | StructureNotifyMask
| ClientMessageMask, handleEvents, sPtr);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
WMCreateEventHandler(sPtr->view, ButtonPressMask | ButtonReleaseMask
| EnterWindowMask | LeaveWindowMask, handleActionEvents, sPtr);
2009-08-20 00:59:40 +02:00
WMAddNotificationObserver(handleViewResized, sPtr, WMViewSizeDidChangeNotification, sPtr->view);
2009-08-20 00:59:40 +02:00
sPtr->subviews = WMCreateArrayWithDestructor(8, wfree);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
return sPtr;
1999-10-27 22:32:12 +00:00
}
2009-08-20 00:59:40 +02:00
void WMAdjustSplitViewSubviews(WMSplitView * sPtr)
1999-10-27 22:32:12 +00:00
{
2009-08-20 00:59:40 +02:00
CHECK_CLASS(sPtr, WC_SplitView);
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
checkSizes(sPtr);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
adjustSplitViewSubviews(sPtr);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
assert(checkSizes(sPtr) == 0);
1999-10-27 22:32:12 +00:00
}
2009-08-20 00:59:40 +02:00
void WMAddSplitViewSubview(WMSplitView * sPtr, WMView * subview)
1999-10-27 22:32:12 +00:00
{
2009-08-20 00:59:40 +02:00
int wasMapped, count;
W_SplitViewSubview *p;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
CHECK_CLASS(sPtr, WC_SplitView);
1999-10-27 22:32:12 +00:00
2010-09-23 17:09:46 +02:00
p = (W_SplitViewSubview *) wmalloc(sizeof(W_SplitViewSubview));
if (!p)
2009-08-20 00:59:40 +02:00
return;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
wasMapped = subview->flags.mapped;
if (wasMapped)
W_UnmapView(subview);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
count = _GetSubviewsCount();
p->view = subview;
getConstraints(sPtr, count, &(p->minSize), &(p->maxSize));
if (sPtr->flags.vertical)
p->size = subview->size.width;
else
p->size = subview->size.height;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
WMAddToArray(sPtr->subviews, p);
reparentView(sPtr, subview, 0);
2009-08-20 00:59:40 +02:00
/*
We should have something like that...
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
WMSetViewNotifySizeChanges(subview, True);
WMAddNotificationObserver(handleSubviewResized, sPtr,
WMViewSizeDidChangeNotification,
subview);
WMSetViewNotifyMoveChanges(subview, True);
WMAddNotificationObserver(handleSubviewResized, sPtr,
WMViewMoveDidChangeNotification,
subview);
*/
if (wasMapped) {
W_MapView(subview);
2001-01-02 14:17:26 +00:00
2009-08-20 00:59:40 +02:00
sPtr->flags.adjustOnPaint = 1;
paintSplitView(sPtr);
} else {
handleViewResized(sPtr, NULL);
}
1999-10-27 22:32:12 +00:00
}
2009-08-20 00:59:40 +02:00
WMView *WMGetSplitViewSubviewAt(WMSplitView * sPtr, int index)
1999-10-27 22:32:12 +00:00
{
2009-08-20 00:59:40 +02:00
CHECK_CLASS(sPtr, WC_SplitView);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
if (index >= 0 && index < _GetSubviewsCount())
return (_GetSubviewAt(index));
else
return (NULL);
1999-10-27 22:32:12 +00:00
}
2009-08-20 00:59:40 +02:00
void WMRemoveSplitViewSubview(WMSplitView * sPtr, WMView * view)
1999-10-27 22:32:12 +00:00
{
2009-08-20 00:59:40 +02:00
W_SplitViewSubview *p;
int i, count;
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
CHECK_CLASS(sPtr, WC_SplitView);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
/* TODO: rewrite this. This code with macros is getting more complex than it worths */
count = _GetSubviewsCount();
for (i = 0; i < count; i++) {
p = _GetPSubviewStructAt(i);
if (p->view == view) {
WMDeleteFromArray(sPtr->subviews, i);
sPtr->flags.adjustOnPaint = 1;
paintSplitView(sPtr);
break;
}
}
1999-10-27 22:32:12 +00:00
}
2009-08-20 00:59:40 +02:00
void WMRemoveSplitViewSubviewAt(WMSplitView * sPtr, int index)
1999-10-27 22:32:12 +00:00
{
2009-08-20 00:59:40 +02:00
CHECK_CLASS(sPtr, WC_SplitView);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
/* TODO: same about rewrite */
if (index >= 0 && index < _GetSubviewsCount()) {
WMDeleteFromArray(sPtr->subviews, index);
sPtr->flags.adjustOnPaint = 1;
paintSplitView(sPtr);
}
1999-10-27 22:32:12 +00:00
}
2009-08-20 00:59:40 +02:00
void WMSetSplitViewConstrainProc(WMSplitView * sPtr, WMSplitViewConstrainProc * proc)
1999-10-27 22:32:12 +00:00
{
2009-08-20 00:59:40 +02:00
CHECK_CLASS(sPtr, WC_SplitView);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
sPtr->constrainProc = proc;
1999-10-27 22:32:12 +00:00
}
2009-08-20 00:59:40 +02:00
int WMGetSplitViewSubviewsCount(WMSplitView * sPtr)
1999-10-27 22:32:12 +00:00
{
2009-08-20 00:59:40 +02:00
CHECK_CLASS(sPtr, WC_SplitView);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
return (_GetSubviewsCount());
1999-10-27 22:32:12 +00:00
}
2009-08-20 00:59:40 +02:00
Bool WMGetSplitViewVertical(WMSplitView * sPtr)
1999-10-27 22:32:12 +00:00
{
2009-08-20 00:59:40 +02:00
CHECK_CLASS(sPtr, WC_SplitView);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
return (sPtr->flags.vertical == 1);
1999-10-27 22:32:12 +00:00
}
2009-08-20 00:59:40 +02:00
void WMSetSplitViewVertical(WMSplitView * sPtr, Bool flag)
1999-10-27 22:32:12 +00:00
{
2009-08-20 00:59:40 +02:00
int vertical;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
CHECK_CLASS(sPtr, WC_SplitView);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
vertical = ((flag == 0) ? 0 : 1);
if (sPtr->flags.vertical == vertical)
return;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
sPtr->flags.vertical = vertical;
2004-10-12 21:28:27 +00:00
2009-08-20 00:59:40 +02:00
/* if (sPtr->view->flags.mapped && sPtr->view->flags.realized) */
handleViewResized(sPtr, NULL);
/* else
sPtr->flags.adjustOnPaint = 1;
*/
1999-10-27 22:32:12 +00:00
}
2014-01-31 21:31:26 +01:00
int WMGetSplitViewDividerThickness(WMSplitView *sPtr)
1999-10-27 22:32:12 +00:00
{
2009-08-20 00:59:40 +02:00
CHECK_CLASS(sPtr, WC_SplitView);
1999-10-27 22:32:12 +00:00
2014-01-31 21:31:26 +01:00
(void) sPtr;
2009-08-20 00:59:40 +02:00
return (DIVIDER_THICKNESS);
1999-10-27 22:32:12 +00:00
}
#if 0
2009-08-20 00:59:40 +02:00
void WMSetSplitViewResizeSubviewsProc(WMSplitView * sPtr, WMSplitViewResizeSubviewsProc * proc)
1999-10-27 22:32:12 +00:00
{
2009-08-20 00:59:40 +02:00
CHECK_CLASS(sPtr, WC_SplitView);
1999-10-27 22:32:12 +00:00
2009-08-20 00:59:40 +02:00
sPtr->resizeSubviewsProc = proc;
1999-10-27 22:32:12 +00:00
}
#endif