Tcl-Tk-Tkwidget-treectrl
view release on metacpan or search on metacpan
generic/tkTreeDisplay.c view on Meta::CPAN
/* Display information for a TreeCtrl. */
struct TreeDInfo_
{
GC scrollGC;
int xOrigin; /* Last seen TreeCtrl.xOrigin */
int yOrigin; /* Last seen TreeCtrl.yOrigin */
int totalWidth; /* Last seen Tree_CanvasWidth() */
int totalHeight; /* Last seen Tree_CanvasHeight() */
int fakeCanvasWidth; /* totalWidth plus any "fake" width resulting
* from the view being locked to the edge of
* a scroll increment. */
int fakeCanvasHeight; /* totalHeight plus any "fake" height resulting
* from the view being locked to the edge of
* a scroll increment.*/
int headerHeight; /* Last seen TreeCtrl.headerHeight */
DItem *dItem; /* Head of list for each displayed item */
DItem *dItemHeader; /* Head of list for each displayed header */
DItem *dItemLast; /* Temp for UpdateDInfo() */
DItem *dItemFree; /* List of unused DItems */
Range *rangeFirst; /* Head of Ranges */
Range *rangeLast; /* Tail of Ranges */
Range *rangeFirstD; /* First range with valid display info */
Range *rangeLastD; /* Last range with valid display info */
RItem *rItem; /* Block of RItems for all Ranges */
int rItemMax; /* size of rItem[] */
int itemHeight; /* Observed max TreeItem height */
int itemWidth; /* Observed max TreeItem width */
TreeDrawable pixmapW; /* Pixmap as big as the window */
TreeDrawable pixmapI; /* Pixmap as big as the largest item */
TreeDrawable pixmapT; /* Pixmap as big as the window.
Use on non-composited desktops when
displaying non-XOR dragimage, marquee
and/or proxies. */
TkRegion dirtyRgn; /* DOUBLEBUFFER_WINDOW */
int flags; /* DINFO_XXX */
DScrollIncrements xScrollIncrements;
DScrollIncrements yScrollIncrements;
TkRegion wsRgn; /* Region containing whitespace */
#ifdef COMPLEX_WHITESPACE
int complexWhitespace;
#endif
Tcl_HashTable itemVisHash; /* Table of visible items */
Tcl_HashTable headerVisHash;/* Table of visible header items */
int requests; /* Incremented for every call to
Tree_EventuallyRedraw */
TreeRectangle bounds; /* Bounds of TREE_AREA_CONTENT. */
TreeRectangle boundsL; /* Bounds of TREE_AREA_LEFT. */
TreeRectangle boundsR; /* Bounds of TREE_AREA_RIGHT. */
int empty, emptyL, emptyR; /* Whether bounds above are zero-sized.*/
int widthOfColumnsLeft; /* Last seen Tree_WidthOfLeftColumns() */
int widthOfColumnsRight; /* Last seen Tree_WidthOfRightColumns() */
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. */
#if REDRAW_RGN == 1
TkRegion redrawRgn; /* Contains all redrawn (not copied) pixels
* during a single Tree_Display call. */
#endif /* REDRAW_RGN */
int overlays; /* TRUE if the dragimage|marquee|proxy
* were drawn in non-XOR mode. */
#if CACHE_BG_IMG
TreeDrawable pixmapBgImg; /* Pixmap containing the -backgroundimage
* for efficient blitting. Not used if the
* -backgroundimage is transparent. */
#endif
};
#ifdef COMPLEX_WHITESPACE
static int ComplexWhitespace(TreeCtrl *tree);
#endif
static int CalcBgImageBounds(TreeCtrl *tree, TreeRectangle *trImage);
/*========*/
void
Tree_FreeItemRInfo(
TreeCtrl *tree,
TreeItem item
)
{
TreeItem_SetRInfo(tree, item, NULL);
}
static Range *
Range_Free(
TreeCtrl *tree,
Range *range
)
{
Range *next = range->next;
WFREE(range, Range);
return next;
}
/*
*----------------------------------------------------------------------
*
* ItemWidthParams --
*
* Calculates the fixed or incremental width of all items.
* This is called when -orient=horizontal.
*
* Results:
* Returns the fixed width all items should be, or -1.
* Returns the width all item widths should be a multiple of, or -1.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static void
ItemWidthParams(
TreeCtrl *tree, /* Widget info. */
int *fixedWidthPtr, /* Returned fixed width or -1. */
int *stepWidthPtr /* Returned incremental width or -1. */
)
generic/tkTreeDisplay.c view on Meta::CPAN
ckfree((char *) Tcl_GetHashValue(hPtr));
#endif
Tcl_DeleteHashEntry(hPtr);
}
/* Add newly-visible items to itemVisHash */
count = TreeItemList_Count(&newV);
for (i = 0; i < count; i++) {
item = TreeItemList_Nth(&newV, i);
hPtr = Tcl_CreateHashEntry(tablePtr, (char *) item, &isNew);
#ifdef DCOLUMN
TrackOnScreenColumnsForItem(tree, item, hPtr);
#endif /* DCOLUMN */
}
if (!doHeaders) {
/*
* Generate an <ItemVisibility> event here. This can be used to set
* an item's styles when the item is about to be displayed, and to
* clear an item's styles when the item is no longer displayed.
*/
if (TreeItemList_Count(&newV) || TreeItemList_Count(&newH)) {
TreeNotify_ItemVisibility(tree, &newV, &newH);
}
}
TreeItemList_Free(&newV);
TreeItemList_Free(&newH);
if (tree->deleted || !Tk_IsMapped(tree->tkwin))
return DISPLAY_EXIT;
if (TreeDisplay_WasThereTrouble(tree, requests))
return DISPLAY_RETRY;
return DISPLAY_OK;
}
/*
*----------------------------------------------------------------------
*
* SetBuffering --
*
* Chooses the appropriate level of offscreen buffering depending
* on whether we need to draw the dragimage|marquee|proxies in non-XOR.
*
* Results:
* tree->doubleBuffer is possibly updated.
*
* Side effects:
* If the buffering level changes then the whole list is redrawn.
*
*----------------------------------------------------------------------
*/
static void
SetBuffering(
TreeCtrl *tree)
{
TreeDInfo dInfo = tree->dInfo;
int overlays = FALSE;
if ((TreeDragImage_IsVisible(tree->dragImage) &&
!TreeDragImage_IsXOR(tree->dragImage)) ||
(TreeMarquee_IsVisible(tree->marquee) &&
!TreeMarquee_IsXOR(tree->marquee)) ||
((tree->columnProxy.xObj || tree->rowProxy.yObj) &&
!Proxy_IsXOR())) {
overlays = TRUE;
}
#if 1
tree->doubleBuffer = DOUBLEBUFFER_WINDOW;
#else
#if defined(MAC_OSX_TK) && (TK_MAJOR_VERSION==8) && (TK_MINOR_VERSION>=6)
/* Do NOT call TkScrollWindow(), it generates an <Expose> event which redraws *all*
* child windows of children of the toplevel this treectrl is in. See Tk bug 3086887. */
tree->doubleBuffer = DOUBLEBUFFER_WINDOW;
#else
if (overlays) {
tree->doubleBuffer = DOUBLEBUFFER_WINDOW;
} else {
tree->doubleBuffer = DOUBLEBUFFER_ITEM;
}
#endif
#endif
if (overlays != dInfo->overlays) {
dInfo->flags |=
DINFO_DRAW_HEADER |
DINFO_INVALIDATE |
DINFO_DRAW_WHITESPACE;
dInfo->overlays = overlays;
}
}
#if 0
struct ExposeRestrictClientData {
TreeCtrl *tree;
unsigned long serial;
};
static Tk_RestrictAction
ExposeRestrictProc(
ClientData clientData,
XEvent *eventPtr
)
{
struct ExposeRestrictClientData *cd = clientData;
TreeCtrl *tree = cd->tree;
dbwin("ExposeRestrictProc type=%d", eventPtr->type);
if ((eventPtr->type == Expose) &&
(eventPtr->xexpose.window == Tk_WindowId(tree->tkwin)) &&
(eventPtr->xany.serial == cd->serial)) {
int x = eventPtr->xexpose.x, y = eventPtr->xexpose.y;
int w = eventPtr->xexpose.width, h = eventPtr->xexpose.height;
if (w > 0 && h > 0)
DblBufWinDirty(tree, x, y, x + w, y + h); /* FIXME: DINFO_DRAW_BORDERS */
return TK_DISCARD_EVENT;
}
return TK_DEFER_EVENT;
}
#endif
/*
*--------------------------------------------------------------
*
* Tree_Display --
*
* This procedure is called at idle time when something has happened
* that might require the list to be redisplayed. An effort is made
* to only redraw what is needed.
*
* Results:
* None.
*
* Side effects:
* Stuff is drawn in the TreeCtrl window.
*
*--------------------------------------------------------------
*/
static void
Tree_Display(
ClientData clientData /* Widget info. */
)
{
TreeCtrl *tree = clientData;
TreeDInfo dInfo = tree->dInfo;
DItem *dItem;
Tk_Window tkwin = tree->tkwin;
int didScrollX = 0, didScrollY = 0;
Drawable drawable;
TreeDrawable tdrawable;
generic/tkTreeDisplay.c view on Meta::CPAN
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 (TreeDisplay_WasThereTrouble(tree, requests)) {
if (tree->deleted || !Tk_IsMapped(tree->tkwin))
goto displayExit;
goto displayRetry;
}
if (dItem->right.flags & DITEM_DIRTY) {
drawn += DisplayDItem(tree, dItem, &dItem->right, COLUMN_LOCK_RIGHT,
dInfo->boundsR, tpixmap, tdrawable);
}
} else {
dItem->right.flags &= ~DITEM_DRAWN;
}
numDraw += drawn ? 1 : 0;
dItem->oldX = dItem->area.x; /* FIXME: could have dInfo->empty */
dItem->oldY = dItem->y;
dItem->oldIndex = dItem->index;
}
}
if (tree->debug.enable && tree->debug.display)
dbwin("copy %d draw %d %s\n", numCopy, numDraw, Tk_PathName(tkwin));
#if 0
/* Eat <Expose> events caused by embedded windows during scrolling. */
if ((tree->doubleBuffer == DOUBLEBUFFER_WINDOW) && (didScrollX || didScrollY)) {
ClientData oldArg;
Tk_RestrictProc *oldProc;
struct ExposeRestrictClientData cd;
int oldMode;
while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {};
oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
cd.tree = tree;
cd.serial = LastKnownRequestProcessed(tree->display);
TkpSync(tree->display);
oldProc = Tk_RestrictEvents(ExposeRestrictProc, &cd, &oldArg);
while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {}
Tk_RestrictEvents(oldProc, oldArg, &oldArg);
/* while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}*/
Tcl_SetServiceMode(oldMode);
}
#endif
#if 0 && REDRAW_RGN == 1
tree->drawableXOrigin = tree->xOrigin;
tree->drawableYOrigin = tree->yOrigin;
if (TreeDragImage_IsXOR(tree->dragImage) == FALSE)
TreeDragImage_DrawClipped(tree->dragImage, tdrawable, dInfo->redrawRgn);
if (TreeMarquee_IsXOR(tree->marquee) == FALSE)
TreeMarquee_DrawClipped(tree->marquee, tdrawable, dInfo->redrawRgn);
Tree_SetEmptyRegion(dInfo->redrawRgn);
#endif /* REDRAW_RGN */
if (dInfo->overlays) {
tdrawable.width = Tk_Width(tkwin);
tdrawable.height = Tk_Height(tkwin);
if (TreeTheme_IsDesktopComposited(tree)) {
tdrawable.drawable = Tk_WindowId(tkwin);
} else {
tdrawable.drawable = DisplayGetPixmap(tree, &dInfo->pixmapT,
Tk_Width(tree->tkwin), Tk_Height(tree->tkwin));
}
/* Copy double-buffer */
/* FIXME: only copy what is in dirtyRgn plus overlays */
XCopyArea(tree->display, dInfo->pixmapW.drawable,
tdrawable.drawable,
tree->copyGC,
Tree_BorderLeft(tree), Tree_BorderTop(tree),
Tree_BorderRight(tree) - Tree_BorderLeft(tree),
Tree_BorderBottom(tree) - Tree_BorderTop(tree),
Tree_BorderLeft(tree), Tree_BorderTop(tree));
/* Draw dragimage|marquee|proxies */
tree->drawableXOrigin = tree->xOrigin;
tree->drawableYOrigin = tree->yOrigin;
if (TreeDragImage_IsXOR(tree->dragImage) == FALSE)
TreeDragImage_Draw(tree->dragImage, tdrawable);
if (TreeMarquee_IsXOR(tree->marquee) == FALSE)
TreeMarquee_Draw(tree->marquee, tdrawable);
if (Proxy_IsXOR() == FALSE)
TreeColumnProxy_Draw(tree, tdrawable);
if (Proxy_IsXOR() == FALSE)
TreeRowProxy_Draw(tree, tdrawable);
if (TreeTheme_IsDesktopComposited(tree) == FALSE) {
/* Copy tripple-buffer to window */
/* FIXME: only copy what is in dirtyRgn plus overlays */
XCopyArea(tree->display, dInfo->pixmapT.drawable,
Tk_WindowId(tkwin),
tree->copyGC,
Tree_BorderLeft(tree), Tree_BorderTop(tree),
Tree_BorderRight(tree) - Tree_BorderLeft(tree),
Tree_BorderBottom(tree) - Tree_BorderTop(tree),
Tree_BorderLeft(tree), Tree_BorderTop(tree));
}
Tree_SetEmptyRegion(dInfo->dirtyRgn);
DisplayDelay(tree);
}
else if (tree->doubleBuffer == DOUBLEBUFFER_WINDOW) {
TreeRectangle box;
drawable = Tk_WindowId(tkwin);
Tree_GetRegionBounds(dInfo->dirtyRgn, &box);
if (box.width > 0 && box.height > 0) {
TkSetRegion(tree->display, tree->copyGC, dInfo->dirtyRgn);
XCopyArea(tree->display, dInfo->pixmapW.drawable, drawable,
tree->copyGC,
box.x, box.y,
box.width, box.height,
box.x, box.y);
XSetClipMask(tree->display, tree->copyGC, None);
}
Tree_SetEmptyRegion(dInfo->dirtyRgn);
DisplayDelay(tree);
}
/* XOR on */
if (TreeMarquee_IsXOR(tree->marquee))
TreeMarquee_Display(tree->marquee);
if (TreeDragImage_IsXOR(tree->dragImage))
TreeDragImage_Display(tree->dragImage);
if (Proxy_IsXOR())
TreeRowProxy_Display(tree);
if (Proxy_IsXOR())
TreeColumnProxy_Display(tree);
if (tree->doubleBuffer == DOUBLEBUFFER_NONE)
dInfo->flags |= DINFO_DRAW_HIGHLIGHT | DINFO_DRAW_BORDER;
if (dInfo->flags & (DINFO_DRAW_BORDER | DINFO_DRAW_HIGHLIGHT)) {
drawable = Tk_WindowId(tkwin);
if (tree->useTheme && TreeTheme_DrawBorders(tree, drawable) == TCL_OK) {
/* nothing */
} else {
/* Draw focus rectangle (outside of 3D-border) */
if ((dInfo->flags & DINFO_DRAW_HIGHLIGHT) &&
(tree->highlightWidth > 0)) {
GC fgGC, bgGC;
DebugDrawBorder(tree, 0, tree->highlightWidth,
tree->highlightWidth, tree->highlightWidth,
tree->highlightWidth);
bgGC = Tk_GCForColor(tree->highlightBgColorPtr, drawable);
( run in 1.071 second using v1.01-cache-2.11-cpan-7fcb06a456a )