summaryrefslogtreecommitdiffstats
path: root/generic/tkTreeDisplay.c
diff options
context:
space:
mode:
authortreectrl <treectrl>2006-10-14 19:58:48 (GMT)
committertreectrl <treectrl>2006-10-14 19:58:48 (GMT)
commit778657d12d2f5eb4682e7eb21c48be5154dc90fd (patch)
tree195ec6f7b69f63173a914b4226c8c0e5f108f2e2 /generic/tkTreeDisplay.c
parent68a068f5ba80bcb4519d76981205f585ba9fb6aa (diff)
downloadtktreectrl-778657d12d2f5eb4682e7eb21c48be5154dc90fd.zip
tktreectrl-778657d12d2f5eb4682e7eb21c48be5154dc90fd.tar.gz
tktreectrl-778657d12d2f5eb4682e7eb21c48be5154dc90fd.tar.bz2
Fix Tree_InvalidateItemDInfo not considering column spans.
Added Tree_AreaBbox for getting the bounds of onscreen areas. Renamed TREE_HIT_xxx to TREE_AREA_xxx. Much improvement in displaying locked columns.
Diffstat (limited to 'generic/tkTreeDisplay.c')
-rw-r--r--generic/tkTreeDisplay.c1463
1 files changed, 724 insertions, 739 deletions
diff --git a/generic/tkTreeDisplay.c b/generic/tkTreeDisplay.c
index f59d4fb..da44a5e 100644
--- a/generic/tkTreeDisplay.c
+++ b/generic/tkTreeDisplay.c
@@ -5,7 +5,7 @@
*
* Copyright (c) 2002-2006 Tim Baker
*
- * RCS: @(#) $Id: tkTreeDisplay.c,v 1.42 2006/10/11 01:26:11 treectrl Exp $
+ * RCS: @(#) $Id: tkTreeDisplay.c,v 1.43 2006/10/14 19:58:48 treectrl Exp $
*/
#include "tkTreeCtrl.h"
@@ -46,6 +46,15 @@ struct Range
Range *next;
};
+typedef struct DItemArea {
+ int x; /* Where it should be drawn, window coords. */
+ int width; /* Current width. */
+ int dirty[4]; /* Dirty area in item coords. */
+#define DITEM_DIRTY 0x0001
+#define DITEM_ALL_DIRTY 0x0002
+ int flags;
+} DItemArea;
+
/* Display information for a TreeItem. */
struct DItem
{
@@ -53,21 +62,20 @@ struct DItem
char magic[4];
#endif
TreeItem item;
- int x, y; /* Where it should be drawn, window coords. */
+ int y; /* Where it should be drawn, window coords. */
+ int height; /* Current height. */
+ DItemArea area;
int oldX, oldY; /* Where it was last drawn, window coords. */
- int width, height; /* Current width and height. */
- int dirty[4]; /* Dirty area in item coords. */
Range *range; /* Range the TreeItem is in. */
int index; /* Used for alternating background colors. */
-#define DITEM_DIRTY 0x0001
-#define DITEM_ALL_DIRTY 0x0002
- int flags;
DItem *next;
#ifdef COLUMN_LOCK
- struct {
- int dirty[4];
- int flags;
- } left, right;
+ DItemArea left, right;
+#endif
+#ifdef COLUMN_SPAN
+ int *spans; /* span[n] is the column index of the item
+ * column displayed at the n'th tree column. */
+ int spanAlloc; /* Size of spans[] */
#endif
};
@@ -124,6 +132,7 @@ struct DInfo
DItem *dItemFree; /* List of unused DItems */
int requests; /* Incremented for every call to
Tree_EventuallyRedraw */
+ int bounds[4], empty; /* Bounds of TREE_AREA_CONTENT */
#ifdef ROW_LABEL
int rowLabelWidth; /* Last seen Tree_WidthOfRowLabels */
DRowLabel *dRowLabel; /* Offset and height of each visible row label. */
@@ -131,14 +140,14 @@ struct DInfo
int dRowLabelAlloc; /* Size of dRowLabel[] */
#endif
#ifdef COLUMN_LOCK
+ int boundsL[4], emptyL; /* Bounds of TREE_AREA_LEFT */
+ int boundsR[4], emptyR; /* Bounds of TREE_AREA_RIGHT */
int widthOfColumnsLeft;
int widthOfColumnsRight;
Range *rangeLock; /* If there is no Range for non-locked
* columns, this range holds the vertical
* offset and height of each ReallyVisible
* item for displaying locked columns. */
- int nonLockedDItems; /* TRUE if DItems exist for non-locked
- * columns. */
#endif
};
@@ -884,21 +893,20 @@ Range_UnderPoint(
range = dInfo->rangeFirst;
if (nearest) {
- int visWidth = Tree_ContentWidth(tree);
- int visHeight = Tree_ContentHeight(tree);
+ int minX, minY, maxX, maxY;
- if ((visWidth <= 0) || (visHeight <= 0))
+ if (!Tree_AreaBbox(tree, TREE_AREA_CONTENT, &minX, &minY, &maxX, &maxY))
return NULL;
/* Keep inside borders and header. Perhaps another flag needed. */
- if (x < Tree_ContentLeft(tree))
- x = Tree_ContentLeft(tree);
- if (x >= Tree_ContentRight(tree))
- x = Tree_ContentRight(tree) - 1;
- if (y < Tree_ContentTop(tree))
- y = Tree_ContentTop(tree);
- if (y >= Tree_ContentBottom(tree))
- y = Tree_ContentBottom(tree) - 1;
+ if (x < minX)
+ x = minX;
+ if (x >= maxX)
+ x = maxX - 1;
+ if (y < minY)
+ y = minY;
+ if (y >= maxY)
+ y = maxY - 1;
}
/* Window -> canvas */
@@ -1833,13 +1841,13 @@ Tree_ItemUnderPoint(
int hit;
hit = Tree_HitTest(tree, *x_, *y_);
- if (!nearest && ((hit == TREE_HIT_LEFT) || (hit == TREE_HIT_RIGHT))) {
+ if (!nearest && ((hit == TREE_AREA_LEFT) || (hit == TREE_AREA_RIGHT))) {
DInfo *dInfo = (DInfo *) tree->dInfo;
Range_RedoIfNeeded(tree);
range = dInfo->rangeFirst;
- /* If range is NULL use dInfo->rItemLock */
+ /* If range is NULL use dInfo->rangeLock */
if (range == NULL) {
if (dInfo->rangeLock == NULL)
return NULL;
@@ -1850,7 +1858,7 @@ Tree_ItemUnderPoint(
int x = *x_;
int y = *y_;
- if (hit == TREE_HIT_RIGHT) {
+ if (hit == TREE_AREA_RIGHT) {
x -= Tree_ContentRight(tree);
} else {
x -= Tree_BorderLeft(tree);
@@ -1880,12 +1888,92 @@ Tree_ItemUnderPoint(
/*
*--------------------------------------------------------------
*
+ * Tree_AreaBbox --
+ *
+ * Return the bounding box of a visible area.
+ *
+ * Results:
+ * Return value is TRUE if the area is non-empty.
+ *
+ * Side effects:
+ * Column and item layout will be updated if needed.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tree_AreaBbox(
+ TreeCtrl *tree,
+ int area,
+ int *x1_,
+ int *y1_,
+ int *x2_,
+ int *y2_
+ )
+{
+ int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+
+ switch (area) {
+ case TREE_AREA_HEADER:
+ x1 = Tree_BorderLeft(tree);
+ y1 = Tree_BorderTop(tree);
+ x2 = Tree_BorderRight(tree);
+ y2 = Tree_ContentTop(tree);
+ break;
+ case TREE_AREA_CONTENT:
+ x1 = Tree_ContentLeft(tree);
+ y1 = Tree_ContentTop(tree);
+ x2 = Tree_ContentRight(tree);
+ y2 = Tree_ContentBottom(tree);
+ break;
+#ifdef COLUMN_LOCK
+ case TREE_AREA_LEFT:
+ x1 = Tree_BorderLeft(tree);
+ y1 = Tree_ContentTop(tree);
+ x2 = Tree_ContentLeft(tree);
+ y2 = Tree_ContentBottom(tree);
+ /* Don't overlap right-locked columns. */
+ if (x2 > Tree_ContentRight(tree))
+ x2 = Tree_ContentRight(tree);
+ break;
+ case TREE_AREA_RIGHT:
+ x1 = Tree_ContentRight(tree);
+ y1 = Tree_ContentTop(tree);
+ x2 = Tree_BorderRight(tree);
+ y2 = Tree_ContentBottom(tree);
+ break;
+#endif
+ }
+
+ if (x2 <= x1 || y2 <= y1)
+ return FALSE;
+
+ if (x1 < Tree_BorderLeft(tree))
+ x1 = Tree_BorderLeft(tree);
+ if (x2 > Tree_BorderRight(tree))
+ x2 = Tree_BorderRight(tree);
+
+ if (y1 < Tree_BorderTop(tree))
+ y1 = Tree_BorderTop(tree);
+ if (y2 > Tree_BorderBottom(tree))
+ y2 = Tree_BorderBottom(tree);
+
+ *x1_ = x1;
+ *y1_ = y1;
+ *x2_ = x2;
+ *y2_ = y2;
+ return (x2 > x1) && (y2 > y1);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
* Tree_HitTest --
*
* Determine which are of the window contains the given point.
*
* Results:
- * Return value is one of the TREE_HIT_xxx constants.
+ * Return value is one of the TREE_AREA_xxx constants.
*
* Side effects:
* Column layout will be updated if needed.
@@ -1901,27 +1989,28 @@ Tree_HitTest(
)
{
if ((x < Tree_BorderLeft(tree)) || (x >= Tree_BorderRight(tree)))
- return TREE_HIT_NONE;
+ return TREE_AREA_NONE;
if ((y < Tree_BorderTop(tree)) || (y >= Tree_BorderBottom(tree)))
- return TREE_HIT_NONE;
+ return TREE_AREA_NONE;
#ifdef ROW_LABEL
if (x < Tree_WidthOfRowLabels(tree))
- return TREE_HIT_ROWLABEL;
+ return TREE_AREA_ROWLABEL;
#endif
if (y < tree->inset + Tree_HeaderHeight(tree)) {
- return TREE_HIT_HEADER;
+ return TREE_AREA_HEADER;
}
#ifdef COLUMN_LOCK
+ /* Right-locked columns are drawn over the left. */
+ if (x >= Tree_ContentRight(tree)) {
+ return TREE_AREA_RIGHT;
+ }
if (x < Tree_ContentLeft(tree)) {
- return TREE_HIT_LEFT;
+ return TREE_AREA_LEFT;
}
-
- if (x >= Tree_ContentRight(tree))
- return TREE_HIT_RIGHT;
#endif
- return TREE_HIT_CONTENT;
+ return TREE_AREA_CONTENT;
}
/*
@@ -2524,7 +2613,7 @@ DItem_Alloc(
strncpy(dItem->magic, "MAGC", 4);
#endif
dItem->item = rItem->item;
- dItem->flags = DITEM_DIRTY | DITEM_ALL_DIRTY;
+ dItem->area.flags = DITEM_DIRTY | DITEM_ALL_DIRTY;
#ifdef COLUMN_LOCK
dItem->left.flags = DITEM_DIRTY | DITEM_ALL_DIRTY;
dItem->right.flags = DITEM_DIRTY | DITEM_ALL_DIRTY;
@@ -2772,7 +2861,28 @@ Tree_ItemsInArea(
}
}
-#define DCOLUMN
+#ifdef COLUMN_SPAN
+static void
+UpdateSpansForItem(
+ TreeCtrl *tree, /* Widget info. */
+ DItem *dItem /* Display info for an item. */
+ )
+{
+ int *spans = dItem->spans;
+
+ if (spans == NULL) {
+ spans = (int *) ckalloc(sizeof(int) * tree->columnCount);
+ dItem->spanAlloc = tree->columnCount;
+ } else if (dItem->spanAlloc < tree->columnCount) {
+ spans = (int *) ckrealloc((char *) spans, sizeof(int) * tree->columnCount);
+ dItem->spanAlloc = tree->columnCount;
+ }
+ TreeItem_GetSpans(tree, dItem->item, spans);
+ dItem->spans = spans;
+}
+#endif
+
+#define DCOLUMNxxx
#ifdef DCOLUMN
static void
UpdateDColumnsForItem(
@@ -2783,7 +2893,7 @@ UpdateDColumnsForItem(
DInfo *dInfo = (DInfo *) tree->dInfo;
int minX, maxX, columnIndex, x = 0;
TreeColumn column, first = NULL, last = NULL;
-return;
+
minX = MAX(dItem->x, Tree_ContentLeft(tree));
maxX = MIN(dItem->x + dItem->width, Tree_ContentRight(tree));
@@ -2841,6 +2951,7 @@ UpdateDInfoForRange(
{
DInfo *dInfo = (DInfo *) tree->dInfo;
DItem *dItem;
+ DItemArea *area;
TreeItem item;
int maxX, maxY;
int index, indexVis;
@@ -2872,35 +2983,36 @@ UpdateDInfoForRange(
}
dItem = (DItem *) TreeItem_GetDInfo(tree, item);
+ area = &dItem->area;
/* Re-use a previously allocated DItem */
if (dItem != NULL) {
dItemHead = DItem_Unlink(dItemHead, dItem);
/* This item is already marked for total redraw */
- if (dItem->flags & DITEM_ALL_DIRTY)
+ if (area->flags & DITEM_ALL_DIRTY)
; /* nothing */
/* All display info is marked as invalid */
else if (dInfo->flags & DINFO_INVALIDATE)
- dItem->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
/* The range may have changed size */
- else if ((dItem->width != range->totalWidth) ||
+ else if ((area->width != range->totalWidth) ||
(dItem->height != rItem->size))
- dItem->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
/* Items may have alternating background colors. */
else if ((tree->columnBgCnt > 1) &&
((index % tree->columnBgCnt) !=
(dItem->index % tree->columnBgCnt)))
- dItem->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
/* We don't copy items horizontally to their new position,
* except for horizontal scrolling which moves the whole
* range */
else if (x != dItem->oldX + (dInfo->xOrigin - tree->xOrigin))
- dItem->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
/* If we are displaying dotted lines and the item has moved
* from odd-top to non-odd-top or vice versa, must redraw
@@ -2909,35 +3021,39 @@ UpdateDInfoForRange(
(tree->lineStyle == LINE_STYLE_DOT) &&
tree->columnTreeVis &&
((dItem->oldY & 1) != (y & 1)))
- dItem->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
/* We can't copy the item to its new position unless it
* has the same part of the background image behind it */
else if ((tree->backgroundImage != NULL) &&
(((dItem->oldY + dInfo->yOrigin) % bgImgHeight) !=
((y + tree->yOrigin) % bgImgHeight)))
- dItem->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
}
/* Make a new DItem */
else {
dItem = DItem_Alloc(tree, rItem);
+ area = &dItem->area;
}
- dItem->x = x;
+ area->x = x;
dItem->y = y;
- dItem->width = Range_TotalWidth(tree, range);
+ area->width = Range_TotalWidth(tree, range);
dItem->height = rItem->size;
dItem->range = range;
dItem->index = index;
+#ifdef COLUMN_SPAN
+ UpdateSpansForItem(tree, dItem);
+#endif
#ifdef DCOLUMN
UpdateDColumnsForItem(tree, dItem);
#endif
/* Keep track of the maximum item size */
- if (dItem->width > dInfo->itemWidth)
- dInfo->itemWidth = dItem->width;
+ if (area->width > dInfo->itemWidth)
+ dInfo->itemWidth = area->width;
if (dItem->height > dInfo->itemHeight)
dInfo->itemHeight = dItem->height;
@@ -2981,33 +3097,34 @@ UpdateDInfoForRange(
}
dItem = (DItem *) TreeItem_GetDInfo(tree, item);
+ area = &dItem->area;
/* Re-use a previously allocated DItem */
if (dItem != NULL) {
dItemHead = DItem_Unlink(dItemHead, dItem);
/* This item is already marked for total redraw */
- if (dItem->flags & DITEM_ALL_DIRTY)
+ if (area->flags & DITEM_ALL_DIRTY)
; /* nothing */
/* All display info is marked as invalid */
else if (dInfo->flags & DINFO_INVALIDATE)
- dItem->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
/* The range may have changed size */
- else if ((dItem->width != rItem->size) ||
+ else if ((area->width != rItem->size) ||
(dItem->height != range->totalHeight))
- dItem->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
/* Items may have alternating background colors. */
else if ((tree->columnBgCnt > 1) && ((index % tree->columnBgCnt) !=
(dItem->index % tree->columnBgCnt)))
- dItem->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
/* We don't copy items vertically to their new position,
* except for vertical scrolling which moves the whole range */
else if (y != dItem->oldY + (dInfo->yOrigin - tree->yOrigin))
- dItem->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
/* If we are displaying dotted lines and the item has moved
* from odd-top to non-odd-top or vice versa, must redraw
@@ -3016,35 +3133,39 @@ UpdateDInfoForRange(
(tree->lineStyle == LINE_STYLE_DOT) &&
tree->columnTreeVis &&
((dItem->oldY & 1) != (y & 1)))
- dItem->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
/* We can't copy the item to its new position unless it
* has the same part of the background image behind it */
else if ((tree->backgroundImage != NULL) &&
(((dItem->oldX + dInfo->xOrigin) % bgImgWidth) !=
((x + tree->xOrigin) % bgImgWidth)))
- dItem->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
}
/* Make a new DItem */
else {
dItem = DItem_Alloc(tree, rItem);
+ area = &dItem->area;
}
- dItem->x = x;
+ area->x = x;
dItem->y = y;
- dItem->width = rItem->size;
+ area->width = rItem->size;
dItem->height = Range_TotalHeight(tree, range);
dItem->range = range;
dItem->index = index;
+#ifdef COLUMN_SPAN
+ UpdateSpansForItem(tree, dItem);
+#endif
#ifdef DCOLUMN
UpdateDColumnsForItem(tree, dItem);
#endif
/* Keep track of the maximum item size */
- if (dItem->width > dInfo->itemWidth)
- dInfo->itemWidth = dItem->width;
+ if (area->width > dInfo->itemWidth)
+ dInfo->itemWidth = area->width;
if (dItem->height > dInfo->itemHeight)
dInfo->itemHeight = dItem->height;
@@ -3062,7 +3183,7 @@ UpdateDInfoForRange(
rItem++;
/* Stop when out of bounds */
- x += dItem->width;
+ x += area->width;
if (x >= maxX)
break;
}
@@ -3111,14 +3232,25 @@ Tree_UpdateDInfo(
dInfo->rangeFirstD = dInfo->rangeLastD = NULL;
dInfo->itemWidth = dInfo->itemHeight = 0;
- minX = Tree_ContentLeft(tree);
- minY = Tree_ContentTop(tree);
- maxX = Tree_ContentRight(tree);
- maxY = Tree_ContentBottom(tree);
-
- if ((maxX - minX < 1) || (maxY - minY < 1))
+ dInfo->empty = !Tree_AreaBbox(tree, TREE_AREA_CONTENT,
+ &dInfo->bounds[0], &dInfo->bounds[1],
+ &dInfo->bounds[2], &dInfo->bounds[3]);
+#ifdef COLUMN_LOCK
+ dInfo->emptyL = !Tree_AreaBbox(tree, TREE_AREA_LEFT,
+ &dInfo->boundsL[0], &dInfo->boundsL[1],
+ &dInfo->boundsL[2], &dInfo->boundsL[3]);
+ dInfo->emptyR = !Tree_AreaBbox(tree, TREE_AREA_RIGHT,
+ &dInfo->boundsR[0], &dInfo->boundsR[1],
+ &dInfo->boundsR[2], &dInfo->boundsR[3]);
+#endif
+ if (dInfo->empty)
goto done;
+ minX = dInfo->bounds[0];
+ minY = dInfo->bounds[1];
+ maxX = dInfo->bounds[2];
+ maxY = dInfo->bounds[3];
+
range = dInfo->rangeFirst;
if (tree->vertical) {
/* Find the first range which could be onscreen horizontally.
@@ -3193,24 +3325,17 @@ Tree_UpdateDInfo(
done:
#ifdef COLUMN_LOCK
- /* This variable tells us whether the list of DItems is valid for
- * the non-locked columns. */
- dInfo->nonLockedDItems = dInfo->dItem != NULL;
-
- if (dInfo->nonLockedDItems)
+ if (dInfo->dItem != NULL)
goto skipLock;
if (!tree->itemVisCount)
goto skipLock;
- if (Tk_Width(tree->tkwin) - tree->inset * 2 <= 0)
- goto skipLock;
- if (maxY - minY <= 0)
+ if (dInfo->emptyL && dInfo->emptyR)
goto skipLock;
range = dInfo->rangeFirst;
if ((range != NULL) && !range->totalHeight)
goto skipLock;
- if (Tree_WidthOfLeftColumns(tree) || Tree_WidthOfRightColumns(tree)) {
-
- int y = minY + tree->yOrigin; /* Window -> Canvas */
+ {
+ int y = Tree_ContentTop(tree) + tree->yOrigin; /* Window -> Canvas */
int index, indexVis;
/* If no non-locked columns are displayed, we have no Range and
@@ -3226,7 +3351,6 @@ done:
y -= tree->yOrigin; /* Canvas -> Window */
while (1) {
-
DItem *dItem = (DItem *) TreeItem_GetDInfo(tree, rItem->item);
/* Re-use a previously allocated DItem */
@@ -3251,6 +3375,10 @@ done:
dItem->height = rItem->size;
dItem->index = index;
+#ifdef COLUMN_SPAN
+ UpdateSpansForItem(tree, dItem);
+#endif
+
/* Keep track of the maximum item size */
if (dItem->height > dInfo->itemHeight)
dInfo->itemHeight = dItem->height;
@@ -3265,57 +3393,73 @@ done:
if (rItem == range->last)
break;
y += rItem->size;
- if (y >= maxY)
+ if (y >= Tree_ContentBottom(tree))
break;
rItem++;
}
}
skipLock:
- if (dInfo->widthOfColumnsLeft || dInfo->widthOfColumnsRight) {
+ if (!dInfo->emptyL || !dInfo->emptyR) {
int bgImgWidth, bgImgHeight;
+ DItemArea *area;
+
+ if (!dInfo->emptyL) {
+ /* Keep track of the maximum item size */
+ if (dInfo->widthOfColumnsLeft > dInfo->itemWidth)
+ dInfo->itemWidth = dInfo->widthOfColumnsLeft;
+ }
+ if (!dInfo->emptyR) {
+ /* Keep track of the maximum item size */
+ if (dInfo->widthOfColumnsRight > dInfo->itemWidth)
+ dInfo->itemWidth = dInfo->widthOfColumnsRight;
+ }
if (tree->backgroundImage != NULL)
Tk_SizeOfImage(tree->backgroundImage, &bgImgWidth, &bgImgHeight);
for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) {
- if (dInfo->widthOfColumnsLeft &&
- !(dItem->left.flags & DITEM_ALL_DIRTY)) {
- /* All display info is marked as invalid */
- if (dInfo->flags & DINFO_INVALIDATE) {
- dItem->left.flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ if (!dInfo->emptyL) {
- /* FIXME: This redraws everything when scrolling */
- } else if (dItem->y != dItem->oldY) {
- dItem->left.flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ area = &dItem->left;
+ area->x = Tree_BorderLeft(tree);
+ area->width = dInfo->widthOfColumnsLeft;
- /* We can't copy the item to its new position unless it
- * has the same part of the background image behind it */
- } else if ((tree->backgroundImage != NULL) &&
- ((dInfo->xOrigin % bgImgWidth) !=
- (tree->xOrigin % bgImgWidth))) {
- dItem->left.flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ if (!(area->flags & DITEM_ALL_DIRTY)) {
+
+ /* All display info is marked as invalid */
+ if (dInfo->flags & DINFO_INVALIDATE) {
+ area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+
+ /* We can't copy the item to its new position unless it
+ * has the same part of the background image behind it */
+ } else if ((tree->backgroundImage != NULL) &&
+ ((dInfo->xOrigin % bgImgWidth) !=
+ (tree->xOrigin % bgImgWidth))) {
+ area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ }
}
}
- if (dInfo->widthOfColumnsRight &&
- !(dItem->right.flags & DITEM_ALL_DIRTY)) {
- x = Tree_ContentRight(tree);
+ if (!dInfo->emptyR) {
- /* All display info is marked as invalid */
- if (dInfo->flags & DINFO_INVALIDATE) {
- dItem->right.flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ area = &dItem->right;
+ area->x = Tree_ContentRight(tree);
+ area->width = dInfo->widthOfColumnsRight;
- /* FIXME: This redraws everything when scrolling */
- } else if (dItem->y != dItem->oldY) {
- dItem->right.flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ if (!(area->flags & DITEM_ALL_DIRTY)) {
- /* We can't copy the item to its new position unless it
- * has the same part of the background image behind it */
- } else if ((tree->backgroundImage != NULL) &&
- ((dInfo->xOrigin % bgImgWidth) !=
- (tree->xOrigin % bgImgWidth))) {
- dItem->right.flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ /* All display info is marked as invalid */
+ if (dInfo->flags & DINFO_INVALIDATE) {
+ area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+
+ /* We can't copy the item to its new position unless it
+ * has the same part of the background image behind it */
+ } else if ((tree->backgroundImage != NULL) &&
+ ((dInfo->xOrigin % bgImgWidth) !=
+ (tree->xOrigin % bgImgWidth))) {
+ area->flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ }
}
}
}
@@ -3328,65 +3472,6 @@ skipLock:
dInfo->flags &= ~DINFO_INVALIDATE;
}
-#ifdef COLUMN_LOCK
-static void
-InvalidateDItemX2(
- int dirty[4], /* Item to mark dirty. */
- int flags,
- int itemX, /* x-coordinate of item. */
- int itemWidth,
- int dirtyX, /* Left edge of area to mark as dirty. */
- int dirtyWidth /* Width of area to mark as dirty. */
- )
-{
- int x1, x2;
-
- if (dirtyX <= itemX)
- dirty[LEFT] = 0;
- else {
- x1 = dirtyX - itemX;
- if (!(flags & DITEM_DIRTY) || (x1 < dirty[LEFT]))
- dirty[LEFT] = x1;
- }
-
- if (dirtyX + dirtyWidth >= itemX + itemWidth)
- dirty[RIGHT] = itemWidth;
- else {
- x2 = dirtyX + dirtyWidth - itemX;
- if (!(flags & DITEM_DIRTY) || (x2 > dirty[RIGHT]))
- dirty[RIGHT] = x2;
- }
-}
-static void
-InvalidateDItemY2(
- int dirty[4], /* Item to mark dirty. */
- int flags,
- int itemY, /* y-coordinate of item. */
- int itemHeight,
- int dirtyY, /* Top edge of area to mark as dirty. */
- int dirtyHeight /* Height of area to mark as dirty. */
- )
-{
- int y1, y2;
-
- if (dirtyY <= itemY)
- dirty[TOP] = 0;
- else {
- y1 = dirtyY - itemY;
- if (!(flags & DITEM_DIRTY) || (y1 < dirty[TOP]))
- dirty[TOP] = y1;
- }
-
- if (dirtyY + dirtyHeight >= itemY + itemHeight)
- dirty[BOTTOM] = itemHeight;
- else {
- y2 = dirtyY + dirtyHeight - itemY;
- if (!(flags & DITEM_DIRTY) || (y2 > dirty[BOTTOM]))
- dirty[BOTTOM] = y2;
- }
-}
-#endif /* COLUMN_LOCK */
-
/*
*--------------------------------------------------------------
*
@@ -3407,6 +3492,7 @@ InvalidateDItemY2(
static void
InvalidateDItemX(
DItem *dItem, /* Item to mark dirty. */
+ DItemArea *area,
int itemX, /* x-coordinate of item. */
int dirtyX, /* Left edge of area to mark as dirty. */
int dirtyWidth /* Width of area to mark as dirty. */
@@ -3415,19 +3501,19 @@ InvalidateDItemX(
int x1, x2;
if (dirtyX <= itemX)
- dItem->dirty[LEFT] = 0;
+ area->dirty[LEFT] = 0;
else {
x1 = dirtyX - itemX;
- if (!(dItem->flags & DITEM_DIRTY) || (x1 < dItem->dirty[LEFT]))
- dItem->dirty[LEFT] = x1;
+ if (!(area->flags & DITEM_DIRTY) || (x1 < area->dirty[LEFT]))
+ area->dirty[LEFT] = x1;
}
- if (dirtyX + dirtyWidth >= itemX + dItem->width)
- dItem->dirty[RIGHT] = dItem->width;
+ if (dirtyX + dirtyWidth >= itemX + area->width)
+ area->dirty[RIGHT] = area->width;
else {
x2 = dirtyX + dirtyWidth - itemX;
- if (!(dItem->flags & DITEM_DIRTY) || (x2 > dItem->dirty[RIGHT]))
- dItem->dirty[RIGHT] = x2;
+ if (!(area->flags & DITEM_DIRTY) || (x2 > area->dirty[RIGHT]))
+ area->dirty[RIGHT] = x2;
}
}
@@ -3451,6 +3537,7 @@ InvalidateDItemX(
static void
InvalidateDItemY(
DItem *dItem, /* Item to mark dirty. */
+ DItemArea *area,
int itemY, /* y-coordinate of item. */
int dirtyY, /* Top edge of area to mark as dirty. */
int dirtyHeight /* Height of area to mark as dirty. */
@@ -3459,19 +3546,19 @@ InvalidateDItemY(
int y1, y2;
if (dirtyY <= itemY)
- dItem->dirty[TOP] = 0;
+ area->dirty[TOP] = 0;
else {
y1 = dirtyY - itemY;
- if (!(dItem->flags & DITEM_DIRTY) || (y1 < dItem->dirty[TOP]))
- dItem->dirty[TOP] = y1;
+ if (!(area->flags & DITEM_DIRTY) || (y1 < area->dirty[TOP]))
+ area->dirty[TOP] = y1;
}
if (dirtyY + dirtyHeight >= itemY + dItem->height)
- dItem->dirty[BOTTOM] = dItem->height;
+ area->dirty[BOTTOM] = dItem->height;
else {
y2 = dirtyY + dirtyHeight - itemY;
- if (!(dItem->flags & DITEM_DIRTY) || (y2 > dItem->dirty[BOTTOM]))
- dItem->dirty[BOTTOM] = y2;
+ if (!(area->flags & DITEM_DIRTY) || (y2 > area->dirty[BOTTOM]))
+ area->dirty[BOTTOM] = y2;
}
}
@@ -3514,6 +3601,26 @@ Range_RedoIfNeeded(
}
}
+static int
+DItemAllDirty(
+ TreeCtrl *tree,
+ DItem *dItem
+ )
+{
+ DInfo *dInfo = (DInfo *) tree->dInfo;
+
+#ifdef COLUMN_LOCK
+ if ((!dInfo->empty && !(dItem->area.flags & DITEM_ALL_DIRTY)) ||
+ (!dInfo->emptyL && !(dItem->left.flags & DITEM_ALL_DIRTY)) ||
+ (!dInfo->emptyR && !(dItem->right.flags & DITEM_ALL_DIRTY)))
+ return 0;
+#else
+ if (!dInfo->empty && !(dItem->area.flags & DITEM_ALL_DIRTY))
+ return 0;
+#endif
+ return 1;
+}
+
/*
*--------------------------------------------------------------
*
@@ -3548,14 +3655,15 @@ ScrollVerticalComplex(
int numCopy = 0;
#ifdef COLUMN_LOCK
- /* Have DItems but only for locked columns. */
- if (!dInfo->nonLockedDItems)
+ if (dInfo->empty && dInfo->emptyL && dInfo->emptyR)
+ return 0;
+#else
+ if (dInfo->empty)
return 0;
#endif
-
- minX = Tree_ContentLeft(tree);
+ minX = Tree_BorderLeft(tree);
minY = Tree_ContentTop(tree);
- maxX = Tree_ContentRight(tree);
+ maxX = Tree_BorderRight(tree);
maxY = Tree_ContentBottom(tree);
/* Try updating the display by copying items on the screen to their
@@ -3566,7 +3674,7 @@ ScrollVerticalComplex(
/* Copy an item to its new location unless:
* (a) item display info is invalid
* (b) item is in same location as last draw */
- if ((dItem->flags & DITEM_ALL_DIRTY) ||
+ if (DItemAllDirty(tree, dItem) ||
(dItem->oldY == dItem->y))
continue;
@@ -3582,7 +3690,7 @@ ScrollVerticalComplex(
dItem2 != NULL;
dItem2 = dItem2->next) {
if ((dItem2->range != range) ||
- (dItem2->flags & DITEM_ALL_DIRTY) ||
+ DItemAllDirty(tree, dItem2) ||
(dItem2->oldY + offset != dItem2->y))
break;
numCopy++;
@@ -3608,8 +3716,18 @@ ScrollVerticalComplex(
if (oldY + offset + height > maxY)
height = maxY - (oldY + offset);
+#ifdef COLUMN_LOCK
+ if (!dInfo->emptyL || !dInfo->emptyR) {
+ oldX = minX;
+ width = maxX - minX;
+ } else {
+ oldX = dItem->oldX;
+ width = dItem->area.width;
+ }
+#else
oldX = dItem->oldX;
- width = dItem->width;
+ width = dItem->area.width;
+#endif
if (oldX < minX) {
width -= minX - oldX;
oldX = minX;
@@ -3621,16 +3739,43 @@ ScrollVerticalComplex(
while (1) {
/* If an item was partially visible, invalidate the exposed area */
if ((dItem->oldY < minY) && (offset > 0)) {
- InvalidateDItemX(dItem, oldX, oldX, width);
- InvalidateDItemY(dItem, dItem->oldY, dItem->oldY, minY - dItem->oldY);
- dItem->flags |= DITEM_DIRTY;
+ if (!dInfo->empty) {
+ InvalidateDItemX(dItem, &dItem->area, oldX, oldX, width);
+ InvalidateDItemY(dItem, &dItem->area, dItem->oldY, dItem->oldY, minY - dItem->oldY);
+ dItem->area.flags |= DITEM_DIRTY;
+ }
+#ifdef COLUMN_LOCK
+ if (!dInfo->emptyL) {
+ InvalidateDItemX(dItem, &dItem->left, oldX, oldX, width);
+ InvalidateDItemY(dItem, &dItem->left, dItem->oldY, dItem->oldY, minY - dItem->oldY);
+ dItem->left.flags |= DITEM_DIRTY;
+ }
+ if (!dInfo->emptyR) {
+ InvalidateDItemX(dItem, &dItem->right, oldX, oldX, width);
+ InvalidateDItemY(dItem, &dItem->right, dItem->oldY, dItem->oldY, minY - dItem->oldY);
+ dItem->right.flags |= DITEM_DIRTY;
+ }
+#endif
}
if ((dItem->oldY + dItem->height > maxY) && (offset < 0)) {
- InvalidateDItemX(dItem, oldX, oldX, width);
- InvalidateDItemY(dItem, dItem->oldY, maxY, maxY - dItem->oldY + dItem->height);
- dItem->flags |= DITEM_DIRTY;
+ if (!dInfo->empty) {
+ InvalidateDItemX(dItem, &dItem->area, oldX, oldX, width);
+ InvalidateDItemY(dItem, &dItem->area, dItem->oldY, maxY, maxY - dItem->oldY + dItem->height);
+ dItem->area.flags |= DITEM_DIRTY;
+ }
+#ifdef COLUMN_LOCK
+ if (!dInfo->emptyL) {
+ InvalidateDItemX(dItem, &dItem->left, oldX, oldX, width);
+ InvalidateDItemY(dItem, &dItem->left, dItem->oldY, maxY, maxY - dItem->oldY + dItem->height);
+ dItem->left.flags |= DITEM_DIRTY;
+ }
+ if (!dInfo->emptyR) {
+ InvalidateDItemX(dItem, &dItem->right, oldX, oldX, width);
+ InvalidateDItemY(dItem, &dItem->right, dItem->oldY, maxY, maxY - dItem->oldY + dItem->height);
+ dItem->right.flags |= DITEM_DIRTY;
+ }
+#endif
}
-
dItem->oldY = dItem->y;
if (dItem->next == dItem2)
break;
@@ -3641,12 +3786,26 @@ ScrollVerticalComplex(
for ( ; dItem2 != NULL; dItem2 = dItem2->next) {
if (dItem2->range != range)
break;
- if (!(dItem2->flags & DITEM_ALL_DIRTY) &&
+ if (!DItemAllDirty(tree, dItem2) &&
(dItem2->oldY + dItem2->height > y) &&
(dItem2->oldY < y + height)) {
- InvalidateDItemX(dItem2, oldX, oldX, width);
- InvalidateDItemY(dItem2, dItem2->oldY, y, height);
- dItem2->flags |= DITEM_DIRTY;
+ if (!dInfo->empty) {
+ InvalidateDItemX(dItem2, &dItem2->area, oldX, oldX, width);
+ InvalidateDItemY(dItem2, &dItem2->area, dItem2->oldY, y, height);
+ dItem2->area.flags |= DITEM_DIRTY;
+ }
+#ifdef COLUMN_LOCK
+ if (!dInfo->emptyL) {
+ InvalidateDItemX(dItem2, &dItem2->left, oldX, oldX, width);
+ InvalidateDItemY(dItem2, &dItem2->left, dItem2->oldY, y, height);
+ dItem2->left.flags |= DITEM_DIRTY;
+ }
+ if (!dInfo->emptyR) {
+ InvalidateDItemX(dItem2, &dItem2->right, oldX, oldX, width);
+ InvalidateDItemY(dItem2, &dItem2->right, dItem2->oldY, y, height);
+ dItem2->right.flags |= DITEM_DIRTY;
+ }
+#endif
}
}
@@ -3708,43 +3867,47 @@ ScrollHorizontalSimple(
{
DInfo *dInfo = (DInfo *) tree->dInfo;
DItem *dItem;
- TkRegion rgn, damageRgn;
- XRectangle rect;
+ TkRegion damageRgn;
int minX, minY, maxX, maxY;
int width, offset;
int x, y;
int dirtyMin, dirtyMax;
-#ifdef COLUMN_LOCK
- /* Have DItems but only for locked columns. */
- if (!dInfo->nonLockedDItems)
+ if (dInfo->xOrigin == tree->xOrigin)
return;
-#endif
- if (dInfo->xOrigin == tree->xOrigin)
+ if (dInfo->empty)
return;
+ minX = dInfo->bounds[0];
+ minY = dInfo->bounds[1];
+ maxX = dInfo->bounds[2];
+ maxY = dInfo->bounds[3];
/* Update oldX */
for (dItem = dInfo->dItem;
dItem != NULL;
dItem = dItem->next) {
- dItem->oldX = dItem->x;
+ dItem->oldX = dItem->area.x;
}
- minX = Tree_ContentLeft(tree);
- minY = Tree_ContentTop(tree);
- maxX = Tree_ContentRight(tree);
- maxY = Tree_ContentBottom(tree);
-
offset = dInfo->xOrigin - tree->xOrigin;
+ /* We only scroll the content, not the whitespace */
+ y = 0 - tree->yOrigin + Tree_TotalHeight(tree);
+ if (y < maxY)
+ maxY = y;
+
/* Simplify if a whole screen was scrolled. */
if (abs(offset) >= maxX - minX) {
- TkSubtractRegion(dInfo->wsRgn, dInfo->wsRgn, dInfo->wsRgn);
Tree_InvalidateArea(tree, minX, minY, maxX, maxY);
return;
}
+ /* We only scroll the content, not the whitespace */
+ x = 0 - tree->xOrigin + Tree_TotalWidth(tree);
+ if (x < maxX)
+ maxX = x;
+
width = maxX - minX - abs(offset);
/* Move pixels right */
@@ -3761,22 +3924,6 @@ ScrollHorizontalSimple(
damageRgn = TkCreateRegion();
- /* Offset and clip the whitespace region */
- Tk_OffsetRegion(dInfo->wsRgn, offset, 0);
- rgn = TkCreateRegion();
- rect.x = minX;
- rect.y = minY;
- rect.width = maxX - minX;
- rect.height = maxY - minY;
- TkUnionRectWithRegion(&rect, rgn, damageRgn);
- TkIntersectRegion(dInfo->wsRgn, damageRgn, dInfo->wsRgn);
- TkDestroyRegion(rgn);
-
- /* We only scroll the content, not the whitespace */
- y = 0 - tree->yOrigin + Tree_TotalHeight(tree);
- if (y < maxY)
- maxY = y;
-
if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) {
XCopyArea(tree->display, dInfo->pixmap, dInfo->pixmap,
tree->copyGC,
@@ -3832,19 +3979,12 @@ ScrollVerticalSimple(
{
DInfo *dInfo = (DInfo *) tree->dInfo;
DItem *dItem;
- TkRegion rgn, damageRgn;
- XRectangle rect;
+ TkRegion damageRgn;
int minX, minY, maxX, maxY;
int height, offset;
int x, y;
int dirtyMin, dirtyMax;
-#ifdef COLUMN_LOCK
- /* Have DItems but only for locked columns. */
- if (!dInfo->nonLockedDItems)
- return;
-#endif
-
if (dInfo->yOrigin == tree->yOrigin)
return;
@@ -3855,16 +3995,18 @@ ScrollVerticalSimple(
dItem->oldY = dItem->y;
}
- minX = Tree_ContentLeft(tree);
- minY = Tree_ContentTop(tree);
- maxX = Tree_ContentRight(tree);
- maxY = Tree_ContentBottom(tree);
+ if (!Tree_AreaBbox(tree, TREE_AREA_CONTENT, &minX, &minY, &maxX, &maxY))
+ return;
offset = dInfo->yOrigin - tree->yOrigin;
+ /* We only scroll the content, not the whitespace */
+ x = 0 - tree->xOrigin + Tree_TotalWidth(tree);
+ if (x < maxX)
+ maxX = x;
+
/* Simplify if a whole screen was scrolled. */
if (abs(offset) > maxY - minY) {
- TkSubtractRegion(dInfo->wsRgn, dInfo->wsRgn, dInfo->wsRgn);
Tree_InvalidateArea(tree, minX, minY, maxX, maxY);
return;
}
@@ -3885,22 +4027,6 @@ ScrollVerticalSimple(
damageRgn = TkCreateRegion();
- /* Offset and clip the whitespace region */
- Tk_OffsetRegion(dInfo->wsRgn, 0, offset);
- rgn = TkCreateRegion();
- rect.x = minX;
- rect.y = minY;
- rect.width = maxX - minX;
- rect.height = maxY - minY;
- TkUnionRectWithRegion(&rect, rgn, damageRgn);
- TkIntersectRegion(dInfo->wsRgn, damageRgn, dInfo->wsRgn);
- TkDestroyRegion(rgn);
-
- /* We only scroll the content, not the whitespace */
- x = 0 - tree->xOrigin + Tree_TotalWidth(tree);
- if (x < maxX)
- maxX = x;
-
if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) {
XCopyArea(tree->display, dInfo->pixmap, dInfo->pixmap,
tree->copyGC,
@@ -3964,16 +4090,8 @@ ScrollHorizontalComplex(
int x;
int numCopy = 0;
-#ifdef COLUMN_LOCK
- /* Have DItems but only for locked columns. */
- if (!dInfo->nonLockedDItems)
+ if (!Tree_AreaBbox(tree, TREE_AREA_CONTENT, &minX, &minY, &maxX, &maxY))
return 0;
-#endif
-
- minX = Tree_ContentLeft(tree);
- minY = Tree_ContentTop(tree);
- maxX = Tree_ContentRight(tree);
- maxY = Tree_ContentBottom(tree);
/* Try updating the display by copying items on the screen to their
* new location */
@@ -3983,8 +4101,8 @@ ScrollHorizontalComplex(
/* Copy an item to its new location unless:
* (a) item display info is invalid
* (b) item is in same location as last draw */
- if ((dItem->flags & DITEM_ALL_DIRTY) ||
- (dItem->oldX == dItem->x))
+ if ((dItem->area.flags & DITEM_ALL_DIRTY) ||
+ (dItem->oldX == dItem->area.x))
continue;
numCopy++;
@@ -3993,20 +4111,20 @@ ScrollHorizontalComplex(
/* This item was previously displayed so it only needs to be
* copied to the new location. Copy all such items as one */
- offset = dItem->x - dItem->oldX;
- width = dItem->width;
+ offset = dItem->area.x - dItem->oldX;
+ width = dItem->area.width;
for (dItem2 = dItem->next;
dItem2 != NULL;
dItem2 = dItem2->next) {
if ((dItem2->range != range) ||
- (dItem2->flags & DITEM_ALL_DIRTY) ||
- (dItem2->oldX + offset != dItem2->x))
+ (dItem2->area.flags & DITEM_ALL_DIRTY) ||
+ (dItem2->oldX + offset != dItem2->area.x))
break;
numCopy++;
- width += dItem2->width;
+ width += dItem2->area.width;
}
- x = dItem->x;
+ x = dItem->area.x;
oldX = dItem->oldX;
/* Don't copy part of the window border */
@@ -4038,17 +4156,16 @@ ScrollHorizontalComplex(
while (1) {
/* If an item was partially visible, invalidate the exposed area */
if ((dItem->oldX < minX) && (offset > 0)) {
- InvalidateDItemX(dItem, dItem->oldX, dItem->oldX, minX - dItem->oldX);
- InvalidateDItemY(dItem, oldY, oldY, height);
- dItem->flags |= DITEM_DIRTY;
+ InvalidateDItemX(dItem, &dItem->area, dItem->oldX, dItem->oldX, minX - dItem->oldX);
+ InvalidateDItemY(dItem, &dItem->area, oldY, oldY, height);
+ dItem->area.flags |= DITEM_DIRTY;
}
- if ((dItem->oldX + dItem->width > maxX) && (offset < 0)) {
- InvalidateDItemX(dItem, dItem->oldX, maxX, maxX - dItem->oldX + dItem->width);
- InvalidateDItemY(dItem, oldY, oldY, height);
- dItem->flags |= DITEM_DIRTY;
+ if ((dItem->oldX + dItem->area.width > maxX) && (offset < 0)) {
+ InvalidateDItemX(dItem, &dItem->area, dItem->oldX, maxX, maxX - dItem->oldX + dItem->area.width);
+ InvalidateDItemY(dItem, &dItem->area, oldY, oldY, height);
+ dItem->area.flags |= DITEM_DIRTY;
}
-
- dItem->oldX = dItem->x;
+ dItem->oldX = dItem->area.x;
if (dItem->next == dItem2)
break;
dItem = dItem->next;
@@ -4058,12 +4175,12 @@ ScrollHorizontalComplex(
for ( ; dItem2 != NULL; dItem2 = dItem2->next) {
if (dItem2->range != range)
break;
- if (!(dItem2->flags & DITEM_ALL_DIRTY) &&
- (dItem2->oldX + dItem2->width > x) &&
+ if (!(dItem2->area.flags & DITEM_ALL_DIRTY) &&
+ (dItem2->oldX + dItem2->area.width > x) &&
(dItem2->oldX < x + width)) {
- InvalidateDItemX(dItem2, dItem2->oldX, x, width);
- InvalidateDItemY(dItem2, oldY, oldY, height);
- dItem2->flags |= DITEM_DIRTY;
+ InvalidateDItemX(dItem2, &dItem2->area, dItem2->oldX, x, width);
+ InvalidateDItemY(dItem2, &dItem2->area, oldY, oldY, height);
+ dItem2->area.flags |= DITEM_DIRTY;
}
}
@@ -4308,19 +4425,53 @@ CalcWhiteSpaceRegion(
x = 0 - tree->xOrigin;
y = 0 - tree->yOrigin;
- minX = Tree_ContentLeft(tree);
- minY = Tree_ContentTop(tree);
- maxX = Tree_ContentRight(tree);
- maxY = Tree_ContentBottom(tree);
-
wsRgn = TkCreateRegion();
+#ifdef COLUMN_LOCK
+ /* Erase area below left columns */
+ if (!dInfo->emptyL) {
+ minX = dInfo->boundsL[0];
+ minY = dInfo->boundsL[1];
+ maxX = dInfo->boundsL[2];
+ maxY = dInfo->boundsL[3];
+ if (y + Tree_TotalHeight(tree) < maxY) {
+ rect.x = minX;
+ rect.y = y + Tree_TotalHeight(tree);
+ rect.width = maxX - minX;
+ rect.height = maxY - (y + Tree_TotalHeight(tree));
+ TkUnionRectWithRegion(&rect, wsRgn, wsRgn);
+ }
+ }
+
+ /* Erase area below right columns */
+ if (!dInfo->emptyR) {
+ minX = dInfo->boundsR[0];
+ minY = dInfo->boundsR[1];
+ maxX = dInfo->boundsR[2];
+ maxY = dInfo->boundsR[3];
+ if (y + Tree_TotalHeight(tree) < maxY) {
+ rect.x = minX;
+ rect.y = y + Tree_TotalHeight(tree);
+ rect.width = maxX - minX;
+ rect.height = maxY - (y + Tree_TotalHeight(tree));
+ TkUnionRectWithRegion(&rect, wsRgn, wsRgn);
+ }
+ }
+#endif
+
+ if (dInfo->empty)
+ return wsRgn;
+ minX = dInfo->bounds[0];
+ minY = dInfo->bounds[1];
+ maxX = dInfo->bounds[2];
+ maxY = dInfo->bounds[3];
+
if (tree->vertical) {
/* Erase area to right of last Range */
if (x + Tree_TotalWidth(tree) < maxX) {
rect.x = x + Tree_TotalWidth(tree);
rect.y = minY;
- rect.width = maxX - (x + Tree_TotalWidth(tree));
+ rect.width = maxX - rect.x;
rect.height = maxY - minY;
TkUnionRectWithRegion(&rect, wsRgn, wsRgn);
}
@@ -4331,7 +4482,7 @@ CalcWhiteSpaceRegion(
rect.x = minX;
rect.y = y + Tree_TotalHeight(tree);
rect.width = maxX - minX;
- rect.height = maxY - (y + Tree_TotalHeight(tree));
+ rect.height = maxY - rect.y;
TkUnionRectWithRegion(&rect, wsRgn, wsRgn);
}
}
@@ -4441,6 +4592,119 @@ Tree_DrawTiledImage(
}
/*
+ *----------------------------------------------------------------------
+ *
+ * DisplayDItem --
+ *
+ * Draw a single item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Stuff is drawn.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DisplayDItem(
+ TreeCtrl *tree, /* Widget info. */
+ DItem *dItem,
+ DItemArea *area,
+#ifdef COLUMN_LOCK
+ int lock, /* Which set of columns. */
+#endif
+ int bounds[4], /* TREE_AREA_xxx bounds of drawing. */
+ Drawable pixmap, /* Where to draw. */
+ Drawable drawable /* Where to copy to. */
+ )
+{
+ DInfo *dInfo = (DInfo *) tree->dInfo;
+ Tk_Window tkwin = tree->tkwin;
+ int left, top, right, bottom;
+
+ left = area->x;
+ right = left + area->width;
+ top = dItem->y;
+ bottom = top + dItem->height;
+
+ if (!(area->flags & DITEM_ALL_DIRTY)) {
+ left += area->dirty[LEFT];
+ right = area->x + area->dirty[RIGHT];
+ top += area->dirty[TOP];
+ bottom = dItem->y + area->dirty[BOTTOM];
+ }
+
+ area->flags &= ~(DITEM_DIRTY | DITEM_ALL_DIRTY);
+
+ if (left < bounds[0])
+ left = bounds[0];
+ if (right > bounds[2])
+ right = bounds[2];
+ if (top < bounds[1])
+ top = bounds[1];
+ if (bottom > bounds[3])
+ bottom = bounds[3];
+
+ if (right <= left || bottom <= top)
+ return 0;
+
+ if (tree->debug.enable && tree->debug.display && tree->debug.drawColor) {
+ XFillRectangle(tree->display, Tk_WindowId(tkwin),
+ tree->debug.gcDraw, left, top, right - left, bottom - top);
+ DisplayDelay(tree);
+ }
+
+ if (tree->doubleBuffer != DOUBLEBUFFER_NONE) {
+
+ if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) {
+ dInfo->dirty[LEFT] = MIN(dInfo->dirty[LEFT], left);
+ dInfo->dirty[TOP] = MIN(dInfo->dirty[TOP], top);
+ dInfo->dirty[RIGHT] = MAX(dInfo->dirty[RIGHT], right);
+ dInfo->dirty[BOTTOM] = MAX(dInfo->dirty[BOTTOM], bottom);
+ }
+
+ /* The top-left corner of the drawable is at this
+ * point in the canvas */
+ tree->drawableXOrigin = left + tree->xOrigin;
+ tree->drawableYOrigin = top + tree->yOrigin;
+
+ TreeItem_Draw(tree, dItem->item,
+#ifdef COLUMN_LOCK
+ lock,
+#endif
+ area->x - left, dItem->y - top,
+ area->width, dItem->height,
+ pixmap,
+ 0, right - left,
+ dItem->index);
+ XCopyArea(tree->display, pixmap, drawable,
+ tree->copyGC,
+ 0, 0,
+ right - left, bottom - top,
+ left, top);
+ } else {
+
+ /* The top-left corner of the drawable is at this
+ * point in the canvas */
+ tree->drawableXOrigin = tree->xOrigin;
+ tree->drawableYOrigin = tree->yOrigin;
+
+ TreeItem_Draw(tree, dItem->item,
+ lock,
+ area->x,
+ dItem->y,
+ area->width, dItem->height,
+ drawable,
+ left, right,
+ dItem->index);
+ }
+
+ return 1;
+}
+
+/*
*--------------------------------------------------------------
*
* Tree_Display --
@@ -4469,7 +4733,6 @@ Tree_Display(
Tk_Window tkwin = tree->tkwin;
Drawable drawable = Tk_WindowId(tkwin);
int minX, minY, maxX, maxY, height, width;
- int left, right, top, bottom;
int count;
int numCopy = 0, numDraw = 0;
TkRegion wsRgnNew, wsRgnDif;
@@ -4703,7 +4966,7 @@ displayRetry:
/* Remove newly-hidden items from itemVisHash */
count = TreeItemList_Count(&newH);
for (i = 0; i < count; i++) {
- item = TreeItemList_ItemN(&newH, i);
+ item = TreeItemList_Nth(&newH, i);
hPtr = Tcl_FindHashEntry(&dInfo->itemVisHash, (char *) item);
Tcl_DeleteHashEntry(hPtr);
}
@@ -4711,7 +4974,7 @@ displayRetry:
/* Add newly-visible items to itemVisHash */
count = TreeItemList_Count(&newV);
for (i = 0; i < count; i++) {
- item = TreeItemList_ItemN(&newV, i);
+ item = TreeItemList_Nth(&newV, i);
hPtr = Tcl_CreateHashEntry(&dInfo->itemVisHash, (char *) item, &isNew);
}
@@ -4744,11 +5007,6 @@ displayRetry:
drawable = dInfo->pixmap;
}
- minX = Tree_ContentLeft(tree);
- minY = Tree_ContentTop(tree);
- maxX = Tree_ContentRight(tree);
- maxY = Tree_ContentBottom(tree);
-
/* XOR off */
TreeColumnProxy_Undisplay(tree);
TreeRowProxy_Undisplay(tree);
@@ -4756,13 +5014,13 @@ displayRetry:
TreeMarquee_Undisplay(tree->marquee);
if (dInfo->flags & DINFO_DRAW_HEADER) {
- if (tree->showHeader) {
+ if (Tree_AreaBbox(tree, TREE_AREA_HEADER, &minX, &minY, &maxX, &maxY)) {
Tree_DrawHeader(tree, drawable, 0 - tree->xOrigin, tree->inset);
if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) {
- dInfo->dirty[LEFT] = tree->inset;
- dInfo->dirty[TOP] = tree->inset;
+ dInfo->dirty[LEFT] = minX;
+ dInfo->dirty[TOP] = minY;
dInfo->dirty[RIGHT] = maxX;
- dInfo->dirty[BOTTOM] = minY;
+ dInfo->dirty[BOTTOM] = maxY;
}
}
dInfo->flags &= ~DINFO_DRAW_HEADER;
@@ -4796,8 +5054,8 @@ displayRetry:
/* Erase entire background. */
/* FIXME: background image? */
Tk_Fill3DRectangle(tree->tkwin, pixmap, tree->border,
- tree->inset, minY, width,
- maxY - minY, 0, TK_RELIEF_FLAT);
+ tree->inset, Tree_ContentTop(tree), width,
+ Tree_ContentHeight(tree), 0, TK_RELIEF_FLAT);
/* This is needed for updating window positions */
tree->drawableXOrigin = tree->xOrigin;
@@ -4807,7 +5065,8 @@ displayRetry:
int onScreen = FALSE;
dRowLabel = &dInfo->dRowLabel[i];
if (dRowLabel->height > 0) {
- if ((y + dRowLabel->height > minY) && (y < maxY)) {
+ if ((y + dRowLabel->height > Tree_ContentTop(tree)) &&
+ (y < Tree_ContentBottom(tree))) {
TreeRowLabel_Draw(dRowLabel->row, tree->inset, y,
width, dRowLabel->height,
pixmap);
@@ -4820,17 +5079,17 @@ displayRetry:
if (tree->doubleBuffer == DOUBLEBUFFER_ITEM) {
XCopyArea(tree->display, pixmap, drawable,
- tree->copyGC, tree->inset, minY,
- width, maxY - minY,
- tree->inset, minY);
+ tree->copyGC, tree->inset, Tree_ContentTop(tree),
+ width, Tree_ContentHeight(tree),
+ tree->inset, Tree_ContentTop(tree));
Tk_FreePixmap(tree->display, pixmap);
}
if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) {
dInfo->dirty[LEFT] = MIN(dInfo->dirty[LEFT], tree->inset);
- dInfo->dirty[TOP] = MIN(dInfo->dirty[TOP], minY);
- dInfo->dirty[RIGHT] = MAX(dInfo->dirty[RIGHT], minX);
- dInfo->dirty[BOTTOM] = MAX(dInfo->dirty[BOTTOM], maxY);
+ dInfo->dirty[TOP] = MIN(dInfo->dirty[TOP], Tree_ContentTop(tree));
+ dInfo->dirty[RIGHT] = MAX(dInfo->dirty[RIGHT], tree->inset);
+ dInfo->dirty[BOTTOM] = MAX(dInfo->dirty[BOTTOM], Tree_ContentBottom(tree));
}
}
}
@@ -4850,11 +5109,11 @@ displayRetry:
if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) {
if ((dInfo->xOrigin != tree->xOrigin) ||
(dInfo->yOrigin != tree->yOrigin)) {
- dInfo->dirty[LEFT] = MIN(dInfo->dirty[LEFT], minX);
+ dInfo->dirty[LEFT] = MIN(dInfo->dirty[LEFT], Tree_BorderLeft(tree));
/* might include header */
- dInfo->dirty[TOP] = MIN(dInfo->dirty[TOP], minY);
- dInfo->dirty[RIGHT] = MAX(dInfo->dirty[RIGHT], maxX);
- dInfo->dirty[BOTTOM] = MAX(dInfo->dirty[BOTTOM], maxY);
+ dInfo->dirty[TOP] = MIN(dInfo->dirty[TOP], Tree_ContentTop(tree));
+ dInfo->dirty[RIGHT] = MAX(dInfo->dirty[RIGHT], Tree_BorderRight(tree));
+ dInfo->dirty[BOTTOM] = MAX(dInfo->dirty[BOTTOM], Tree_ContentBottom(tree));
}
}
@@ -4955,361 +5214,88 @@ displayRetry:
for (dItem = dInfo->dItem;
dItem != NULL;
dItem = dItem->next) {
+ if (!dInfo->empty && (dItem->area.flags & DITEM_DIRTY)) {
+ count++;
+ break;
+ }
#ifdef COLUMN_LOCK
- /* Have DItems but only for locked columns. */
- if (!dInfo->nonLockedDItems)
+ if (!dInfo->emptyL && (dItem->left.flags & DITEM_DIRTY)) {
+ count++;
break;
-#endif
- if (dItem->flags & DITEM_DIRTY) {
+ }
+ if (!dInfo->emptyR && (dItem->right.flags & DITEM_DIRTY)) {
count++;
break;
}
+#endif
}
-#ifdef COLUMN_LOCK
- if ((dInfo->dItem != NULL) && (dInfo->widthOfColumnsLeft ||
- dInfo->widthOfColumnsRight)) {
-
+ /* Display dirty items */
+ if (count > 0) {
Drawable pixmap = drawable;
if (tree->doubleBuffer != DOUBLEBUFFER_NONE) {
- width = MAX(dInfo->widthOfColumnsLeft, dInfo->widthOfColumnsRight);
- height = MIN(maxY - minY, dInfo->itemHeight);
+ /* Allocate pixmap for largest item */
+ width = MIN(Tk_Width(tkwin), dInfo->itemWidth);
+ height = MIN(Tk_Height(tkwin), dInfo->itemHeight);
pixmap = Tk_GetPixmap(tree->display, Tk_WindowId(tkwin),
width, height, Tk_Depth(tkwin));
}
for (dItem = dInfo->dItem;
- dItem != NULL;
- dItem = dItem->next) {
-
- if (!(dItem->left.flags & DITEM_DIRTY) &&
- !(dItem->right.flags & DITEM_DIRTY))
- continue;
-
- if (tree->doubleBuffer != DOUBLEBUFFER_NONE) {
- int dItemX;
-
- if (dInfo->widthOfColumnsLeft &&
- (dItem->left.flags & DITEM_DIRTY)) {
- dItemX = tree->inset;
-
- left = dItemX;
- right = minX;
- top = dItem->y;
- bottom = top + dItem->height;
-
- if (!(dItem->left.flags & DITEM_ALL_DIRTY)) {
- left += dItem->left.dirty[LEFT];
- right = dItemX + dItem->left.dirty[RIGHT];
- top += dItem->left.dirty[TOP];
- bottom = dItem->y + dItem->left.dirty[BOTTOM];
- }
-
- if (right > Tree_BorderRight(tree))
- right = Tree_BorderRight(tree);
- if (top < minY)
- top = minY;
- if (bottom > maxY)
- bottom = maxY;
-
- if (right <= left || bottom <= top) {
- dItem->left.flags &= ~(DITEM_DIRTY | DITEM_ALL_DIRTY);
- continue;
- }
-
- if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) {
- dInfo->dirty[LEFT] = MIN(dInfo->dirty[LEFT], left);
- dInfo->dirty[TOP] = MIN(dInfo->dirty[TOP], top);
- dInfo->dirty[RIGHT] = MAX(dInfo->dirty[RIGHT], right);
- dInfo->dirty[BOTTOM] = MAX(dInfo->dirty[BOTTOM], bottom);
- }
-
- if (tree->debug.enable && tree->debug.display && tree->debug.drawColor) {
- XFillRectangle(tree->display, Tk_WindowId(tkwin),
- tree->debug.gcDraw, left, top, right - left, bottom - top);
- DisplayDelay(tree);
- }
-
- /* The top-left corner of the drawable is at this
- * point in the canvas */
- tree->drawableXOrigin = left + tree->xOrigin;
- tree->drawableYOrigin = top + tree->yOrigin;
-
- TreeItem_Draw(tree, dItem->item,
- COLUMN_LOCK_LEFT,
- dItemX - left, dItem->y - top,
- dInfo->widthOfColumnsLeft, dItem->height,
- pixmap,
- 0, right - left,
- dItem->index);
- XCopyArea(tree->display, pixmap, drawable,
- tree->copyGC,
- 0, 0,
- right - left, bottom - top,
- left, top);
-
- dItem->left.flags &= ~(DITEM_DIRTY | DITEM_ALL_DIRTY);
- }
-
- if (dInfo->widthOfColumnsRight &&
- (dItem->right.flags & DITEM_DIRTY)) {
- dItemX = maxX;
-
- left = dItemX;
- right = Tree_BorderRight(tree);
- top = dItem->y;
- bottom = top + dItem->height;
-
- if (!(dItem->right.flags & DITEM_ALL_DIRTY)) {
- left += dItem->right.dirty[LEFT];
- right = dItemX + dItem->right.dirty[RIGHT];
- top += dItem->right.dirty[TOP];
- bottom = dItem->y + dItem->right.dirty[BOTTOM];
- }
-
- if (left < tree->inset)
- left = tree->inset;
- if (top < minY)
- top = minY;
- if (bottom > maxY)
- bottom = maxY;
-
- if (right <= left || bottom <= top) {
- dItem->right.flags &= ~(DITEM_DIRTY | DITEM_ALL_DIRTY);
- continue;
- }
-
- if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) {
- dInfo->dirty[LEFT] = MIN(dInfo->dirty[LEFT], left);
- dInfo->dirty[TOP] = MIN(dInfo->dirty[TOP], top);
- dInfo->dirty[RIGHT] = MAX(dInfo->dirty[RIGHT], right);
- dInfo->dirty[BOTTOM] = MAX(dInfo->dirty[BOTTOM], bottom);
- }
-
- if (tree->debug.enable && tree->debug.display && tree->debug.drawColor) {
- XFillRectangle(tree->display, Tk_WindowId(tkwin),
- tree->debug.gcDraw, left, top, right - left, bottom - top);
- DisplayDelay(tree);
- }
-
- /* The top-left corner of the drawable is at this
- * point in the canvas */
- tree->drawableXOrigin = left + tree->xOrigin;
- tree->drawableYOrigin = top + tree->yOrigin;
-
- TreeItem_Draw(tree, dItem->item,
- COLUMN_LOCK_RIGHT,
- dItemX - left, dItem->y - top,
- dInfo->widthOfColumnsRight, dItem->height,
- pixmap,
- 0, right - left,
- dItem->index);
- XCopyArea(tree->display, pixmap, drawable,
- tree->copyGC,
- 0, 0,
- right - left, bottom - top,
- left, top);
-
- dItem->right.flags &= ~(DITEM_DIRTY | DITEM_ALL_DIRTY);
- }
- } else {
+ dItem != NULL;
+ dItem = dItem->next) {
- /* The top-left corner of the drawable is at this
- * point in the canvas */
+#ifdef COLUMN_LOCK
+ if (!dInfo->empty) {
+ /* FIXME: may "draw" window elements twice. */
tree->drawableXOrigin = tree->xOrigin;
tree->drawableYOrigin = tree->yOrigin;
-
- if (dInfo->widthOfColumnsLeft &&
- (dItem->left.flags & DITEM_DIRTY)) {
- TreeItem_Draw(tree, dItem->item,
- COLUMN_LOCK_LEFT,
- tree->inset,
- dItem->y,
- dInfo->widthOfColumnsLeft, dItem->height,
- drawable,
- tree->inset, tree->inset + dInfo->widthOfColumnsLeft,
- dItem->index);
- dItem->left.flags &= ~(DITEM_DIRTY | DITEM_ALL_DIRTY);
- }
-
- if (dInfo->widthOfColumnsRight &&
- (dItem->right.flags & DITEM_DIRTY)) {
- TreeItem_Draw(tree, dItem->item,
- COLUMN_LOCK_RIGHT,
- maxX,
- dItem->y,
- dInfo->widthOfColumnsRight, dItem->height,
- drawable,
- maxX, Tree_BorderRight(tree),
- dItem->index);
- dItem->right.flags &= ~(DITEM_DIRTY | DITEM_ALL_DIRTY);
+ TreeItem_UpdateWindowPositions(tree, dItem->item, COLUMN_LOCK_NONE,
+ dItem->area.x, dItem->y, dItem->area.width, dItem->height);
+ if (dItem->area.flags & DITEM_DIRTY) {
+ numDraw += DisplayDItem(tree, dItem, &dItem->area,
+ COLUMN_LOCK_NONE, dInfo->bounds, pixmap, drawable);
}
}
- }
-
- if (tree->doubleBuffer != DOUBLEBUFFER_NONE) {
- Tk_FreePixmap(tree->display, pixmap);
- }
-
- /* Erase background below the last item. */
- top = dInfo->dItemLast->y + dInfo->dItemLast->height;
- bottom = Tree_BorderBottom(tree);
- if (top < bottom) {
- if (dInfo->widthOfColumnsLeft) {
- left = Tree_BorderLeft(tree);
- width = dInfo->widthOfColumnsLeft;
- if (tree->debug.enable && tree->debug.display && tree->debug.drawColor) {
- XFillRectangle(tree->display, Tk_WindowId(tkwin),
- tree->debug.gcDraw, left, top, width, bottom - top);
- DisplayDelay(tree);
- }
- if (tree->backgroundImage != NULL) {
- Tree_DrawTiledImage(tree, drawable, tree->backgroundImage,
- left, top, left + width, bottom,
- tree->xOrigin, tree->yOrigin);
- } else {
- GC gc = Tk_3DBorderGC(tkwin, tree->border, TK_3D_FLAT_GC);
- XFillRectangle(tree->display, drawable,
- gc, left, top, width, bottom - top);
+ if (!dInfo->emptyL) {
+ tree->drawableXOrigin = tree->xOrigin;
+ tree->drawableYOrigin = tree->yOrigin;
+ TreeItem_UpdateWindowPositions(tree, dItem->item,
+ COLUMN_LOCK_LEFT, dItem->left.x, dItem->y,
+ dItem->left.width, dItem->height);
+ if (dItem->left.flags & DITEM_DIRTY) {
+ DisplayDItem(tree, dItem, &dItem->left, COLUMN_LOCK_LEFT,
+ dInfo->boundsL, pixmap, drawable);
}
}
- if (dInfo->widthOfColumnsRight) {
- left = maxX;
- width = dInfo->widthOfColumnsRight;
- if (tree->debug.enable && tree->debug.display && tree->debug.drawColor) {
- XFillRectangle(tree->display, Tk_WindowId(tkwin),
- tree->debug.gcDraw, left, top, width, bottom - top);
- DisplayDelay(tree);
- }
- if (tree->backgroundImage != NULL) {
- Tree_DrawTiledImage(tree, drawable, tree->backgroundImage,
- left, top, left + width, bottom,
- tree->xOrigin, tree->yOrigin);
- } else {
- GC gc = Tk_3DBorderGC(tkwin, tree->border, TK_3D_FLAT_GC);
- XFillRectangle(tree->display, drawable,
- gc, left, top, width, bottom - top);
+ if (!dInfo->emptyR) {
+ tree->drawableXOrigin = tree->xOrigin;
+ tree->drawableYOrigin = tree->yOrigin;
+ TreeItem_UpdateWindowPositions(tree, dItem->item,
+ COLUMN_LOCK_RIGHT, dItem->right.x, dItem->y,
+ dItem->right.width, dItem->height);
+ if (dItem->right.flags & DITEM_DIRTY) {
+ DisplayDItem(tree, dItem, &dItem->right, COLUMN_LOCK_RIGHT,
+ dInfo->boundsR, pixmap, drawable);
}
}
- }
- }
-#endif /* COLUMN_LOCK */
-
- /* Display dirty items */
- if (count > 0) {
- Drawable pixmap = drawable;
- if (tree->doubleBuffer != DOUBLEBUFFER_NONE) {
- /* Allocate pixmap for largest item */
- width = MIN(maxX - minX, dInfo->itemWidth);
- height = MIN(maxY - minY, dInfo->itemHeight);
- pixmap = Tk_GetPixmap(tree->display, Tk_WindowId(tkwin),
- width, height, Tk_Depth(tkwin));
- }
- for (dItem = dInfo->dItem;
- dItem != NULL;
- dItem = dItem->next) {
-
- /*
- * FIXME.
- */
- tree->drawableXOrigin = tree->xOrigin;
- tree->drawableYOrigin = tree->yOrigin;
- TreeItem_UpdateWindowPositions(tree, dItem->item,
- dItem->x, dItem->y, dItem->width, dItem->height);
-
- if (!(dItem->flags & DITEM_DIRTY)) {
- continue;
- }
-
- if (dItem->flags & DITEM_ALL_DIRTY) {
- left = dItem->x;
- right = dItem->x + dItem->width;
- top = dItem->y;
- bottom = dItem->y + dItem->height;
- }
- else {
- left = dItem->x + dItem->dirty[LEFT];
- right = dItem->x + dItem->dirty[RIGHT];
- top = dItem->y + dItem->dirty[TOP];
- bottom = dItem->y + dItem->dirty[BOTTOM];
- }
-
- if (left < minX)
- left = minX;
- if (right > maxX)
- right = maxX;
- if (top < minY)
- top = minY;
- if (bottom > maxY)
- bottom = maxY;
-
- if (right <= left || bottom <= top) {
- dItem->oldX = dItem->x;
- dItem->oldY = dItem->y;
- dItem->flags &= ~(DITEM_DIRTY | DITEM_ALL_DIRTY);
- continue;
- }
-
- if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) {
- dInfo->dirty[LEFT] = MIN(dInfo->dirty[LEFT], left);
- dInfo->dirty[TOP] = MIN(dInfo->dirty[TOP], top);
- dInfo->dirty[RIGHT] = MAX(dInfo->dirty[RIGHT], right);
- dInfo->dirty[BOTTOM] = MAX(dInfo->dirty[BOTTOM], bottom);
- }
-
- if (tree->debug.enable && tree->debug.display && tree->debug.drawColor) {
- XFillRectangle(tree->display, Tk_WindowId(tkwin),
- tree->debug.gcDraw, left, top, right - left, bottom - top);
- DisplayDelay(tree);
- }
-
- if (tree->doubleBuffer != DOUBLEBUFFER_NONE) {
- /* The top-left corner of the drawable is at this
- * point in the canvas */
- tree->drawableXOrigin = left + tree->xOrigin;
- tree->drawableYOrigin = top + tree->yOrigin;
-
- TreeItem_Draw(tree, dItem->item,
-#ifdef COLUMN_LOCK
- COLUMN_LOCK_NONE,
-#endif
- dItem->x - left,
- dItem->y - top,
- dItem->width, dItem->height,
- pixmap,
- 0, right - left,
- dItem->index);
- XCopyArea(tree->display, pixmap, drawable,
- tree->copyGC,
- 0, 0,
- right - left, bottom - top,
- left, top);
- }
- /* DOUBLEBUFFER_NONE */
- else {
- /* The top-left corner of the drawable is at this
- * point in the canvas */
+#else
+ if (!dInfo->empty) {
+ /* FIXME: may "draw" window elements twice. */
tree->drawableXOrigin = tree->xOrigin;
tree->drawableYOrigin = tree->yOrigin;
-
- TreeItem_Draw(tree, dItem->item,
-#ifdef COLUMN_LOCK
- COLUMN_LOCK_NONE,
-#endif
- dItem->x,
- dItem->y,
- dItem->width, dItem->height,
- pixmap,
- minX, maxX,
- dItem->index);
+ TreeItem_UpdateWindowPositions(tree, dItem->item, COLUMN_LOCK_NONE,
+ dItem->area.x, dItem->y, dItem->area.width, dItem->height);
+ if (dItem->area.flags & DITEM_DIRTY) {
+ numDraw += DisplayDItem(tree, dItem, &dItem->area,
+ COLUMN_LOCK_NONE, bounds, pixmap, drawable);
+ }
}
- DisplayDelay(tree);
- numDraw++;
+#endif
- dItem->oldX = dItem->x;
+ dItem->oldX = dItem->area.x;
dItem->oldY = dItem->y;
- dItem->flags &= ~(DITEM_DIRTY | DITEM_ALL_DIRTY);
}
if (tree->doubleBuffer != DOUBLEBUFFER_NONE)
Tk_FreePixmap(tree->display, pixmap);
@@ -6193,7 +6179,7 @@ Tree_InvalidateItemDInfo(
dItem = (DItem *) TreeItem_GetDInfo(tree, item);
if (dItem != NULL) {
if (column == NULL) {
- dItem->flags |= (DITEM_DIRTY | DITEM_ALL_DIRTY);
+ dItem->area.flags |= (DITEM_DIRTY | DITEM_ALL_DIRTY);
#ifdef COLUMN_LOCK
dItem->left.flags |= (DITEM_DIRTY | DITEM_ALL_DIRTY);
dItem->right.flags |= (DITEM_DIRTY | DITEM_ALL_DIRTY);
@@ -6205,12 +6191,10 @@ Tree_InvalidateItemDInfo(
* is currently being invalidated. */
int columnIndex = TreeColumn_Index(column);
int i, left = dInfo->columns[columnIndex].offset;
- /* FIXME: is this the actual display width if only one
- * column is visible? */
+ /* This may not be the actual display width if this is the
+ * only visible non-locked column. */
int width = dInfo->columns[columnIndex].width;
-#ifdef COLUMN_LOCK
- int itemWidth;
-#endif
+
/* If a hidden column was moved we can't rely on
* dInfo->columns[] being in the right order. */
if (dInfo->flags & DINFO_CHECK_COLUMN_WIDTH) {
@@ -6225,24 +6209,33 @@ Tree_InvalidateItemDInfo(
width = dInfo->columns[i].width;
}
-#ifdef COLUMN_LOCK
+#ifdef COLUMN_SPAN
+ width = 0;
+ i = dItem->spans[columnIndex];
+ while (dItem->spans[i] == dItem->spans[columnIndex]) {
+ width += dInfo->columns[i].width;
+ if (++i == tree->columnCount)
+ break;
+ }
+#endif
+#ifdef COLUMN_LOCK
switch (TreeColumn_Lock(column)) {
case COLUMN_LOCK_NONE:
- InvalidateDItemX(dItem, 0, left, width);
- InvalidateDItemY(dItem, dItem->y, dItem->y, dItem->height);
- dItem->flags |= DITEM_DIRTY;
+ if (tree->columnCountVis == 1)
+ width = dItem->area.width;
+ InvalidateDItemX(dItem, &dItem->area, 0, left, width);
+ InvalidateDItemY(dItem, &dItem->area, dItem->y, dItem->y, dItem->height);
+ dItem->area.flags |= DITEM_DIRTY;
break;
case COLUMN_LOCK_LEFT:
- itemWidth = dInfo->widthOfColumnsLeft;
- InvalidateDItemX2(dItem->left.dirty, dItem->left.flags, 0, itemWidth, left, width);
- InvalidateDItemY2(dItem->left.dirty, dItem->left.flags, 0, dItem->height, 0, dItem->height);
+ InvalidateDItemX(dItem, &dItem->left, 0, left, width);
+ InvalidateDItemY(dItem, &dItem->left, 0, 0, dItem->height);
dItem->left.flags |= DITEM_DIRTY;
break;
case COLUMN_LOCK_RIGHT:
- itemWidth = dInfo->widthOfColumnsRight;
- InvalidateDItemX2(dItem->right.dirty, dItem->right.flags, 0, itemWidth, left, width);
- InvalidateDItemY2(dItem->right.dirty, dItem->right.flags, 0, dItem->height, 0, dItem->height);
+ InvalidateDItemX(dItem, &dItem->right, 0, left, width);
+ InvalidateDItemY(dItem, &dItem->right, 0, 0, dItem->height);
dItem->right.flags |= DITEM_DIRTY;
break;
}
@@ -6397,32 +6390,26 @@ Tree_InvalidateArea(
dItem = dInfo->dItem;
while (dItem != NULL) {
-#ifdef COLUMN_LOCK
- if (!(dItem->flags & DITEM_ALL_DIRTY) && dInfo->nonLockedDItems &&
-#else
- if (!(dItem->flags & DITEM_ALL_DIRTY) &&
-#endif
- (x2 > dItem->x) && (x1 < dItem->x + dItem->width) &&
+ if (!(dItem->area.flags & DITEM_ALL_DIRTY) && !dInfo->empty &&
+ (x2 > dItem->area.x) && (x1 < dItem->area.x + dItem->area.width) &&
(y2 > dItem->y) && (y1 < dItem->y + dItem->height)) {
- InvalidateDItemX(dItem, dItem->x, x1, x2 - x1);
- InvalidateDItemY(dItem, dItem->y, y1, y2 - y1);
- dItem->flags |= DITEM_DIRTY;
+ InvalidateDItemX(dItem, &dItem->area, dItem->area.x, x1, x2 - x1);
+ InvalidateDItemY(dItem, &dItem->area, dItem->y, y1, y2 - y1);
+ dItem->area.flags |= DITEM_DIRTY;
}
#ifdef COLUMN_LOCK
- if (dInfo->widthOfColumnsLeft &&
- !(dItem->left.flags & DITEM_ALL_DIRTY) &&
- (x2 > Tree_BorderLeft(tree)) && (x1 < Tree_ContentLeft(tree)) &&
+ if (!dInfo->emptyL && !(dItem->left.flags & DITEM_ALL_DIRTY) &&
+ (x2 > dInfo->boundsL[0]) && (x1 < dInfo->boundsL[2]) &&
(y2 > dItem->y) && (y1 < dItem->y + dItem->height)) {
- InvalidateDItemX2(dItem->left.dirty, dItem->left.flags, tree->inset, dInfo->widthOfColumnsLeft, x1, x2 - x1);
- InvalidateDItemY2(dItem->left.dirty, dItem->left.flags, dItem->y, dItem->height, y1, y2 - y1);
+ InvalidateDItemX(dItem, &dItem->left, dItem->left.x, x1, x2 - x1);
+ InvalidateDItemY(dItem, &dItem->left, dItem->y, y1, y2 - y1);
dItem->left.flags |= DITEM_DIRTY;
}
- if (dInfo->widthOfColumnsRight &&
- !(dItem->right.flags & DITEM_ALL_DIRTY) &&
- (x2 > Tree_ContentRight(tree)) && (x1 < Tree_BorderRight(tree)) &&
+ if (!dInfo->emptyR && !(dItem->right.flags & DITEM_ALL_DIRTY) &&
+ (x2 > dInfo->boundsR[0]) && (x1 < dInfo->boundsR[2]) &&
(y2 > dItem->y) && (y1 < dItem->y + dItem->height)) {
- InvalidateDItemX2(dItem->right.dirty, dItem->right.flags, Tree_ContentRight(tree), dInfo->widthOfColumnsRight, x1, x2 - x1);
- InvalidateDItemY2(dItem->right.dirty, dItem->right.flags, dItem->y, dItem->height, y1, y2 - y1);
+ InvalidateDItemX(dItem, &dItem->right, dItem->right.x, x1, x2 - x1);
+ InvalidateDItemY(dItem, &dItem->right, dItem->y, y1, y2 - y1);
dItem->right.flags |= DITEM_DIRTY;
}
#endif
@@ -6442,6 +6429,21 @@ Tree_InvalidateArea(
}
}
+ /* Invalidate part of the whitespace */
+ if ((x1 < x2 && y1 < y2) && TkRectInRegion(dInfo->wsRgn, x1, y1,
+ x2 - x1, y2 - y1)) {
+ XRectangle rect;
+ TkRegion rgn = TkCreateRegion();
+
+ rect.x = x1;
+ rect.y = y1;
+ rect.width = x2 - x1;
+ rect.height = y2 - y1;
+ TkUnionRectWithRegion(&rect, rgn, rgn);
+ TkSubtractRegion(dInfo->wsRgn, rgn, dInfo->wsRgn);
+ TkDestroyRegion(rgn);
+ }
+
if (tree->debug.enable && tree->debug.display && tree->debug.eraseColor) {
XFillRectangle(tree->display, Tk_WindowId(tree->tkwin),
tree->debug.gcErase, x1, y1, x2 - x1, y2 - y1);
@@ -6485,13 +6487,10 @@ Tree_InvalidateRegion(
TkClipBox(region, &rect);
if (!rect.width || !rect.height)
return;
- x1 = rect.x, x2 = rect.x + rect.width;
- y1 = rect.y, y2 = rect.y + rect.height;
-
- rgn = TkCreateRegion();
- if (TkRectInRegion(region, minX, minY, maxX - minX,
- Tree_HeaderHeight(tree)) != RectangleOut)
+ if (Tree_AreaBbox(tree, TREE_AREA_HEADER, &minX, &minY, &maxX, &maxY) &&
+ TkRectInRegion(region, minX, minY, maxX - minX, maxY - minY)
+ != RectangleOut)
dInfo->flags |= DINFO_DRAW_HEADER;
#ifdef ROW_LABEL
@@ -6501,61 +6500,53 @@ Tree_InvalidateRegion(
dInfo->flags |= DINFO_DRAW_ROWLABELS;
#endif
+ rgn = TkCreateRegion();
+
dItem = dInfo->dItem;
while (dItem != NULL) {
-#ifdef COLUMN_LOCK
- if (!(dItem->flags & DITEM_ALL_DIRTY) && dInfo->nonLockedDItems) {
-#else
- if (!(dItem->flags & DITEM_ALL_DIRTY)) {
-#endif
- rect.x = dItem->x;
+ if (!dInfo->empty && !(dItem->area.flags & DITEM_ALL_DIRTY)) {
+ rect.x = dItem->area.x;
rect.y = dItem->y;
- rect.width = dItem->width;
+ rect.width = dItem->area.width;
rect.height = dItem->height;
TkSubtractRegion(rgn, rgn, rgn);
TkUnionRectWithRegion(&rect, rgn, rgn);
TkIntersectRegion(region, rgn, rgn);
TkClipBox(rgn, &rect);
if (rect.width > 0 && rect.height > 0) {
- InvalidateDItemX(dItem, dItem->x, rect.x, rect.width);
- InvalidateDItemY(dItem, dItem->y, rect.y, rect.height);
- dItem->flags |= DITEM_DIRTY;
+ InvalidateDItemX(dItem, &dItem->area, dItem->area.x, rect.x, rect.width);
+ InvalidateDItemY(dItem, &dItem->area, dItem->y, rect.y, rect.height);
+ dItem->area.flags |= DITEM_DIRTY;
}
}
#ifdef COLUMN_LOCK
- if (!(dItem->left.flags & DITEM_ALL_DIRTY) &&
- dInfo->widthOfColumnsLeft) {
- int x = tree->inset, w = dInfo->widthOfColumnsLeft;
-
- rect.x = x;
+ if (!dInfo->emptyL && !(dItem->left.flags & DITEM_ALL_DIRTY)) {
+ rect.x = dItem->left.x;
rect.y = dItem->y;
- rect.width = w;
+ rect.width = dItem->left.width;
rect.height = dItem->height;
TkSubtractRegion(rgn, rgn, rgn);
TkUnionRectWithRegion(&rect, rgn, rgn);
TkIntersectRegion(region, rgn, rgn);
TkClipBox(rgn, &rect);
if (rect.width > 0 && rect.height > 0) {
- InvalidateDItemX2(dItem->left.dirty, dItem->left.flags, x, w, rect.x, rect.width);
- InvalidateDItemY2(dItem->left.dirty, dItem->left.flags, dItem->y, dItem->height, rect.y, rect.height);
+ InvalidateDItemX(dItem, &dItem->left, dItem->left.x, rect.x, rect.width);
+ InvalidateDItemY(dItem, &dItem->left, dItem->y, rect.y, rect.height);
dItem->left.flags |= DITEM_DIRTY;
}
}
- if (!(dItem->right.flags & DITEM_ALL_DIRTY) &&
- dInfo->widthOfColumnsRight) {
- int x = Tree_ContentRight(tree), w = dInfo->widthOfColumnsRight;
-
- rect.x = x;
+ if (!dInfo->emptyR && !(dItem->right.flags & DITEM_ALL_DIRTY)) {
+ rect.x = dItem->right.x;
rect.y = dItem->y;
- rect.width = w;
+ rect.width = dItem->right.width;
rect.height = dItem->height;
TkSubtractRegion(rgn, rgn, rgn);
TkUnionRectWithRegion(&rect, rgn, rgn);
TkIntersectRegion(region, rgn, rgn);
TkClipBox(rgn, &rect);
if (rect.width > 0 && rect.height > 0) {
- InvalidateDItemX2(dItem->right.dirty, dItem->right.flags, x, w, rect.x, rect.width);
- InvalidateDItemY2(dItem->right.dirty, dItem->right.flags, dItem->y, dItem->height, rect.y, rect.height);
+ InvalidateDItemX(dItem, &dItem->right, dItem->right.x, rect.x, rect.width);
+ InvalidateDItemY(dItem, &dItem->right, dItem->y, rect.y, rect.height);
dItem->right.flags |= DITEM_DIRTY;
}
}
@@ -6565,6 +6556,8 @@ Tree_InvalidateRegion(
/* Could check border and highlight separately */
if (tree->inset > 0) {
+ x1 = rect.x, x2 = rect.x + rect.width;
+ y1 = rect.y, y2 = rect.y + rect.height;
if ((x1 < minX) || (y1 < minY) || (x2 > maxX) || (y2 > maxY)) {
if (tree->highlightWidth > 0)
dInfo->flags |= DINFO_DRAW_HIGHLIGHT;
@@ -6573,6 +6566,9 @@ Tree_InvalidateRegion(
}
}
+ /* Invalidate part of the whitespace */
+ TkSubtractRegion(dInfo->wsRgn, region, dInfo->wsRgn);
+
TkDestroyRegion(rgn);
if (tree->debug.enable && tree->debug.display && tree->debug.eraseColor) {
@@ -6648,21 +6644,6 @@ Tree_RedrawArea(
* coordinates. */
)
{
- DInfo *dInfo = (DInfo *) tree->dInfo;
-
- if (x1 < x2 && y1 < y2) {
- XRectangle rect;
- TkRegion rgn = TkCreateRegion();
-
- rect.x = x1;
- rect.y = y1;
- rect.width = x2 - x1;
- rect.height = y2 - y1;
- TkUnionRectWithRegion(&rect, rgn, rgn);
- TkSubtractRegion(dInfo->wsRgn, rgn, dInfo->wsRgn);
- TkDestroyRegion(rgn);
- }
-
Tree_InvalidateArea(tree, x1, y1, x2, y2);
Tree_EventuallyRedraw(tree);
}
@@ -6736,6 +6717,10 @@ TreeDInfo_Free(
#endif
while (dInfo->dItem != NULL) {
DItem *next = dInfo->dItem->next;
+#ifdef COLUMN_SPAN
+ if (dInfo->dItem->spans != NULL)
+ ckfree((char *) dInfo->dItem->spans);
+#endif
WFREE(dInfo->dItem, DItem);
dInfo->dItem = next;
}
@@ -6785,10 +6770,10 @@ DumpDInfo(
} else {
dbwin(" item %d x,y,w,h %d,%d,%d,%d dirty %d,%d,%d,%d flags %0X\n",
TreeItem_GetID(tree, dItem->item),
- dItem->x, dItem->y, dItem->width, dItem->height,
- dItem->dirty[LEFT], dItem->dirty[TOP],
- dItem->dirty[RIGHT], dItem->dirty[BOTTOM],
- dItem->flags);
+ dItem->area.x, dItem->y, dItem->area.width, dItem->height,
+ dItem->area.dirty[LEFT], dItem->area.dirty[TOP],
+ dItem->area.dirty[RIGHT], dItem->area.dirty[BOTTOM],
+ dItem->area.flags);
}
dItem = dItem->next;
}