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 )