JDK-4761990 : 1.4 REGRESSION: Highlighting Color Behavior has changed
  • Type: Enhancement
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: nb_3.4dev,1.4.1
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_2000,windows_xp
  • CPU: x86
  • Submitted: 2002-10-11
  • Updated: 2004-10-20
  • Resolved: 2003-08-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other Other
1.4.1_07 07Fixed 1.4.2_02Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
Name: jk109818			Date: 10/11/2002


FULL PRODUCT VERSION :
oldest version where seen: Java version 1.4.0_01
java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0_01-b03)
Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)

Has also happened on 1.4.1

FULL OPERATING SYSTEM VERSION :Windows 2000, 5.00.2195,
service pack 3


ADDITIONAL OPERATING SYSTEMS : I have had reports on other
operating systems as well - so it is consistent.



A DESCRIPTION OF THE PROBLEM :
In javahelp the search highlight was previously a light
grey color.  Now the search highlight appears as a dark
blue - in checking this on Windows this highlight co-
incides with the color defined in the windows area
of 'Appearance/Scheme/selected item property.'  This is
fine in windows where the underlying font changes property
to display as white when a dark color is displayed, but in
this case the underlying font does *not* change color when
a dark color is used in this selection.  Whatever swing
previously used in this area, please return to it.

Much thanks.

REGRESSION.  Last worked in version 1.3.1

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1.create a javahelp system
2.include it in an application
3.choose to display a search item - note the color of the
highlight.

EXPECTED VERSUS ACTUAL BEHAVIOR :
Previously the highlight was a light gray (using the
default windows color scheme) now the highlight is a dark
blue (using the same color scheme.)  After looking at the
color scheme the color of the highlight can be changed by
changing the color of the 'selected item property'.

REPRODUCIBILITY :
This bug can be reproduced always.

CUSTOMER WORKAROUND :
Change the selected item property on the windows system.
However, doing this also changes default windows uses.

Release Regression From : 1.3.1
The above release value was the last known release where this 
bug was known to work. Since then there has been a regression.

(Review ID: 164915) 
======================================================================
###@###.### 10/20/04 21:07 GMT

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: 1.4.1_07 1.4.2_02 generic tiger tiger-beta FIXED IN: 1.4.1_07 1.4.2_02 tiger tiger-beta INTEGRATED IN: 1.4.1_07 1.4.2_02 tiger-b25 tiger-beta VERIFIED IN: 1.4.1_07 1.4.2_02
14-06-2004

SUGGESTED FIX tinue; ! } else { ! continue; ! } ! if (hStart <= p0 && hEnd >= p1){ ! // the whole view is selected ! paintTextUsingColor(g, a, selFG, p0, p1); ! paintedText = true; ! break; ! } ! // the array is lazily created only when the view ! // is partially selected ! if (!initialized) { ! initSelections(p0, p1); ! initialized = true; ! } ! hStart = Math.max(p0, hStart); ! hEnd = Math.min(p1, hEnd); ! paintTextUsingColor(g, a, selFG, hStart, hEnd); ! // the array represents view positions [0, p1-p0+1] ! // later will iterate this array and sum its ! // elements. Positions with sum == 0 are not selected. ! selections[hStart-p0]++; ! selections[hEnd-p0]--; ! viewSelectionCount++; ! } ! if (!paintedText && viewSelectionCount > 0) { ! // the view is partially selected ! int curPos = -1; ! int startPos = 0; ! int viewLen = p1 - p0; ! while (curPos++ < viewLen) { ! // searching for the next selection start ! while(curPos < viewLen && ! selections[curPos] == 0) curPos++; ! if (startPos != curPos) { ! // paint unselected text ! paintTextUsingColor(g, a, fg, ! p0 + startPos, p0 + curPos); ! } ! int checkSum = 0; ! // searching for next start position of unselected text ! while (curPos < viewLen && ! (checkSum += selections[curPos]) != 0) curPos++; ! startPos = curPos; ! } paintedText = true; } } } ! // } if(!paintedText) paintTextUsingColor(g, a, fg, p0, p1); } *************** *** 872,877 **** --- 920,930 ---- // --- variables ------------------------------------------------ + /** + * Used by paint() to store highlighted view positions + */ + private byte[] selections = null; + int offset; int length; // if it is an implied newline character *** /net/crown/export1/naa/tiger//webrev/4761990/src/share/classes/javax/swing/text/LayeredHighlighter.java- Fri Sep 5 19:45:17 2003 --- LayeredHighlighter.java Fri Sep 5 16:57:22 2003 *************** *** 6,13 **** */ package javax.swing.text; ! import java.awt.Graphics; ! import java.awt.Shape; /** * --- 6,12 ---- */ package javax.swing.text; ! import java.awt.*; /** * *************** *** 42,46 **** --- 41,48 ---- public abstract Shape paintLayer(Graphics g, int p0, int p1, Shape viewBounds,JTextComponent editor, View view); + public Color getForegroundColor() { + return null; + } } } ###@###.### ======================================================================
11-06-2004

SUGGESTED FIX Name: anR10225 Date: 09/18/2003 *** /net/crown/export1/naa/tiger//webrev/4761990/src/share/classes/com/sun/java/swing/plaf/windows/WindowsTextUI.java- Fri Sep 5 19:45:18 2003 --- WindowsTextUI.java Fri Sep 5 19:41:44 2003 *************** *** 46,51 **** --- 46,53 ---- /* public */ static class WindowsCaret extends DefaultCaret implements UIResource { + Highlighter.HighlightPainter p = null; + /** * Gets the painter for the Highlighter. * *************** *** 52,58 **** * @return the painter */ protected Highlighter.HighlightPainter getSelectionPainter() { ! return WindowsTextUI.WindowsPainter; } } --- 54,60 ---- * @return the painter */ protected Highlighter.HighlightPainter getSelectionPainter() { ! return new WindowsHighlightPainter(null, getComponent().getSelectedTextColor()); } } *************** *** 63,68 **** --- 65,73 ---- super(c); } + WindowsHighlightPainter(Color c, Color fgColor) { + super(c, fgColor); + } // --- HighlightPainter methods --------------------------------------- /** *** /net/crown/export1/naa/tiger//webrev/4761990/src/share/classes/javax/swing/text/DefaultCaret.java- Fri Sep 5 19:45:17 2003 --- DefaultCaret.java Fri Sep 5 18:08:10 2003 *************** *** 98,103 **** --- 98,104 ---- */ public DefaultCaret() { async = false; + width = 1; } /** *************** *** 169,178 **** */ protected synchronized void damage(Rectangle r) { if (r != null) { ! x = r.x - 4; ! y = r.y; ! width = 10; ! height = r.height; repaint(); } } --- 170,188 ---- */ protected synchronized void damage(Rectangle r) { if (r != null) { ! if (isBidiCaret()) { ! if (dotLTR) { ! x = r.x; ! } else { ! x = r.x - 4; ! } ! width = 5; ! } else { ! x = r.x; ! width = 1; ! } ! y = r.y; ! height = r.height; repaint(); } } *************** *** 204,210 **** * @return the painter */ protected Highlighter.HighlightPainter getSelectionPainter() { ! return DefaultHighlighter.DefaultPainter; } /** --- 214,226 ---- * @return the painter */ protected Highlighter.HighlightPainter getSelectionPainter() { ! if (highlightPainter == null) { ! highlightPainter = ! new DefaultHighlighter.DefaultHighlightPainter( ! null, ! component.getSelectedTextColor()); ! } ! return highlightPainter; } /** *************** *** 514,532 **** // PENDING(prinz) this should be done through // protected methods so that alternative LAF // will show bidi information. ! Document doc = component.getDocument(); ! if (doc instanceof AbstractDocument) { ! Element bidi = ((AbstractDocument)doc).getBidiRootElement(); ! if ((bidi != null) && (bidi.getElementCount() > 1)) { ! // there are multiple directions present. ! flagXPoints[0] = r.x; ! flagYPoints[0] = r.y; ! flagXPoints[1] = r.x; ! flagYPoints[1] = r.y + 4; ! flagYPoints[2] = r.y; ! flagXPoints[2] = (dotLTR) ? r.x + 5 : r.x - 4; ! g.fillPolygon(flagXPoints, flagYPoints, 3); ! } } } catch (BadLocationException e) { // can't render I guess --- 530,544 ---- // PENDING(prinz) this should be done through // protected methods so that alternative LAF // will show bidi information. ! if (isBidiCaret()) { ! // there are multiple directions present. ! flagXPoints[0] = r.x; ! flagYPoints[0] = r.y; ! flagXPoints[1] = r.x; ! flagYPoints[1] = r.y + 4; ! flagYPoints[2] = r.y; ! flagXPoints[2] = (dotLTR) ? r.x + 5 : r.x - 4; ! g.fillPolygon(flagXPoints, flagYPoints, 3); } } catch (BadLocationException e) { // can't render I guess *************** *** 535,540 **** --- 547,561 ---- } } + boolean isBidiCaret() { + Document doc = component.getDocument(); + if (doc instanceof AbstractDocument) { + Element bidi = ((AbstractDocument)doc).getBidiRootElement(); + return (bidi != null) && (bidi.getElementCount() > 1); + } + return false; + } + /** * Called when the UI is being installed into the * interface of a JTextComponent. This can be used *************** *** 1116,1134 **** Rectangle newLoc; try { newLoc = mapper.modelToView(component, this.dot, this.dotBias); } catch (BadLocationException e) { newLoc = null; } ! if (newLoc != null) { ! adjustVisibility(newLoc); ! // If there is no magic caret position, make one ! if (getMagicCaretPosition() == null) { ! setMagicCaretPosition(new Point(newLoc.x, newLoc.y)); ! } ! } ! ! // repaint the new position ! damage(newLoc); } } } --- 1137,1160 ---- Rectangle newLoc; try { newLoc = mapper.modelToView(component, this.dot, this.dotBias); + if (newLoc != null) { + // calculate new caret bounds + damage(newLoc); + adjustVisibility(this); + // If there is no magic caret position, make one + if (getMagicCaretPosition() == null) { + setMagicCaretPosition(new Point(newLoc.x, newLoc.y)); + } + } + // after adjusting visibility of TextField view coordinates + // may change, we should get view coordinates again + newLoc = mapper.modelToView(component, this.dot, this.dotBias); } catch (BadLocationException e) { newLoc = null; } ! ! // repaint the new position ! damage(newLoc); } } } *************** *** 1320,1325 **** --- 1346,1353 ---- // package-private to avoid inner classes private member // access bug JTextComponent component; + + private Highlighter.HighlightPainter highlightPainter = null; /** * flag to indicate if async updates should *************** *** 1586,1599 **** if(enabled == Boolean.TRUE) { if(component.isEditable()) { setVisible(true); ! } setSelectionVisible(true); } else { setVisible(false); setSelectionVisible(false); ! } } ! } } --- 1614,1629 ---- if(enabled == Boolean.TRUE) { if(component.isEditable()) { setVisible(true); ! } setSelectionVisible(true); } else { setVisible(false); setSelectionVisible(false); ! } } ! } else if("selectedTextColor".equals(evt.getPropertyName())) { ! highlightPainter = null; ! } } *************** *** 1604,1610 **** * Toggles the visibility of the selection when ownership is lost. */ public void lostOwnership(Clipboard clipboard, ! Transferable contents) { if (ownsSelection) { ownsSelection = false; if (component != null && !component.hasFocus()) { --- 1634,1640 ---- * Toggles the visibility of the selection when ownership is lost. */ public void lostOwnership(Clipboard clipboard, ! Transferable contents) { if (ownsSelection) { ownsSelection = false; if (component != null && !component.hasFocus()) { *************** *** 1613,1620 **** } } } ! ! private class DefaultFilterBypass extends NavigationFilter.FilterBypass { public Caret getCaret() { return DefaultCaret.this; --- 1643,1649 ---- } } } ! private class DefaultFilterBypass extends NavigationFilter.FilterBypass { public Caret getCaret() { return DefaultCaret.this; *** /net/crown/export1/naa/tiger//webrev/4761990/src/share/classes/javax/swing/text/DefaultHighlighter.java- Fri Sep 5 19:45:16 2003 --- DefaultHighlighter.java Fri Sep 5 18:00:32 2003 *************** *** 238,244 **** * @see Highlighter#getHighlights */ public Highlighter.Highlight[] getHighlights() { ! Highlighter.Highlight[] h = new Highlighter.Highlight[highlights.size()]; highlights.copyInto(h); return h; } --- 238,248 ---- * @see Highlighter#getHighlights */ public Highlighter.Highlight[] getHighlights() { ! int size = highlights.size(); ! if (size == 0) { ! return noHighlights; ! } ! Highlighter.Highlight[] h = new Highlighter.Highlight[size]; highlights.copyInto(h); return h; } *************** *** 291,296 **** --- 295,302 ---- // ---- member variables -------------------------------------------- + private final static Highlighter.Highlight[] noHighlights = + new Highlighter.Highlight[0]; private Vector highlights = new Vector(); // Vector<HighlightInfo> private JTextComponent component; private boolean drawsLayeredHighlights; *************** *** 318,326 **** * @param c the color for the highlight */ public DefaultHighlightPainter(Color c) { ! color = c; } /** * Returns the color of the highlight. * --- 324,337 ---- * @param c the color for the highlight */ public DefaultHighlightPainter(Color c) { ! this(c, null); } + public DefaultHighlightPainter(Color hlColor, Color fgColor) { + this.hlColor = hlColor; + this.fgColor = fgColor; + } + /** * Returns the color of the highlight. * *************** *** 327,336 **** * @return the color */ public Color getColor() { ! return color; } // --- HighlightPainter methods --------------------------------------- /** * Paints a highlight. --- 338,350 ---- * @return the color */ public Color getColor() { ! return hlColor; } // --- HighlightPainter methods --------------------------------------- + public Color getForegroundColor() { + return fgColor; + } /** * Paints a highlight. *************** *** 432,439 **** return null; } ! private Color color; ! } --- 446,453 ---- return null; } ! private Color hlColor; ! private Color fgColor; } *** /net/crown/export1/naa/tiger//webrev/4761990/src/share/classes/javax/swing/text/GlyphView.java- Fri Sep 5 19:45:16 2003 --- GlyphView.java Fri Sep 5 18:08:10 2003 *************** *** 332,337 **** --- 332,349 ---- } /** + * Lazily initializes the selections field + */ + private void initSelections(int p0, int p1) { + int viewPosCount = p1 - p0 + 1; + if (selections == null || viewPosCount > selections.length) { + selections = new byte[viewPosCount]; + return; + } + for (int i = 0; i < viewPosCount; selections[i++] = 0); + } + + /** * Renders a portion of a text style run. * * @param g the rendering surface to use *************** *** 372,414 **** paintedText = true; } else if(c instanceof JTextComponent) { JTextComponent tc = (JTextComponent) c; ! Color selFG = tc.getSelectedTextColor(); ! Caret caret = tc.getCaret(); ! if ((caret != null) && (! caret.isSelectionVisible())) { ! // selection currently not visible ! selFG = fg; ! } ! if(selFG != null && !selFG.equals(fg)) { ! int selStart = tc.getSelectionStart(); ! int selEnd = tc.getSelectionEnd(); ! if(selStart != selEnd) { ! // Something is selected, does p0 - p1 fall in that range? ! int pMin; ! int pMax; ! if(selStart <= p0) ! pMin = p0; ! else ! pMin = Math.min(selStart, p1); ! if(selEnd >= p1) ! pMax = p1; ! else ! pMax = Math.max(selEnd, p0); ! // If pMin == pMax (also == p0), selection isn't in this ! // block. ! if(pMin != pMax) { paintedText = true; - if(pMin > p0) - paintTextUsingColor(g, a, fg, p0, pMin); - paintTextUsingColor(g, a, selFG, pMin, pMax); - if(pMax < p1) - paintTextUsingColor(g, a, fg, pMax, p1); } } } ! } if(!paintedText) paintTextUsingColor(g, a, fg, p0, p1); } --- 384,462 ---- paintedText = true; } else if(c instanceof JTextComponent) { JTextComponent tc = (JTextComponent) c; ! Color defaultSelFG = tc.getSelectedTextColor(); ! // if(selFG != null && !selFG.equals(fg)) { ! Highlighter.Highlight[] h = tc.getHighlighter().getHighlights(); ! if(h.length != 0) { ! boolean initialized = false; ! int viewSelectionCount = 0; ! for (int i = 0; i < h.length; i++) { ! Highlighter.Highlight highlight = h[i]; ! int hStart = highlight.getStartOffset(); ! int hEnd = highlight.getEndOffset(); ! if (hStart > p1 || hEnd < p0) { ! // the selection is out of this view ! continue; ! } ! Color selFG; ! Highlighter.HighlightPainter p = highlight.getPainter(); ! if (p instanceof LayeredHighlighter.LayerPainter) { ! selFG =((LayeredHighlighter.LayerPainter) p). ! getForegroundColor(); ! if (selFG == null) con
11-06-2004

EVALUATION Not sure how to create a help system, have emailed submitter for details. ###@###.### 2002-10-14 Refer to the comments section, based on the feedback this sounds like an RFE for the ability for highlights to effect text color, or to have highlights automatically change the text color to be selectedTextColor. ###@###.### 2002-10-29 Name: ik75403Date: 11/04/2002 I do not see how to implement this feature using current API. We can not change API for mantis. Commiting this feature to tiger release ====================================================================== Name: anR10225Date: 04/11/2003 The reason is in the GlyphView.paint() method implementation. It paints the text with 'selectedTextForegroundColor' only in the range of caret dot and mark. It should take into account that there might be a number of selected regions. So Highlighter.getHighlights() should be used instead of JTextComponent.getSelectionStart/End(). ====================================================================== Including the suggested fix from Anton (###@###.###) in the attachment (4761990.tar). ###@###.### 2003-07-11 =================== there was a regression caused by the fix for this bug. 5003294 [REGRESSION: unselected text is painted using the selected text color] You can find a fix for 5003294 here: http://sa.sfbay.sun.com/projects/swing_data/tiger/5003294/ ###@###.### 10/20/04 21:07 GMT
20-10-0004