United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4761990 1.4 REGRESSION: Highlighting Color Behavior has changed
JDK-4761990 : 1.4 REGRESSION: Highlighting Color Behavior has changed

Details
Type:
Enhancement
Submit Date:
2002-10-11
Status:
Closed
Updated Date:
2004-10-20
Project Name:
JDK
Resolved Date:
2003-08-07
Component:
client-libs
OS:
windows_xp,windows_2000
Sub-Component:
javax.swing
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
nb_3.4dev,1.4.1
Fixed Versions:
1.4.1_07 (07)

Related Reports
Backport:
Backport:
Duplicate:
Relates:
Relates:

Sub Tasks

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
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
                                     
4-10-20 00:00:00
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;
+         }
      }
  }

###@###.### 

======================================================================
                                     
2004-06-11
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
                                     
2004-06-11
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


                                     
2004-06-14



Hardware and Software, Engineered to Work Together