summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornijtmans@users.sourceforge.net <jan.nijtmans>2016-01-22 09:21:46 (GMT)
committernijtmans@users.sourceforge.net <jan.nijtmans>2016-01-22 09:21:46 (GMT)
commit2870fe2f2202657c1f9d769e46c84a85800fc5a5 (patch)
treebbacdf995b9be6ee4985f44b38690cff1534ec8a
parent20f2dd8a0ee571f286720135e04cfcde8dee170b (diff)
parentcbd418527ce6227005c9fc1777d08d77b5be1cfd (diff)
downloadtk-2870fe2f2202657c1f9d769e46c84a85800fc5a5.zip
tk-2870fe2f2202657c1f9d769e46c84a85800fc5a5.tar.gz
tk-2870fe2f2202657c1f9d769e46c84a85800fc5a5.tar.bz2
Implement TIP #441: Add -justify Configuration Option to the listbox Widget
-rw-r--r--doc/listbox.n7
-rw-r--r--generic/tkListbox.c110
-rw-r--r--library/demos/states.tcl11
-rw-r--r--macosx/tkMacOSXDefault.h1
-rw-r--r--tests/listbox.test69
-rw-r--r--unix/tkUnixDefault.h1
-rw-r--r--win/tkWinDefault.h1
7 files changed, 173 insertions, 27 deletions
diff --git a/doc/listbox.n b/doc/listbox.n
index 9f34b5e..0f263b4 100644
--- a/doc/listbox.n
+++ b/doc/listbox.n
@@ -17,9 +17,10 @@ listbox \- Create and manipulate 'listbox' item list widgets
\-background \-borderwidth \-cursor
\-disabledforeground \-exportselection \-font
\-foreground \-highlightbackground \-highlightcolor
-\-highlightthickness \-relief \-selectbackground
-\-selectborderwidth \-selectforeground \-setgrid
-\-takefocus \-xscrollcommand \-yscrollcommand
+\-highlightthickness \-justify \-relief
+\-selectbackground \-selectborderwidth \-selectforeground
+\-setgrid \-takefocus \-xscrollcommand
+\-yscrollcommand
.SE
.SH "WIDGET-SPECIFIC OPTIONS"
.OP \-activestyle activeStyle ActiveStyle
diff --git a/generic/tkListbox.c b/generic/tkListbox.c
index 95f7862..c7effdd 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. */
@@ -114,7 +114,8 @@ typedef struct {
int xOffset; /* The left edge of each string in the listbox
* is offset to the left by this many pixels
* (0 means no offset, positive means there is
- * an offset). */
+ * an offset). This is x scrolling information
+ * is not linked to justification. */
/*
* Information about what's selected or active, if any.
@@ -131,7 +132,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 +166,7 @@ typedef struct {
Pixmap gray; /* Pixmap for displaying disabled text. */
int flags; /* Various flag bits: see below for
* definitions. */
+ Tk_Justify justify; /* Justification. */
} Listbox;
/*
@@ -197,7 +199,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 +277,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 +317,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 +344,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 +440,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 +551,7 @@ Tk_ListboxObjCmd(
listPtr->cursor = None;
listPtr->state = STATE_NORMAL;
listPtr->gray = None;
+ listPtr->justify = TK_JUSTIFY_LEFT;
/*
* Keep a hold of the associated tkwin until we destroy the listbox,
@@ -613,7 +619,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,
@@ -1076,6 +1082,7 @@ ListboxBboxSubCmd(
Listbox *listPtr, /* Information about the listbox */
int index) /* Index of the element to get bbox info on */
{
+ register Tk_Window tkwin = listPtr->tkwin;
int lastVisibleIndex;
/*
@@ -1111,7 +1118,15 @@ ListboxBboxSubCmd(
Tk_GetFontMetrics(listPtr->tkfont, &fm);
pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, stringLen);
- x = listPtr->inset + listPtr->selBorderWidth - listPtr->xOffset;
+ if (listPtr->justify == TK_JUSTIFY_LEFT) {
+ x = (listPtr->inset + listPtr->selBorderWidth) - listPtr->xOffset;
+ } else if (listPtr->justify == TK_JUSTIFY_RIGHT) {
+ x = Tk_Width(tkwin) - (listPtr->inset + listPtr->selBorderWidth)
+ - pixelWidth - listPtr->xOffset + GetMaxOffset(listPtr);
+ } else {
+ x = (Tk_Width(tkwin) - pixelWidth)/2
+ - listPtr->xOffset + GetMaxOffset(listPtr)/2;
+ }
y = ((index - listPtr->topIndex)*listPtr->lineHeight)
+ listPtr->inset + listPtr->selBorderWidth;
results[0] = Tcl_NewIntObj(x);
@@ -1837,6 +1852,7 @@ DisplayListbox(
* or right edge of the listbox is
* off-screen. */
Pixmap pixmap;
+ int textWidth;
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,24 @@ DisplayListbox(
* Draw the actual text of this item.
*/
+ Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &curElement);
+ stringRep = Tcl_GetStringFromObj(curElement, &stringLen);
+ textWidth = Tk_TextWidth(listPtr->tkfont, stringRep, stringLen);
+
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 = Tk_Width(tkwin) - (listPtr->inset + listPtr->selBorderWidth)
+ - textWidth - listPtr->xOffset + GetMaxOffset(listPtr);
+ } else {
+ x = (Tk_Width(tkwin) - textWidth)/2
+ - listPtr->xOffset + GetMaxOffset(listPtr)/2;
+ }
+
+ Tk_DrawChars(listPtr->display, pixmap, gc, listPtr->tkfont,
stringRep, stringLen, x, y);
/*
@@ -2458,7 +2486,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) {
@@ -2735,7 +2763,11 @@ GetListboxIndex(
stringRep = Tcl_GetString(indexObj);
if (stringRep[0] == '@') {
- /* @x,y index */
+
+ /*
+ * @x,y index
+ */
+
int y;
const char *start;
char *end;
@@ -2844,9 +2876,7 @@ ChangeListboxOffset(
*/
offset += listPtr->xScrollUnit / 2;
- maxOffset = listPtr->maxWidth - (Tk_Width(listPtr->tkwin) -
- 2*listPtr->inset - 2*listPtr->selBorderWidth)
- + listPtr->xScrollUnit - 1;
+ maxOffset = GetMaxOffset(listPtr);
if (offset > maxOffset) {
offset = maxOffset;
}
@@ -2887,9 +2917,7 @@ ListboxScanTo(
int newTopIndex, newOffset, maxIndex, maxOffset;
maxIndex = listPtr->nElements - listPtr->fullLines;
- maxOffset = listPtr->maxWidth + (listPtr->xScrollUnit - 1)
- - (Tk_Width(listPtr->tkwin) - 2*listPtr->inset
- - 2*listPtr->selBorderWidth - listPtr->xScrollUnit);
+ maxOffset = GetMaxOffset(listPtr);
/*
* Compute new top line for screen by amplifying the difference between
@@ -3465,7 +3493,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 +3611,42 @@ MigrateHashEntries(
}
/*
+ *----------------------------------------------------------------------
+ *
+ * GetMaxOffset --
+ *
+ * Passing in a listbox pointer, returns the maximum offset for the box,
+ * i.e. the maximum possible horizontal scrolling value (in pixels).
+ *
+ * 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) {
+
+ /*
+ * Listbox is larger in width than its largest width item.
+ */
+
+ maxOffset = 0;
+ }
+ maxOffset -= maxOffset % listPtr->xScrollUnit;
+
+ return maxOffset;
+}
+/*
* Local Variables:
* mode: c
* c-basic-offset: 4
diff --git a/library/demos/states.tcl b/library/demos/states.tcl
index 92b1f1e..aeb3d5b 100644
--- a/library/demos/states.tcl
+++ b/library/demos/states.tcl
@@ -19,6 +19,17 @@ positionWindow $w
label $w.msg -font $font -wraplength 4i -justify left -text "A listbox containing the 50 states is displayed below, along with a scrollbar. You can scan the list either using the scrollbar or by scanning. To scan, press button 2 in the widget and drag up or down."
pack $w.msg -side top
+labelframe $w.justif -text Justification
+foreach c {Left Center Right} {
+ set lower [string tolower $c]
+ radiobutton $w.justif.$lower -text $c -variable just \
+ -relief flat -value $lower -anchor w \
+ -command "$w.frame.list configure -justify \$just" \
+ -tristatevalue "multi"
+ pack $w.justif.$lower -side left -pady 2 -fill x
+}
+pack $w.justif
+
## See Code / Dismiss buttons
set btns [addSeeDismiss $w.buttons $w]
pack $btns -side bottom -fill x
diff --git a/macosx/tkMacOSXDefault.h b/macosx/tkMacOSXDefault.h
index 528ea10..65762b7 100644
--- a/macosx/tkMacOSXDefault.h
+++ b/macosx/tkMacOSXDefault.h
@@ -259,6 +259,7 @@
#define DEF_LISTBOX_HIGHLIGHT_BG NORMAL_BG
#define DEF_LISTBOX_HIGHLIGHT BLACK
#define DEF_LISTBOX_HIGHLIGHT_WIDTH "0"
+#define DEF_LISTBOX_JUSTIFY "left"
#define DEF_LISTBOX_RELIEF "solid"
#define DEF_LISTBOX_SCROLL_COMMAND ""
#define DEF_LISTBOX_LIST_VARIABLE ""
diff --git a/tests/listbox.test b/tests/listbox.test
index 9ca0411..76a4349 100644
--- a/tests/listbox.test
+++ b/tests/listbox.test
@@ -204,6 +204,21 @@ test listbox-1.31 {configuration options} -body {
} -cleanup {
.l configure -highlightthickness [lindex [.l configure -highlightthickness] 3]
} -result {0 0}
+test listbox-1.32.1 {configuration options} -setup {
+ set res {}
+} -body {
+ .l configure -justify left
+ set res [list [lindex [.l configure -justify] 4] [.l cget -justify]]
+ .l configure -justify center
+ lappend res [lindex [.l configure -justify] 4] [.l cget -justify]
+ .l configure -justify right
+ lappend res [lindex [.l configure -justify] 4] [.l cget -justify]
+} -cleanup {
+ .l configure -justify [lindex [.l configure -justify] 3]
+} -result {left left center center right right}
+test listbox-1.32.2 {configuration options} -body {
+ .l configure -justify bogus
+} -returnCodes error -result {bad justification "bogus": must be left, right, or center}
test listbox-1.33 {configuration options} -body {
.l configure -relief groove
list [lindex [.l configure -relief] 4] [.l cget -relief]
@@ -442,6 +457,58 @@ test listbox-3.18 {ListboxWidgetCmd procedure, "bbox" option, partial last line}
mkPartial
list [.partial.l bbox 3] [.partial.l bbox 4]
} -result {{5 56 24 14} {5 73 23 14}}
+test listbox-3.18a {ListboxWidgetCmd procedure, "bbox" option, justified} -constraints {
+ fonts
+} -setup {
+ destroy .top.l .top
+ unset -nocomplain res
+} -body {
+ toplevel .top
+ listbox .top.l -justify left
+ .top.l insert end Item1 LongerItem2 MuchLongerItem3
+ pack .top.l
+ update
+ lappend res [.top.l bbox 0] [.top.l bbox 1] [.top.l bbox 2]
+ .top.l configure -justify center
+ lappend res [.top.l bbox 0] [.top.l bbox 1] [.top.l bbox 2]
+ .top.l configure -justify right
+ lappend res [.top.l bbox 0] [.top.l bbox 1] [.top.l bbox 2]
+} -cleanup {
+ destroy .top.l .top
+ unset -nocomplain res
+} -result [list \
+ {5 5 34 14} {5 22 74 14} {5 39 106 14} \
+ {58 5 34 14} {38 22 74 14} {22 39 106 14} \
+ {111 5 34 14} {71 22 74 14} {39 39 106 14} \
+]
+test listbox-3.18b {ListboxWidgetCmd procedure, "bbox" option, justified, non-default borderwidth} -setup {
+ destroy .top.l .top
+ unset -nocomplain lres res
+} -body {
+ # This test checks whether all "x" values from bbox for different size
+ # items with different justification settings are all positive or zero
+ # This checks a bit the calculation of this x value with non-default
+ # borders widths of the listbox
+ toplevel .top
+ listbox .top.l -justify left -borderwidth 17 -highlightthickness 19 -selectborderwidth 22
+ .top.l insert end Item1 LongerItem2 MuchLongerItem3
+ .top.l selection set 1
+ pack .top.l
+ update
+ lappend lres [.top.l bbox 0] [.top.l bbox 1] [.top.l bbox 2]
+ .top.l configure -justify center
+ lappend lres [.top.l bbox 0] [.top.l bbox 1] [.top.l bbox 2]
+ .top.l configure -justify right
+ lappend lres [.top.l bbox 0] [.top.l bbox 1] [.top.l bbox 2]
+ set res 1
+ for {set i 0} {$i < [llength $lres]} {incr i 4} {
+ set res [expr {$res * [expr {[lindex $lres $i] >= 0}] }]
+ }
+ set res
+} -cleanup {
+ destroy .top.l .top
+ unset -nocomplain lres res
+} -result {1}
test listbox-3.19 {ListboxWidgetCmd procedure, "cget" option} -body {
.l cget
} -returnCodes error -result {wrong # args: should be ".l cget option"}
@@ -456,7 +523,7 @@ test listbox-3.22 {ListboxWidgetCmd procedure, "cget" option} -body {
} -result {0}
test listbox-3.23 {ListboxWidgetCmd procedure, "configure" option} -body {
llength [.l configure]
-} -result {27}
+} -result {28}
test listbox-3.24 {ListboxWidgetCmd procedure, "configure" option} -body {
.l configure -gorp
} -returnCodes error -result {unknown option "-gorp"}
diff --git a/unix/tkUnixDefault.h b/unix/tkUnixDefault.h
index d214aa5..2c3854d 100644
--- a/unix/tkUnixDefault.h
+++ b/unix/tkUnixDefault.h
@@ -221,6 +221,7 @@
#define DEF_LISTBOX_HIGHLIGHT_BG NORMAL_BG
#define DEF_LISTBOX_HIGHLIGHT BLACK
#define DEF_LISTBOX_HIGHLIGHT_WIDTH "1"
+#define DEF_LISTBOX_JUSTIFY "left"
#define DEF_LISTBOX_RELIEF "sunken"
#define DEF_LISTBOX_SCROLL_COMMAND ""
#define DEF_LISTBOX_LIST_VARIABLE ""
diff --git a/win/tkWinDefault.h b/win/tkWinDefault.h
index c52cc4d..f389075 100644
--- a/win/tkWinDefault.h
+++ b/win/tkWinDefault.h
@@ -224,6 +224,7 @@
#define DEF_LISTBOX_HIGHLIGHT_BG NORMAL_BG
#define DEF_LISTBOX_HIGHLIGHT HIGHLIGHT
#define DEF_LISTBOX_HIGHLIGHT_WIDTH "1"
+#define DEF_LISTBOX_JUSTIFY "left"
#define DEF_LISTBOX_RELIEF "sunken"
#define DEF_LISTBOX_SCROLL_COMMAND ""
#define DEF_LISTBOX_LIST_VARIABLE ""