/** * Provides a mapping, for a given region, from the document model coordinate space to the view * coordinate space. The specified region is created as a union of the first and last character * positions. * * <p>This is implemented to subtract the width of the second character, as this view's <code> * modelToView</code> actually returns the width of the character instead of "1" or "0" like the * View implementations in <code>javax.swing.text</code>. Thus, if we don't override this method, * the <code>View</code> implementation will return one character's width too much for its * consumers (implementations of <code>javax.swing.text.Highlighter</code>). * * @param p0 the position of the first character (>=0) * @param b0 The bias of the first character position, toward the previous character or the next * character represented by the offset, in case the position is a boundary of two views; * <code>b0</code> will have one of these values: * <ul> * <li><code>Position.Bias.Forward</code> * <li><code>Position.Bias.Backward</code> * </ul> * * @param p1 the position of the last character (>=0) * @param b1 the bias for the second character position, defined one of the legal values shown * above * @param a the area of the view, which encompasses the requested region * @return the bounding box which is a union of the region specified by the first and last * character positions * @exception BadLocationException if the given position does not represent a valid location in * the associated document * @exception IllegalArgumentException if <code>b0</code> or <code>b1</code> are not one of the * legal <code>Position.Bias</code> values listed above * @see View#viewToModel */ @Override public Shape modelToView(int p0, Position.Bias b0, int p1, Position.Bias b1, Shape a) throws BadLocationException { Shape s0 = modelToView(p0, a, b0); Shape s1; if (p1 == getEndOffset()) { try { s1 = modelToView(p1, a, b1); } catch (BadLocationException ble) { s1 = null; } if (s1 == null) { // Assume extends left to right. Rectangle alloc = (a instanceof Rectangle) ? (Rectangle) a : a.getBounds(); s1 = new Rectangle(alloc.x + alloc.width - 1, alloc.y, 1, alloc.height); } } else { s1 = modelToView(p1, a, b1); } Rectangle r0 = s0 instanceof Rectangle ? (Rectangle) s0 : s0.getBounds(); Rectangle r1 = s1 instanceof Rectangle ? (Rectangle) s1 : s1.getBounds(); if (r0.y != r1.y) { // If it spans lines, force it to be the width of the view. Rectangle alloc = (a instanceof Rectangle) ? (Rectangle) a : a.getBounds(); r0.x = alloc.x; r0.width = alloc.width; } r0.add(r1); // The next line is the only difference between this method and // View's implementation. We're subtracting the width of the second // character. This is because this method is used by Highlighter // implementations to get the area to "highlight", and if we don't do // this, one character too many is highlighted thanks to our // modelToView() implementation returning the actual width of the // character requested! if (p1 > p0) { r0.width -= r1.width; } return r0; }