summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authortreectrl <treectrl>2006-12-23 04:02:54 (GMT)
committertreectrl <treectrl>2006-12-23 04:02:54 (GMT)
commit7a1f3a1803962cbe153d3a0820d61898119a140b (patch)
tree6cc54e8f255f7991e3a7e5b45789b25060aecb7a /generic
parent62862abf64aa7ce8962bf6d59e43d9ded75d381c (diff)
downloadtktreectrl-7a1f3a1803962cbe153d3a0820d61898119a140b.zip
tktreectrl-7a1f3a1803962cbe153d3a0820d61898119a140b.tar.gz
tktreectrl-7a1f3a1803962cbe153d3a0820d61898119a140b.tar.bz2
Changed the way text elements display an ellipsis. At least 1 character plus the ellipsis is displayed if the text element is squeezed. Previously the ellipsis would not be drawn once there wasn't room for 1 character plus the ellipsis.
Fixed a layout bug with multi-line text elements when the unsqueezed element did not require a multi-line layout but the squeezed element did.
Diffstat (limited to 'generic')
-rw-r--r--generic/tkTreeElem.c31
-rw-r--r--generic/tkTreeUtils.c79
2 files changed, 63 insertions, 47 deletions
diff --git a/generic/tkTreeElem.c b/generic/tkTreeElem.c
index 8d1e37b..0965b58 100644
--- a/generic/tkTreeElem.c
+++ b/generic/tkTreeElem.c
@@ -5,7 +5,7 @@
*
* Copyright (c) 2002-2006 Tim Baker
*
- * RCS: @(#) $Id: tkTreeElem.c,v 1.61 2006/12/22 22:33:00 treectrl Exp $
+ * RCS: @(#) $Id: tkTreeElem.c,v 1.62 2006/12/23 04:02:54 treectrl Exp $
*/
#include "tkTreeCtrl.h"
@@ -2732,8 +2732,9 @@ TextUpdateLayout(
DynamicOption *opt;
if (tree->debug.enable && tree->debug.textLayout)
- dbwin("TextUpdateLayout: %s %p (%s) %s\n",
- Tk_PathName(tree->tkwin), elemX, masterX ? "instance" : "master", func);
+ dbwin("TextUpdateLayout: %s %p (%s) %s\n fixedWidth %d maxWidth %d\n",
+ Tk_PathName(tree->tkwin), elemX, masterX ? "instance" : "master",
+ func, fixedWidth, maxWidth);
etl2 = DynamicOption_FindData(elem->options, 1007);
if (etl2 != NULL && etl2->layout != NULL) {
@@ -2800,7 +2801,7 @@ TextUpdateLayout(
if (width == 0)
return etl2;
textWidth = Tk_TextWidth(tkfont, text, textLen);
-if (tree->debug.enable && tree->debug.textLayout) dbwin(" textWidth %d\n", textWidth);
+if (tree->debug.enable && tree->debug.textLayout) dbwin(" available width %d textWidth %d\n", width, textWidth);
if (width >= textWidth)
return etl2;
}
@@ -2813,9 +2814,15 @@ if (tree->debug.enable && tree->debug.textLayout) dbwin(" textWidth %d\n", te
if (wrap == TEXT_WRAP_WORD)
flags |= TK_WHOLE_WORDS;
- opt = (DynamicOption *) DynamicOption_AllocIfNeeded(tree, &elem->options,
- 1007, sizeof(ElementTextLayout2), NULL);
- etl2 = (ElementTextLayout2 *) opt->data;
+ if (etl2 == NULL) {
+ opt = (DynamicOption *) DynamicOption_AllocIfNeeded(tree,
+ &elem->options, 1007, sizeof(ElementTextLayout2), NULL);
+ etl2 = (ElementTextLayout2 *) opt->data;
+ /* It is possible that the needed size of this element does not
+ * require a TextLayout, in which case neededWidth never gets
+ * set. */
+ etl2->neededWidth = -1;
+ }
etl2->layout = TextLayout_Compute(tkfont, text,
Tcl_NumUtfChars(text, textLen), width, justify, lines, flags);
@@ -3033,6 +3040,7 @@ TextRedoLayoutIfNeeded(
return etl2;
if (etl2 != NULL && etl2->layout != NULL) {
+
/* See comment in NeededProc about totalWidth */
if ((etl2->neededWidth != -1) && (fixedWidth >= etl2->neededWidth))
fixedWidth = etl2->totalWidth;
@@ -3147,6 +3155,7 @@ static void DisplayProcText(ElementArgs *args)
if (layout != NULL) {
TextLayout_Size(layout, &width, &height);
+ pixelsForText = width;
/* Hack -- The actual size of the text may be slightly smaller than
* the available space when squeezed. If so we don't want to center
* the text horizontally */
@@ -3156,8 +3165,8 @@ static void DisplayProcText(ElementArgs *args)
args->display.width, args->display.height,
FALSE, FALSE,
&x, &y, &width, &height);
- /* Use clipping if text is taller than display height */
- if (height > args->display.height) {
+ /* Use clipping if text is larger than the display area. */
+ if (pixelsForText > args->display.width || height > args->display.height) {
XRectangle rect;
clipRgn = Tree_GetRegion(tree);
rect.x = x;
@@ -3190,8 +3199,8 @@ static void DisplayProcText(ElementArgs *args)
args->display.width, args->display.height,
FALSE, FALSE,
&x, &y, &width, &height);
- /* Use clipping if text is taller than display height */
- if (height > args->display.height) {
+ /* Use clipping if text is larger than the display area. */
+ if (pixelsForText > args->display.width || height > args->display.height) {
XRectangle rect;
clipRgn = Tree_GetRegion(tree);
rect.x = x;
diff --git a/generic/tkTreeUtils.c b/generic/tkTreeUtils.c
index 3645e9b..a369526 100644
--- a/generic/tkTreeUtils.c
+++ b/generic/tkTreeUtils.c
@@ -5,7 +5,7 @@
*
* Copyright (c) 2002-2006 Tim Baker
*
- * RCS: @(#) $Id: tkTreeUtils.c,v 1.61 2006/12/22 22:33:00 treectrl Exp $
+ * RCS: @(#) $Id: tkTreeUtils.c,v 1.62 2006/12/23 04:02:55 treectrl Exp $
*/
#include "tkTreeCtrl.h"
@@ -126,10 +126,15 @@ DStringAppendf(
* with an ellipsis "..." appended that will fit.
*
* Results:
- * When the return value is positive the caller should add the
- * ellipsis to the string (unless the entire string fits).
- * When the return value is negative the caller should not add
- * the ellipsis because only a few characters fit.
+ * When the return value is equal to numBytes the caller should
+ * not add the ellipsis to the string (unless force is TRUE). In
+ * this case maxPixels contains the number of pixels for the entire
+ * string (plus ellipsis if force is TRUE).
+ *
+ * When the return value is less than numBytes the caller should add
+ * the ellipsis because only a substring fits. In this case
+ * maxPixels contains the number of pixels for the substring
+ * plus ellipsis. The substring has a minimum of one character.
*
* Side effects:
* None.
@@ -154,6 +159,8 @@ Ellipsis(
char staticStr[256], *tmpStr = staticStr;
int pixels, pixelsTest, bytesThatFit, bytesTest;
int ellipsisNumBytes = strlen(ellipsis);
+ int bytesInFirstCh;
+ Tcl_UniChar uniCh;
bytesThatFit = Tk_MeasureChars(tkfont, string, numBytes, *maxPixels, 0,
&pixels);
@@ -164,9 +171,9 @@ Ellipsis(
return numBytes;
}
- if (bytesThatFit <= 1) {
- (*maxPixels) = pixels;
- return -bytesThatFit;
+ bytesInFirstCh = Tcl_UtfToUniChar(string, &uniCh);
+ if (bytesThatFit <= bytesInFirstCh) {
+ goto singleChar;
}
/* Strip off one character at a time, adding ellipsis, until it fits */
@@ -191,12 +198,19 @@ Ellipsis(
bytesTest = Tcl_UtfPrev(string + bytesTest, string) - string;
}
- /* No single char + ellipsis fits. Return number of chars that fit */
- /* Negative tells caller to not add ellipsis */
+ singleChar:
+ /* No single char + ellipsis fits. Return the number of bytes for
+ * the first character. The returned pixel width is the width of the
+ * first character plus ellipsis. */
+ bytesThatFit = bytesInFirstCh;
+ memcpy(tmpStr, string, bytesThatFit);
+ memcpy(tmpStr + bytesThatFit, ellipsis, ellipsisNumBytes);
+ (void) Tk_MeasureChars(tkfont, tmpStr, bytesThatFit + ellipsisNumBytes,
+ -1, 0, &pixels);
(*maxPixels) = pixels;
if (tmpStr != staticStr)
ckfree(tmpStr);
- return -bytesThatFit;
+ return bytesThatFit;
}
/*
@@ -1537,9 +1551,7 @@ TextLayout TextLayout_Compute(
if (freeLayoutInfo != NULL) {
layoutPtr = freeLayoutInfo;
freeLayoutInfo = layoutPtr->nextFree;
- }
- else
- {
+ } else {
maxChunks = 1;
layoutPtr = (LayoutInfo *) ckalloc(sizeof(LayoutInfo) +
(maxChunks - 1) * sizeof(LayoutChunk));
@@ -1617,9 +1629,7 @@ TextLayout TextLayout_Compute(
flags &= ~TK_AT_LEAST_ONE;
continue;
}
- }
- else
- {
+ } else {
#ifdef TEXTLAYOUT_ALLOCHAX
NewChunk(&layoutPtr, start, 1, curX, curX,
#else
@@ -1696,6 +1706,7 @@ wrapLine:
char *ellipsis = "...";
int ellipsisLen = strlen(ellipsis);
char staticStr[256], *buf = staticStr;
+ int pixelsForText;
chunkPtr = &layoutPtr->chunks[layoutPtr->numChunks - 1];
if (wrapLength > 0) {
@@ -1710,28 +1721,29 @@ wrapLine:
if (chunkPtr->start[0] == '\n')
continue;
- newX = chunkPtr->totalWidth - 1;
if (chunkPtr->x + chunkPtr->totalWidth < wrapLength)
- newX = wrapLength - chunkPtr->x;
+ pixelsForText = wrapLength - chunkPtr->x;
+ else
+ pixelsForText = chunkPtr->totalWidth - 1;
bytesThisChunk = Ellipsis(tkfont, (char *) chunkPtr->start,
- chunkPtr->numBytes, &newX, ellipsis, TRUE);
+ chunkPtr->numBytes, &pixelsForText, ellipsis, TRUE);
+ if (pixelsForText > wrapLength - chunkPtr->x)
+ pixelsForText = wrapLength - chunkPtr->x;
if (bytesThisChunk > 0) {
chunkPtr->numBytes = bytesThisChunk;
chunkPtr->numChars = Tcl_NumUtfChars(chunkPtr->start, bytesThisChunk);
chunkPtr->numDisplayChars = chunkPtr->numChars;
chunkPtr->ellipsis = TRUE;
- chunkPtr->displayWidth = newX;
- chunkPtr->totalWidth = newX;
+ chunkPtr->displayWidth = pixelsForText;
+ chunkPtr->totalWidth = pixelsForText;
lineLengths = (int *) Tcl_DStringValue(&lineBuffer);
- lineLengths[layoutPtr->numLines - 1] = chunkPtr->x + newX;
- if (chunkPtr->x + newX > maxWidth)
- maxWidth = chunkPtr->x + newX;
+ lineLengths[layoutPtr->numLines - 1] = chunkPtr->x + pixelsForText;
+ if (chunkPtr->x + pixelsForText > maxWidth)
+ maxWidth = chunkPtr->x + pixelsForText;
break;
}
}
- }
- else
- {
+ } else {
if (chunkPtr->start[0] == '\n') {
if (layoutPtr->numChunks == 1)
goto finish;
@@ -1775,9 +1787,7 @@ layoutPtr->totalWidth = 0;
layoutPtr->chunks[0].y = fm.ascent;
layoutPtr->chunks[0].totalWidth = 0;
layoutPtr->chunks[0].displayWidth = 0;
- }
- else
- {
+ } else {
curLine = 0;
chunkPtr = layoutPtr->chunks;
y = chunkPtr->y;
@@ -1876,9 +1886,7 @@ void TextLayout_Draw(
drawX = 0;
firstChar = 0;
firstByte = chunkPtr->start;
- }
- else
- {
+ } else {
firstByte = Tcl_UtfAtIndex(chunkPtr->start, firstChar);
Tk_MeasureChars(layoutPtr->tkfont, chunkPtr->start,
firstByte - chunkPtr->start, -1, 0, &drawX);
@@ -1901,8 +1909,7 @@ void TextLayout_Draw(
x + chunkPtr->x + drawX, y + chunkPtr->y);
if (buf != staticStr)
ckfree(buf);
- }
- else
+ } else
#endif
Tk_DrawChars(display, drawable, gc, layoutPtr->tkfont,
firstByte, lastByte - firstByte, x + chunkPtr->x + drawX,