/** @see javax.swing.plaf.basic.BasicTextUI#getPreferredSize(javax.swing.JComponent) */ public Dimension getPreferredSize(JComponent c) { // The following code has been derived from BasicTextUI. Document doc = ((JTextComponent) c).getDocument(); Insets i = c.getInsets(); Dimension d = c.getSize(); View rootView = getRootView((JTextComponent) c); if (doc instanceof AbstractDocument) { ((AbstractDocument) doc).readLock(); } try { if ((d.width > (i.left + i.right)) && (d.height > (i.top + i.bottom))) { rootView.setSize(d.width - i.left - i.right, d.height - i.top - i.bottom); } else if (d.width == 0 && d.height == 0) { // Probably haven't been layed out yet, force some sort of // initial sizing. rootView.setSize(Integer.MAX_VALUE, Integer.MAX_VALUE); } d.width = (int) Math.min( (long) rootView.getPreferredSpan(View.X_AXIS) + (long) i.left + (long) i.right, Integer.MAX_VALUE); d.height = (int) Math.min( (long) rootView.getPreferredSpan(View.Y_AXIS) + (long) i.top + (long) i.bottom, Integer.MAX_VALUE); } finally { if (doc instanceof AbstractDocument) { ((AbstractDocument) doc).readUnlock(); } } // Fix: The preferred width is always two pixels too small on a Mac. d.width += 2; // We'd like our heights to be odd by default. if ((d.height & 1) == 0) { d.height--; } return d; }
public Dimension getMaximumSize(JComponent c) { Dimension d = getPreferredSize(c); View v = (View) c.getClientProperty(BasicHTML.propertyKey); if (v != null) { d.width += v.getMaximumSpan(View.X_AXIS) - v.getPreferredSpan(View.X_AXIS); } return d; }
/** * Returns the preferred span of the View used to display the alt text, or 0 if the view does not * exist. */ private float getPreferredSpanFromAltView(int axis) { if (getImage() == null) { View view = getAltView(); if (view != null) { return view.getPreferredSpan(axis); } } return 0f; }
/** * Adjusts the given row if possible to fit within the layout span. By default this will try to * find the highest break weight possible nearest the end of the row. If a forced break is * encountered, the break will be positioned there. * * @param rowIndex the row to adjust to the current layout span. * @param desiredSpan the current layout span >= 0 * @param x the location r starts at. */ protected void adjustRow(FlowView fv, int rowIndex, int desiredSpan, int x) { final int flowAxis = fv.getFlowAxis(); View r = fv.getView(rowIndex); int n = r.getViewCount(); int span = 0; int bestWeight = BadBreakWeight; int bestSpan = 0; int bestIndex = -1; int bestOffset = 0; View v; for (int i = 0; i < n; i++) { v = r.getView(i); int spanLeft = desiredSpan - span; int w = v.getBreakWeight(flowAxis, x + span, spanLeft); if ((w >= bestWeight) && (w > BadBreakWeight)) { bestWeight = w; bestIndex = i; bestSpan = span; if (w >= ForcedBreakWeight) { // it's a forced break, so there is // no point in searching further. break; } } span += v.getPreferredSpan(flowAxis); } if (bestIndex < 0) { // there is nothing that can be broken, leave // it in it's current state. return; } // Break the best candidate view, and patch up the row. int spanLeft = desiredSpan - bestSpan; v = r.getView(bestIndex); v = v.breakView(flowAxis, v.getStartOffset(), x + bestSpan, spanLeft); View[] va = new View[1]; va[0] = v; View lv = getLogicalView(fv); for (int i = bestIndex; i < n; i++) { View tmpView = r.getView(i); if (contains(lv, tmpView)) { tmpView.setParent(lv); } else if (tmpView.getViewCount() > 0) { recursiveReparent(tmpView, lv); } } r.replace(bestIndex, n - bestIndex, va); }
/** * Determines the preferred span for this view along an axis. * * @param axis may be either View.X_AXIS or View.Y_AXIS * @return the span the view would like to be rendered into. Typically the view is told to * render into the span that is returned, although there is no guarantee. The parent may * choose to resize or break the view. * @see View#getPreferredSpan */ public float getPreferredSpan(int axis) { float maxpref = 0; float pref = 0; int n = getViewCount(); for (int i = 0; i < n; i++) { View v = getView(i); pref += v.getPreferredSpan(axis); if (v.getBreakWeight(axis, 0, Short.MAX_VALUE) >= ForcedBreakWeight) { maxpref = Math.max(maxpref, pref); pref = 0; } } maxpref = Math.max(maxpref, pref); return maxpref; }
/** * Gets the alignment. * * @param axis may be either X_AXIS or Y_AXIS * @return the alignment */ public float getAlignment(int axis) { switch (axis) { case View.X_AXIS: return 0; case View.Y_AXIS: if (getViewCount() == 0) { return 0; } float span = getPreferredSpan(View.Y_AXIS); View v = getView(0); float above = v.getPreferredSpan(View.Y_AXIS); float a = (((int) span) != 0) ? (above * v.getAlignment(View.Y_AXIS)) / span : 0; return a; default: throw new IllegalArgumentException("Invalid axis: " + axis); } }
/** Returns the baseline for single line text components, like <code>JTextField</code>. */ private static int getSingleLineTextBaseline(JTextComponent textComponent, int h) { View rootView = textComponent.getUI().getRootView(textComponent); if (rootView.getViewCount() > 0) { Insets insets = textComponent.getInsets(); int height = h - insets.top - insets.bottom; int y = insets.top; View fieldView = rootView.getView(0); int vspan = (int) fieldView.getPreferredSpan(View.Y_AXIS); if (height != vspan) { int slop = height - vspan; y += slop / 2; } FontMetrics fm = textComponent.getFontMetrics(textComponent.getFont()); y += fm.getAscent(); return y; } return -1; }
/** * Determines the minimum span for this view along an axis. The is implemented to find the * minimum unbreakable span. * * @param axis may be either View.X_AXIS or View.Y_AXIS * @return the span the view would like to be rendered into. Typically the view is told to * render into the span that is returned, although there is no guarantee. The parent may * choose to resize or break the view. * @see View#getPreferredSpan */ public float getMinimumSpan(int axis) { float maxmin = 0; float min = 0; boolean nowrap = false; int n = getViewCount(); for (int i = 0; i < n; i++) { View v = getView(i); if (v.getBreakWeight(axis, 0, Short.MAX_VALUE) == BadBreakWeight) { min += v.getPreferredSpan(axis); nowrap = true; } else if (nowrap) { maxmin = Math.max(min, maxmin); nowrap = false; min = 0; } } maxmin = Math.max(maxmin, min); return maxmin; }
/** * Determines the preferred span for this view along an axis. * * @param axis may be either X_AXIS or Y_AXIS * @return the span the view would like to be rendered into; typically the view is told to render * into the span that is returned, although there is no guarantee; the parent may choose to * resize or break the view */ @Override public float getPreferredSpan(int axis) { sync(); // If the attributes specified a width/height, always use it! if (axis == View.X_AXIS && (state & WIDTH_FLAG) == WIDTH_FLAG) { getPreferredSpanFromAltView(axis); return width + leftInset + rightInset; } if (axis == View.Y_AXIS && (state & HEIGHT_FLAG) == HEIGHT_FLAG) { getPreferredSpanFromAltView(axis); return height + topInset + bottomInset; } Image image = getImage(); if (image != null) { switch (axis) { case View.X_AXIS: return width + leftInset + rightInset; case View.Y_AXIS: return height + topInset + bottomInset; default: throw new IllegalArgumentException("Invalid axis: " + axis); } } else { View view = getAltView(); float retValue = 0f; if (view != null) { retValue = view.getPreferredSpan(axis); } switch (axis) { case View.X_AXIS: return retValue + (width + leftInset + rightInset); case View.Y_AXIS: return retValue + (height + topInset + bottomInset); default: throw new IllegalArgumentException("Invalid axis: " + axis); } } }
protected int getPreferredRowHeight(JTable table, SymbolEditorComponent editorComponent) { View v = editorComponent.getTextComponent().getUI().getRootView(editorComponent.getTextComponent()); v.setSize(table.getWidth(), Integer.MAX_VALUE); return (int) v.getPreferredSpan(View.Y_AXIS); }
/** * Creates a row of views that will fit within the layout span of the row. This is called by the * layout method. This is implemented to fill the row by repeatedly calling the createView * method until the available span has been exhausted, a forced break was encountered, or the * createView method returned null. If the remaining span was exhaused, the adjustRow method * will be called to perform adjustments to the row to try and make it fit into the given span. * * @param rowIndex the index of the row to fill in with views. The row is assumed to be empty on * entry. * @param pos The current position in the children of this views element from which to start. * @return the position to start the next row */ protected int layoutRow(FlowView fv, int rowIndex, int pos) { View row = fv.getView(rowIndex); int x = fv.getFlowStart(rowIndex); int spanLeft = fv.getFlowSpan(rowIndex); int end = fv.getEndOffset(); TabExpander te = (fv instanceof TabExpander) ? (TabExpander) fv : null; // Indentation. int preX = x; int availableSpan = spanLeft; preX = x; final int flowAxis = fv.getFlowAxis(); boolean forcedBreak = false; while (pos < end && spanLeft > 0) { View v = createView(fv, pos, spanLeft, rowIndex); if (v == null) { break; } int chunkSpan; if ((flowAxis == X_AXIS) && (v instanceof TabableView)) { chunkSpan = (int) ((TabableView) v).getTabbedSpan(x, te); } else { chunkSpan = (int) v.getPreferredSpan(flowAxis); } // If a forced break is necessary, break if (v.getBreakWeight(flowAxis, pos, spanLeft) >= ForcedBreakWeight) { int n = row.getViewCount(); if (n > 0) { /* If this is a forced break and it's not the only view * the view should be replaced with a call to breakView. * If it's it only view, it should be used directly. In * either case no more children should be added beyond this * view. */ v = v.breakView(flowAxis, pos, x, spanLeft); if (v != null) { if ((flowAxis == X_AXIS) && (v instanceof TabableView)) { chunkSpan = (int) ((TabableView) v).getTabbedSpan(x, te); } else { chunkSpan = (int) v.getPreferredSpan(flowAxis); } } else { chunkSpan = 0; } } forcedBreak = true; } spanLeft -= chunkSpan; x += chunkSpan; if (v != null) { row.append(v); pos = v.getEndOffset(); } if (forcedBreak) { break; } } if (spanLeft < 0) { // This row is too long and needs to be adjusted. adjustRow(fv, rowIndex, availableSpan, preX); } else if (row.getViewCount() == 0) { // Impossible spec... put in whatever is left. View v = createView(fv, pos, Integer.MAX_VALUE, rowIndex); row.append(v); } return row.getEndOffset(); }