summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
Diffstat (limited to 'generic')
-rw-r--r--generic/tkListbox.c152
1 files changed, 137 insertions, 15 deletions
diff --git a/generic/tkListbox.c b/generic/tkListbox.c
index 95f7862..490f795 100644
--- a/generic/tkListbox.c
+++ b/generic/tkListbox.c
@@ -90,14 +90,14 @@ typedef struct {
* display. */
int topIndex; /* Index of top-most element visible in
* window. */
- int fullLines; /* Number of lines that fit are completely
+ int fullLines; /* Number of lines that are completely
* visible in window. There may be one
* additional line at the bottom that is
* partially visible. */
int partialLine; /* 0 means that the window holds exactly
* fullLines lines. 1 means that there is one
* additional line that is partially
- * visble. */
+ * visible. */
int setGrid; /* Non-zero means pass gridding information to
* window manager. */
@@ -131,7 +131,7 @@ typedef struct {
int active; /* Index of "active" element (the one that has
* been selected by keyboard traversal). -1
* means none. */
- int activeStyle; /* style in which to draw the active element.
+ int activeStyle; /* Style in which to draw the active element.
* One of: underline, none, dotbox */
/*
@@ -165,6 +165,9 @@ typedef struct {
Pixmap gray; /* Pixmap for displaying disabled text. */
int flags; /* Various flag bits: see below for
* definitions. */
+ Tk_Justify justify; /* Justification. */
+ int oldMaxOffset; /* Used in scrolling for right/center
+ * justification. */
} Listbox;
/*
@@ -197,7 +200,7 @@ typedef struct {
* be updated.
* GOT_FOCUS: Non-zero means this widget currently has the
* input focus.
- * MAXWIDTH_IS_STALE: Stored maxWidth may be out-of-date
+ * MAXWIDTH_IS_STALE: Stored maxWidth may be out-of-date.
* LISTBOX_DELETED: This listbox has been effectively destroyed.
*/
@@ -275,6 +278,8 @@ static const Tk_OptionSpec optionSpecs[] = {
{TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
"HighlightThickness", DEF_LISTBOX_HIGHLIGHT_WIDTH, -1,
Tk_Offset(Listbox, highlightWidth), 0, 0, 0},
+ {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
+ DEF_LISTBOX_JUSTIFY, -1, Tk_Offset(Listbox, justify), 0, 0, 0},
{TK_OPTION_RELIEF, "-relief", "relief", "Relief",
DEF_LISTBOX_RELIEF, -1, Tk_Offset(Listbox, relief), 0, 0, 0},
{TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground",
@@ -313,7 +318,7 @@ static const Tk_OptionSpec optionSpecs[] = {
/*
* The itemAttrOptionSpecs table defines the valid configuration options for
- * listbox items
+ * listbox items.
*/
static const Tk_OptionSpec itemAttrOptionSpecs[] = {
@@ -340,7 +345,7 @@ static const Tk_OptionSpec itemAttrOptionSpecs[] = {
};
/*
- * The following tables define the listbox widget commands (and sub- commands)
+ * The following tables define the listbox widget commands (and sub-commands)
* and map the indexes into the string tables into enumerated types used to
* dispatch the listbox widget command.
*/
@@ -436,6 +441,7 @@ static char * ListboxListVarProc(ClientData clientData,
const char *name2, int flags);
static void MigrateHashEntries(Tcl_HashTable *table,
int first, int last, int offset);
+static int GetMaxOffset(Listbox *listPtr);
/*
* The structure below defines button class behavior by means of procedures
@@ -546,6 +552,8 @@ Tk_ListboxObjCmd(
listPtr->cursor = None;
listPtr->state = STATE_NORMAL;
listPtr->gray = None;
+ listPtr->justify = TK_JUSTIFY_LEFT;
+ listPtr->oldMaxOffset = 0;
/*
* Keep a hold of the associated tkwin until we destroy the listbox,
@@ -572,6 +580,13 @@ Tk_ListboxObjCmd(
return TCL_ERROR;
}
+ if (listPtr->justify == TK_JUSTIFY_RIGHT) {
+ listPtr->xOffset = GetMaxOffset(listPtr);
+ } else if (listPtr->justify == TK_JUSTIFY_CENTER) {
+ listPtr->xOffset = GetMaxOffset(listPtr) / 2;
+ listPtr->xOffset -= listPtr->xOffset % listPtr->xScrollUnit;
+ }
+
Tcl_SetObjResult(interp, TkNewWindowObj(listPtr->tkwin));
return TCL_OK;
}
@@ -613,7 +628,7 @@ ListboxWidgetObjCmd(
/*
* Parse the command by looking up the second argument in the list of
- * valid subcommand names
+ * valid subcommand names.
*/
result = Tcl_GetIndexFromObj(interp, objv[1], commandNames,
@@ -1837,6 +1852,7 @@ DisplayListbox(
* or right edge of the listbox is
* off-screen. */
Pixmap pixmap;
+ int totalLength, height;
listPtr->flags &= ~REDRAW_PENDING;
if (listPtr->flags & LISTBOX_DELETED) {
@@ -2016,7 +2032,7 @@ DisplayListbox(
} else {
/*
* If there is an item attributes record for this item, draw
- * the background box and set the foreground color accordingly
+ * the background box and set the foreground color accordingly.
*/
if (entry != NULL) {
@@ -2056,12 +2072,26 @@ DisplayListbox(
* Draw the actual text of this item.
*/
+ Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &curElement);
+ stringRep = Tcl_GetStringFromObj(curElement, &stringLen);
+ Tk_ComputeTextLayout(listPtr->tkfont, stringRep, stringLen, 0,
+ listPtr->justify, TK_IGNORE_NEWLINES, &totalLength, &height);
+
Tk_GetFontMetrics(listPtr->tkfont, &fm);
y += fm.ascent + listPtr->selBorderWidth;
- x = listPtr->inset + listPtr->selBorderWidth - listPtr->xOffset;
- Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &curElement);
- stringRep = Tcl_GetStringFromObj(curElement, &stringLen);
- Tk_DrawChars(listPtr->display, pixmap, gc, listPtr->tkfont,
+
+ if (listPtr->justify == TK_JUSTIFY_LEFT) {
+ x = listPtr->inset + listPtr->selBorderWidth - listPtr->xOffset;
+ } else if (listPtr->justify == TK_JUSTIFY_RIGHT) {
+ x = width - totalLength - listPtr->inset -
+ listPtr->selBorderWidth - listPtr->xOffset +
+ GetMaxOffset(listPtr) - 1;
+ } else {
+ x = (width + GetMaxOffset(listPtr))/2 - totalLength/2 -
+ listPtr->xOffset;
+ }
+
+ Tk_DrawChars(listPtr->display, pixmap, gc, listPtr->tkfont,
stringRep, stringLen, x, y);
/*
@@ -2458,7 +2488,7 @@ ListboxDeleteSubCmd(
/*
* Check width of the element. We only have to check if widthChanged
* has not already been set to 1, because we only need one maxWidth
- * element to disappear for us to have to recompute the width
+ * element to disappear for us to have to recompute the width.
*/
if (widthChanged == 0) {
@@ -2581,6 +2611,7 @@ ListboxEventProc(
ClientData clientData, /* Information about window. */
XEvent *eventPtr) /* Information about event. */
{
+ int tmpOffset, tmpOffset2, maxOffset;
Listbox *listPtr = clientData;
if (eventPtr->type == Expose) {
@@ -2612,6 +2643,63 @@ ListboxEventProc(
}
listPtr->flags |= UPDATE_V_SCROLLBAR|UPDATE_H_SCROLLBAR;
ChangeListboxView(listPtr, listPtr->topIndex);
+ if (listPtr->justify == TK_JUSTIFY_RIGHT) {
+ maxOffset = GetMaxOffset(listPtr);
+ if (maxOffset != listPtr->oldMaxOffset && listPtr->oldMaxOffset > 0) {
+
+ /*
+ * Window has shrunk.
+ */
+
+ if (maxOffset > listPtr->oldMaxOffset) {
+ tmpOffset = maxOffset - listPtr->oldMaxOffset;
+ } else {
+ tmpOffset = listPtr->oldMaxOffset - maxOffset;
+ }
+ tmpOffset -= tmpOffset % listPtr->xScrollUnit;
+ if ((tmpOffset + listPtr->xOffset) > maxOffset) {
+ tmpOffset = maxOffset - listPtr->xOffset;
+ }
+ if (tmpOffset < 0) {
+ tmpOffset = 0;
+ }
+ listPtr->xOffset += tmpOffset;
+ } else {
+ listPtr->xOffset = maxOffset;
+ }
+ listPtr->oldMaxOffset = maxOffset;
+ } else if (listPtr->justify == TK_JUSTIFY_CENTER) {
+ maxOffset = GetMaxOffset(listPtr);
+ if (maxOffset != listPtr->oldMaxOffset && listPtr->oldMaxOffset > 0) {
+
+ /*
+ * Window has shrunk.
+ */
+
+ tmpOffset2 = maxOffset / 2;
+ if (maxOffset > listPtr->oldMaxOffset) {
+ tmpOffset = maxOffset/2 - listPtr->oldMaxOffset/2;
+ } else {
+ tmpOffset = listPtr->oldMaxOffset/2 - maxOffset/2;
+ }
+ tmpOffset -= tmpOffset % listPtr->xScrollUnit;
+ if ((tmpOffset + listPtr->xOffset) > maxOffset) {
+ tmpOffset = maxOffset - listPtr->xOffset;
+ }
+ if (tmpOffset < 0) {
+ tmpOffset = 0;
+ }
+ if (listPtr->xOffset < tmpOffset2) {
+ listPtr->xOffset += tmpOffset;
+ } else {
+ listPtr->xOffset -= tmpOffset;
+ }
+ } else {
+ listPtr->xOffset = maxOffset/2;
+ listPtr->xOffset -= listPtr->xOffset % listPtr->xScrollUnit;
+ }
+ listPtr->oldMaxOffset = maxOffset;
+ }
ChangeListboxOffset(listPtr, listPtr->xOffset);
/*
@@ -2735,7 +2823,11 @@ GetListboxIndex(
stringRep = Tcl_GetString(indexObj);
if (stringRep[0] == '@') {
- /* @x,y index */
+
+ /*
+ * @x,y index
+ */
+
int y;
const char *start;
char *end;
@@ -3465,7 +3557,7 @@ ListboxListVarProc(
/*
* If the list length has decreased, then we should clean up selection and
- * attributes information for elements past the end of the new list
+ * attributes information for elements past the end of the new list.
*/
oldLength = listPtr->nElements;
@@ -3583,6 +3675,36 @@ MigrateHashEntries(
}
/*
+ *----------------------------------------------------------------------
+ *
+ * GetMaxOffset --
+ *
+ * Passing in a listbox pointer, returns the maximum offset for the box.
+ *
+ * Results:
+ * Listbox's maxOffset.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+*/
+static int GetMaxOffset(
+ register Listbox *listPtr)
+{
+ int maxOffset;
+
+ maxOffset = listPtr->maxWidth -
+ (Tk_Width(listPtr->tkwin) - 2*listPtr->inset -
+ 2*listPtr->selBorderWidth) + listPtr->xScrollUnit - 1;
+ if (maxOffset < 0) {
+ maxOffset = 0;
+ }
+ maxOffset -= maxOffset % listPtr->xScrollUnit;
+
+ return maxOffset;
+}
+/*
* Local Variables:
* mode: c
* c-basic-offset: 4