summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authortreectrl <treectrl>2006-12-03 00:22:52 (GMT)
committertreectrl <treectrl>2006-12-03 00:22:52 (GMT)
commit70119230076c08f6bae58a17b9ab93a5fccee8a2 (patch)
tree1e15dceb5acceccbe006715727092137b1919270 /generic
parent164bb382bc7d505ff42383c2ab840fa7189d343b (diff)
downloadtktreectrl-70119230076c08f6bae58a17b9ab93a5fccee8a2.zip
tktreectrl-70119230076c08f6bae58a17b9ab93a5fccee8a2.tar.gz
tktreectrl-70119230076c08f6bae58a17b9ab93a5fccee8a2.tar.bz2
Changed how the display code tracks column headers to better detect changes to column size, position or visibility.
Don't mark display info OUT_OF_DATE in some cases where only INVALIDATE is needed to redraw the items.
Diffstat (limited to 'generic')
-rw-r--r--generic/tkTreeColumn.c77
-rw-r--r--generic/tkTreeCtrl.h5
-rw-r--r--generic/tkTreeDisplay.c157
3 files changed, 144 insertions, 95 deletions
diff --git a/generic/tkTreeColumn.c b/generic/tkTreeColumn.c
index f95e96e..1bc051e 100644
--- a/generic/tkTreeColumn.c
+++ b/generic/tkTreeColumn.c
@@ -7,7 +7,7 @@
* Copyright (c) 2002-2003 Christian Krone
* Copyright (c) 2003 ActiveState Corporation
*
- * RCS: @(#) $Id: tkTreeColumn.c,v 1.70 2006/12/02 21:18:40 treectrl Exp $
+ * RCS: @(#) $Id: tkTreeColumn.c,v 1.71 2006/12/03 00:22:52 treectrl Exp $
*/
#include "tkTreeCtrl.h"
@@ -121,6 +121,7 @@ struct TreeColumn_
UniformGroup *uniform; /* -uniform */
int weight; /* -weight */
#endif
+ TreeColumnDInfo dInfo; /* Display info. */
};
#ifdef UNIFORM_GROUP
@@ -1971,10 +1972,7 @@ renumber:
/* Also update columnTreeLeft. */
tree->widthOfColumns = -1;
tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1;
- Tree_DInfoChanged(tree, DINFO_CHECK_COLUMN_WIDTH |
- DINFO_INVALIDATE | DINFO_OUT_OF_DATE);
- /* BUG 784245 */
- Tree_DInfoChanged(tree, DINFO_DRAW_HEADER);
+ Tree_DInfoChanged(tree, DINFO_CHECK_COLUMN_WIDTH);
}
}
@@ -2205,7 +2203,7 @@ Column_Config(
walk = walk->next;
}
}
- Tree_DInfoChanged(tree, DINFO_INVALIDATE | DINFO_OUT_OF_DATE);
+ Tree_DInfoChanged(tree, DINFO_INVALIDATE);
}
if (!createFlag && (column->lock != lock)) {
@@ -2249,18 +2247,12 @@ Column_Config(
/* FIXME: only this column needs to be redisplayed. */
if (mask & COLU_CONF_JUSTIFY)
- Tree_DInfoChanged(tree, DINFO_INVALIDATE | DINFO_OUT_OF_DATE);
+ Tree_DInfoChanged(tree, DINFO_INVALIDATE);
/* -stepwidth and -widthhack */
if (mask & COLU_CONF_RANGES)
Tree_DInfoChanged(tree, DINFO_REDO_RANGES);
- /* If one column becomes visible and another of equal width becomes
- * hidden, and the two columns swap places with each other, then
- * display ranges are unaffected but items must be redrawn. */
- if (visible != column->visible)
- Tree_DInfoChanged(tree, DINFO_INVALIDATE | DINFO_OUT_OF_DATE);
-
/* Redraw everything */
if (mask & (COLU_CONF_TWIDTH | COLU_CONF_NWIDTH | COLU_CONF_NHEIGHT)) {
tree->widthOfColumns = -1;
@@ -2369,6 +2361,57 @@ Column_Free(
/*
*----------------------------------------------------------------------
*
+ * TreeColumn_SetDInfo --
+ *
+ * Store a display-info token in a column. Called by the display
+ * code.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TreeColumn_SetDInfo(
+ TreeColumn column, /* Column record. */
+ TreeColumnDInfo dInfo /* Display info token. */
+ )
+{
+ column->dInfo = dInfo;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TreeColumn_GetDInfo --
+ *
+ * Return the display-info token of a column. Called by the display
+ * code.
+ *
+ * Results:
+ * The display-info token or NULL.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TreeColumnDInfo
+TreeColumn_GetDInfo(
+ TreeColumn column /* Column record. */
+ )
+{
+ return column->dInfo;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TreeColumn_FixedWidth --
*
* Return the value of the -width option.
@@ -4963,7 +5006,7 @@ Tree_InvalidateColumnWidth(
}
tree->widthOfColumns = -1;
tree->widthOfColumnsLeft = tree->widthOfColumnsRight = -1;
- Tree_DInfoChanged(tree, DINFO_CHECK_COLUMN_WIDTH | DINFO_DRAW_HEADER);
+ Tree_DInfoChanged(tree, DINFO_CHECK_COLUMN_WIDTH);
}
/*
@@ -5445,10 +5488,8 @@ doOffsets:
totalWidth = 0;
column = first;
while (column != NULL && column->lock == first->lock) {
- if (column->visible) {
- column->offset = totalWidth;
- totalWidth += column->useWidth;
- }
+ column->offset = totalWidth;
+ totalWidth += column->useWidth;
column = column->next;
}
return totalWidth;
diff --git a/generic/tkTreeCtrl.h b/generic/tkTreeCtrl.h
index 1ed2b51..941df69 100644
--- a/generic/tkTreeCtrl.h
+++ b/generic/tkTreeCtrl.h
@@ -7,7 +7,7 @@
* Copyright (c) 2002-2003 Christian Krone
* Copyright (c) 2003 ActiveState Corporation
*
- * RCS: @(#) $Id: tkTreeCtrl.h,v 1.78 2006/12/02 21:42:19 treectrl Exp $
+ * RCS: @(#) $Id: tkTreeCtrl.h,v 1.79 2006/12/03 00:22:52 treectrl Exp $
*/
#include "tkPort.h"
@@ -39,6 +39,7 @@
typedef struct TreeCtrl TreeCtrl;
typedef struct TreeColumn_ *TreeColumn;
+typedef struct TreeColumnDInfo_ *TreeColumnDInfo;
typedef struct TreeDInfo_ *TreeDInfo;
typedef struct TreeDragImage_ *TreeDragImage;
typedef struct TreeItem_ *TreeItem;
@@ -702,6 +703,8 @@ extern int Tree_WidthOfColumns(TreeCtrl *tree);
extern int Tree_WidthOfLeftColumns(TreeCtrl *tree);
extern int Tree_WidthOfRightColumns(TreeCtrl *tree);
extern void TreeColumn_TreeChanged(TreeCtrl *tree, int flagT);
+extern void TreeColumn_SetDInfo(TreeColumn column, TreeColumnDInfo dInfo);
+extern TreeColumnDInfo TreeColumn_GetDInfo(TreeColumn column);
/* tkTreeDrag.c */
extern int TreeDragImage_Init(TreeCtrl *tree);
diff --git a/generic/tkTreeDisplay.c b/generic/tkTreeDisplay.c
index 3674949..4fa8a0b 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.68 2006/12/02 21:22:51 treectrl Exp $
+ * RCS: @(#) $Id: tkTreeDisplay.c,v 1.69 2006/12/03 00:22:52 treectrl Exp $
*/
#include "tkTreeCtrl.h"
@@ -16,6 +16,7 @@
#define COMPLEX_WHITESPACE
+typedef struct TreeColumnDInfo_ TreeColumnDInfo_;
typedef struct TreeDInfo_ TreeDInfo_;
typedef struct RItem RItem;
typedef struct Range Range;
@@ -81,11 +82,11 @@ struct DItem
DItem *next;
};
-typedef struct ColumnInfo {
- TreeColumn column;
+/* Display information for a TreeColumn. */
+struct TreeColumnDInfo_ {
int offset; /* Last seen x-offset */
int width; /* Last seen column width */
-} ColumnInfo;
+};
/* Display information for a TreeCtrl. */
struct TreeDInfo_
@@ -95,8 +96,6 @@ struct TreeDInfo_
int yOrigin; /* Last seen TreeCtrl.yOrigin */
int totalWidth; /* Last seen Tree_TotalWidth() */
int totalHeight; /* Last seen Tree_TotalHeight() */
- ColumnInfo *columns; /* Last seen offset & width of each column */
- int columnsSize; /* Num elements in columns[] */
int headerHeight; /* Last seen TreeCtrl.headerHeight */
DItem *dItem; /* Head of list for each displayed item */
DItem *dItemLast; /* Temp for UpdateDInfo() */
@@ -2665,9 +2664,8 @@ GetOnScreenColumnsForItemAux(
TreeColumnList *columns /* Initialized list to append to. */
)
{
- TreeDInfo dInfo = tree->dInfo;
int minX, maxX, columnIndex = 0, x = 0, i, width;
- TreeColumn column;
+ TreeColumn column = NULL, column2;
minX = MAX(area->x, bounds[0]);
maxX = MIN(area->x + area->width, bounds[2]);
@@ -2677,30 +2675,33 @@ GetOnScreenColumnsForItemAux(
switch (lock) {
case COLUMN_LOCK_LEFT:
- columnIndex = TreeColumn_Index(tree->columnLockLeft);
+ column = tree->columnLockLeft;
break;
case COLUMN_LOCK_NONE:
- columnIndex = TreeColumn_Index(tree->columnLockNone);
+ column = tree->columnLockNone;
break;
case COLUMN_LOCK_RIGHT:
- columnIndex = TreeColumn_Index(tree->columnLockRight);
+ column = tree->columnLockRight;
break;
}
- for (/* nothing */; columnIndex < tree->columnCount; columnIndex++) {
- column = dInfo->columns[columnIndex].column;
+ for (columnIndex = TreeColumn_Index(column);
+ columnIndex < tree->columnCount; columnIndex++) {
if (TreeColumn_Lock(column) != lock)
break;
- if (!TreeColumn_Visible(column))
- continue;
- width = dInfo->columns[columnIndex].width;
+ width = TreeColumn_GetDInfo(column)->width;
+ if (width == 0) /* also handles hidden columns */
+ goto next;
if (dItem->spans != NULL) {
+ /* FIXME: not possible since I skip over the entire span. */
if (dItem->spans[columnIndex] != columnIndex)
goto next;
- /* Start of a span */
+ /* Calculate the width of the span. */
+ column2 = TreeColumn_Next(column);
for (i = columnIndex + 1; columnIndex < tree->columnCount &&
dItem->spans[i] == columnIndex; i++) {
- width += dInfo->columns[i].width;
+ width += TreeColumn_GetDInfo(column2)->width;
+ column2 = TreeColumn_Next(column2);
}
columnIndex = i - 1;
}
@@ -2711,6 +2712,7 @@ next:
x += width;
if (x >= maxX)
break;
+ column = TreeColumn_Next(column);
}
}
@@ -4714,20 +4716,19 @@ DrawWhitespaceBelowItem(
int index /* Used for alternating background colors. */
)
{
- TreeDInfo dInfo = tree->dInfo;
- int i = 0;
- TreeColumn treeColumn;
+ int i = 0, width;
+ TreeColumn treeColumn = NULL;
XRectangle boundsBox, columnBox;
switch (lock) {
case COLUMN_LOCK_LEFT:
- i = TreeColumn_Index(tree->columnLockLeft);
+ treeColumn = tree->columnLockLeft;
break;
case COLUMN_LOCK_NONE:
- i = TreeColumn_Index(tree->columnLockNone);
+ treeColumn = tree->columnLockNone;
break;
case COLUMN_LOCK_RIGHT:
- i = TreeColumn_Index(tree->columnLockRight);
+ treeColumn = tree->columnLockRight;
break;
}
@@ -4736,15 +4737,15 @@ DrawWhitespaceBelowItem(
boundsBox.width = bounds[2] - bounds[0];
boundsBox.height = bounds[3] - bounds[1];
- for (/*nothing*/; i < tree->columnCount; i++) {
- treeColumn = dInfo->columns[i].column;
+ for (i = TreeColumn_Index(treeColumn); i < tree->columnCount; i++) {
if (TreeColumn_Lock(treeColumn) != lock)
break;
- if (dInfo->columns[i].width == 0)
- continue;
+ width = TreeColumn_GetDInfo(treeColumn)->width;
+ if (width == 0) /* also handles hidden columns */
+ goto next;
columnBox.x = left;
columnBox.y = top;
- columnBox.width = dInfo->columns[i].width;
+ columnBox.width = width;
columnBox.height = bounds[3] - top;
if (Tree_IntersectRect(&columnBox, &boundsBox, &columnBox)) {
TkSubtractRegion(columnRgn, columnRgn, columnRgn);
@@ -4753,7 +4754,9 @@ DrawWhitespaceBelowItem(
DrawColumnBackground(tree, drawable, treeColumn,
columnRgn, &columnBox, (RItem *) NULL, height, index);
}
- left += dInfo->columns[i].width;
+ left += width;
+next:
+ treeColumn = TreeColumn_Next(treeColumn);
}
}
@@ -5262,46 +5265,49 @@ displayRetry:
}
/* DINFO_REDO_COLUMN_WIDTH - A column was created or deleted. */
- /* DINFO_CHECK_COLUMN_WIDTH - The width of one or more columns
- * *might* have changed. Column visibility
- might have changed. */
+ /* DINFO_CHECK_COLUMN_WIDTH - The width, offset or visibility of one or
+ * more columns *might* have changed. */
if (dInfo->flags & (DINFO_REDO_COLUMN_WIDTH | DINFO_CHECK_COLUMN_WIDTH)) {
TreeColumn treeColumn = tree->columns;
- ColumnInfo *cinfo;
+ TreeColumnDInfo dColumn;
int force = (dInfo->flags & DINFO_REDO_COLUMN_WIDTH) != 0;
- int changed = force;
-
- if (dInfo->columnsSize < tree->columnCount) {
- dInfo->columnsSize = tree->columnCount + 10;
- dInfo->columns = (ColumnInfo *) ckrealloc((char *) dInfo->columns,
- sizeof(ColumnInfo) * dInfo->columnsSize);
- }
+ int redoRanges = force, drawItems = force, drawHeader = force;
+ int offset, width;
/* Set max -itembackground as well. */
tree->columnBgCnt = 0;
- cinfo = dInfo->columns;
while (treeColumn != NULL) {
- cinfo->column = treeColumn;
- cinfo->offset = TreeColumn_Offset(treeColumn);
- if (force || (cinfo->width != TreeColumn_UseWidth(treeColumn))) {
- cinfo->width = TreeColumn_UseWidth(treeColumn);
- changed = TRUE;
+ offset = TreeColumn_Offset(treeColumn);
+ width = TreeColumn_UseWidth(treeColumn);
+ dColumn = TreeColumn_GetDInfo(treeColumn);
+
+ /* Haven't seen this column before. */
+ if (dColumn == NULL) {
+ dColumn = (TreeColumnDInfo) ckalloc(sizeof(TreeColumnDInfo_));
+ TreeColumn_SetDInfo(treeColumn, dColumn);
+ if (width > 0)
+ redoRanges = drawItems = drawHeader = TRUE;
+ } else {
+ /* Changes to observed width also detects column visibililty
+ * changing. */
+ if (dColumn->width != width) {
+ redoRanges = drawItems = drawHeader = TRUE;
+ } else if ((dColumn->offset != offset) && (width > 0)) {
+ drawItems = drawHeader = TRUE;
+ }
}
+ dColumn->offset = offset;
+ dColumn->width = width;
if (TreeColumn_Visible(treeColumn) &&
(TreeColumn_BackgroundCount(treeColumn) > tree->columnBgCnt))
tree->columnBgCnt = TreeColumn_BackgroundCount(treeColumn);
- ++cinfo;
treeColumn = TreeColumn_Next(treeColumn);
}
+ if (redoRanges) dInfo->flags |= DINFO_REDO_RANGES | DINFO_OUT_OF_DATE;
+ if (drawHeader) dInfo->flags |= DINFO_DRAW_HEADER;
+ if (drawItems) dInfo->flags |= DINFO_INVALIDATE;
dInfo->flags &= ~(DINFO_REDO_COLUMN_WIDTH | DINFO_CHECK_COLUMN_WIDTH);
- if (changed) {
- dInfo->flags |=
- DINFO_INVALIDATE |
- DINFO_OUT_OF_DATE |
- DINFO_REDO_RANGES |
- DINFO_DRAW_HEADER;
- }
}
if (dInfo->headerHeight != Tree_HeaderHeight(tree)) {
dInfo->headerHeight = Tree_HeaderHeight(tree);
@@ -5406,6 +5412,14 @@ displayRetry:
Tree_UpdateDInfo(tree);
dInfo->flags &= ~DINFO_OUT_OF_DATE;
}
+ if (dInfo->flags & DINFO_INVALIDATE) {
+ for (dItem = dInfo->dItem; dItem != NULL; dItem = dItem->next) {
+ dItem->area.flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ dItem->left.flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ dItem->right.flags |= DITEM_DIRTY | DITEM_ALL_DIRTY;
+ }
+ dInfo->flags &= ~DINFO_INVALIDATE;
+ }
/*
* When an item goes from visible to hidden, "window" elements in the
@@ -6613,6 +6627,7 @@ Tree_InvalidateItemDInfo(
)
{
TreeDInfo dInfo = tree->dInfo;
+ TreeColumn column2;
DItem *dItem;
TreeItem item = item1;
int changed = 0;
@@ -6631,6 +6646,7 @@ Tree_InvalidateItemDInfo(
dItem->right.flags |= (DITEM_DIRTY | DITEM_ALL_DIRTY);
changed = 1;
} else {
+ TreeColumnDInfo dColumn = TreeColumn_GetDInfo(column);
int columnIndex, left, width, i;
DItemArea *area = NULL;
@@ -6649,22 +6665,8 @@ Tree_InvalidateItemDInfo(
if (area->flags & DITEM_ALL_DIRTY)
goto next;
- /* 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) {
- for (columnIndex = 0; columnIndex < tree->columnCount;
- columnIndex++) {
- if (dInfo->columns[columnIndex].column == column)
- break;
- }
- if (columnIndex == tree->columnCount) {
- panic("Tree_InvalidateItemDInfo: can't find a column");
- }
- } else {
- columnIndex = TreeColumn_Index(column);
- }
-
- left = dInfo->columns[columnIndex].offset;
+ columnIndex = TreeColumn_Index(column);
+ left = dColumn->offset;
/* Calculate the width of the entire span. */
/* Do NOT call TreeColumn_UseWidth() or another routine
@@ -6672,14 +6674,16 @@ Tree_InvalidateItemDInfo(
* up recalculating the size of items whose display info
* is currently being invalidated. */
if (dItem->spans == NULL) {
- width = dInfo->columns[columnIndex].width;
+ width = dColumn->width;
} else {
width = 0;
+ column2 = column;
i = dItem->spans[columnIndex];
while (dItem->spans[i] == dItem->spans[columnIndex]) {
- width += dInfo->columns[i].width;
+ width += TreeColumn_GetDInfo(column2)->width;
if (++i == tree->columnCount)
break;
+ column2 = TreeColumn_Next(column2);
}
}
@@ -6763,6 +6767,7 @@ TreeDisplay_ColumnDeleted(
TreeColumn column /* Column to remove. */
)
{
+ TreeColumnDInfo dColumn = TreeColumn_GetDInfo(column);
#ifdef DCOLUMN
TreeDInfo dInfo = tree->dInfo;
Tcl_HashSearch search;
@@ -6789,6 +6794,9 @@ if (tree->debug.enable && tree->debug.display)
hPtr = Tcl_NextHashEntry(&search);
}
#endif
+
+ if (dColumn != NULL)
+ ckfree((char *) dColumn);
}
/*
@@ -7138,8 +7146,6 @@ TreeDInfo_Init(
gcValues.graphics_exposures = True;
dInfo->scrollGC = Tk_GetGC(tree->tkwin, GCGraphicsExposures, &gcValues);
dInfo->flags = DINFO_OUT_OF_DATE;
- dInfo->columnsSize = 10;
- dInfo->columns = (ColumnInfo *) ckalloc(sizeof(ColumnInfo) * dInfo->columnsSize);
dInfo->wsRgn = TkCreateRegion();
Tcl_InitHashTable(&dInfo->itemVisHash, TCL_ONE_WORD_KEYS);
tree->dInfo = dInfo;
@@ -7205,7 +7211,6 @@ TreeDInfo_Free(
}
#endif
Tcl_DeleteHashTable(&dInfo->itemVisHash);
- ckfree((char *) dInfo->columns);
WFREE(dInfo, TreeDInfo_);
}