[llvm-commits] [llvm-gcc-4.2] r43913 [54/80] - in /llvm-gcc-4.2/trunk: boehm-gc/ boehm-gc/Mac_files/ boehm-gc/cord/ boehm-gc/doc/ boehm-gc/include/ boehm-gc/include/private/ boehm-gc/tests/ libffi/ libffi/include/ libffi/src/ libffi/src/alpha/ libffi/src/arm/ libffi/src/cris/ libffi/src/frv/ libffi/src/ia64/ libffi/src/m32r/ libffi/src/m68k/ libffi/src/mips/ libffi/src/pa/ libffi/src/powerpc/ libffi/src/s390/ libffi/src/sh/ libffi/src/sh64/ libffi/src/sparc/ libffi/src/x86/ libffi/testsuite/ libffi/testsuite/config/ li...
Bill Wendling
isanbard at gmail.com
Thu Nov 8 14:57:11 PST 2007
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/DefaultTableColumnModel.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/DefaultTableColumnModel.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/DefaultTableColumnModel.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/DefaultTableColumnModel.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,671 @@
+/* DefaultTableColumnModel.java --
+ Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.table;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.EventListener;
+import java.util.Vector;
+
+import javax.swing.DefaultListSelectionModel;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.EventListenerList;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.event.TableColumnModelEvent;
+import javax.swing.event.TableColumnModelListener;
+
+/**
+ * A model that stores information about the columns used in a {@link JTable}.
+ *
+ * @see JTable#setColumnModel(TableColumnModel)
+ *
+ * @author Andrew Selkirk
+ */
+public class DefaultTableColumnModel
+ implements TableColumnModel, PropertyChangeListener, ListSelectionListener,
+ Serializable
+{
+ private static final long serialVersionUID = 6580012493508960512L;
+
+ /**
+ * Storage for the table columns.
+ */
+ protected Vector tableColumns;
+
+ /**
+ * A selection model that keeps track of column selections.
+ */
+ protected ListSelectionModel selectionModel;
+
+ /**
+ * The space between the columns (the default value is <code>1</code>).
+ */
+ protected int columnMargin;
+
+ /**
+ * Storage for the listeners registered with the model.
+ */
+ protected EventListenerList listenerList = new EventListenerList();
+
+ /**
+ * A change event used when notifying listeners of a change to the
+ * <code>columnMargin</code> field. This single event is reused for all
+ * notifications (it is lazily instantiated within the
+ * {@link #fireColumnMarginChanged()} method).
+ */
+ protected transient ChangeEvent changeEvent;
+
+ /**
+ * A flag that indicates whether or not columns can be selected.
+ */
+ protected boolean columnSelectionAllowed;
+
+ /**
+ * The total width of all the columns in this model.
+ */
+ protected int totalColumnWidth;
+
+ /**
+ * Creates a new table column model with zero columns. A default column
+ * selection model is created by calling {@link #createSelectionModel()}.
+ * The default value for <code>columnMargin</code> is <code>1</code> and
+ * the default value for <code>columnSelectionAllowed</code> is
+ * <code>false</code>.
+ */
+ public DefaultTableColumnModel()
+ {
+ tableColumns = new Vector();
+ selectionModel = createSelectionModel();
+ selectionModel.addListSelectionListener(this);
+ columnMargin = 1;
+ columnSelectionAllowed = false;
+ }
+
+ /**
+ * Adds a column to the model then calls
+ * {@link #fireColumnAdded(TableColumnModelEvent)} to notify the registered
+ * listeners. The model registers itself with the column as a
+ * {@link PropertyChangeListener} so that changes to the column width will
+ * invalidate the cached {@link #totalColumnWidth} value.
+ *
+ * @param column the column (<code>null</code> not permitted).
+ *
+ * @throws IllegalArgumentException if <code>column</code> is
+ * <code>null</code>.
+ *
+ * @see #removeColumn(TableColumn)
+ */
+ public void addColumn(TableColumn column)
+ {
+ if (column == null)
+ throw new IllegalArgumentException("Null 'col' argument.");
+ tableColumns.add(column);
+ column.addPropertyChangeListener(this);
+ invalidateWidthCache();
+ fireColumnAdded(new TableColumnModelEvent(this, 0,
+ tableColumns.size() - 1));
+ }
+
+ /**
+ * Removes a column from the model then calls
+ * {@link #fireColumnRemoved(TableColumnModelEvent)} to notify the registered
+ * listeners. If the specified column does not belong to the model, or is
+ * <code>null</code>, this method does nothing.
+ *
+ * @param column the column to be removed (<code>null</code> permitted).
+ *
+ * @see #addColumn(TableColumn)
+ */
+ public void removeColumn(TableColumn column)
+ {
+ int index = this.tableColumns.indexOf(column);
+ if (index < 0)
+ return;
+ tableColumns.remove(column);
+ fireColumnRemoved(new TableColumnModelEvent(this, index, 0));
+ column.removePropertyChangeListener(this);
+ invalidateWidthCache();
+ }
+
+ /**
+ * Moves the column at index i to the position specified by index j, then
+ * calls {@link #fireColumnMoved(TableColumnModelEvent)} to notify registered
+ * listeners.
+ *
+ * @param i index of the column that will be moved.
+ * @param j index of the column's new location.
+ *
+ * @throws IllegalArgumentException if <code>i</code> or <code>j</code> are
+ * outside the range <code>0</code> to <code>N-1</code>, where
+ * <code>N</code> is the column count.
+ */
+ public void moveColumn(int i, int j)
+ {
+ int columnCount = getColumnCount();
+ if (i < 0 || i >= columnCount)
+ throw new IllegalArgumentException("Index 'i' out of range.");
+ if (j < 0 || j >= columnCount)
+ throw new IllegalArgumentException("Index 'j' out of range.");
+ Object column = tableColumns.remove(i);
+ tableColumns.add(j, column);
+ fireColumnMoved(new TableColumnModelEvent(this, i, j));
+ }
+
+ /**
+ * Sets the column margin then calls {@link #fireColumnMarginChanged()} to
+ * notify the registered listeners.
+ *
+ * @param margin the column margin.
+ *
+ * @see #getColumnMargin()
+ */
+ public void setColumnMargin(int margin)
+ {
+ columnMargin = margin;
+ fireColumnMarginChanged();
+ }
+
+ /**
+ * Returns the number of columns in the model.
+ *
+ * @return The column count.
+ */
+ public int getColumnCount()
+ {
+ return tableColumns.size();
+ }
+
+ /**
+ * Returns an enumeration of the columns in the model.
+ *
+ * @return An enumeration of the columns in the model.
+ */
+ public Enumeration getColumns()
+ {
+ return tableColumns.elements();
+ }
+
+ /**
+ * Returns the index of the {@link TableColumn} with the given identifier.
+ *
+ * @param identifier the identifier (<code>null</code> not permitted).
+ *
+ * @return The index of the {@link TableColumn} with the given identifier.
+ *
+ * @throws IllegalArgumentException if <code>identifier</code> is
+ * <code>null</code> or there is no column with that identifier.
+ */
+ public int getColumnIndex(Object identifier)
+ {
+ if (identifier == null)
+ throw new IllegalArgumentException("Null identifier.");
+ int columnCount = tableColumns.size();
+ for (int i = 0; i < columnCount; i++)
+ {
+ TableColumn tc = (TableColumn) tableColumns.get(i);
+ if (identifier.equals(tc.getIdentifier()))
+ return i;
+ }
+ throw new IllegalArgumentException("No TableColumn with that identifier.");
+ }
+
+ /**
+ * Returns the column at the specified index.
+ *
+ * @param columnIndex the column index (in the range from <code>0</code> to
+ * <code>N-1</code>, where <code>N</code> is the number of columns in
+ * the model).
+ *
+ * @return The column at the specified index.
+ *
+ * @throws ArrayIndexOutOfBoundsException if <code>i</code> is not within
+ * the specified range.
+ */
+ public TableColumn getColumn(int columnIndex)
+ {
+ return (TableColumn) tableColumns.get(columnIndex);
+ }
+
+ /**
+ * Returns the column margin.
+ *
+ * @return The column margin.
+ *
+ * @see #setColumnMargin(int)
+ */
+ public int getColumnMargin()
+ {
+ return columnMargin;
+ }
+
+ /**
+ * Returns the index of the column that contains the specified x-coordinate.
+ * This method assumes that:
+ * <ul>
+ * <li>column zero begins at position zero;</li>
+ * <li>all columns appear in order;</li>
+ * <li>individual column widths are taken into account, but the column margin
+ * is ignored.</li>
+ * </ul>
+ * If no column contains the specified position, this method returns
+ * <code>-1</code>.
+ *
+ * @param x the x-position.
+ *
+ * @return The column index, or <code>-1</code>.
+ */
+ public int getColumnIndexAtX(int x)
+ {
+ for (int i = 0; i < tableColumns.size(); ++i)
+ {
+ int w = ((TableColumn) tableColumns.get(i)).getWidth();
+ if (0 <= x && x < w)
+ return i;
+ else
+ x -= w;
+ }
+ return -1;
+ }
+
+ /**
+ * Returns total width of all the columns in the model, ignoring the
+ * {@link #columnMargin}.
+ *
+ * @return The total width of all the columns.
+ */
+ public int getTotalColumnWidth()
+ {
+ if (totalColumnWidth == -1)
+ recalcWidthCache();
+ return totalColumnWidth;
+ }
+
+ /**
+ * Sets the selection model that will be used to keep track of the selected
+ * columns.
+ *
+ * @param model the selection model (<code>null</code> not permitted).
+ *
+ * @throws IllegalArgumentException if <code>model</code> is
+ * <code>null</code>.
+ *
+ * @see #getSelectionModel()
+ */
+ public void setSelectionModel(ListSelectionModel model)
+ {
+ if (model == null)
+ throw new IllegalArgumentException();
+
+ selectionModel.removeListSelectionListener(this);
+ selectionModel = model;
+ selectionModel.addListSelectionListener(this);
+ }
+
+ /**
+ * Returns the selection model used to track table column selections.
+ *
+ * @return The selection model.
+ *
+ * @see #setSelectionModel(ListSelectionModel)
+ */
+ public ListSelectionModel getSelectionModel()
+ {
+ return selectionModel;
+ }
+
+ /**
+ * Sets the flag that indicates whether or not column selection is allowed.
+ *
+ * @param flag the new flag value.
+ *
+ * @see #getColumnSelectionAllowed()
+ */
+ public void setColumnSelectionAllowed(boolean flag)
+ {
+ columnSelectionAllowed = flag;
+ }
+
+ /**
+ * Returns <code>true</code> if column selection is allowed, and
+ * <code>false</code> if column selection is not allowed.
+ *
+ * @return A boolean.
+ *
+ * @see #setColumnSelectionAllowed(boolean)
+ */
+ public boolean getColumnSelectionAllowed()
+ {
+ return columnSelectionAllowed;
+ }
+
+ /**
+ * Returns an array containing the indices of the selected columns.
+ *
+ * @return An array containing the indices of the selected columns.
+ */
+ public int[] getSelectedColumns()
+ {
+ // FIXME: Implementation of this method was taken from private method
+ // JTable.getSelections(), which is used in various places in JTable
+ // including selected row calculations and cannot be simply removed.
+ // This design should be improved to illuminate duplication of code.
+
+ ListSelectionModel lsm = this.selectionModel;
+ int sz = getSelectedColumnCount();
+ int [] ret = new int[sz];
+
+ int lo = lsm.getMinSelectionIndex();
+ int hi = lsm.getMaxSelectionIndex();
+ int j = 0;
+ java.util.ArrayList ls = new java.util.ArrayList();
+ if (lo != -1 && hi != -1)
+ {
+ switch (lsm.getSelectionMode())
+ {
+ case ListSelectionModel.SINGLE_SELECTION:
+ ret[0] = lo;
+ break;
+
+ case ListSelectionModel.SINGLE_INTERVAL_SELECTION:
+ for (int i = lo; i <= hi; ++i)
+ ret[j++] = i;
+ break;
+
+ case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:
+ for (int i = lo; i <= hi; ++i)
+ if (lsm.isSelectedIndex(i))
+ ret[j++] = i;
+ break;
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Returns the number of selected columns in the model.
+ *
+ * @return The selected column count.
+ *
+ * @see #getSelectionModel()
+ */
+ public int getSelectedColumnCount()
+ {
+ // FIXME: Implementation of this method was taken from private method
+ // JTable.countSelections(), which is used in various places in JTable
+ // including selected row calculations and cannot be simply removed.
+ // This design should be improved to illuminate duplication of code.
+
+ ListSelectionModel lsm = this.selectionModel;
+ int lo = lsm.getMinSelectionIndex();
+ int hi = lsm.getMaxSelectionIndex();
+ int sum = 0;
+
+ if (lo != -1 && hi != -1)
+ {
+ switch (lsm.getSelectionMode())
+ {
+ case ListSelectionModel.SINGLE_SELECTION:
+ sum = 1;
+ break;
+
+ case ListSelectionModel.SINGLE_INTERVAL_SELECTION:
+ sum = hi - lo + 1;
+ break;
+
+ case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:
+ for (int i = lo; i <= hi; ++i)
+ if (lsm.isSelectedIndex(i))
+ ++sum;
+ break;
+ }
+ }
+
+ return sum;
+ }
+
+ /**
+ * Registers a listener with the model, so that it will receive
+ * {@link TableColumnModelEvent} notifications.
+ *
+ * @param listener the listener (<code>null</code> ignored).
+ */
+ public void addColumnModelListener(TableColumnModelListener listener)
+ {
+ listenerList.add(TableColumnModelListener.class, listener);
+ }
+
+ /**
+ * Deregisters a listener so that it no longer receives notification of
+ * changes to this model.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeColumnModelListener(TableColumnModelListener listener)
+ {
+ listenerList.remove(TableColumnModelListener.class, listener);
+ }
+
+ /**
+ * Returns an array containing the listeners that are registered with the
+ * model. If there are no listeners, an empty array is returned.
+ *
+ * @return An array containing the listeners that are registered with the
+ * model.
+ *
+ * @see #addColumnModelListener(TableColumnModelListener)
+ * @since 1.4
+ */
+ public TableColumnModelListener[] getColumnModelListeners()
+ {
+ return (TableColumnModelListener[])
+ listenerList.getListeners(TableColumnModelListener.class);
+ }
+
+ /**
+ * Sends the specified {@link TableColumnModelEvent} to all registered
+ * listeners, to indicate that a column has been added to the model. The
+ * event's <code>toIndex</code> attribute should contain the index of the
+ * added column.
+ *
+ * @param e the event.
+ *
+ * @see #addColumn(TableColumn)
+ */
+ protected void fireColumnAdded(TableColumnModelEvent e)
+ {
+ TableColumnModelListener[] listeners = getColumnModelListeners();
+
+ for (int i = 0; i < listeners.length; i++)
+ listeners[i].columnAdded(e);
+ }
+
+ /**
+ * Sends the specified {@link TableColumnModelEvent} to all registered
+ * listeners, to indicate that a column has been removed from the model. The
+ * event's <code>fromIndex</code> attribute should contain the index of the
+ * removed column.
+ *
+ * @param e the event.
+ *
+ * @see #removeColumn(TableColumn)
+ */
+ protected void fireColumnRemoved(TableColumnModelEvent e)
+ {
+ TableColumnModelListener[] listeners = getColumnModelListeners();
+
+ for (int i = 0; i < listeners.length; i++)
+ listeners[i].columnRemoved(e);
+ }
+
+ /**
+ * Sends the specified {@link TableColumnModelEvent} to all registered
+ * listeners, to indicate that a column in the model has been moved. The
+ * event's <code>fromIndex</code> attribute should contain the old column
+ * index, and the <code>toIndex</code> attribute should contain the new
+ * column index.
+ *
+ * @param e the event.
+ *
+ * @see #moveColumn(int, int)
+ */
+ protected void fireColumnMoved(TableColumnModelEvent e)
+ {
+ TableColumnModelListener[] listeners = getColumnModelListeners();
+
+ for (int i = 0; i < listeners.length; i++)
+ listeners[i].columnMoved(e);
+ }
+
+ /**
+ * Sends the specified {@link ListSelectionEvent} to all registered listeners,
+ * to indicate that the column selections have changed.
+ *
+ * @param e the event.
+ *
+ * @see #valueChanged(ListSelectionEvent)
+ */
+ protected void fireColumnSelectionChanged(ListSelectionEvent e)
+ {
+ EventListener [] listeners = getListeners(TableColumnModelListener.class);
+ for (int i = 0; i < listeners.length; ++i)
+ ((TableColumnModelListener) listeners[i]).columnSelectionChanged(e);
+ }
+
+ /**
+ * Sends a {@link ChangeEvent} to the model's registered listeners to
+ * indicate that the column margin was changed.
+ *
+ * @see #setColumnMargin(int)
+ */
+ protected void fireColumnMarginChanged()
+ {
+ EventListener[] listeners = getListeners(TableColumnModelListener.class);
+ if (changeEvent == null && listeners.length > 0)
+ changeEvent = new ChangeEvent(this);
+ for (int i = 0; i < listeners.length; ++i)
+ ((TableColumnModelListener) listeners[i]).columnMarginChanged(changeEvent);
+ }
+
+ /**
+ * Returns an array containing the listeners (of the specified type) that
+ * are registered with this model.
+ *
+ * @param listenerType the listener type (must indicate a subclass of
+ * {@link EventListener}, <code>null</code> not permitted).
+ *
+ * @return An array containing the listeners (of the specified type) that
+ * are registered with this model.
+ */
+ public EventListener[] getListeners(Class listenerType)
+ {
+ return listenerList.getListeners(listenerType);
+ }
+
+ /**
+ * Receives notification of property changes for the columns in the model.
+ * If the <code>width</code> property for any column changes, we invalidate
+ * the {@link #totalColumnWidth} value here.
+ *
+ * @param event the event.
+ */
+ public void propertyChange(PropertyChangeEvent event)
+ {
+ if (event.getPropertyName().equals("width"))
+ invalidateWidthCache();
+ }
+
+ /**
+ * Receives notification of the change to the list selection model, and
+ * responds by calling
+ * {@link #fireColumnSelectionChanged(ListSelectionEvent)}.
+ *
+ * @param e the list selection event.
+ *
+ * @see #getSelectionModel()
+ */
+ public void valueChanged(ListSelectionEvent e)
+ {
+ fireColumnSelectionChanged(e);
+ }
+
+ /**
+ * Creates a default selection model to track the currently selected
+ * column(s). This method is called by the constructor and returns a new
+ * instance of {@link DefaultListSelectionModel}.
+ *
+ * @return A new default column selection model.
+ */
+ protected ListSelectionModel createSelectionModel()
+ {
+ return new DefaultListSelectionModel();
+ }
+
+ /**
+ * Recalculates the total width of the columns, if the cached value is
+ * <code>-1</code>. Otherwise this method does nothing.
+ *
+ * @see #getTotalColumnWidth()
+ */
+ protected void recalcWidthCache()
+ {
+ if (totalColumnWidth == -1)
+ {
+ totalColumnWidth = 0;
+ for (int i = 0; i < tableColumns.size(); ++i)
+ {
+ totalColumnWidth += ((TableColumn) tableColumns.get(i)).getWidth();
+ }
+ }
+ }
+
+ /**
+ * Sets the {@link #totalColumnWidth} field to <code>-1</code>.
+ *
+ * @see #recalcWidthCache()
+ */
+ private void invalidateWidthCache()
+ {
+ totalColumnWidth = -1;
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/DefaultTableModel.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/DefaultTableModel.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/DefaultTableModel.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/DefaultTableModel.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,634 @@
+/* DefaultTableModel.java --
+ Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.table;
+
+import java.io.Serializable;
+import java.util.Vector;
+
+import javax.swing.event.TableModelEvent;
+
+/**
+ * A two dimensional data structure used to store <code>Object</code>
+ * instances, usually for display in a <code>JTable</code> component.
+ *
+ * @author Andrew Selkirk
+ */
+public class DefaultTableModel extends AbstractTableModel
+ implements Serializable
+{
+ static final long serialVersionUID = 6680042567037222321L;
+
+ /**
+ * Storage for the rows in the table (each row is itself
+ * a <code>Vector</code>).
+ */
+ protected Vector dataVector;
+
+ /**
+ * Storage for the column identifiers.
+ */
+ protected Vector columnIdentifiers;
+
+ /**
+ * Creates an empty table with zero rows and zero columns.
+ */
+ public DefaultTableModel()
+ {
+ this(0, 0);
+ }
+
+ /**
+ * Creates a new table with the specified number of rows and columns.
+ * All cells in the table are initially empty (set to <code>null</code>).
+ *
+ * @param numRows the number of rows.
+ * @param numColumns the number of columns.
+ */
+ public DefaultTableModel(int numRows, int numColumns)
+ {
+ Vector defaultNames = new Vector(numColumns);
+ Vector data = new Vector(numRows);
+ for (int i = 0; i < numColumns; i++)
+ {
+ defaultNames.add(super.getColumnName(i));
+ }
+ for (int r = 0; r < numRows; r++)
+ {
+ Vector tmp = new Vector(numColumns);
+ tmp.setSize(numColumns);
+ data.add(tmp);
+ }
+ setDataVector(data, defaultNames);
+ }
+
+ /**
+ * Creates a new table with the specified column names and number of
+ * rows. The number of columns is determined by the number of column
+ * names supplied.
+ *
+ * @param columnNames the column names.
+ * @param numRows the number of rows.
+ */
+ public DefaultTableModel(Vector columnNames, int numRows)
+ {
+ if (numRows < 0)
+ throw new IllegalArgumentException("numRows < 0");
+ Vector data = new Vector();
+ int numColumns = 0;
+
+ if (columnNames != null)
+ numColumns = columnNames.size();
+
+ while (0 < numRows--)
+ {
+ Vector rowData = new Vector();
+ rowData.setSize(numColumns);
+ data.add(rowData);
+ }
+ setDataVector(data, columnNames);
+ }
+
+ /**
+ * Creates a new table with the specified column names and row count.
+ *
+ * @param columnNames the column names.
+ * @param numRows the number of rows.
+ */
+ public DefaultTableModel(Object[] columnNames, int numRows)
+ {
+ this(convertToVector(columnNames), numRows);
+ }
+
+ /**
+ * Creates a new table with the specified data values and column names.
+ *
+ * @param data the data values.
+ * @param columnNames the column names.
+ */
+ public DefaultTableModel(Vector data, Vector columnNames)
+ {
+ setDataVector(data, columnNames);
+ }
+
+ /**
+ * Creates a new table with the specified data values and column names.
+ *
+ * @param data the data values.
+ * @param columnNames the column names.
+ */
+ public DefaultTableModel(Object[][] data, Object[] columnNames)
+ {
+ this(convertToVector(data), convertToVector(columnNames));
+ }
+
+ /**
+ * Returns the vector containing the row data for the table.
+ *
+ * @return The data vector.
+ */
+ public Vector getDataVector()
+ {
+ return dataVector;
+ }
+
+ /**
+ * Sets the data and column identifiers for the table. The data vector
+ * contains a <code>Vector</code> for each row in the table - if the
+ * number of objects in each row does not match the number of column
+ * names specified, the row data is truncated or expanded (by adding
+ * <code>null</code> values) as required.
+ *
+ * @param data the data for the table (a vector of row vectors).
+ * @param columnNames the column names.
+ *
+ * @throws NullPointerException if either argument is <code>null</code>.
+ */
+ public void setDataVector(Vector data, Vector columnNames)
+ {
+ if (data == null)
+ dataVector = new Vector();
+ else
+ dataVector = data;
+ setColumnIdentifiers(columnNames);
+ }
+
+ /**
+ * Sets the data and column identifiers for the table.
+ *
+ * @param data the data for the table.
+ * @param columnNames the column names.
+ *
+ * @throws NullPointerException if either argument is <code>null</code>.
+ */
+ public void setDataVector(Object[][] data, Object[] columnNames)
+ {
+ setDataVector(convertToVector(data),
+ convertToVector(columnNames));
+ }
+
+ /**
+ * Sends the specified <code>event</code> to all registered listeners.
+ * This method is equivalent to
+ * {@link AbstractTableModel#fireTableChanged(TableModelEvent)}.
+ *
+ * @param event the event.
+ */
+ public void newDataAvailable(TableModelEvent event)
+ {
+ fireTableChanged(event);
+ }
+
+ /**
+ * Sends the specified <code>event</code> to all registered listeners.
+ * This method is equivalent to
+ * {@link AbstractTableModel#fireTableChanged(TableModelEvent)}.
+ *
+ * @param event the event.
+ */
+ public void newRowsAdded(TableModelEvent event)
+ {
+ fireTableChanged(event);
+ }
+
+ /**
+ * Sends the specified <code>event</code> to all registered listeners.
+ * This method is equivalent to
+ * {@link AbstractTableModel#fireTableChanged(TableModelEvent)}.
+ *
+ * @param event the event.
+ */
+ public void rowsRemoved(TableModelEvent event)
+ {
+ fireTableChanged(event);
+ }
+
+ /**
+ * Sets the column identifiers, updates the data rows (truncating
+ * or padding each row with <code>null</code> values) to match the
+ * number of columns, and sends a {@link TableModelEvent} to all
+ * registered listeners.
+ *
+ * @param columnIdentifiers the column identifiers.
+ */
+ public void setColumnIdentifiers(Vector columnIdentifiers)
+ {
+ this.columnIdentifiers = columnIdentifiers;
+ setColumnCount(columnIdentifiers == null ? 0 : columnIdentifiers.size());
+ }
+
+ /**
+ * Sets the column identifiers, updates the data rows (truncating
+ * or padding each row with <code>null</code> values) to match the
+ * number of columns, and sends a {@link TableModelEvent} to all
+ * registered listeners.
+ *
+ * @param columnIdentifiers the column identifiers.
+ */
+ public void setColumnIdentifiers(Object[] columnIdentifiers)
+ {
+ setColumnIdentifiers(convertToVector(columnIdentifiers));
+ }
+
+ /**
+ * This method is obsolete, use {@link #setRowCount(int)} instead.
+ *
+ * @param numRows the number of rows.
+ */
+ public void setNumRows(int numRows)
+ {
+ setRowCount(numRows);
+ }
+
+ /**
+ * Sets the number of rows in the table. If <code>rowCount</code> is less
+ * than the current number of rows in the table, rows are discarded.
+ * If <code>rowCount</code> is greater than the current number of rows in
+ * the table, new (empty) rows are added.
+ *
+ * @param rowCount the row count.
+ */
+ public void setRowCount(int rowCount)
+ {
+ int existingRowCount = dataVector.size();
+ if (rowCount < existingRowCount)
+ {
+ dataVector.setSize(rowCount);
+ fireTableRowsDeleted(rowCount, existingRowCount - 1);
+ }
+ else
+ {
+ int rowsToAdd = rowCount - existingRowCount;
+ addExtraRows(rowsToAdd, columnIdentifiers.size());
+ fireTableRowsInserted(existingRowCount, rowCount - 1);
+ }
+ }
+
+ /**
+ * Sets the number of columns in the table. Existing rows are truncated
+ * or padded with <code>null</code> values to match the new column count.
+ * A {@link TableModelEvent} is sent to all registered listeners.
+ *
+ * @param columnCount the column count.
+ */
+ public void setColumnCount(int columnCount)
+ {
+ for (int i = 0; i < dataVector.size(); ++i)
+ {
+ ((Vector) dataVector.get(i)).setSize(columnCount);
+ }
+ if (columnIdentifiers != null)
+ columnIdentifiers.setSize(columnCount);
+ fireTableStructureChanged();
+ }
+
+ /**
+ * Adds a column with the specified name to the table. All cell values
+ * for the column are initially set to <code>null</code>.
+ *
+ * @param columnName the column name (<code>null</code> permitted).
+ */
+ public void addColumn(Object columnName)
+ {
+ addColumn(columnName, (Object[]) null);
+ }
+
+ /**
+ * Adds a column with the specified name and data values to the table.
+ *
+ * @param columnName the column name (<code>null</code> permitted).
+ * @param columnData the column data.
+ */
+ public void addColumn(Object columnName, Vector columnData)
+ {
+ Object[] dataArray = null;
+ if (columnData != null)
+ {
+ int rowCount = dataVector.size();
+ if (columnData.size() < rowCount)
+ columnData.setSize(rowCount);
+ dataArray = columnData.toArray();
+ }
+ addColumn(columnName, dataArray);
+ }
+
+ /**
+ * Adds a column with the specified name and data values to the table.
+ *
+ * @param columnName the column name (<code>null</code> permitted).
+ * @param columnData the column data.
+ */
+ public void addColumn(Object columnName, Object[] columnData)
+ {
+ if (columnData != null)
+ {
+ // check columnData array for cases where the number of items
+ // doesn't match the number of rows in the existing table
+ if (columnData.length > dataVector.size())
+ {
+ int rowsToAdd = columnData.length - dataVector.size();
+ addExtraRows(rowsToAdd, columnIdentifiers.size());
+ }
+ else if (columnData.length < dataVector.size())
+ {
+ Object[] tmp = new Object[dataVector.size()];
+ System.arraycopy(columnData, 0, tmp, 0, columnData.length);
+ columnData = tmp;
+ }
+ }
+ for (int i = 0; i < dataVector.size(); ++i)
+ {
+ ((Vector) dataVector.get(i)).add(columnData == null ? null : columnData[i]);
+ }
+ columnIdentifiers.add(columnName);
+ fireTableStructureChanged();
+ }
+
+ /**
+ * Adds a new row containing the specified data to the table and sends a
+ * {@link TableModelEvent} to all registered listeners.
+ *
+ * @param rowData the row data (<code>null</code> permitted).
+ */
+ public void addRow(Vector rowData)
+ {
+ int rowIndex = dataVector.size();
+ dataVector.add(rowData);
+ newRowsAdded(new TableModelEvent(
+ this, rowIndex, rowIndex, -1, TableModelEvent.INSERT)
+ );
+ }
+
+ /**
+ * Adds a new row containing the specified data to the table and sends a
+ * {@link TableModelEvent} to all registered listeners.
+ *
+ * @param rowData the row data (<code>null</code> permitted).
+ */
+ public void addRow(Object[] rowData)
+ {
+ addRow(convertToVector(rowData));
+ }
+
+ /**
+ * Inserts a new row into the table.
+ *
+ * @param row the row index.
+ * @param rowData the row data.
+ */
+ public void insertRow(int row, Vector rowData)
+ {
+ dataVector.add(row, rowData);
+ fireTableRowsInserted(row, row);
+ }
+
+ /**
+ * Inserts a new row into the table.
+ *
+ * @param row the row index.
+ * @param rowData the row data.
+ */
+ public void insertRow(int row, Object[] rowData)
+ {
+ insertRow(row, convertToVector(rowData));
+ }
+
+ /**
+ * Moves the rows from <code>startIndex</code> to <code>endIndex</code>
+ * (inclusive) to the specified row.
+ *
+ * @param startIndex the start row.
+ * @param endIndex the end row.
+ * @param toIndex the row to move to.
+ */
+ public void moveRow(int startIndex, int endIndex, int toIndex)
+ {
+ Vector removed = new Vector();
+ for (int i = endIndex; i >= startIndex; i--)
+ {
+ removed.add(this.dataVector.remove(i));
+ }
+ for (int i = 0; i <= endIndex - startIndex; i++)
+ {
+ dataVector.insertElementAt(removed.get(i), toIndex);
+ }
+ int firstRow = Math.min(startIndex, toIndex);
+ int lastRow = Math.max(endIndex, toIndex + (endIndex - startIndex));
+ fireTableRowsUpdated(firstRow, lastRow);
+ }
+
+ /**
+ * Removes a row from the table and sends a {@link TableModelEvent} to
+ * all registered listeners.
+ *
+ * @param row the row index.
+ */
+ public void removeRow(int row)
+ {
+ dataVector.remove(row);
+ fireTableRowsDeleted(row, row);
+ }
+
+ /**
+ * Returns the number of rows in the model.
+ *
+ * @return The row count.
+ */
+ public int getRowCount()
+ {
+ return dataVector.size();
+ }
+
+ /**
+ * Returns the number of columns in the model.
+ *
+ * @return The column count.
+ */
+ public int getColumnCount()
+ {
+ return columnIdentifiers == null ? 0 : columnIdentifiers.size();
+ }
+
+ /**
+ * Get the name of the column. If the column has the column identifier set,
+ * the return value is the result of the .toString() method call on that
+ * identifier. If the identifier is not explicitly set, the returned value
+ * is calculated by {@link AbstractTableModel#getColumnName(int)}.
+ *
+ * @param column the column index.
+ *
+ * @return The column name.
+ */
+ public String getColumnName(int column)
+ {
+ String result = "";
+ if (columnIdentifiers == null)
+ result = super.getColumnName(column);
+ else
+ {
+ if (column < getColumnCount())
+ {
+ checkSize();
+ Object id = columnIdentifiers.get(column);
+ if (id != null)
+ result = id.toString();
+ else
+ result = super.getColumnName(column);
+ }
+ else
+ result = super.getColumnName(column);
+ }
+ return result;
+ }
+
+ /**
+ * Returns <code>true</code> if the specified cell can be modified, and
+ * <code>false</code> otherwise. For this implementation, the method
+ * always returns <code>true</code>.
+ *
+ * @param row the row index.
+ * @param column the column index.
+ *
+ * @return <code>true</code> in all cases.
+ */
+ public boolean isCellEditable(int row, int column)
+ {
+ return true;
+ }
+
+ /**
+ * Returns the value at the specified cell in the table.
+ *
+ * @param row the row index.
+ * @param column the column index.
+ *
+ * @return The value (<code>Object</code>, possibly <code>null</code>) at
+ * the specified cell in the table.
+ */
+ public Object getValueAt(int row, int column)
+ {
+ return ((Vector) dataVector.get(row)).get(column);
+ }
+
+ /**
+ * Sets the value for the specified cell in the table and sends a
+ * {@link TableModelEvent} to all registered listeners.
+ *
+ * @param value the value (<code>Object</code>, <code>null</code> permitted).
+ * @param row the row index.
+ * @param column the column index.
+ */
+ public void setValueAt(Object value, int row, int column)
+ {
+ ((Vector) dataVector.get(row)).set(column, value);
+ fireTableCellUpdated(row, column);
+ }
+
+ /**
+ * Converts the data array to a <code>Vector</code>.
+ *
+ * @param data the data array (<code>null</code> permitted).
+ *
+ * @return A vector (or <code>null</code> if the data array
+ * is <code>null</code>).
+ */
+ protected static Vector convertToVector(Object[] data)
+ {
+ if (data == null)
+ return null;
+ Vector vector = new Vector(data.length);
+ for (int i = 0; i < data.length; i++)
+ vector.add(data[i]);
+ return vector;
+ }
+
+ /**
+ * Converts the data array to a <code>Vector</code> of rows.
+ *
+ * @param data the data array (<code>null</code> permitted).
+ *
+ * @return A vector (or <code>null</code> if the data array
+ * is <code>null</code>.
+ */
+ protected static Vector convertToVector(Object[][] data)
+ {
+ if (data == null)
+ return null;
+ Vector vector = new Vector(data.length);
+ for (int i = 0; i < data.length; i++)
+ vector.add(convertToVector(data[i]));
+ return vector;
+ }
+
+ /**
+ * This method adds some rows to <code>dataVector</code>.
+ *
+ * @param rowsToAdd number of rows to add
+ * @param nbColumns size of the added rows
+ */
+ private void addExtraRows(int rowsToAdd, int nbColumns)
+ {
+ for (int i = 0; i < rowsToAdd; i++)
+ {
+ Vector tmp = new Vector();
+ tmp.setSize(columnIdentifiers.size());
+ dataVector.add(tmp);
+ }
+ }
+
+ /**
+ * Checks the real columns/rows sizes against the ones returned by
+ * <code>getColumnCount()</code> and <code>getRowCount()</code>.
+ * If the supposed one are bigger, then we grow <code>columIdentifiers</code>
+ * and <code>dataVector</code> to their expected size.
+ */
+ private void checkSize()
+ {
+ int columnCount = getColumnCount();
+ int rowCount = getRowCount();
+
+ if (columnCount > columnIdentifiers.size())
+ columnIdentifiers.setSize(columnCount);
+
+ if (rowCount > dataVector.size())
+ {
+ int rowsToAdd = rowCount - dataVector.size();
+ addExtraRows(rowsToAdd, columnCount);
+ }
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/JTableHeader.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/JTableHeader.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/JTableHeader.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/JTableHeader.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,1055 @@
+/* JTableHeader.java --
+ Copyright (C) 2003, 2004, 2005, 2006, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.table;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.FocusListener;
+import java.beans.PropertyChangeListener;
+import java.util.Locale;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleAction;
+import javax.accessibility.AccessibleComponent;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleSelection;
+import javax.accessibility.AccessibleStateSet;
+import javax.accessibility.AccessibleText;
+import javax.accessibility.AccessibleValue;
+import javax.swing.JComponent;
+import javax.swing.JTable;
+import javax.swing.UIManager;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.TableColumnModelEvent;
+import javax.swing.event.TableColumnModelListener;
+import javax.swing.plaf.TableHeaderUI;
+
+/**
+ * Represents the table header. The header displays the column header values,
+ * is always visible event if the rest of the table scrolls up and down and
+ * supports column reordering and resizing with mouse.
+ */
+public class JTableHeader extends JComponent
+ implements TableColumnModelListener, Accessible
+{
+ protected class AccessibleJTableHeader extends AccessibleJComponent
+ {
+ protected class AccessibleJTableHeaderEntry extends AccessibleContext
+ implements Accessible, AccessibleComponent
+ {
+
+ private int columnIndex;
+
+ private JTableHeader parent;
+
+ private JTable table;
+
+ public AccessibleJTableHeaderEntry(int c, JTableHeader p, JTable t)
+ {
+ columnIndex = c;
+ parent = p;
+ table = t;
+ }
+
+ /**
+ * Returns the column header renderer.
+ *
+ * @return The column header renderer.
+ */
+ Component getColumnHeaderRenderer()
+ {
+ TableColumn tc = parent.getColumnModel().getColumn(columnIndex);
+ TableCellRenderer r = tc.getHeaderRenderer();
+ if (r == null)
+ r = parent.getDefaultRenderer();
+ return r.getTableCellRendererComponent(table, tc.headerValue,
+ false, false, -1, columnIndex);
+ }
+
+ /**
+ * Returns the accessible context for the column header renderer, or
+ * <code>null</code>.
+ *
+ * @return The accessible context.
+ */
+ AccessibleContext getAccessibleColumnHeaderRenderer()
+ {
+ Component c = getColumnHeaderRenderer();
+ if (c instanceof Accessible)
+ return c.getAccessibleContext();
+ return null;
+ }
+
+ /**
+ * @see #removeFocusListener(FocusListener)
+ */
+ public void addFocusListener(FocusListener l)
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent c = ac.getAccessibleComponent();
+ if (c != null)
+ c.addFocusListener(l);
+ }
+
+ /**
+ * @see #removePropertyChangeListener(PropertyChangeListener)
+ */
+ public void addPropertyChangeListener(PropertyChangeListener l)
+ {
+ // add the listener to the accessible context for the header
+ // renderer...
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ if (ac != null)
+ ac.addPropertyChangeListener(l);
+ }
+
+ public boolean contains(Point p)
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent c = ac.getAccessibleComponent();
+ if (c != null)
+ return c.contains(p);
+ else
+ return false;
+ }
+
+ public AccessibleAction getAccessibleAction()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ if (ac instanceof AccessibleAction)
+ return (AccessibleAction) ac;
+ else
+ return null;
+ }
+
+ public Accessible getAccessibleAt(Point p)
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent c = ac.getAccessibleComponent();
+ if (c != null)
+ return c.getAccessibleAt(p);
+ else
+ return null;
+ }
+
+ /**
+ * Returns <code>null</code> as the header entry has no accessible
+ * children.
+ *
+ * @return <code>null</code>.
+ */
+ public Accessible getAccessibleChild(int i)
+ {
+ return null;
+ }
+
+ /**
+ * Returns the number of accessible children, zero in this case.
+ *
+ * @return 0
+ */
+ public int getAccessibleChildrenCount()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns the accessible component for this header entry.
+ *
+ * @return <code>this</code>.
+ */
+ public AccessibleComponent getAccessibleComponent()
+ {
+ return this;
+ }
+
+ /**
+ * Returns the accessible context for this header entry.
+ *
+ * @return <code>this</code>.
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ return this;
+ }
+
+ /**
+ * Returns the accessible description.
+ *
+ * @return The accessible description.
+ *
+ * @see #setAccessibleDescription(String)
+ */
+ public String getAccessibleDescription()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ if (ac != null)
+ return ac.getAccessibleDescription();
+ return accessibleDescription;
+ }
+
+ /**
+ * Returns the index of this header entry.
+ *
+ * @return The index of this header entry.
+ */
+ public int getAccessibleIndexInParent()
+ {
+ return columnIndex;
+ }
+
+ /**
+ * Returns the accessible name.
+ *
+ * @return The accessible name.
+ *
+ * @see #setAccessibleName(String)
+ */
+ public String getAccessibleName()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ if (ac != null)
+ return ac.getAccessibleName();
+ return accessibleName;
+ }
+
+ /**
+ * Returns the accessible role for the header entry.
+ *
+ * @return The accessible role.
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ if (ac != null)
+ return ac.getAccessibleRole();
+ else
+ return null;
+ }
+
+ public AccessibleSelection getAccessibleSelection()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ if (ac instanceof AccessibleValue)
+ return (AccessibleSelection) ac;
+ else
+ return null;
+ }
+
+ public AccessibleStateSet getAccessibleStateSet()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ if (ac != null)
+ return ac.getAccessibleStateSet();
+ else
+ return null;
+ }
+
+ public AccessibleText getAccessibleText()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ if (ac != null)
+ return ac.getAccessibleText();
+ else
+ return null;
+ }
+
+ public AccessibleValue getAccessibleValue()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ if (ac instanceof AccessibleValue)
+ return (AccessibleValue) ac;
+ else
+ return null;
+ }
+
+ public Color getBackground()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent c = ac.getAccessibleComponent();
+ if (c != null)
+ return c.getBackground();
+ else
+ return null;
+ }
+
+ public Rectangle getBounds()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent c = ac.getAccessibleComponent();
+ if (c != null)
+ return c.getBounds();
+ else
+ return null;
+ }
+
+ public Cursor getCursor()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent c = ac.getAccessibleComponent();
+ if (c != null)
+ return c.getCursor();
+ else
+ return null;
+ }
+
+ public Font getFont()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent c = ac.getAccessibleComponent();
+ if (c != null)
+ return c.getFont();
+ else
+ return null;
+ }
+
+ public FontMetrics getFontMetrics(Font f)
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent c = ac.getAccessibleComponent();
+ if (c != null)
+ return c.getFontMetrics(f);
+ else
+ return null;
+ }
+
+ public Color getForeground()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent c = ac.getAccessibleComponent();
+ if (c != null)
+ return c.getForeground();
+ else
+ return null;
+ }
+
+ public Locale getLocale()
+ {
+ Component c = getColumnHeaderRenderer();
+ if (c != null)
+ return c.getLocale();
+ return null;
+ }
+
+ public Point getLocation()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent c = ac.getAccessibleComponent();
+ if (c != null)
+ return c.getLocation();
+ else
+ return null;
+ }
+
+ public Point getLocationOnScreen()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent c = ac.getAccessibleComponent();
+ if (c != null)
+ return c.getLocationOnScreen();
+ else
+ return null;
+ }
+
+ public Dimension getSize()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent c = ac.getAccessibleComponent();
+ if (c != null)
+ return c.getSize();
+ else
+ return null;
+ }
+
+ public boolean isEnabled()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent c = ac.getAccessibleComponent();
+ if (c != null)
+ return c.isEnabled();
+ else
+ return false;
+ }
+
+ public boolean isFocusTraversable()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent c = ac.getAccessibleComponent();
+ if (c != null)
+ return c.isFocusTraversable();
+ else
+ return false;
+ }
+
+ public boolean isShowing()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent c = ac.getAccessibleComponent();
+ if (c != null)
+ return c.isShowing();
+ else
+ return false;
+ }
+
+ public boolean isVisible()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent c = ac.getAccessibleComponent();
+ if (c != null)
+ return c.isVisible();
+ else
+ return false;
+ }
+
+ /**
+ * @see #addFocusListener(FocusListener)
+ */
+ public void removeFocusListener(FocusListener l)
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent c = ac.getAccessibleComponent();
+ if (c != null)
+ c.removeFocusListener(l);
+ }
+
+ /**
+ * @see #addPropertyChangeListener(PropertyChangeListener)
+ */
+ public void removePropertyChangeListener(PropertyChangeListener l)
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ if (ac != null)
+ ac.removePropertyChangeListener(l);
+ }
+
+ /**
+ * @see #addFocusListener(FocusListener)
+ */
+ public void requestFocus()
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent c = ac.getAccessibleComponent();
+ if (c != null)
+ c.requestFocus();
+ }
+
+ /**
+ * @see #getAccessibleDescription()
+ */
+ public void setAccessibleDescription(String s)
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ if (ac != null)
+ ac.setAccessibleDescription(s);
+ else
+ accessibleDescription = s;
+ }
+
+ /**
+ * @see #getAccessibleName()
+ */
+ public void setAccessibleName(String s)
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ if (ac != null)
+ ac.setAccessibleName(s);
+ }
+
+ public void setBackground(Color c)
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent comp = ac.getAccessibleComponent();
+ if (comp != null)
+ comp.setBackground(c);
+ }
+
+ public void setBounds(Rectangle r)
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent comp = ac.getAccessibleComponent();
+ if (comp != null)
+ comp.setBounds(r);
+ }
+
+ public void setCursor(Cursor c)
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent comp = ac.getAccessibleComponent();
+ if (comp != null)
+ comp.setCursor(c);
+ }
+
+ public void setEnabled(boolean b)
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent comp = ac.getAccessibleComponent();
+ if (comp != null)
+ comp.setEnabled(b);
+ }
+
+ public void setFont(Font f)
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent comp = ac.getAccessibleComponent();
+ if (comp != null)
+ comp.setFont(f);
+ }
+
+ public void setForeground(Color c)
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent comp = ac.getAccessibleComponent();
+ if (comp != null)
+ comp.setForeground(c);
+ }
+
+ public void setLocation(Point p)
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent comp = ac.getAccessibleComponent();
+ if (comp != null)
+ comp.setLocation(p);
+ }
+
+ public void setSize(Dimension d)
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent comp = ac.getAccessibleComponent();
+ if (comp != null)
+ comp.setSize(d);
+ }
+
+ public void setVisible(boolean b)
+ {
+ AccessibleContext ac = getAccessibleColumnHeaderRenderer();
+ AccessibleComponent comp = ac.getAccessibleComponent();
+ if (comp != null)
+ comp.setVisible(b);
+ }
+ };
+
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.PANEL;
+ }
+
+ public int getAccessibleChildrenCount()
+ {
+ return table.getColumnCount();
+ }
+
+ public Accessible getAccessibleChild(int i)
+ {
+ return new AccessibleJTableHeaderEntry(i, JTableHeader.this, table);
+ }
+
+ public Accessible getAccessibleAt(Point p)
+ {
+ return getAccessibleChild(columnAtPoint(p));
+ }
+ }
+
+ /**
+ * Use serialVersionUid for interoperability.
+ */
+ private static final long serialVersionUID = 5144633983372967710L;
+
+ /**
+ * The columnModel property.
+ */
+ protected TableColumnModel columnModel;
+
+ /**
+ * The draggedColumn property.
+ */
+ protected TableColumn draggedColumn;
+
+ /**
+ * The draggedDistance property.
+ */
+ protected int draggedDistance;
+
+ /**
+ * The opaque property.
+ */
+ boolean opaque;
+
+ /**
+ * The reorderingAllowed property.
+ */
+ protected boolean reorderingAllowed;
+
+ /**
+ * The resizingAllowed property.
+ */
+ protected boolean resizingAllowed = true;
+
+ /**
+ * The resizingColumn property.
+ */
+ protected TableColumn resizingColumn;
+
+ /**
+ * The table property.
+ */
+ protected JTable table;
+
+ /**
+ * The updateTableInRealTime property.
+ */
+ protected boolean updateTableInRealTime;
+
+ TableCellRenderer cellRenderer;
+
+ /**
+ * Creates a new default instance.
+ */
+ public JTableHeader()
+ {
+ this(null);
+ }
+
+ /**
+ * Creates a new header. If <code>cm</code> is <code>null</code>, a new
+ * table column model is created by calling
+ * {@link #createDefaultColumnModel()}.
+ *
+ * @param cm the table column model (<code>null</code> permitted).
+ */
+ public JTableHeader(TableColumnModel cm)
+ {
+ columnModel = cm == null ? createDefaultColumnModel() : cm;
+ initializeLocalVars();
+ updateUI();
+ }
+
+ /**
+ * Creates a default table column model.
+ *
+ * @return A default table column model.
+ */
+ protected TableColumnModel createDefaultColumnModel()
+ {
+ return new DefaultTableColumnModel();
+ }
+
+ /**
+ * Get the value of the {@link #accessibleContext} property.
+ *
+ * @return The current value of the property
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ return accessibleContext;
+ }
+
+ /**
+ * Get the value of the {@link #columnModel} property.
+ *
+ * @return The current value of the property
+ */
+ public TableColumnModel getColumnModel()
+ {
+ return columnModel;
+ }
+
+ /**
+ * Get the column that is currently being dragged. This is used when
+ * handling the column reordering with mouse.
+ *
+ * @return the column being dragged, null if none.
+ */
+ public TableColumn getDraggedColumn()
+ {
+ return draggedColumn;
+ }
+
+ /**
+ * Get the value of the {@link #draggedDistance} property.
+ *
+ * @return The current value of the property
+ */
+ public int getDraggedDistance()
+ {
+ return draggedDistance;
+ }
+
+ /**
+ * Check if it is possible to reorder the table columns by dragging column
+ * header with mouse. The table reordering is enabled by default, but can be
+ * disabled with {@link #setReorderingAllowed(boolean)}.
+ *
+ * @return true if reordering is allowed, false otherwise.
+ */
+ public boolean getReorderingAllowed()
+ {
+ return reorderingAllowed;
+ }
+
+ /**
+ * Check if it is possible to resize the table columns by dragging the column
+ * boundary in the table header with mouse. The resizing is enabled
+ * by default, but can be disabled with {@link #setResizingAllowed(boolean)}.
+ *
+ * @return true if resizing is allowed, false otherwise.
+ */
+ public boolean getResizingAllowed()
+ {
+ return resizingAllowed;
+ }
+
+ /**
+ * Get the column that is currently being resized. This is used when
+ * handling the column resizing with mouse.
+ *
+ * @return the column being currently resized, null if none.
+ */
+ public TableColumn getResizingColumn()
+ {
+ return resizingColumn;
+ }
+
+ /**
+ * Get the table, having this header.
+ *
+ * @return the table, having this header.
+ */
+ public JTable getTable()
+ {
+ return table;
+ }
+
+ /**
+ * Get the value of the {@link #updateTableInRealTime} property.
+ *
+ * @return The current value of the property
+ */
+ public boolean getUpdateTableInRealTime()
+ {
+ return updateTableInRealTime;
+ }
+
+ /**
+ * Get the value of the {@link #opaque} property.
+ *
+ * @return The current value of the property
+ */
+ public boolean isOpaque()
+ {
+ return opaque;
+ }
+
+ /**
+ * Set the value of the {@link #columnModel} property.
+ *
+ * @param c The new value of the property
+ */
+ public void setColumnModel(TableColumnModel c)
+ {
+ columnModel.removeColumnModelListener(this);
+ columnModel = c;
+ columnModel.addColumnModelListener(this);
+ }
+
+ /**
+ * Set the column that is currently being dragged. This is used when
+ * dragging the column with mouse. Setting to null will stop the
+ * dragging session immediately.
+ *
+ * @param draggingIt the column being currently dragged, null if none.
+ */
+ public void setDraggedColumn(TableColumn draggingIt)
+ {
+ draggedColumn = draggingIt;
+ }
+
+ /**
+ * Set the value of the {@link #draggedDistance} property.
+ *
+ * @param d The new value of the property
+ */
+ public void setDraggedDistance(int d)
+ {
+ draggedDistance = d;
+ }
+
+ /**
+ * Set the value of the {@link #opaque} property.
+ *
+ * @param o The new value of the property
+ */
+ public void setOpaque(boolean o)
+ {
+ opaque = o;
+ }
+
+ /**
+ * Set the table ability to reorder columns by dragging column header
+ * with mouse. The table reordering is enabled by default, but can be
+ * disabled with this method.
+ *
+ * @param allowed true if reordering is allowed, false otherwise.
+ */
+ public void setReorderingAllowed(boolean allowed)
+ {
+ reorderingAllowed = allowed;
+ }
+
+ /**
+ * Set the table ability to resize columns by dragging the column
+ * boundary in the table header with mouse. The resizing is enabled
+ * by default, but can be disabled using this method.
+ *
+ * @param allowed true if resizing is allowed, false otherwise.
+ */
+ public void setResizingAllowed(boolean allowed)
+ {
+ resizingAllowed = allowed;
+ }
+
+ /**
+ * The the column that is currently being resized. This property is used
+ * when handling table resizing with mouse. Setting to null would stop
+ * the resizing session immediately.
+ *
+ * @param resizingIt the column being currently resized
+ */
+ public void setResizingColumn(TableColumn resizingIt)
+ {
+ resizingColumn = resizingIt;
+ }
+
+ /**
+ * Set the value of the {@link #table} property.
+ *
+ * @param t The new value of the property
+ */
+ public void setTable(JTable t)
+ {
+ table = t;
+ }
+
+ /**
+ * Set the value of the {@link #updateTableInRealTime} property.
+ *
+ * @param u The new value of the property
+ */
+ public void setUpdateTableInRealTime(boolean u)
+ {
+ updateTableInRealTime = u;
+ }
+
+ /**
+ * Creates a default renderer.
+ *
+ * @return A default renderer.
+ */
+ protected TableCellRenderer createDefaultRenderer()
+ {
+ return new DefaultTableCellRenderer();
+ }
+
+ /**
+ * Returns the default table cell renderer.
+ *
+ * @return The default table cell renderer.
+ */
+ public TableCellRenderer getDefaultRenderer()
+ {
+ return cellRenderer;
+ }
+
+ /**
+ * Sets the default table cell renderer.
+ *
+ * @param cellRenderer the renderer.
+ */
+ public void setDefaultRenderer(TableCellRenderer cellRenderer)
+ {
+ this.cellRenderer = cellRenderer;
+ }
+
+ /**
+ * Get the rectangle, occupied by the header of the given column.
+ *
+ * @param column the column, for that the header area is requested.
+ *
+ * @return the column header area.
+ */
+ public Rectangle getHeaderRect(int column)
+ {
+ Rectangle r = getTable().getCellRect(-1, column, false);
+ r.height = getHeight();
+ return r;
+ }
+
+ protected String paramString()
+ {
+ return "JTableHeader";
+ }
+
+ // UI support
+
+ public String getUIClassID()
+ {
+ return "TableHeaderUI";
+ }
+
+ public TableHeaderUI getUI()
+ {
+ return (TableHeaderUI) ui;
+ }
+
+ public void setUI(TableHeaderUI u)
+ {
+ super.setUI(u);
+ }
+
+ public void updateUI()
+ {
+ setUI((TableHeaderUI) UIManager.getUI(this));
+ }
+
+ /**
+ * Returns the index of the column at the specified point.
+ *
+ * @param point the point.
+ *
+ * @return The column index, or -1.
+ */
+ public int columnAtPoint(Point point)
+ {
+ if (getBounds().contains(point))
+ return columnModel.getColumnIndexAtX(point.x);
+
+ return -1;
+ }
+
+ /**
+ * Receives notification when a column is added to the column model.
+ *
+ * @param event the table column model event
+ */
+ public void columnAdded(TableColumnModelEvent event)
+ {
+ // TODO: What else to do here (if anything)?
+ resizeAndRepaint();
+ }
+
+ /**
+ * Receives notification when a column margin changes in the column model.
+ *
+ * @param event the table column model event
+ */
+ public void columnMarginChanged(ChangeEvent event)
+ {
+ // TODO: What else to do here (if anything)?
+ resizeAndRepaint();
+ }
+
+ /**
+ * Receives notification when a column is moved within the column model.
+ *
+ * @param event the table column model event
+ */
+ public void columnMoved(TableColumnModelEvent event)
+ {
+ // TODO: What else to do here (if anything)?
+ resizeAndRepaint();
+ }
+
+ /**
+ * Receives notification when a column is removed from the column model.
+ *
+ * @param event the table column model event
+ */
+ public void columnRemoved(TableColumnModelEvent event)
+ {
+ // TODO: What else to do here (if anything)?
+ resizeAndRepaint();
+ }
+
+ /**
+ * Receives notification when the column selection has changed.
+ *
+ * @param event the table column model event
+ */
+ public void columnSelectionChanged(ListSelectionEvent event)
+ {
+ // TODO: What else to do here (if anything)?
+ resizeAndRepaint();
+ }
+
+ /**
+ * Validates the layout of this table header and repaints it. This is
+ * equivalent to <code>revalidate()</code> followed by
+ * <code>repaint()</code>.
+ */
+ public void resizeAndRepaint()
+ {
+ revalidate();
+ repaint();
+ }
+
+ /**
+ * Initializes the fields and properties of this class with default values.
+ * This is called by the constructors.
+ */
+ protected void initializeLocalVars()
+ {
+ accessibleContext = new AccessibleJTableHeader();
+ draggedColumn = null;
+ draggedDistance = 0;
+ opaque = true;
+ reorderingAllowed = true;
+ resizingAllowed = true;
+ resizingColumn = null;
+ table = null;
+ updateTableInRealTime = true;
+ cellRenderer = createDefaultRenderer();
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableCellEditor.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableCellEditor.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableCellEditor.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableCellEditor.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,65 @@
+/* TableCellEditor.java --
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.table;
+
+import java.awt.Component;
+
+import javax.swing.CellEditor;
+import javax.swing.JTable;
+
+/**
+ * TableCellEditor public interface
+ * @author Andrew Selkirk
+ */
+public interface TableCellEditor extends CellEditor
+{
+
+ /**
+ * Get table cell editor component
+ * @param table JTable
+ * @param value Value of cell
+ * @param isSelected Cell selected
+ * @param row Row of cell
+ * @param column Column of cell
+ * @return Component
+ */
+ Component getTableCellEditorComponent(JTable table, Object value,
+ boolean isSelected, int row, int column);
+
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableCellRenderer.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableCellRenderer.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableCellRenderer.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableCellRenderer.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,66 @@
+/* TableCellRenderer.java --
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.table;
+
+import java.awt.Component;
+
+import javax.swing.JTable;
+
+/**
+ * TableCellRenderer public interface
+ * @author Andrew Selkirk
+ */
+public interface TableCellRenderer
+{
+
+ /**
+ * Get table cell renderer component
+ * @param table JTable
+ * @param value Value of cell
+ * @param isSelected Cell selected
+ * @param hasFocus Cell has focus
+ * @param row Row of cell
+ * @param column Column of cell
+ * @return Component
+ */
+ Component getTableCellRendererComponent(JTable table, Object value,
+ boolean isSelected, boolean hasFocus, int row, int column);
+
+
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableColumn.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableColumn.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableColumn.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableColumn.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,693 @@
+/* TableColumn.java --
+ Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.table;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.Serializable;
+
+import javax.swing.event.SwingPropertyChangeSupport;
+
+/**
+ * Represents the attributes of a column in a table, including the column index,
+ * width, minimum width, preferred width and maximum width.
+ *
+ * @author Andrew Selkirk
+ */
+public class TableColumn
+ implements Serializable
+{
+ static final long serialVersionUID = -6113660025878112608L;
+
+ /**
+ * The name for the <code>columnWidth</code> property (this field is
+ * obsolete and no longer used). Note also that the typo in the value
+ * string is deliberate, to match the specification.
+ */
+ public static final String COLUMN_WIDTH_PROPERTY = "columWidth";
+
+ /**
+ * The name for the <code>headerValue</code> property.
+ */
+ public static final String HEADER_VALUE_PROPERTY = "headerValue";
+
+ /**
+ * The name for the <code>headerRenderer</code> property.
+ */
+ public static final String HEADER_RENDERER_PROPERTY = "headerRenderer";
+
+ /**
+ * The name for the <code>cellRenderer</code> property.
+ */
+ public static final String CELL_RENDERER_PROPERTY = "cellRenderer";
+
+ /**
+ * The index of the corresponding column in the table model.
+ */
+ protected int modelIndex;
+
+ /**
+ * The identifier for the column.
+ */
+ protected Object identifier;
+
+ /**
+ * The current width for the column.
+ */
+ protected int width;
+
+ /**
+ * The minimum width for the column.
+ */
+ protected int minWidth = 15;
+
+ /**
+ * The preferred width for the column.
+ */
+ private int preferredWidth;
+
+ /**
+ * The maximum width for the column.
+ */
+ protected int maxWidth = Integer.MAX_VALUE;
+
+ /**
+ * The renderer for the column header.
+ */
+ protected TableCellRenderer headerRenderer;
+
+ /**
+ * The value for the column header.
+ */
+ protected Object headerValue;
+
+ /**
+ * The renderer for the regular cells in this column.
+ */
+ protected TableCellRenderer cellRenderer;
+
+ /**
+ * An editor for the regular cells in this column.
+ */
+ protected TableCellEditor cellEditor;
+
+ /**
+ * A flag that determines whether or not the column is resizable (the default
+ * is <code>true</code>).
+ */
+ protected boolean isResizable = true;
+
+ /**
+ * resizedPostingDisableCount
+ *
+ * @deprecated 1.3
+ */
+ protected transient int resizedPostingDisableCount;
+
+ /**
+ * A storage and notification mechanism for property change listeners.
+ */
+ private SwingPropertyChangeSupport changeSupport =
+ new SwingPropertyChangeSupport(this);
+
+ /**
+ * Creates a new <code>TableColumn</code> that maps to column 0 in the
+ * related table model. The default width is <code>75</code> units.
+ */
+ public TableColumn()
+ {
+ this(0, 75, null, null);
+ }
+
+ /**
+ * Creates a new <code>TableColumn</code> that maps to the specified column
+ * in the related table model. The default width is <code>75</code> units.
+ *
+ * @param modelIndex the index of the column in the model
+ */
+ public TableColumn(int modelIndex)
+ {
+ this(modelIndex, 75, null, null);
+ }
+
+ /**
+ * Creates a new <code>TableColumn</code> that maps to the specified column
+ * in the related table model, and has the specified <code>width</code>.
+ *
+ * @param modelIndex the index of the column in the model
+ * @param width the width
+ */
+ public TableColumn(int modelIndex, int width)
+ {
+ this(modelIndex, width, null, null);
+ }
+
+ /**
+ * Creates a new <code>TableColumn</code> that maps to the specified column
+ * in the related table model, and has the specified <code>width</code>,
+ * <code>cellRenderer</code> and <code>cellEditor</code>.
+ *
+ * @param modelIndex the index of the column in the model
+ * @param width the width
+ * @param cellRenderer the cell renderer (<code>null</code> permitted).
+ * @param cellEditor the cell editor (<code>null</code> permitted).
+ */
+ public TableColumn(int modelIndex, int width,
+ TableCellRenderer cellRenderer, TableCellEditor cellEditor)
+ {
+ this.modelIndex = modelIndex;
+ this.width = width;
+ this.preferredWidth = width;
+ this.cellRenderer = cellRenderer;
+ this.cellEditor = cellEditor;
+ this.headerValue = null;
+ this.identifier = null;
+ }
+
+ /**
+ * Sets the index of the column in the related {@link TableModel} that this
+ * <code>TableColumn</code> maps to, and sends a {@link PropertyChangeEvent}
+ * (with the property name 'modelIndex') to all registered listeners.
+ *
+ * @param modelIndex the column index in the model.
+ *
+ * @see #getModelIndex()
+ */
+ public void setModelIndex(int modelIndex)
+ {
+ if (this.modelIndex != modelIndex)
+ {
+ int oldValue = this.modelIndex;
+ this.modelIndex = modelIndex;
+ changeSupport.firePropertyChange("modelIndex", oldValue, modelIndex);
+ }
+ }
+
+ /**
+ * Returns the index of the column in the related {@link TableModel} that
+ * this <code>TableColumn</code> maps to.
+ *
+ * @return the model index.
+ *
+ * @see #setModelIndex(int)
+ */
+ public int getModelIndex()
+ {
+ return modelIndex;
+ }
+
+ /**
+ * Sets the identifier for the column and sends a {@link PropertyChangeEvent}
+ * (with the property name 'identifier') to all registered listeners.
+ *
+ * @param identifier the identifier (<code>null</code> permitted).
+ *
+ * @see #getIdentifier()
+ */
+ public void setIdentifier(Object identifier)
+ {
+ if (this.identifier != identifier)
+ {
+ Object oldValue = this.identifier;
+ this.identifier = identifier;
+ changeSupport.firePropertyChange("identifier", oldValue, identifier);
+ }
+ }
+
+ /**
+ * Returns the identifier for the column, or {@link #getHeaderValue()} if the
+ * identifier is <code>null</code>.
+ *
+ * @return The identifier (or {@link #getHeaderValue()} if the identifier is
+ * <code>null</code>).
+ */
+ public Object getIdentifier()
+ {
+ if (identifier == null)
+ return getHeaderValue();
+ return identifier;
+ }
+
+ /**
+ * Sets the header value and sends a {@link PropertyChangeEvent} (with the
+ * property name {@link #HEADER_VALUE_PROPERTY}) to all registered listeners.
+ *
+ * @param headerValue the value of the header (<code>null</code> permitted).
+ *
+ * @see #getHeaderValue()
+ */
+ public void setHeaderValue(Object headerValue)
+ {
+ if (this.headerValue == headerValue)
+ return;
+
+ Object oldValue = this.headerValue;
+ this.headerValue = headerValue;
+ changeSupport.firePropertyChange(HEADER_VALUE_PROPERTY, oldValue,
+ headerValue);
+ }
+
+ /**
+ * Returns the header value.
+ *
+ * @return the value of the header.
+ *
+ * @see #getHeaderValue()
+ */
+ public Object getHeaderValue()
+ {
+ return headerValue;
+ }
+
+ /**
+ * Sets the renderer for the column header and sends a
+ * {@link PropertyChangeEvent} (with the property name
+ * {@link #HEADER_RENDERER_PROPERTY}) to all registered listeners.
+ *
+ * @param renderer the header renderer (<code>null</code> permitted).
+ *
+ * @see #getHeaderRenderer()
+ */
+ public void setHeaderRenderer(TableCellRenderer renderer)
+ {
+ if (headerRenderer == renderer)
+ return;
+
+ TableCellRenderer oldRenderer = headerRenderer;
+ headerRenderer = renderer;
+ changeSupport.firePropertyChange(HEADER_RENDERER_PROPERTY, oldRenderer,
+ headerRenderer);
+ }
+
+ /**
+ * Returns the renderer for the column header.
+ *
+ * @return The renderer for the column header (possibly <code>null</code>).
+ *
+ * @see #setHeaderRenderer(TableCellRenderer)
+ */
+ public TableCellRenderer getHeaderRenderer()
+ {
+ return headerRenderer;
+ }
+
+ /**
+ * Sets the renderer for cells in this column and sends a
+ * {@link PropertyChangeEvent} (with the property name
+ * {@link #CELL_RENDERER_PROPERTY}) to all registered listeners.
+ *
+ * @param renderer the cell renderer (<code>null</code> permitted).
+ *
+ * @see #getCellRenderer()
+ */
+ public void setCellRenderer(TableCellRenderer renderer)
+ {
+ if (cellRenderer == renderer)
+ return;
+
+ TableCellRenderer oldRenderer = cellRenderer;
+ cellRenderer = renderer;
+ changeSupport.firePropertyChange(CELL_RENDERER_PROPERTY, oldRenderer,
+ cellRenderer);
+ }
+
+ /**
+ * Returns the renderer for the table cells in this column.
+ *
+ * @return The cell renderer (possibly <code>null</code>).
+ *
+ * @see #setCellRenderer(TableCellRenderer)
+ */
+ public TableCellRenderer getCellRenderer()
+ {
+ return cellRenderer;
+ }
+
+ /**
+ * Sets the cell editor for the column and sends a {@link PropertyChangeEvent}
+ * (with the property name 'cellEditor') to all registered listeners.
+ *
+ * @param cellEditor the cell editor (<code>null</code> permitted).
+ *
+ * @see #getCellEditor()
+ */
+ public void setCellEditor(TableCellEditor cellEditor)
+ {
+ if (this.cellEditor != cellEditor)
+ {
+ TableCellEditor oldValue = this.cellEditor;
+ this.cellEditor = cellEditor;
+ changeSupport.firePropertyChange("cellEditor", oldValue, cellEditor);
+ }
+ }
+
+ /**
+ * Returns the cell editor for the column (the default value is
+ * <code>null</code>).
+ *
+ * @return The cell editor (possibly <code>null</code>).
+ *
+ * @see #setCellEditor(TableCellEditor)
+ */
+ public TableCellEditor getCellEditor()
+ {
+ return cellEditor;
+ }
+
+ /**
+ * Sets the width for the column and sends a {@link PropertyChangeEvent}
+ * (with the property name 'width') to all registered listeners. If the new
+ * width falls outside the range getMinWidth() to getMaxWidth() it is
+ * adjusted to the appropriate boundary value.
+ *
+ * @param newWidth the width.
+ *
+ * @see #getWidth()
+ */
+ public void setWidth(int newWidth)
+ {
+ int oldWidth = width;
+
+ if (newWidth < minWidth)
+ width = minWidth;
+ else if (newWidth > maxWidth)
+ width = maxWidth;
+ else
+ width = newWidth;
+
+ if (width == oldWidth)
+ return;
+
+ // We do have a constant field COLUMN_WIDTH_PROPERTY,
+ // however, tests show that the actual fired property name is 'width'
+ // and even Sun's API docs say that this constant field is obsolete and
+ // not used.
+ changeSupport.firePropertyChange("width", oldWidth, width);
+ }
+
+ /**
+ * Returns the width for the column (the default value is <code>75</code>).
+ *
+ * @return The width.
+ *
+ * @see #setWidth(int)
+ */
+ public int getWidth()
+ {
+ return width;
+ }
+
+ /**
+ * Sets the preferred width for the column and sends a
+ * {@link PropertyChangeEvent} (with the property name 'preferredWidth') to
+ * all registered listeners. If necessary, the supplied value will be
+ * adjusted to fit in the range {@link #getMinWidth()} to
+ * {@link #getMaxWidth()}.
+ *
+ * @param preferredWidth the preferred width.
+ *
+ * @see #getPreferredWidth()
+ */
+ public void setPreferredWidth(int preferredWidth)
+ {
+ int oldPrefWidth = this.preferredWidth;
+
+ if (preferredWidth < minWidth)
+ this.preferredWidth = minWidth;
+ else if (preferredWidth > maxWidth)
+ this.preferredWidth = maxWidth;
+ else
+ this.preferredWidth = preferredWidth;
+
+ changeSupport.firePropertyChange("preferredWidth", oldPrefWidth,
+ this.preferredWidth);
+ }
+
+ /**
+ * Returns the preferred width for the column (the default value is
+ * <code>75</code>).
+ *
+ * @return The preferred width.
+ *
+ * @see #setPreferredWidth(int)
+ */
+ public int getPreferredWidth()
+ {
+ return preferredWidth;
+ }
+
+ /**
+ * Sets the minimum width for the column and sends a
+ * {@link PropertyChangeEvent} (with the property name 'minWidth') to all
+ * registered listeners. If the current <code>width</code> and/or
+ * <code>preferredWidth</code> are less than the new minimum width, they are
+ * adjusted accordingly.
+ *
+ * @param minWidth the minimum width (negative values are treated as 0).
+ *
+ * @see #getMinWidth()
+ */
+ public void setMinWidth(int minWidth)
+ {
+ if (minWidth < 0)
+ minWidth = 0;
+ if (this.minWidth != minWidth)
+ {
+ if (width < minWidth)
+ setWidth(minWidth);
+ if (preferredWidth < minWidth)
+ setPreferredWidth(minWidth);
+ int oldValue = this.minWidth;
+ this.minWidth = minWidth;
+ changeSupport.firePropertyChange("minWidth", oldValue, minWidth);
+ }
+ }
+
+ /**
+ * Returns the <code>TableColumn</code>'s minimum width (the default value
+ * is <code>15</code>).
+ *
+ * @return The minimum width.
+ *
+ * @see #setMinWidth(int)
+ */
+ public int getMinWidth()
+ {
+ return minWidth;
+ }
+
+ /**
+ * Sets the maximum width for the column and sends a
+ * {@link PropertyChangeEvent} (with the property name 'maxWidth') to all
+ * registered listeners. If the current <code>width</code> and/or
+ * <code>preferredWidth</code> are greater than the new maximum width, they
+ * are adjusted accordingly.
+ *
+ * @param maxWidth the maximum width.
+ *
+ * @see #getMaxWidth()
+ */
+ public void setMaxWidth(int maxWidth)
+ {
+ if (this.maxWidth != maxWidth)
+ {
+ if (width > maxWidth)
+ setWidth(maxWidth);
+ if (preferredWidth > maxWidth)
+ setPreferredWidth(maxWidth);
+ int oldValue = this.maxWidth;
+ this.maxWidth = maxWidth;
+ changeSupport.firePropertyChange("maxWidth", oldValue, maxWidth);
+ }
+ }
+
+ /**
+ * Returns the maximum width for the column (the default value is
+ * {@link Integer#MAX_VALUE}).
+ *
+ * @return The maximum width for the column.
+ *
+ * @see #setMaxWidth(int)
+ */
+ public int getMaxWidth()
+ {
+ return maxWidth;
+ }
+
+ /**
+ * Sets the flag that controls whether or not the column is resizable, and
+ * sends a {@link PropertyChangeEvent} (with the property name 'isResizable')
+ * to all registered listeners.
+ *
+ * @param isResizable <code>true</code> if this column is resizable,
+ * <code>false</code> otherwise.
+ *
+ * @see #getResizable()
+ */
+ public void setResizable(boolean isResizable)
+ {
+ if (this.isResizable != isResizable)
+ {
+ this.isResizable = isResizable;
+ changeSupport.firePropertyChange("isResizable", !this.isResizable,
+ isResizable);
+ }
+ }
+
+ /**
+ * Returns the flag that controls whether or not the column is resizable.
+ *
+ * @return <code>true</code> if this column is resizable,
+ * <code>false</code> otherwise.
+ *
+ * @see #setResizable(boolean)
+ */
+ public boolean getResizable()
+ {
+ return isResizable;
+ }
+
+ /**
+ * Sets the minimum, maximum, preferred and current width to match the
+ * minimum, maximum and preferred width of the header renderer component.
+ * If there is no header renderer component, this method does nothing.
+ */
+ public void sizeWidthToFit()
+ {
+ if (headerRenderer == null)
+ return;
+ Component c = headerRenderer.getTableCellRendererComponent(null,
+ getHeaderValue(), false, false, 0, 0);
+ Dimension min = c.getMinimumSize();
+ Dimension max = c.getMaximumSize();
+ Dimension pref = c.getPreferredSize();
+ setMinWidth(min.width);
+ setMaxWidth(max.width);
+ setPreferredWidth(pref.width);
+ setWidth(pref.width);
+ }
+
+ /**
+ * This method is empty, unused and deprecated.
+ * @deprecated 1.3
+ */
+ public void disableResizedPosting()
+ {
+ // Does nothing
+ }
+
+ /**
+ * This method is empty, unused and deprecated.
+ * @deprecated 1.3
+ */
+ public void enableResizedPosting()
+ {
+ // Does nothing
+ }
+
+ /**
+ * Adds a listener so that it receives {@link PropertyChangeEvent}
+ * notifications from this column. The properties defined by the column are:
+ * <ul>
+ * <li><code>width</code> - see {@link #setWidth(int)};</li>
+ * <li><code>preferredWidth</code> - see {@link #setPreferredWidth(int)};</li>
+ * <li><code>minWidth</code> - see {@link #setMinWidth(int)};</li>
+ * <li><code>maxWidth</code> - see {@link #setMaxWidth(int)};</li>
+ * <li><code>modelIndex</code> - see {@link #setModelIndex(int)};</li>
+ * <li><code>isResizable</code> - see {@link #setResizable(boolean)};</li>
+ * <li><code>cellRenderer</code> - see
+ * {@link #setCellRenderer(TableCellRenderer)};</li>
+ * <li><code>cellEditor</code> - see
+ * {@link #setCellEditor(TableCellEditor)};</li>
+ * <li><code>headerRenderer</code> - see
+ * {@link #setHeaderRenderer(TableCellRenderer)};</li>
+ * <li><code>headerValue</code> - see {@link #setHeaderValue(Object)};</li>
+ * <li><code>identifier</code> - see {@link #setIdentifier(Object)}.</li>
+ * </ul>
+ *
+ * @param listener the listener to add (<code>null</code> is ignored).
+ *
+ * @see #removePropertyChangeListener(PropertyChangeListener)
+ */
+ public synchronized void addPropertyChangeListener(
+ PropertyChangeListener listener)
+ {
+ changeSupport.addPropertyChangeListener(listener);
+ }
+
+ /**
+ * Removes a listener so that it no longer receives
+ * {@link PropertyChangeEvent} notifications from this column. If
+ * <code>listener</code> is not registered with the column, or is
+ * <code>null</code>, this method does nothing.
+ *
+ * @param listener the listener to remove (<code>null</code> is ignored).
+ */
+ public synchronized void removePropertyChangeListener(
+ PropertyChangeListener listener)
+ {
+ changeSupport.removePropertyChangeListener(listener);
+ }
+
+ /**
+ * Returns the property change listeners for this <code>TableColumn</code>.
+ * An empty array is returned if there are currently no listeners registered.
+ *
+ * @return The property change listeners registered with this column.
+ *
+ * @since 1.4
+ */
+ public PropertyChangeListener[] getPropertyChangeListeners()
+ {
+ return changeSupport.getPropertyChangeListeners();
+ }
+
+ /**
+ * Creates and returns a default renderer for the column header (in this case,
+ * a new instance of {@link DefaultTableCellRenderer}).
+ *
+ * @return A default renderer for the column header.
+ */
+ protected TableCellRenderer createDefaultHeaderRenderer()
+ {
+ return new DefaultTableCellRenderer();
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableColumnModel.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableColumnModel.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableColumnModel.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableColumnModel.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,232 @@
+/* TableColumnModel.java --
+ Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.table;
+
+import java.util.Enumeration;
+
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.TableColumnModelEvent;
+import javax.swing.event.TableColumnModelListener;
+
+/**
+ * The interface used by {@link JTable} to access the columns in the table
+ * view.
+ *
+ * @author Andrew Selkirk
+ */
+public interface TableColumnModel
+{
+ /**
+ * Adds a column to the model.
+ *
+ * @param column the new column (<code>null</code> not permitted).
+ *
+ * @throws IllegalArgumentException if <code>column</code> is
+ * <code>null</code>.
+ */
+ void addColumn(TableColumn column);
+
+ /**
+ * Removes a column from the model. If <code>column</code> is not defined
+ * in the model, this method does nothing.
+ *
+ * @param column TableColumn
+ */
+ void removeColumn(TableColumn column);
+
+ /**
+ * Moves a column.
+ *
+ * @param columnIndex Index of column to move
+ * @param newIndex New index of column
+ */
+ void moveColumn(int columnIndex, int newIndex);
+
+ /**
+ * Sets the column margin and sends a {@link ChangeEvent} to all registered
+ * {@link TableColumnModelListener}s registered with the model.
+ *
+ * @param margin the column margin.
+ *
+ * @see #getColumnMargin()
+ */
+ void setColumnMargin(int margin);
+
+ /**
+ * Returns the number of columns in the model.
+ *
+ * @return The column count.
+ */
+ int getColumnCount();
+
+ /**
+ * Returns an enumeration of the columns in the model.
+ *
+ * @return An enumeration of the columns in the model.
+ */
+ Enumeration getColumns();
+
+ /**
+ * Returns the index of the {@link TableColumn} with the given identifier.
+ *
+ * @param identifier the identifier (<code>null</code> not permitted).
+ *
+ * @return The index of the {@link TableColumn} with the given identifier.
+ *
+ * @throws IllegalArgumentException if <code>identifier</code> is
+ * <code>null</code> or there is no column with that identifier.
+ */
+ int getColumnIndex(Object identifier);
+
+ /**
+ * Returns the <code>TableColumn</code> at the specified index.
+ *
+ * @param columnIndex the column index.
+ *
+ * @return The table column.
+ */
+ TableColumn getColumn(int columnIndex);
+
+ /**
+ * Returns the column margin.
+ *
+ * @return The column margin.
+ *
+ * @see #setColumnMargin(int)
+ */
+ int getColumnMargin();
+
+ /**
+ * Returns the index of the column that contains the specified x-coordinate,
+ * assuming that:
+ * <ul>
+ * <li>column zero begins at position zero;</li>
+ * <li>all columns appear in order;</li>
+ * <li>individual column widths are taken into account, but the column margin
+ * is ignored.</li>
+ * </ul>
+ * If no column contains the specified position, this method returns
+ * <code>-1</code>.
+ *
+ * @param xPosition the x-position.
+ *
+ * @return The column index, or <code>-1</code>.
+ */
+ int getColumnIndexAtX(int xPosition);
+
+ /**
+ * Returns total width of all the columns in the model, ignoring the
+ * column margin (see {@link #getColumnMargin()}).
+ *
+ * @return The total width of all the columns.
+ */
+ int getTotalColumnWidth();
+
+ /**
+ * Sets the flag that indicates whether or not column selection is allowed.
+ *
+ * @param allowed the new flag value.
+ *
+ * @see #getColumnSelectionAllowed()
+ */
+ void setColumnSelectionAllowed(boolean allowed);
+
+ /**
+ * Returns <code>true</code> if column selection is allowed, and
+ * <code>false</code> if column selection is not allowed.
+ *
+ * @return A boolean.
+ *
+ * @see #setColumnSelectionAllowed(boolean)
+ */
+ boolean getColumnSelectionAllowed();
+
+ /**
+ * getSelectedColumns
+ * @return Selected columns
+ */
+ int[] getSelectedColumns();
+
+ /**
+ * Returns the number of selected columns in the model.
+ *
+ * @return The selected column count.
+ *
+ * @see #getSelectionModel()
+ */
+ int getSelectedColumnCount();
+
+ /**
+ * Sets the selection model that will be used to keep track of the selected
+ * columns.
+ *
+ * @param model the selection model (<code>null</code> not permitted).
+ *
+ * @throws IllegalArgumentException if <code>model</code> is
+ * <code>null</code>.
+ */
+ void setSelectionModel(ListSelectionModel model);
+
+ /**
+ * Returns the selection model used to track table column selections.
+ *
+ * @return The selection model.
+ *
+ * @see #setSelectionModel(ListSelectionModel)
+ */
+ ListSelectionModel getSelectionModel();
+
+ /**
+ * Registers a listener with the model, so that it will receive
+ * {@link TableColumnModelEvent} notifications.
+ *
+ * @param listener the listener (<code>null</code> ignored).
+ */
+ void addColumnModelListener(TableColumnModelListener listener);
+
+ /**
+ * Deregisters a listener, so that it will no longer receive
+ * {@link TableColumnModelEvent} notifications.
+ *
+ * @param listener the listener.
+ */
+ void removeColumnModelListener(TableColumnModelListener listener);
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableModel.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableModel.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableModel.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/TableModel.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,134 @@
+/* TableModel.java --
+ Copyright (C) 2002, 2005, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.table;
+
+import javax.swing.event.TableModelListener;
+
+/**
+ * A <code>TableModel</code> is a two dimensional data structure that
+ * can store arbitrary <code>Object</code> instances, usually for the
+ * purpose of display in a {@link javax.swing.JTable} component. Individual
+ * objects can be accessed by specifying the row index and column index for
+ * the object. Each column in the model has a name associated with it.
+ * <p>
+ * The {@link DefaultTableModel} class provides one implementation of
+ * this interface.
+ *
+ * @author Andrew Selkirk
+ */
+public interface TableModel
+{
+ /**
+ * Returns the number of rows in the model.
+ *
+ * @return The row count.
+ */
+ int getRowCount();
+
+ /**
+ * Returns the number of columns in the model.
+ *
+ * @return The column count
+ */
+ int getColumnCount();
+
+ /**
+ * Returns the name of a column in the model.
+ *
+ * @param columnIndex the column index.
+ *
+ * @return The column name.
+ */
+ String getColumnName(int columnIndex);
+
+ /**
+ * Returns the <code>Class</code> for all <code>Object</code> instances
+ * in the specified column.
+ *
+ * @param columnIndex the column index.
+ *
+ * @return The class.
+ */
+ Class getColumnClass(int columnIndex);
+
+ /**
+ * Returns <code>true</code> if the cell is editable, and <code>false</code>
+ * otherwise.
+ *
+ * @param rowIndex the row index.
+ * @param columnIndex the column index.
+ *
+ * @return <code>true</code> if editable, <code>false</code> otherwise.
+ */
+ boolean isCellEditable(int rowIndex, int columnIndex);
+
+ /**
+ * Returns the value (<code>Object</code>) at a particular cell in the
+ * table.
+ *
+ * @param rowIndex the row index.
+ * @param columnIndex the column index.
+ *
+ * @return The value at the specified cell.
+ */
+ Object getValueAt(int rowIndex, int columnIndex);
+
+ /**
+ * Sets the value at a particular cell in the table.
+ *
+ * @param aValue the value (<code>null</code> permitted).
+ * @param rowIndex the row index.
+ * @param columnIndex the column index.
+ */
+ void setValueAt(Object aValue, int rowIndex, int columnIndex);
+
+ /**
+ * Adds a listener to the model. The listener will receive notification
+ * of updates to the model.
+ *
+ * @param listener the listener.
+ */
+ void addTableModelListener(TableModelListener listener);
+
+ /**
+ * Removes a listener from the model.
+ *
+ * @param listener the listener.
+ */
+ void removeTableModelListener(TableModelListener listener);
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/package.html
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/package.html?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/package.html (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/table/package.html Thu Nov 8 16:56:19 2007
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in javax.swing.table package.
+ Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - javax.swing.table</title></head>
+
+<body>
+<p>Interfaces and classes that support the {@link javax.swing.JTable}
+component.</p>
+
+</body>
+</html>
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AbstractDocument.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AbstractDocument.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AbstractDocument.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AbstractDocument.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,2369 @@
+/* AbstractDocument.java --
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.io.PrintStream;
+import java.io.Serializable;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.EventListener;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.event.EventListenerList;
+import javax.swing.event.UndoableEditEvent;
+import javax.swing.event.UndoableEditListener;
+import javax.swing.text.DocumentFilter;
+import javax.swing.tree.TreeNode;
+import javax.swing.undo.AbstractUndoableEdit;
+import javax.swing.undo.CompoundEdit;
+import javax.swing.undo.UndoableEdit;
+
+/**
+ * An abstract base implementation for the {@link Document} interface.
+ * This class provides some common functionality for all <code>Element</code>s,
+ * most notably it implements a locking mechanism to make document modification
+ * thread-safe.
+ *
+ * @author original author unknown
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public abstract class AbstractDocument implements Document, Serializable
+{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 6842927725919637215L;
+
+ /**
+ * Standard error message to indicate a bad location.
+ */
+ protected static final String BAD_LOCATION = "document location failure";
+
+ /**
+ * Standard name for unidirectional <code>Element</code>s.
+ */
+ public static final String BidiElementName = "bidi level";
+
+ /**
+ * Standard name for content <code>Element</code>s. These are usually
+ * {@link LeafElement}s.
+ */
+ public static final String ContentElementName = "content";
+
+ /**
+ * Standard name for paragraph <code>Element</code>s. These are usually
+ * {@link BranchElement}s.
+ */
+ public static final String ParagraphElementName = "paragraph";
+
+ /**
+ * Standard name for section <code>Element</code>s. These are usually
+ * {@link DefaultStyledDocument.SectionElement}s.
+ */
+ public static final String SectionElementName = "section";
+
+ /**
+ * Attribute key for storing the element name.
+ */
+ public static final String ElementNameAttribute = "$ename";
+
+ /**
+ * The actual content model of this <code>Document</code>.
+ */
+ Content content;
+
+ /**
+ * The AttributeContext for this <code>Document</code>.
+ */
+ AttributeContext context;
+
+ /**
+ * The currently installed <code>DocumentFilter</code>.
+ */
+ DocumentFilter documentFilter;
+
+ /**
+ * The documents properties.
+ */
+ Dictionary properties;
+
+ /**
+ * Manages event listeners for this <code>Document</code>.
+ */
+ protected EventListenerList listenerList = new EventListenerList();
+
+ /**
+ * Stores the current writer thread. Used for locking.
+ */
+ private Thread currentWriter = null;
+
+ /**
+ * The number of readers. Used for locking.
+ */
+ private int numReaders = 0;
+
+ /**
+ * Tells if there are one or more writers waiting.
+ */
+ private int numWritersWaiting = 0;
+
+ /**
+ * A condition variable that readers and writers wait on.
+ */
+ private Object documentCV = new Object();
+
+ /** An instance of a DocumentFilter.FilterBypass which allows calling
+ * the insert, remove and replace method without checking for an installed
+ * document filter.
+ */
+ private DocumentFilter.FilterBypass bypass;
+
+ /**
+ * The bidi root element.
+ */
+ private Element bidiRoot;
+
+ /**
+ * Creates a new <code>AbstractDocument</code> with the specified
+ * {@link Content} model.
+ *
+ * @param doc the <code>Content</code> model to be used in this
+ * <code>Document<code>
+ *
+ * @see GapContent
+ * @see StringContent
+ */
+ protected AbstractDocument(Content doc)
+ {
+ this(doc, StyleContext.getDefaultStyleContext());
+ }
+
+ /**
+ * Creates a new <code>AbstractDocument</code> with the specified
+ * {@link Content} model and {@link AttributeContext}.
+ *
+ * @param doc the <code>Content</code> model to be used in this
+ * <code>Document<code>
+ * @param ctx the <code>AttributeContext</code> to use
+ *
+ * @see GapContent
+ * @see StringContent
+ */
+ protected AbstractDocument(Content doc, AttributeContext ctx)
+ {
+ content = doc;
+ context = ctx;
+
+ // FIXME: This is determined using a Mauve test. Make the document
+ // actually use this.
+ putProperty("i18n", Boolean.FALSE);
+
+ // FIXME: Fully implement bidi.
+ bidiRoot = new BranchElement(null, null);
+ }
+
+ /** Returns the DocumentFilter.FilterBypass instance for this
+ * document and create it if it does not exist yet.
+ *
+ * @return This document's DocumentFilter.FilterBypass instance.
+ */
+ private DocumentFilter.FilterBypass getBypass()
+ {
+ if (bypass == null)
+ bypass = new Bypass();
+
+ return bypass;
+ }
+
+ /**
+ * Returns the paragraph {@link Element} that holds the specified position.
+ *
+ * @param pos the position for which to get the paragraph element
+ *
+ * @return the paragraph {@link Element} that holds the specified position
+ */
+ public abstract Element getParagraphElement(int pos);
+
+ /**
+ * Returns the default root {@link Element} of this <code>Document</code>.
+ * Usual <code>Document</code>s only have one root element and return this.
+ * However, there may be <code>Document</code> implementations that
+ * support multiple root elements, they have to return a default root element
+ * here.
+ *
+ * @return the default root {@link Element} of this <code>Document</code>
+ */
+ public abstract Element getDefaultRootElement();
+
+ /**
+ * Creates and returns a branch element with the specified
+ * <code>parent</code> and <code>attributes</code>. Note that the new
+ * <code>Element</code> is linked to the parent <code>Element</code>
+ * through {@link Element#getParentElement}, but it is not yet added
+ * to the parent <code>Element</code> as child.
+ *
+ * @param parent the parent <code>Element</code> for the new branch element
+ * @param attributes the text attributes to be installed in the new element
+ *
+ * @return the new branch <code>Element</code>
+ *
+ * @see BranchElement
+ */
+ protected Element createBranchElement(Element parent,
+ AttributeSet attributes)
+ {
+ return new BranchElement(parent, attributes);
+ }
+
+ /**
+ * Creates and returns a leaf element with the specified
+ * <code>parent</code> and <code>attributes</code>. Note that the new
+ * <code>Element</code> is linked to the parent <code>Element</code>
+ * through {@link Element#getParentElement}, but it is not yet added
+ * to the parent <code>Element</code> as child.
+ *
+ * @param parent the parent <code>Element</code> for the new branch element
+ * @param attributes the text attributes to be installed in the new element
+ *
+ * @return the new branch <code>Element</code>
+ *
+ * @see LeafElement
+ */
+ protected Element createLeafElement(Element parent, AttributeSet attributes,
+ int start, int end)
+ {
+ return new LeafElement(parent, attributes, start, end);
+ }
+
+ /**
+ * Creates a {@link Position} that keeps track of the location at the
+ * specified <code>offset</code>.
+ *
+ * @param offset the location in the document to keep track by the new
+ * <code>Position</code>
+ *
+ * @return the newly created <code>Position</code>
+ *
+ * @throws BadLocationException if <code>offset</code> is not a valid
+ * location in the documents content model
+ */
+ public Position createPosition(final int offset) throws BadLocationException
+ {
+ return content.createPosition(offset);
+ }
+
+ /**
+ * Notifies all registered listeners when the document model changes.
+ *
+ * @param event the <code>DocumentEvent</code> to be fired
+ */
+ protected void fireChangedUpdate(DocumentEvent event)
+ {
+ DocumentListener[] listeners = getDocumentListeners();
+
+ for (int index = 0; index < listeners.length; ++index)
+ listeners[index].changedUpdate(event);
+ }
+
+ /**
+ * Notifies all registered listeners when content is inserted in the document
+ * model.
+ *
+ * @param event the <code>DocumentEvent</code> to be fired
+ */
+ protected void fireInsertUpdate(DocumentEvent event)
+ {
+ DocumentListener[] listeners = getDocumentListeners();
+
+ for (int index = 0; index < listeners.length; ++index)
+ listeners[index].insertUpdate(event);
+ }
+
+ /**
+ * Notifies all registered listeners when content is removed from the
+ * document model.
+ *
+ * @param event the <code>DocumentEvent</code> to be fired
+ */
+ protected void fireRemoveUpdate(DocumentEvent event)
+ {
+ DocumentListener[] listeners = getDocumentListeners();
+
+ for (int index = 0; index < listeners.length; ++index)
+ listeners[index].removeUpdate(event);
+ }
+
+ /**
+ * Notifies all registered listeners when an <code>UndoableEdit</code> has
+ * been performed on this <code>Document</code>.
+ *
+ * @param event the <code>UndoableEditEvent</code> to be fired
+ */
+ protected void fireUndoableEditUpdate(UndoableEditEvent event)
+ {
+ UndoableEditListener[] listeners = getUndoableEditListeners();
+
+ for (int index = 0; index < listeners.length; ++index)
+ listeners[index].undoableEditHappened(event);
+ }
+
+ /**
+ * Returns the asynchronous loading priority. Returns <code>-1</code> if this
+ * document should not be loaded asynchronously.
+ *
+ * @return the asynchronous loading priority
+ */
+ public int getAsynchronousLoadPriority()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns the {@link AttributeContext} used in this <code>Document</code>.
+ *
+ * @return the {@link AttributeContext} used in this <code>Document</code>
+ */
+ protected final AttributeContext getAttributeContext()
+ {
+ return context;
+ }
+
+ /**
+ * Returns the root element for bidirectional content.
+ *
+ * @return the root element for bidirectional content
+ */
+ public Element getBidiRootElement()
+ {
+ return bidiRoot;
+ }
+
+ /**
+ * Returns the {@link Content} model for this <code>Document</code>
+ *
+ * @return the {@link Content} model for this <code>Document</code>
+ *
+ * @see GapContent
+ * @see StringContent
+ */
+ protected final Content getContent()
+ {
+ return content;
+ }
+
+ /**
+ * Returns the thread that currently modifies this <code>Document</code>
+ * if there is one, otherwise <code>null</code>. This can be used to
+ * distinguish between a method call that is part of an ongoing modification
+ * or if it is a separate modification for which a new lock must be aquired.
+ *
+ * @return the thread that currently modifies this <code>Document</code>
+ * if there is one, otherwise <code>null</code>
+ */
+ protected final Thread getCurrentWriter()
+ {
+ return currentWriter;
+ }
+
+ /**
+ * Returns the properties of this <code>Document</code>.
+ *
+ * @return the properties of this <code>Document</code>
+ */
+ public Dictionary getDocumentProperties()
+ {
+ // FIXME: make me thread-safe
+ if (properties == null)
+ properties = new Hashtable();
+
+ return properties;
+ }
+
+ /**
+ * Returns a {@link Position} which will always mark the end of the
+ * <code>Document</code>.
+ *
+ * @return a {@link Position} which will always mark the end of the
+ * <code>Document</code>
+ */
+ public final Position getEndPosition()
+ {
+ // FIXME: Properly implement this by calling Content.createPosition().
+ return new Position()
+ {
+ public int getOffset()
+ {
+ return getLength();
+ }
+ };
+ }
+
+ /**
+ * Returns the length of this <code>Document</code>'s content.
+ *
+ * @return the length of this <code>Document</code>'s content
+ */
+ public int getLength()
+ {
+ // We return Content.getLength() -1 here because there is always an
+ // implicit \n at the end of the Content which does count in Content
+ // but not in Document.
+ return content.length() - 1;
+ }
+
+ /**
+ * Returns all registered listeners of a given listener type.
+ *
+ * @param listenerType the type of the listeners to be queried
+ *
+ * @return all registered listeners of the specified type
+ */
+ public EventListener[] getListeners(Class listenerType)
+ {
+ return listenerList.getListeners(listenerType);
+ }
+
+ /**
+ * Returns a property from this <code>Document</code>'s property list.
+ *
+ * @param key the key of the property to be fetched
+ *
+ * @return the property for <code>key</code> or <code>null</code> if there
+ * is no such property stored
+ */
+ public final Object getProperty(Object key)
+ {
+ // FIXME: make me thread-safe
+ Object value = null;
+ if (properties != null)
+ value = properties.get(key);
+
+ return value;
+ }
+
+ /**
+ * Returns all root elements of this <code>Document</code>. By default
+ * this just returns the single root element returned by
+ * {@link #getDefaultRootElement()}. <code>Document</code> implementations
+ * that support multiple roots must override this method and return all roots
+ * here.
+ *
+ * @return all root elements of this <code>Document</code>
+ */
+ public Element[] getRootElements()
+ {
+ Element[] elements = new Element[2];
+ elements[0] = getDefaultRootElement();
+ elements[1] = getBidiRootElement();
+ return elements;
+ }
+
+ /**
+ * Returns a {@link Position} which will always mark the beginning of the
+ * <code>Document</code>.
+ *
+ * @return a {@link Position} which will always mark the beginning of the
+ * <code>Document</code>
+ */
+ public final Position getStartPosition()
+ {
+ // FIXME: Properly implement this using Content.createPosition().
+ return new Position()
+ {
+ public int getOffset()
+ {
+ return 0;
+ }
+ };
+ }
+
+ /**
+ * Returns a piece of this <code>Document</code>'s content.
+ *
+ * @param offset the start offset of the content
+ * @param length the length of the content
+ *
+ * @return the piece of content specified by <code>offset</code> and
+ * <code>length</code>
+ *
+ * @throws BadLocationException if <code>offset</code> or <code>offset +
+ * length</code> are invalid locations with this
+ * <code>Document</code>
+ */
+ public String getText(int offset, int length) throws BadLocationException
+ {
+ return content.getString(offset, length);
+ }
+
+ /**
+ * Fetches a piece of this <code>Document</code>'s content and stores
+ * it in the given {@link Segment}.
+ *
+ * @param offset the start offset of the content
+ * @param length the length of the content
+ * @param segment the <code>Segment</code> to store the content in
+ *
+ * @throws BadLocationException if <code>offset</code> or <code>offset +
+ * length</code> are invalid locations with this
+ * <code>Document</code>
+ */
+ public void getText(int offset, int length, Segment segment)
+ throws BadLocationException
+ {
+ content.getChars(offset, length, segment);
+ }
+
+ /**
+ * Inserts a String into this <code>Document</code> at the specified
+ * position and assigning the specified attributes to it.
+ *
+ * <p>If a {@link DocumentFilter} is installed in this document, the
+ * corresponding method of the filter object is called.</p>
+ *
+ * <p>The method has no effect when <code>text</code> is <code>null</code>
+ * or has a length of zero.</p>
+ *
+ *
+ * @param offset the location at which the string should be inserted
+ * @param text the content to be inserted
+ * @param attributes the text attributes to be assigned to that string
+ *
+ * @throws BadLocationException if <code>offset</code> is not a valid
+ * location in this <code>Document</code>
+ */
+ public void insertString(int offset, String text, AttributeSet attributes)
+ throws BadLocationException
+ {
+ // Bail out if we have a bogus insertion (Behavior observed in RI).
+ if (text == null || text.length() == 0)
+ return;
+
+ if (documentFilter == null)
+ insertStringImpl(offset, text, attributes);
+ else
+ documentFilter.insertString(getBypass(), offset, text, attributes);
+ }
+
+ void insertStringImpl(int offset, String text, AttributeSet attributes)
+ throws BadLocationException
+ {
+ // Just return when no text to insert was given.
+ if (text == null || text.length() == 0)
+ return;
+ DefaultDocumentEvent event =
+ new DefaultDocumentEvent(offset, text.length(),
+ DocumentEvent.EventType.INSERT);
+
+ try
+ {
+ writeLock();
+ UndoableEdit undo = content.insertString(offset, text);
+ if (undo != null)
+ event.addEdit(undo);
+
+ insertUpdate(event, attributes);
+
+ fireInsertUpdate(event);
+ if (undo != null)
+ fireUndoableEditUpdate(new UndoableEditEvent(this, undo));
+ }
+ finally
+ {
+ writeUnlock();
+ }
+ }
+
+ /**
+ * Called to indicate that text has been inserted into this
+ * <code>Document</code>. The default implementation does nothing.
+ * This method is executed within a write lock.
+ *
+ * @param chng the <code>DefaultDocumentEvent</code> describing the change
+ * @param attr the attributes of the changed content
+ */
+ protected void insertUpdate(DefaultDocumentEvent chng, AttributeSet attr)
+ {
+ // Do nothing here. Subclasses may want to override this.
+ }
+
+ /**
+ * Called after some content has been removed from this
+ * <code>Document</code>. The default implementation does nothing.
+ * This method is executed within a write lock.
+ *
+ * @param chng the <code>DefaultDocumentEvent</code> describing the change
+ */
+ protected void postRemoveUpdate(DefaultDocumentEvent chng)
+ {
+ // Do nothing here. Subclasses may want to override this.
+ }
+
+ /**
+ * Stores a property in this <code>Document</code>'s property list.
+ *
+ * @param key the key of the property to be stored
+ * @param value the value of the property to be stored
+ */
+ public final void putProperty(Object key, Object value)
+ {
+ // FIXME: make me thread-safe
+ if (properties == null)
+ properties = new Hashtable();
+
+ properties.put(key, value);
+ }
+
+ /**
+ * Blocks until a read lock can be obtained. Must block if there is
+ * currently a writer modifying the <code>Document</code>.
+ */
+ public final void readLock()
+ {
+ if (currentWriter != null && currentWriter.equals(Thread.currentThread()))
+ return;
+ synchronized (documentCV)
+ {
+ while (currentWriter != null || numWritersWaiting > 0)
+ {
+ try
+ {
+ documentCV.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ throw new Error("interrupted trying to get a readLock");
+ }
+ }
+ numReaders++;
+ }
+ }
+
+ /**
+ * Releases the read lock. If this was the only reader on this
+ * <code>Document</code>, writing may begin now.
+ */
+ public final void readUnlock()
+ {
+ // Note we could have a problem here if readUnlock was called without a
+ // prior call to readLock but the specs simply warn users to ensure that
+ // balance by using a finally block:
+ // readLock()
+ // try
+ // {
+ // doSomethingHere
+ // }
+ // finally
+ // {
+ // readUnlock();
+ // }
+
+ // All that the JDK seems to check for is that you don't call unlock
+ // more times than you've previously called lock, but it doesn't make
+ // sure that the threads calling unlock were the same ones that called lock
+
+ // If the current thread holds the write lock, and attempted to also obtain
+ // a readLock, then numReaders hasn't been incremented and we don't need
+ // to unlock it here.
+ if (currentWriter == Thread.currentThread())
+ return;
+
+ // FIXME: the reference implementation throws a
+ // javax.swing.text.StateInvariantError here
+ if (numReaders == 0)
+ throw new IllegalStateException("document lock failure");
+
+ synchronized (documentCV)
+ {
+ // If currentWriter is not null, the application code probably had a
+ // writeLock and then tried to obtain a readLock, in which case
+ // numReaders wasn't incremented
+ if (currentWriter == null)
+ {
+ numReaders --;
+ if (numReaders == 0 && numWritersWaiting != 0)
+ documentCV.notify();
+ }
+ }
+ }
+
+ /**
+ * Removes a piece of content from this <code>Document</code>.
+ *
+ * <p>If a {@link DocumentFilter} is installed in this document, the
+ * corresponding method of the filter object is called. The
+ * <code>DocumentFilter</code> is called even if <code>length</code>
+ * is zero. This is different from {@link #replace}.</p>
+ *
+ * <p>Note: When <code>length</code> is zero or below the call is not
+ * forwarded to the underlying {@link AbstractDocument.Content} instance
+ * of this document and no exception is thrown.</p>
+ *
+ * @param offset the start offset of the fragment to be removed
+ * @param length the length of the fragment to be removed
+ *
+ * @throws BadLocationException if <code>offset</code> or
+ * <code>offset + length</code> or invalid locations within this
+ * document
+ */
+ public void remove(int offset, int length) throws BadLocationException
+ {
+ if (documentFilter == null)
+ removeImpl(offset, length);
+ else
+ documentFilter.remove(getBypass(), offset, length);
+ }
+
+ void removeImpl(int offset, int length) throws BadLocationException
+ {
+ // The RI silently ignores all requests that have a negative length.
+ // Don't ask my why, but that's how it is.
+ if (length > 0)
+ {
+ if (offset < 0 || offset > getLength())
+ throw new BadLocationException("Invalid remove position", offset);
+
+ if (offset + length > getLength())
+ throw new BadLocationException("Invalid remove length", offset);
+
+ DefaultDocumentEvent event =
+ new DefaultDocumentEvent(offset, length,
+ DocumentEvent.EventType.REMOVE);
+
+ try
+ {
+ writeLock();
+
+ // The order of the operations below is critical!
+ removeUpdate(event);
+ UndoableEdit temp = content.remove(offset, length);
+
+ postRemoveUpdate(event);
+ fireRemoveUpdate(event);
+ }
+ finally
+ {
+ writeUnlock();
+ }
+ }
+ }
+
+ /**
+ * Replaces a piece of content in this <code>Document</code> with
+ * another piece of content.
+ *
+ * <p>If a {@link DocumentFilter} is installed in this document, the
+ * corresponding method of the filter object is called.</p>
+ *
+ * <p>The method has no effect if <code>length</code> is zero (and
+ * only zero) and, at the same time, <code>text</code> is
+ * <code>null</code> or has zero length.</p>
+ *
+ * @param offset the start offset of the fragment to be removed
+ * @param length the length of the fragment to be removed
+ * @param text the text to replace the content with
+ * @param attributes the text attributes to assign to the new content
+ *
+ * @throws BadLocationException if <code>offset</code> or
+ * <code>offset + length</code> or invalid locations within this
+ * document
+ *
+ * @since 1.4
+ */
+ public void replace(int offset, int length, String text,
+ AttributeSet attributes)
+ throws BadLocationException
+ {
+ // Bail out if we have a bogus replacement (Behavior observed in RI).
+ if (length == 0
+ && (text == null || text.length() == 0))
+ return;
+
+ if (documentFilter == null)
+ {
+ // It is important to call the methods which again do the checks
+ // of the arguments and the DocumentFilter because subclasses may
+ // have overridden these methods and provide crucial behavior
+ // which would be skipped if we call the non-checking variants.
+ // An example for this is PlainDocument where insertString can
+ // provide a filtering of newlines.
+ remove(offset, length);
+ insertString(offset, text, attributes);
+ }
+ else
+ documentFilter.replace(getBypass(), offset, length, text, attributes);
+
+ }
+
+ void replaceImpl(int offset, int length, String text,
+ AttributeSet attributes)
+ throws BadLocationException
+ {
+ removeImpl(offset, length);
+ insertStringImpl(offset, text, attributes);
+ }
+
+ /**
+ * Adds a <code>DocumentListener</code> object to this document.
+ *
+ * @param listener the listener to add
+ */
+ public void addDocumentListener(DocumentListener listener)
+ {
+ listenerList.add(DocumentListener.class, listener);
+ }
+
+ /**
+ * Removes a <code>DocumentListener</code> object from this document.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeDocumentListener(DocumentListener listener)
+ {
+ listenerList.remove(DocumentListener.class, listener);
+ }
+
+ /**
+ * Returns all registered <code>DocumentListener</code>s.
+ *
+ * @return all registered <code>DocumentListener</code>s
+ */
+ public DocumentListener[] getDocumentListeners()
+ {
+ return (DocumentListener[]) getListeners(DocumentListener.class);
+ }
+
+ /**
+ * Adds an {@link UndoableEditListener} to this <code>Document</code>.
+ *
+ * @param listener the listener to add
+ */
+ public void addUndoableEditListener(UndoableEditListener listener)
+ {
+ listenerList.add(UndoableEditListener.class, listener);
+ }
+
+ /**
+ * Removes an {@link UndoableEditListener} from this <code>Document</code>.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeUndoableEditListener(UndoableEditListener listener)
+ {
+ listenerList.remove(UndoableEditListener.class, listener);
+ }
+
+ /**
+ * Returns all registered {@link UndoableEditListener}s.
+ *
+ * @return all registered {@link UndoableEditListener}s
+ */
+ public UndoableEditListener[] getUndoableEditListeners()
+ {
+ return (UndoableEditListener[]) getListeners(UndoableEditListener.class);
+ }
+
+ /**
+ * Called before some content gets removed from this <code>Document</code>.
+ * The default implementation does nothing but may be overridden by
+ * subclasses to modify the <code>Document</code> structure in response
+ * to a remove request. The method is executed within a write lock.
+ *
+ * @param chng the <code>DefaultDocumentEvent</code> describing the change
+ */
+ protected void removeUpdate(DefaultDocumentEvent chng)
+ {
+ // Do nothing here. Subclasses may wish to override this.
+ }
+
+ /**
+ * Called to render this <code>Document</code> visually. It obtains a read
+ * lock, ensuring that no changes will be made to the <code>document</code>
+ * during the rendering process. It then calls the {@link Runnable#run()}
+ * method on <code>runnable</code>. This method <em>must not</em> attempt
+ * to modifiy the <code>Document</code>, since a deadlock will occur if it
+ * tries to obtain a write lock. When the {@link Runnable#run()} method
+ * completes (either naturally or by throwing an exception), the read lock
+ * is released. Note that there is nothing in this method related to
+ * the actual rendering. It could be used to execute arbitrary code within
+ * a read lock.
+ *
+ * @param runnable the {@link Runnable} to execute
+ */
+ public void render(Runnable runnable)
+ {
+ readLock();
+ try
+ {
+ runnable.run();
+ }
+ finally
+ {
+ readUnlock();
+ }
+ }
+
+ /**
+ * Sets the asynchronous loading priority for this <code>Document</code>.
+ * A value of <code>-1</code> indicates that this <code>Document</code>
+ * should be loaded synchronously.
+ *
+ * @param p the asynchronous loading priority to set
+ */
+ public void setAsynchronousLoadPriority(int p)
+ {
+ // TODO: Implement this properly.
+ }
+
+ /**
+ * Sets the properties of this <code>Document</code>.
+ *
+ * @param p the document properties to set
+ */
+ public void setDocumentProperties(Dictionary p)
+ {
+ // FIXME: make me thread-safe
+ properties = p;
+ }
+
+ /**
+ * Blocks until a write lock can be obtained. Must wait if there are
+ * readers currently reading or another thread is currently writing.
+ */
+ protected final void writeLock()
+ {
+ if (currentWriter != null && currentWriter.equals(Thread.currentThread()))
+ return;
+ synchronized (documentCV)
+ {
+ numWritersWaiting++;
+ while (numReaders > 0)
+ {
+ try
+ {
+ documentCV.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ throw new Error("interruped while trying to obtain write lock");
+ }
+ }
+ numWritersWaiting --;
+ currentWriter = Thread.currentThread();
+ }
+ }
+
+ /**
+ * Releases the write lock. This allows waiting readers or writers to
+ * obtain the lock.
+ */
+ protected final void writeUnlock()
+ {
+ synchronized (documentCV)
+ {
+ if (Thread.currentThread().equals(currentWriter))
+ {
+ currentWriter = null;
+ documentCV.notifyAll();
+ }
+ }
+ }
+
+ /**
+ * Returns the currently installed {@link DocumentFilter} for this
+ * <code>Document</code>.
+ *
+ * @return the currently installed {@link DocumentFilter} for this
+ * <code>Document</code>
+ *
+ * @since 1.4
+ */
+ public DocumentFilter getDocumentFilter()
+ {
+ return documentFilter;
+ }
+
+ /**
+ * Sets the {@link DocumentFilter} for this <code>Document</code>.
+ *
+ * @param filter the <code>DocumentFilter</code> to set
+ *
+ * @since 1.4
+ */
+ public void setDocumentFilter(DocumentFilter filter)
+ {
+ this.documentFilter = filter;
+ }
+
+ /**
+ * Dumps diagnostic information to the specified <code>PrintStream</code>.
+ *
+ * @param out the stream to write the diagnostic information to
+ */
+ public void dump(PrintStream out)
+ {
+ ((AbstractElement) getDefaultRootElement()).dump(out, 0);
+ }
+
+ /**
+ * Defines a set of methods for managing text attributes for one or more
+ * <code>Document</code>s.
+ *
+ * Replicating {@link AttributeSet}s throughout a <code>Document</code> can
+ * be very expensive. Implementations of this interface are intended to
+ * provide intelligent management of <code>AttributeSet</code>s, eliminating
+ * costly duplication.
+ *
+ * @see StyleContext
+ */
+ public interface AttributeContext
+ {
+ /**
+ * Returns an {@link AttributeSet} that contains the attributes
+ * of <code>old</code> plus the new attribute specified by
+ * <code>name</code> and <code>value</code>.
+ *
+ * @param old the attribute set to be merged with the new attribute
+ * @param name the name of the attribute to be added
+ * @param value the value of the attribute to be added
+ *
+ * @return the old attributes plus the new attribute
+ */
+ AttributeSet addAttribute(AttributeSet old, Object name, Object value);
+
+ /**
+ * Returns an {@link AttributeSet} that contains the attributes
+ * of <code>old</code> plus the new attributes in <code>attributes</code>.
+ *
+ * @param old the set of attributes where to add the new attributes
+ * @param attributes the attributes to be added
+ *
+ * @return an {@link AttributeSet} that contains the attributes
+ * of <code>old</code> plus the new attributes in
+ * <code>attributes</code>
+ */
+ AttributeSet addAttributes(AttributeSet old, AttributeSet attributes);
+
+ /**
+ * Returns an empty {@link AttributeSet}.
+ *
+ * @return an empty {@link AttributeSet}
+ */
+ AttributeSet getEmptySet();
+
+ /**
+ * Called to indicate that the attributes in <code>attributes</code> are
+ * no longer used.
+ *
+ * @param attributes the attributes are no longer used
+ */
+ void reclaim(AttributeSet attributes);
+
+ /**
+ * Returns a {@link AttributeSet} that has the attribute with the specified
+ * <code>name</code> removed from <code>old</code>.
+ *
+ * @param old the attribute set from which an attribute is removed
+ * @param name the name of the attribute to be removed
+ *
+ * @return the attributes of <code>old</code> minus the attribute
+ * specified by <code>name</code>
+ */
+ AttributeSet removeAttribute(AttributeSet old, Object name);
+
+ /**
+ * Removes all attributes in <code>attributes</code> from <code>old</code>
+ * and returns the resulting <code>AttributeSet</code>.
+ *
+ * @param old the set of attributes from which to remove attributes
+ * @param attributes the attributes to be removed from <code>old</code>
+ *
+ * @return the attributes of <code>old</code> minus the attributes in
+ * <code>attributes</code>
+ */
+ AttributeSet removeAttributes(AttributeSet old, AttributeSet attributes);
+
+ /**
+ * Removes all attributes specified by <code>names</code> from
+ * <code>old</code> and returns the resulting <code>AttributeSet</code>.
+ *
+ * @param old the set of attributes from which to remove attributes
+ * @param names the names of the attributes to be removed from
+ * <code>old</code>
+ *
+ * @return the attributes of <code>old</code> minus the attributes in
+ * <code>attributes</code>
+ */
+ AttributeSet removeAttributes(AttributeSet old, Enumeration names);
+ }
+
+ /**
+ * A sequence of data that can be edited. This is were the actual content
+ * in <code>AbstractDocument</code>'s is stored.
+ */
+ public interface Content
+ {
+ /**
+ * Creates a {@link Position} that keeps track of the location at
+ * <code>offset</code>.
+ *
+ * @return a {@link Position} that keeps track of the location at
+ * <code>offset</code>.
+ *
+ * @throw BadLocationException if <code>offset</code> is not a valid
+ * location in this <code>Content</code> model
+ */
+ Position createPosition(int offset) throws BadLocationException;
+
+ /**
+ * Returns the length of the content.
+ *
+ * @return the length of the content
+ */
+ int length();
+
+ /**
+ * Inserts a string into the content model.
+ *
+ * @param where the offset at which to insert the string
+ * @param str the string to be inserted
+ *
+ * @return an <code>UndoableEdit</code> or <code>null</code> if undo is
+ * not supported by this <code>Content</code> model
+ *
+ * @throws BadLocationException if <code>where</code> is not a valid
+ * location in this <code>Content</code> model
+ */
+ UndoableEdit insertString(int where, String str)
+ throws BadLocationException;
+
+ /**
+ * Removes a piece of content from the content model.
+ *
+ * @param where the offset at which to remove content
+ * @param nitems the number of characters to be removed
+ *
+ * @return an <code>UndoableEdit</code> or <code>null</code> if undo is
+ * not supported by this <code>Content</code> model
+ *
+ * @throws BadLocationException if <code>where</code> is not a valid
+ * location in this <code>Content</code> model
+ */
+ UndoableEdit remove(int where, int nitems) throws BadLocationException;
+
+ /**
+ * Returns a piece of content.
+ *
+ * @param where the start offset of the requested fragment
+ * @param len the length of the requested fragment
+ *
+ * @return the requested fragment
+ * @throws BadLocationException if <code>offset</code> or
+ * <code>offset + len</code>is not a valid
+ * location in this <code>Content</code> model
+ */
+ String getString(int where, int len) throws BadLocationException;
+
+ /**
+ * Fetches a piece of content and stores it in <code>txt</code>.
+ *
+ * @param where the start offset of the requested fragment
+ * @param len the length of the requested fragment
+ * @param txt the <code>Segment</code> where to fragment is stored into
+ *
+ * @throws BadLocationException if <code>offset</code> or
+ * <code>offset + len</code>is not a valid
+ * location in this <code>Content</code> model
+ */
+ void getChars(int where, int len, Segment txt) throws BadLocationException;
+ }
+
+ /**
+ * An abstract base implementation of the {@link Element} interface.
+ */
+ public abstract class AbstractElement
+ implements Element, MutableAttributeSet, TreeNode, Serializable
+ {
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 1712240033321461704L;
+
+ /** The number of characters that this Element spans. */
+ int count;
+
+ /** The starting offset of this Element. */
+ int offset;
+
+ /** The attributes of this Element. */
+ AttributeSet attributes;
+
+ /** The parent element. */
+ Element element_parent;
+
+ /** The parent in the TreeNode interface. */
+ TreeNode tree_parent;
+
+ /** The children of this element. */
+ Vector tree_children;
+
+ /**
+ * Creates a new instance of <code>AbstractElement</code> with a
+ * specified parent <code>Element</code> and <code>AttributeSet</code>.
+ *
+ * @param p the parent of this <code>AbstractElement</code>
+ * @param s the attributes to be assigned to this
+ * <code>AbstractElement</code>
+ */
+ public AbstractElement(Element p, AttributeSet s)
+ {
+ element_parent = p;
+ AttributeContext ctx = getAttributeContext();
+ attributes = ctx.getEmptySet();
+ if (s != null)
+ attributes = ctx.addAttributes(attributes, s);
+ }
+
+ /**
+ * Returns the child nodes of this <code>Element</code> as an
+ * <code>Enumeration</code> of {@link TreeNode}s.
+ *
+ * @return the child nodes of this <code>Element</code> as an
+ * <code>Enumeration</code> of {@link TreeNode}s
+ */
+ public abstract Enumeration children();
+
+ /**
+ * Returns <code>true</code> if this <code>AbstractElement</code>
+ * allows children.
+ *
+ * @return <code>true</code> if this <code>AbstractElement</code>
+ * allows children
+ */
+ public abstract boolean getAllowsChildren();
+
+ /**
+ * Returns the child of this <code>AbstractElement</code> at
+ * <code>index</code>.
+ *
+ * @param index the position in the child list of the child element to
+ * be returned
+ *
+ * @return the child of this <code>AbstractElement</code> at
+ * <code>index</code>
+ */
+ public TreeNode getChildAt(int index)
+ {
+ return (TreeNode) tree_children.get(index);
+ }
+
+ /**
+ * Returns the number of children of this <code>AbstractElement</code>.
+ *
+ * @return the number of children of this <code>AbstractElement</code>
+ */
+ public int getChildCount()
+ {
+ return tree_children.size();
+ }
+
+ /**
+ * Returns the index of a given child <code>TreeNode</code> or
+ * <code>-1</code> if <code>node</code> is not a child of this
+ * <code>AbstractElement</code>.
+ *
+ * @param node the node for which the index is requested
+ *
+ * @return the index of a given child <code>TreeNode</code> or
+ * <code>-1</code> if <code>node</code> is not a child of this
+ * <code>AbstractElement</code>
+ */
+ public int getIndex(TreeNode node)
+ {
+ return tree_children.indexOf(node);
+ }
+
+ /**
+ * Returns the parent <code>TreeNode</code> of this
+ * <code>AbstractElement</code> or <code>null</code> if this element
+ * has no parent.
+ *
+ * @return the parent <code>TreeNode</code> of this
+ * <code>AbstractElement</code> or <code>null</code> if this
+ * element has no parent
+ */
+ public TreeNode getParent()
+ {
+ return tree_parent;
+ }
+
+ /**
+ * Returns <code>true</code> if this <code>AbstractElement</code> is a
+ * leaf element, <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if this <code>AbstractElement</code> is a
+ * leaf element, <code>false</code> otherwise
+ */
+ public abstract boolean isLeaf();
+
+ /**
+ * Adds an attribute to this element.
+ *
+ * @param name the name of the attribute to be added
+ * @param value the value of the attribute to be added
+ */
+ public void addAttribute(Object name, Object value)
+ {
+ attributes = getAttributeContext().addAttribute(attributes, name, value);
+ }
+
+ /**
+ * Adds a set of attributes to this element.
+ *
+ * @param attrs the attributes to be added to this element
+ */
+ public void addAttributes(AttributeSet attrs)
+ {
+ attributes = getAttributeContext().addAttributes(attributes, attrs);
+ }
+
+ /**
+ * Removes an attribute from this element.
+ *
+ * @param name the name of the attribute to be removed
+ */
+ public void removeAttribute(Object name)
+ {
+ attributes = getAttributeContext().removeAttribute(attributes, name);
+ }
+
+ /**
+ * Removes a set of attributes from this element.
+ *
+ * @param attrs the attributes to be removed
+ */
+ public void removeAttributes(AttributeSet attrs)
+ {
+ attributes = getAttributeContext().removeAttributes(attributes, attrs);
+ }
+
+ /**
+ * Removes a set of attribute from this element.
+ *
+ * @param names the names of the attributes to be removed
+ */
+ public void removeAttributes(Enumeration names)
+ {
+ attributes = getAttributeContext().removeAttributes(attributes, names);
+ }
+
+ /**
+ * Sets the parent attribute set against which the element can resolve
+ * attributes that are not defined in itself.
+ *
+ * @param parent the resolve parent to set
+ */
+ public void setResolveParent(AttributeSet parent)
+ {
+ attributes = getAttributeContext().addAttribute(attributes,
+ ResolveAttribute,
+ parent);
+ }
+
+ /**
+ * Returns <code>true</code> if this element contains the specified
+ * attribute.
+ *
+ * @param name the name of the attribute to check
+ * @param value the value of the attribute to check
+ *
+ * @return <code>true</code> if this element contains the specified
+ * attribute
+ */
+ public boolean containsAttribute(Object name, Object value)
+ {
+ return attributes.containsAttribute(name, value);
+ }
+
+ /**
+ * Returns <code>true</code> if this element contains all of the
+ * specified attributes.
+ *
+ * @param attrs the attributes to check
+ *
+ * @return <code>true</code> if this element contains all of the
+ * specified attributes
+ */
+ public boolean containsAttributes(AttributeSet attrs)
+ {
+ return attributes.containsAttributes(attrs);
+ }
+
+ /**
+ * Returns a copy of the attributes of this element.
+ *
+ * @return a copy of the attributes of this element
+ */
+ public AttributeSet copyAttributes()
+ {
+ return attributes.copyAttributes();
+ }
+
+ /**
+ * Returns the attribute value with the specified key. If this attribute
+ * is not defined in this element and this element has a resolving
+ * parent, the search goes upward to the resolve parent chain.
+ *
+ * @param key the key of the requested attribute
+ *
+ * @return the attribute value for <code>key</code> of <code>null</code>
+ * if <code>key</code> is not found locally and cannot be resolved
+ * in this element's resolve parents
+ */
+ public Object getAttribute(Object key)
+ {
+ Object result = attributes.getAttribute(key);
+ if (result == null)
+ {
+ AttributeSet resParent = getResolveParent();
+ if (resParent != null)
+ result = resParent.getAttribute(key);
+ }
+ return result;
+ }
+
+ /**
+ * Returns the number of defined attributes in this element.
+ *
+ * @return the number of defined attributes in this element
+ */
+ public int getAttributeCount()
+ {
+ return attributes.getAttributeCount();
+ }
+
+ /**
+ * Returns the names of the attributes of this element.
+ *
+ * @return the names of the attributes of this element
+ */
+ public Enumeration getAttributeNames()
+ {
+ return attributes.getAttributeNames();
+ }
+
+ /**
+ * Returns the resolve parent of this element.
+ * This is taken from the AttributeSet, but if this is null,
+ * this method instead returns the Element's parent's
+ * AttributeSet
+ *
+ * @return the resolve parent of this element
+ *
+ * @see #setResolveParent(AttributeSet)
+ */
+ public AttributeSet getResolveParent()
+ {
+ return attributes.getResolveParent();
+ }
+
+ /**
+ * Returns <code>true</code> if an attribute with the specified name
+ * is defined in this element, <code>false</code> otherwise.
+ *
+ * @param attrName the name of the requested attributes
+ *
+ * @return <code>true</code> if an attribute with the specified name
+ * is defined in this element, <code>false</code> otherwise
+ */
+ public boolean isDefined(Object attrName)
+ {
+ return attributes.isDefined(attrName);
+ }
+
+ /**
+ * Returns <code>true</code> if the specified <code>AttributeSet</code>
+ * is equal to this element's <code>AttributeSet</code>, <code>false</code>
+ * otherwise.
+ *
+ * @param attrs the attributes to compare this element to
+ *
+ * @return <code>true</code> if the specified <code>AttributeSet</code>
+ * is equal to this element's <code>AttributeSet</code>,
+ * <code>false</code> otherwise
+ */
+ public boolean isEqual(AttributeSet attrs)
+ {
+ return attributes.isEqual(attrs);
+ }
+
+ /**
+ * Returns the attributes of this element.
+ *
+ * @return the attributes of this element
+ */
+ public AttributeSet getAttributes()
+ {
+ return this;
+ }
+
+ /**
+ * Returns the {@link Document} to which this element belongs.
+ *
+ * @return the {@link Document} to which this element belongs
+ */
+ public Document getDocument()
+ {
+ return AbstractDocument.this;
+ }
+
+ /**
+ * Returns the child element at the specified <code>index</code>.
+ *
+ * @param index the index of the requested child element
+ *
+ * @return the requested element
+ */
+ public abstract Element getElement(int index);
+
+ /**
+ * Returns the name of this element.
+ *
+ * @return the name of this element
+ */
+ public String getName()
+ {
+ return (String) getAttribute(NameAttribute);
+ }
+
+ /**
+ * Returns the parent element of this element.
+ *
+ * @return the parent element of this element
+ */
+ public Element getParentElement()
+ {
+ return element_parent;
+ }
+
+ /**
+ * Returns the offset inside the document model that is after the last
+ * character of this element.
+ *
+ * @return the offset inside the document model that is after the last
+ * character of this element
+ */
+ public abstract int getEndOffset();
+
+ /**
+ * Returns the number of child elements of this element.
+ *
+ * @return the number of child elements of this element
+ */
+ public abstract int getElementCount();
+
+ /**
+ * Returns the index of the child element that spans the specified
+ * offset in the document model.
+ *
+ * @param offset the offset for which the responsible element is searched
+ *
+ * @return the index of the child element that spans the specified
+ * offset in the document model
+ */
+ public abstract int getElementIndex(int offset);
+
+ /**
+ * Returns the start offset if this element inside the document model.
+ *
+ * @return the start offset if this element inside the document model
+ */
+ public abstract int getStartOffset();
+
+ /**
+ * Prints diagnostic output to the specified stream.
+ *
+ * @param stream the stream to write to
+ * @param indent the indentation level
+ */
+ public void dump(PrintStream stream, int indent)
+ {
+ StringBuffer b = new StringBuffer();
+ for (int i = 0; i < indent; ++i)
+ b.append(' ');
+ b.append('<');
+ b.append(getName());
+ // Dump attributes if there are any.
+ if (getAttributeCount() > 0)
+ {
+ b.append('\n');
+ Enumeration attNames = getAttributeNames();
+ while (attNames.hasMoreElements())
+ {
+ for (int i = 0; i < indent + 2; ++i)
+ b.append(' ');
+ Object attName = attNames.nextElement();
+ b.append(attName);
+ b.append('=');
+ Object attribute = getAttribute(attName);
+ b.append(attribute);
+ b.append('\n');
+ }
+ }
+ b.append(">\n");
+
+ // Dump element content for leaf elements.
+ if (isLeaf())
+ {
+ for (int i = 0; i < indent + 2; ++i)
+ b.append(' ');
+ int start = getStartOffset();
+ int end = getEndOffset();
+ b.append('[');
+ b.append(start);
+ b.append(',');
+ b.append(end);
+ b.append("][");
+ try
+ {
+ b.append(getDocument().getText(start, end - start));
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError err = new AssertionError("BadLocationException "
+ + "must not be thrown "
+ + "here.");
+ err.initCause(ex);
+ throw err;
+ }
+ b.append("]\n");
+ }
+ stream.print(b.toString());
+
+ // Dump child elements if any.
+ int count = getElementCount();
+ for (int i = 0; i < count; ++i)
+ {
+ Element el = getElement(i);
+ if (el instanceof AbstractElement)
+ ((AbstractElement) el).dump(stream, indent + 2);
+ }
+ }
+ }
+
+ /**
+ * An implementation of {@link Element} to represent composite
+ * <code>Element</code>s that contain other <code>Element</code>s.
+ */
+ public class BranchElement extends AbstractElement
+ {
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = -6037216547466333183L;
+
+ /**
+ * The child elements of this BranchElement.
+ */
+ private Element[] children;;
+
+ /**
+ * The number of children in the branch element.
+ */
+ private int numChildren;
+
+ /**
+ * Creates a new <code>BranchElement</code> with the specified
+ * parent and attributes.
+ *
+ * @param parent the parent element of this <code>BranchElement</code>
+ * @param attributes the attributes to set on this
+ * <code>BranchElement</code>
+ */
+ public BranchElement(Element parent, AttributeSet attributes)
+ {
+ super(parent, attributes);
+ children = new Element[1];
+ numChildren = 0;
+ }
+
+ /**
+ * Returns the children of this <code>BranchElement</code>.
+ *
+ * @return the children of this <code>BranchElement</code>
+ */
+ public Enumeration children()
+ {
+ if (children.length == 0)
+ return null;
+
+ Vector tmp = new Vector();
+
+ for (int index = 0; index < numChildren; ++index)
+ tmp.add(children[index]);
+
+ return tmp.elements();
+ }
+
+ /**
+ * Returns <code>true</code> since <code>BranchElements</code> allow
+ * child elements.
+ *
+ * @return <code>true</code> since <code>BranchElements</code> allow
+ * child elements
+ */
+ public boolean getAllowsChildren()
+ {
+ return true;
+ }
+
+ /**
+ * Returns the child element at the specified <code>index</code>.
+ *
+ * @param index the index of the requested child element
+ *
+ * @return the requested element
+ */
+ public Element getElement(int index)
+ {
+ if (index < 0 || index >= numChildren)
+ return null;
+
+ return children[index];
+ }
+
+ /**
+ * Returns the number of child elements of this element.
+ *
+ * @return the number of child elements of this element
+ */
+ public int getElementCount()
+ {
+ return numChildren;
+ }
+
+ /**
+ * Returns the index of the child element that spans the specified
+ * offset in the document model.
+ *
+ * @param offset the offset for which the responsible element is searched
+ *
+ * @return the index of the child element that spans the specified
+ * offset in the document model
+ */
+ public int getElementIndex(int offset)
+ {
+ // If offset is less than the start offset of our first child,
+ // return 0
+ if (offset < getStartOffset())
+ return 0;
+
+ // XXX: There is surely a better algorithm
+ // as beginning from first element each time.
+ for (int index = 0; index < numChildren - 1; ++index)
+ {
+ Element elem = children[index];
+
+ if ((elem.getStartOffset() <= offset)
+ && (offset < elem.getEndOffset()))
+ return index;
+ // If the next element's start offset is greater than offset
+ // then we have to return the closest Element, since no Elements
+ // will contain the offset
+ if (children[index + 1].getStartOffset() > offset)
+ {
+ if ((offset - elem.getEndOffset()) > (children[index + 1].getStartOffset() - offset))
+ return index + 1;
+ else
+ return index;
+ }
+ }
+
+ // If offset is greater than the index of the last element, return
+ // the index of the last element.
+ return getElementCount() - 1;
+ }
+
+ /**
+ * Returns the offset inside the document model that is after the last
+ * character of this element.
+ * This is the end offset of the last child element. If this element
+ * has no children, this method throws a <code>NullPointerException</code>.
+ *
+ * @return the offset inside the document model that is after the last
+ * character of this element
+ *
+ * @throws NullPointerException if this branch element has no children
+ */
+ public int getEndOffset()
+ {
+ // This might accss one cached element or trigger an NPE for
+ // numChildren == 0. This is checked by a Mauve test.
+ Element child = numChildren > 0 ? children[numChildren - 1]
+ : children[0];
+ return child.getEndOffset();
+ }
+
+ /**
+ * Returns the name of this element. This is {@link #ParagraphElementName}
+ * in this case.
+ *
+ * @return the name of this element
+ */
+ public String getName()
+ {
+ return ParagraphElementName;
+ }
+
+ /**
+ * Returns the start offset of this element inside the document model.
+ * This is the start offset of the first child element. If this element
+ * has no children, this method throws a <code>NullPointerException</code>.
+ *
+ * @return the start offset of this element inside the document model
+ *
+ * @throws NullPointerException if this branch element has no children and
+ * no startOffset value has been cached
+ */
+ public int getStartOffset()
+ {
+ // Do not explicitly throw an NPE here. If the first element is null
+ // then the NPE gets thrown anyway. If it isn't, then it either
+ // holds a real value (for numChildren > 0) or a cached value
+ // (for numChildren == 0) as we don't fully remove elements in replace()
+ // when removing single elements.
+ // This is checked by a Mauve test.
+ return children[0].getStartOffset();
+ }
+
+ /**
+ * Returns <code>false</code> since <code>BranchElement</code> are no
+ * leafes.
+ *
+ * @return <code>false</code> since <code>BranchElement</code> are no
+ * leafes
+ */
+ public boolean isLeaf()
+ {
+ return false;
+ }
+
+ /**
+ * Returns the <code>Element</code> at the specified <code>Document</code>
+ * offset.
+ *
+ * @return the <code>Element</code> at the specified <code>Document</code>
+ * offset
+ *
+ * @see #getElementIndex(int)
+ */
+ public Element positionToElement(int position)
+ {
+ // XXX: There is surely a better algorithm
+ // as beginning from first element each time.
+ for (int index = 0; index < numChildren; ++index)
+ {
+ Element elem = children[index];
+
+ if ((elem.getStartOffset() <= position)
+ && (position < elem.getEndOffset()))
+ return elem;
+ }
+
+ return null;
+ }
+
+ /**
+ * Replaces a set of child elements with a new set of child elemens.
+ *
+ * @param offset the start index of the elements to be removed
+ * @param length the number of elements to be removed
+ * @param elements the new elements to be inserted
+ */
+ public void replace(int offset, int length, Element[] elements)
+ {
+ int delta = elements.length - length;
+ int copyFrom = offset + length; // From where to copy.
+ int copyTo = copyFrom + delta; // Where to copy to.
+ int numMove = numChildren - copyFrom; // How many elements are moved.
+ if (numChildren + delta > children.length)
+ {
+ // Gotta grow the array.
+ int newSize = Math.max(2 * children.length, numChildren + delta);
+ Element[] target = new Element[newSize];
+ System.arraycopy(children, 0, target, 0, offset);
+ System.arraycopy(elements, 0, target, offset, elements.length);
+ System.arraycopy(children, copyFrom, target, copyTo, numMove);
+ children = target;
+ }
+ else
+ {
+ System.arraycopy(children, copyFrom, children, copyTo, numMove);
+ System.arraycopy(elements, 0, children, offset, elements.length);
+ }
+ numChildren += delta;
+ }
+
+ /**
+ * Returns a string representation of this element.
+ *
+ * @return a string representation of this element
+ */
+ public String toString()
+ {
+ return ("BranchElement(" + getName() + ") "
+ + getStartOffset() + "," + getEndOffset() + "\n");
+ }
+ }
+
+ /**
+ * Stores the changes when a <code>Document</code> is beeing modified.
+ */
+ public class DefaultDocumentEvent extends CompoundEdit
+ implements DocumentEvent
+ {
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 5230037221564563284L;
+
+ /** The starting offset of the change. */
+ private int offset;
+
+ /** The length of the change. */
+ private int length;
+
+ /** The type of change. */
+ private DocumentEvent.EventType type;
+
+ /**
+ * Maps <code>Element</code> to their change records.
+ */
+ Hashtable changes;
+
+ /**
+ * Indicates if this event has been modified or not. This is used to
+ * determine if this event is thrown.
+ */
+ boolean modified;
+
+ /**
+ * Creates a new <code>DefaultDocumentEvent</code>.
+ *
+ * @param offset the starting offset of the change
+ * @param length the length of the change
+ * @param type the type of change
+ */
+ public DefaultDocumentEvent(int offset, int length,
+ DocumentEvent.EventType type)
+ {
+ this.offset = offset;
+ this.length = length;
+ this.type = type;
+ changes = new Hashtable();
+ modified = false;
+ }
+
+ /**
+ * Adds an UndoableEdit to this <code>DocumentEvent</code>. If this
+ * edit is an instance of {@link ElementEdit}, then this record can
+ * later be fetched by calling {@link #getChange}.
+ *
+ * @param edit the undoable edit to add
+ */
+ public boolean addEdit(UndoableEdit edit)
+ {
+ // XXX - Fully qualify ElementChange to work around gcj bug #2499.
+ if (edit instanceof DocumentEvent.ElementChange)
+ {
+ modified = true;
+ DocumentEvent.ElementChange elEdit =
+ (DocumentEvent.ElementChange) edit;
+ changes.put(elEdit.getElement(), elEdit);
+ }
+ return super.addEdit(edit);
+ }
+
+ /**
+ * Returns the document that has been modified.
+ *
+ * @return the document that has been modified
+ */
+ public Document getDocument()
+ {
+ return AbstractDocument.this;
+ }
+
+ /**
+ * Returns the length of the modification.
+ *
+ * @return the length of the modification
+ */
+ public int getLength()
+ {
+ return length;
+ }
+
+ /**
+ * Returns the start offset of the modification.
+ *
+ * @return the start offset of the modification
+ */
+ public int getOffset()
+ {
+ return offset;
+ }
+
+ /**
+ * Returns the type of the modification.
+ *
+ * @return the type of the modification
+ */
+ public DocumentEvent.EventType getType()
+ {
+ return type;
+ }
+
+ /**
+ * Returns the changes for an element.
+ *
+ * @param elem the element for which the changes are requested
+ *
+ * @return the changes for <code>elem</code> or <code>null</code> if
+ * <code>elem</code> has not been changed
+ */
+ public DocumentEvent.ElementChange getChange(Element elem)
+ {
+ // XXX - Fully qualify ElementChange to work around gcj bug #2499.
+ return (DocumentEvent.ElementChange) changes.get(elem);
+ }
+
+ /**
+ * Returns a String description of the change event. This returns the
+ * toString method of the Vector of edits.
+ */
+ public String toString()
+ {
+ return edits.toString();
+ }
+ }
+
+ /**
+ * An implementation of {@link DocumentEvent.ElementChange} to be added
+ * to {@link DefaultDocumentEvent}s.
+ */
+ public static class ElementEdit extends AbstractUndoableEdit
+ implements DocumentEvent.ElementChange
+ {
+ /** The serial version UID of ElementEdit. */
+ private static final long serialVersionUID = -1216620962142928304L;
+
+ /**
+ * The changed element.
+ */
+ private Element elem;
+
+ /**
+ * The index of the change.
+ */
+ private int index;
+
+ /**
+ * The removed elements.
+ */
+ private Element[] removed;
+
+ /**
+ * The added elements.
+ */
+ private Element[] added;
+
+ /**
+ * Creates a new <code>ElementEdit</code>.
+ *
+ * @param elem the changed element
+ * @param index the index of the change
+ * @param removed the removed elements
+ * @param added the added elements
+ */
+ public ElementEdit(Element elem, int index,
+ Element[] removed, Element[] added)
+ {
+ this.elem = elem;
+ this.index = index;
+ this.removed = removed;
+ this.added = added;
+ }
+
+ /**
+ * Returns the added elements.
+ *
+ * @return the added elements
+ */
+ public Element[] getChildrenAdded()
+ {
+ return added;
+ }
+
+ /**
+ * Returns the removed elements.
+ *
+ * @return the removed elements
+ */
+ public Element[] getChildrenRemoved()
+ {
+ return removed;
+ }
+
+ /**
+ * Returns the changed element.
+ *
+ * @return the changed element
+ */
+ public Element getElement()
+ {
+ return elem;
+ }
+
+ /**
+ * Returns the index of the change.
+ *
+ * @return the index of the change
+ */
+ public int getIndex()
+ {
+ return index;
+ }
+ }
+
+ /**
+ * An implementation of {@link Element} that represents a leaf in the
+ * document structure. This is used to actually store content.
+ */
+ public class LeafElement extends AbstractElement
+ {
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = -8906306331347768017L;
+
+ /**
+ * Manages the start offset of this element.
+ */
+ private Position startPos;
+
+ /**
+ * Manages the end offset of this element.
+ */
+ private Position endPos;
+
+ /**
+ * Creates a new <code>LeafElement</code>.
+ *
+ * @param parent the parent of this <code>LeafElement</code>
+ * @param attributes the attributes to be set
+ * @param start the start index of this element inside the document model
+ * @param end the end index of this element inside the document model
+ */
+ public LeafElement(Element parent, AttributeSet attributes, int start,
+ int end)
+ {
+ super(parent, attributes);
+ try
+ {
+ startPos = createPosition(start);
+ endPos = createPosition(end);
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError as;
+ as = new AssertionError("BadLocationException thrown "
+ + "here. start=" + start
+ + ", end=" + end
+ + ", length=" + getLength());
+ as.initCause(ex);
+ throw as;
+ }
+ }
+
+ /**
+ * Returns <code>null</code> since <code>LeafElement</code>s cannot have
+ * children.
+ *
+ * @return <code>null</code> since <code>LeafElement</code>s cannot have
+ * children
+ */
+ public Enumeration children()
+ {
+ return null;
+ }
+
+ /**
+ * Returns <code>false</code> since <code>LeafElement</code>s cannot have
+ * children.
+ *
+ * @return <code>false</code> since <code>LeafElement</code>s cannot have
+ * children
+ */
+ public boolean getAllowsChildren()
+ {
+ return false;
+ }
+
+ /**
+ * Returns <code>null</code> since <code>LeafElement</code>s cannot have
+ * children.
+ *
+ * @return <code>null</code> since <code>LeafElement</code>s cannot have
+ * children
+ */
+ public Element getElement(int index)
+ {
+ return null;
+ }
+
+ /**
+ * Returns <code>0</code> since <code>LeafElement</code>s cannot have
+ * children.
+ *
+ * @return <code>0</code> since <code>LeafElement</code>s cannot have
+ * children
+ */
+ public int getElementCount()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns <code>-1</code> since <code>LeafElement</code>s cannot have
+ * children.
+ *
+ * @return <code>-1</code> since <code>LeafElement</code>s cannot have
+ * children
+ */
+ public int getElementIndex(int offset)
+ {
+ return -1;
+ }
+
+ /**
+ * Returns the end offset of this <code>Element</code> inside the
+ * document.
+ *
+ * @return the end offset of this <code>Element</code> inside the
+ * document
+ */
+ public int getEndOffset()
+ {
+ return endPos.getOffset();
+ }
+
+ /**
+ * Returns the name of this <code>Element</code>. This is
+ * {@link #ContentElementName} in this case.
+ *
+ * @return the name of this <code>Element</code>
+ */
+ public String getName()
+ {
+ String name = super.getName();
+ if (name == null)
+ name = ContentElementName;
+ return name;
+ }
+
+ /**
+ * Returns the start offset of this <code>Element</code> inside the
+ * document.
+ *
+ * @return the start offset of this <code>Element</code> inside the
+ * document
+ */
+ public int getStartOffset()
+ {
+ return startPos.getOffset();
+ }
+
+ /**
+ * Returns <code>true</code>.
+ *
+ * @return <code>true</code>
+ */
+ public boolean isLeaf()
+ {
+ return true;
+ }
+
+ /**
+ * Returns a string representation of this <code>Element</code>.
+ *
+ * @return a string representation of this <code>Element</code>
+ */
+ public String toString()
+ {
+ return ("LeafElement(" + getName() + ") "
+ + getStartOffset() + "," + getEndOffset() + "\n");
+ }
+ }
+
+ /** A class whose methods delegate to the insert, remove and replace methods
+ * of this document which do not check for an installed DocumentFilter.
+ */
+ class Bypass extends DocumentFilter.FilterBypass
+ {
+
+ public Document getDocument()
+ {
+ return AbstractDocument.this;
+ }
+
+ public void insertString(int offset, String string, AttributeSet attr)
+ throws BadLocationException
+ {
+ AbstractDocument.this.insertStringImpl(offset, string, attr);
+ }
+
+ public void remove(int offset, int length)
+ throws BadLocationException
+ {
+ AbstractDocument.this.removeImpl(offset, length);
+ }
+
+ public void replace(int offset, int length, String string,
+ AttributeSet attrs)
+ throws BadLocationException
+ {
+ AbstractDocument.this.replaceImpl(offset, length, string, attrs);
+ }
+
+ }
+
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AbstractWriter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AbstractWriter.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AbstractWriter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AbstractWriter.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,481 @@
+/* AbstractWriter.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.Enumeration;
+
+/**
+ * This is an abstract base class for writing Document instances to a
+ * Writer. A concrete subclass must implement a method to iterate
+ * over the Elements of the Document and correctly format them.
+ */
+public abstract class AbstractWriter
+{
+ /**
+ * The default line separator character.
+ * @specnote although this is a constant, it is not static in the JDK
+ */
+ protected static final char NEWLINE = '\n';
+
+ // Where we write.
+ private Writer writer;
+ // How we iterate over the document.
+ private ElementIterator iter;
+ // The document over which we iterate.
+ private Document document;
+ // Maximum number of characters per line.
+ private int maxLineLength = 100;
+ // Number of characters we have currently written.
+ private int lineLength;
+ // True if we can apply line wrapping.
+ private boolean canWrapLines; // FIXME default?
+ // The number of spaces per indentation level.
+ private int indentSpace = 2;
+ // The current indentation level.
+ private int indentLevel;
+ // True if we have indented this line.
+ private boolean indented;
+ // Starting offset in document.
+ private int startOffset;
+ // Ending offset in document.
+ private int endOffset;
+ // The line separator string.
+ private String lineSeparator = "" + NEWLINE;
+ // The characters making up the line separator.
+ private char[] lineSeparatorChars = lineSeparator.toCharArray();
+
+ /**
+ * Create a new AbstractWriter with the indicated Writer and
+ * Document. The full range of the Document will be used. The
+ * internal ElementIterator will be initialized with the Document's
+ * root node.
+ */
+ protected AbstractWriter(Writer writer, Document doc)
+ {
+ this.writer = writer;
+ this.iter = new ElementIterator(doc);
+ this.document = doc;
+ this.startOffset = 0;
+ this.endOffset = doc.getLength();
+ }
+
+ /**
+ * Create a new AbstractWriter with the indicated Writer and
+ * Document. The full range of the Document will be used. The
+ * internal ElementIterator will be initialized with the Document's
+ * root node.
+ */
+ protected AbstractWriter(Writer writer, Document doc, int pos, int len)
+ {
+ this.writer = writer;
+ this.iter = new ElementIterator(doc);
+ this.document = doc;
+ this.startOffset = pos;
+ this.endOffset = pos + len;
+ }
+
+ /**
+ * Create a new AbstractWriter with the indicated Writer and
+ * Element. The full range of the Element will be used.
+ */
+ protected AbstractWriter(Writer writer, Element elt)
+ {
+ this.writer = writer;
+ this.iter = new ElementIterator(elt);
+ this.document = elt.getDocument();
+ this.startOffset = elt.getStartOffset();
+ this.endOffset = elt.getEndOffset();
+ }
+
+ /**
+ * Create a new AbstractWriter with the indicated Writer and
+ * Element. The full range of the Element will be used. The range
+ * will be limited to the indicated range of the Document.
+ */
+ protected AbstractWriter(Writer writer, Element elt, int pos, int len)
+ {
+ this.writer = writer;
+ this.iter = new ElementIterator(elt);
+ this.document = elt.getDocument();
+ this.startOffset = pos;
+ this.endOffset = pos + len;
+ }
+
+ /**
+ * Return the ElementIterator for this writer.
+ */
+ protected ElementIterator getElementIterator()
+ {
+ return iter;
+ }
+
+ /**
+ * Return the Writer to which we are writing.
+ * @since 1.3
+ */
+ protected Writer getWriter()
+ {
+ return writer;
+ }
+
+ /**
+ * Return this writer's Document.
+ */
+ protected Document getDocument()
+ {
+ return document;
+ }
+
+ /**
+ * This method must be overridden by a concrete subclass. It is
+ * responsible for iterating over the Elements of the Document and
+ * writing them out.
+ */
+ protected abstract void write() throws IOException, BadLocationException;
+
+ /**
+ * Return the text of the Document that is associated with the given
+ * Element. If the Element is not a leaf Element, this will throw
+ * BadLocationException.
+ *
+ * @throws BadLocationException if the element is not a leaf
+ */
+ protected String getText(Element elt) throws BadLocationException
+ {
+ if (! elt.isLeaf())
+ throw new BadLocationException("Element is not a leaf",
+ elt.getStartOffset());
+ return document.getText(elt.getStartOffset(),
+ elt.getEndOffset() - elt.getStartOffset());
+ }
+
+ /**
+ * This method calls Writer.write on the indicated data, and updates
+ * the current line length. This method does not look for newlines
+ * in the written data; the caller is responsible for that.
+ *
+ * @since 1.3
+ */
+ protected void output(char[] data, int start, int len) throws IOException
+ {
+ writer.write(data, start, len);
+ lineLength += len;
+ }
+
+ /**
+ * Write a line separator using the output method, and then reset
+ * the current line length.
+ *
+ * @since 1.3
+ */
+ protected void writeLineSeparator() throws IOException
+ {
+ output(lineSeparatorChars, 0, lineSeparatorChars.length);
+ lineLength = 0;
+ indented = false;
+ }
+
+ /**
+ * Write a single character.
+ */
+ protected void write(char ch) throws IOException
+ {
+ write(new char[] { ch }, 0, 1);
+ }
+
+ /**
+ * Write a String.
+ */
+ protected void write(String s) throws IOException
+ {
+ char[] v = s.toCharArray();
+ write(v, 0, v.length);
+ }
+
+ /**
+ * Write a character array to the output Writer, properly handling
+ * newlines and, if needed, wrapping lines as they are output.
+ * @since 1.3
+ */
+ protected void write(char[] data, int start, int len) throws IOException
+ {
+ if (getCanWrapLines())
+ {
+ // FIXME: should we be handling newlines specially here?
+ for (int i = 0; i < len; )
+ {
+ int start_i = i;
+ // Find next space.
+ while (i < len && data[start + i] != ' ')
+ ++i;
+ if (i < len && lineLength + i - start_i >= maxLineLength)
+ writeLineSeparator();
+ else if (i < len)
+ {
+ // Write the trailing space.
+ ++i;
+ }
+ // Write out the text.
+ output(data, start + start_i, start + i - start_i);
+ }
+ }
+ else
+ {
+ int saved_i = start;
+ for (int i = start; i < start + len; ++i)
+ {
+ if (data[i] == NEWLINE)
+ {
+ output(data, saved_i, i - saved_i);
+ writeLineSeparator();
+ }
+ }
+ if (saved_i < start + len - 1)
+ output(data, saved_i, start + len - saved_i);
+ }
+ }
+
+ /**
+ * Indent this line by emitting spaces, according to the current
+ * indent level and the current number of spaces per indent. After
+ * this method is called, the current line is no longer considered
+ * to be empty, even if no spaces are actually written.
+ */
+ protected void indent() throws IOException
+ {
+ int spaces = indentLevel * indentSpace;
+ if (spaces > 0)
+ {
+ char[] v = new char[spaces];
+ Arrays.fill(v, ' ');
+ write(v, 0, v.length);
+ }
+ indented = true;
+ }
+
+ /**
+ * Return the index of the Document at which output starts.
+ * @since 1.3
+ */
+ public int getStartOffset()
+ {
+ return startOffset;
+ }
+
+ /**
+ * Return the index of the Document at which output ends.
+ * @since 1.3
+ */
+ public int getEndOffset()
+ {
+ return endOffset;
+ }
+
+ /**
+ * Return true if the Element's range overlaps our desired output
+ * range; false otherwise.
+ */
+ protected boolean inRange(Element elt)
+ {
+ int eltStart = elt.getStartOffset();
+ int eltEnd = elt.getEndOffset();
+ return ((eltStart >= startOffset && eltStart < endOffset)
+ || (eltEnd >= startOffset && eltEnd < endOffset));
+ }
+
+ /**
+ * Output the text of the indicated Element, properly clipping it to
+ * the range of the Document specified when the AbstractWriter was
+ * created.
+ */
+ protected void text(Element elt) throws BadLocationException, IOException
+ {
+ int eltStart = elt.getStartOffset();
+ int eltEnd = elt.getEndOffset();
+
+ eltStart = Math.max(eltStart, startOffset);
+ eltEnd = Math.min(eltEnd, endOffset);
+ write(document.getText(eltStart, eltEnd));
+ }
+
+ /**
+ * Set the maximum line length.
+ */
+ protected void setLineLength(int maxLineLength)
+ {
+ this.maxLineLength = maxLineLength;
+ }
+
+ /**
+ * Return the maximum line length.
+ * @since 1.3
+ */
+ protected int getLineLength()
+ {
+ return maxLineLength;
+ }
+
+ /**
+ * Set the current line length.
+ * @since 1.3
+ */
+ protected void setCurrentLineLength(int lineLength)
+ {
+ this.lineLength = lineLength;
+ }
+
+ /**
+ * Return the current line length.
+ * @since 1.3
+ */
+ protected int getCurrentLineLength()
+ {
+ return lineLength;
+ }
+
+ /**
+ * Return true if the line is empty, false otherwise. The line is
+ * empty if nothing has been written since the last newline, and
+ * indent has not been invoked.
+ */
+ protected boolean isLineEmpty()
+ {
+ return lineLength == 0 && ! indented;
+ }
+
+ /**
+ * Set the flag indicating whether lines will wrap. This affects
+ * the behavior of write().
+ * @since 1.3
+ */
+ protected void setCanWrapLines(boolean canWrapLines)
+ {
+ this.canWrapLines = canWrapLines;
+ }
+
+ /**
+ * Return true if lines printed via write() will wrap, false
+ * otherwise.
+ * @since 1.3
+ */
+ protected boolean getCanWrapLines()
+ {
+ return canWrapLines;
+ }
+
+ /**
+ * Set the number of spaces per indent level.
+ * @since 1.3
+ */
+ protected void setIndentSpace(int indentSpace)
+ {
+ this.indentSpace = indentSpace;
+ }
+
+ /**
+ * Return the number of spaces per indent level.
+ * @since 1.3
+ */
+ protected int getIndentSpace()
+ {
+ return indentSpace;
+ }
+
+ /**
+ * Set the current line separator.
+ * @since 1.3
+ */
+ public void setLineSeparator(String lineSeparator)
+ {
+ this.lineSeparator = lineSeparator;
+ this.lineSeparatorChars = lineSeparator.toCharArray();
+ }
+
+ /**
+ * Return the current line separator.
+ * @since 1.3
+ */
+ public String getLineSeparator()
+ {
+ return lineSeparator;
+ }
+
+ /**
+ * Increment the indent level.
+ */
+ protected void incrIndent()
+ {
+ ++indentLevel;
+ }
+
+ /**
+ * Decrement the indent level.
+ */
+ protected void decrIndent()
+ {
+ --indentLevel;
+ }
+
+ /**
+ * Return the current indent level.
+ * @since 1.3
+ */
+ protected int getIndentLevel()
+ {
+ return indentLevel;
+ }
+
+ /**
+ * Print the given AttributeSet as a sequence of assignment-like
+ * strings, e.g. "key=value".
+ */
+ protected void writeAttributes(AttributeSet attrs) throws IOException
+ {
+ Enumeration e = attrs.getAttributeNames();
+ while (e.hasMoreElements())
+ {
+ Object name = e.nextElement();
+ Object val = attrs.getAttribute(name);
+ write(name + "=" + val);
+ writeLineSeparator();
+ }
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AsyncBoxView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AsyncBoxView.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AsyncBoxView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AsyncBoxView.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,1480 @@
+/* AsyncBoxView.java -- A box view that performs layout asynchronously
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.util.ArrayList;
+
+import javax.swing.event.DocumentEvent;
+import javax.swing.text.Position.Bias;
+
+/**
+ * A {@link View} implementation that lays out its child views in a box, either
+ * vertically or horizontally. The difference to {@link BoxView} is that the
+ * layout is performed in an asynchronous manner. This helps to keep the
+ * eventqueue free from non-GUI related tasks.
+ *
+ * This view is currently not used in standard text components. In order to
+ * use it you would have to implement a special {@link EditorKit} with a
+ * {@link ViewFactory} that returns this view. For example:
+ *
+ * <pre>
+ * static class AsyncEditorKit extends StyledEditorKit implements ViewFactory
+ * {
+ * public View create(Element el)
+ * {
+ * if (el.getName().equals(AbstractDocument.SectionElementName))
+ * return new AsyncBoxView(el, View.Y_AXIS);
+ * return super.getViewFactory().create(el);
+ * }
+ * public ViewFactory getViewFactory() {
+ * return this;
+ * }
+ * }
+ * </pre>
+ *
+ * @author Roman Kennke (kennke at aicas.com)
+ *
+ * @since 1.3
+ */
+public class AsyncBoxView
+ extends View
+{
+
+ /**
+ * Manages the effective position of child views. That keeps the visible
+ * layout stable while the AsyncBoxView might be changing until the layout
+ * thread decides to publish the new layout.
+ */
+ public class ChildLocator
+ {
+
+ /**
+ * The last valid location.
+ */
+ protected ChildState lastValidOffset;
+
+ /**
+ * The last allocation.
+ */
+ protected Rectangle lastAlloc;
+
+ /**
+ * A Rectangle used for child allocation calculation to avoid creation
+ * of lots of garbage Rectangle objects.
+ */
+ protected Rectangle childAlloc;
+
+ /**
+ * Creates a new ChildLocator.
+ */
+ public ChildLocator()
+ {
+ lastAlloc = new Rectangle();
+ childAlloc = new Rectangle();
+ }
+
+ /**
+ * Receives notification that a child has changed. This is called by
+ * child state objects that have changed it's major span.
+ *
+ * This sets the {@link #lastValidOffset} field to <code>cs</code> if
+ * the new child state's view start offset is smaller than the start offset
+ * of the current child state's view or when <code>lastValidOffset</code>
+ * is <code>null</code>.
+ *
+ * @param cs the child state object that has changed
+ */
+ public synchronized void childChanged(ChildState cs)
+ {
+ if (lastValidOffset == null
+ || cs.getChildView().getStartOffset()
+ < lastValidOffset.getChildView().getStartOffset())
+ {
+ lastValidOffset = cs;
+ }
+ }
+
+ /**
+ * Returns the view index of the view that occupies the specified area, or
+ * <code>-1</code> if there is no such child view.
+ *
+ * @param x the x coordinate (relative to <code>a</code>)
+ * @param y the y coordinate (relative to <code>a</code>)
+ * @param a the current allocation of this view
+ *
+ * @return the view index of the view that occupies the specified area, or
+ * <code>-1</code> if there is no such child view
+ */
+ public int getViewIndexAtPoint(float x, float y, Shape a)
+ {
+ setAllocation(a);
+ float targetOffset = (getMajorAxis() == X_AXIS) ? x - lastAlloc.x
+ : y - lastAlloc.y;
+ int index = getViewIndexAtVisualOffset(targetOffset);
+ return index;
+ }
+
+ /**
+ * Returns the current allocation for a child view. This updates the
+ * offsets for all children <em>before</em> the requested child view.
+ *
+ * @param index the index of the child view
+ * @param a the current allocation of this view
+ *
+ * @return the current allocation for a child view
+ */
+ public synchronized Shape getChildAllocation(int index, Shape a)
+ {
+ if (a == null)
+ return null;
+ setAllocation(a);
+ ChildState cs = getChildState(index);
+ if (cs.getChildView().getStartOffset()
+ > lastValidOffset.getChildView().getStartOffset())
+ {
+ updateChildOffsetsToIndex(index);
+ }
+ Shape ca = getChildAllocation(index);
+ return ca;
+ }
+
+ /**
+ * Paints all child views.
+ *
+ * @param g the graphics context to use
+ */
+ public synchronized void paintChildren(Graphics g)
+ {
+ Rectangle clip = g.getClipBounds();
+ float targetOffset = (getMajorAxis() == X_AXIS) ? clip.x - lastAlloc.x
+ : clip.y - lastAlloc.y;
+ int index = getViewIndexAtVisualOffset(targetOffset);
+ int n = getViewCount();
+ float offs = getChildState(index).getMajorOffset();
+ for (int i = index; i < n; i++)
+ {
+ ChildState cs = getChildState(i);
+ cs.setMajorOffset(offs);
+ Shape ca = getChildAllocation(i);
+ if (ca.intersects(clip))
+ {
+ synchronized (cs)
+ {
+ View v = cs.getChildView();
+ v.paint(g, ca);
+ }
+ }
+ else
+ {
+ // done painting intersection
+ break;
+ }
+ offs += cs.getMajorSpan();
+ }
+ }
+
+ /**
+ * Returns the current allocation of the child view with the specified
+ * index. Note that this will <em>not</em> update any location information.
+ *
+ * @param index the index of the requested child view
+ *
+ * @return the current allocation of the child view with the specified
+ * index
+ */
+ protected Shape getChildAllocation(int index)
+ {
+ ChildState cs = getChildState(index);
+ if (! cs.isLayoutValid())
+ cs.run();
+
+ if (getMajorAxis() == X_AXIS)
+ {
+ childAlloc.x = lastAlloc.x + (int) cs.getMajorOffset();
+ childAlloc.y = lastAlloc.y + (int) cs.getMinorOffset();
+ childAlloc.width = (int) cs.getMajorSpan();
+ childAlloc.height = (int) cs.getMinorSpan();
+ }
+ else
+ {
+ childAlloc.y = lastAlloc.y + (int) cs.getMajorOffset();
+ childAlloc.x = lastAlloc.x + (int) cs.getMinorOffset();
+ childAlloc.height = (int) cs.getMajorSpan();
+ childAlloc.width = (int) cs.getMinorSpan();
+ }
+ return childAlloc;
+ }
+
+ /**
+ * Sets the current allocation for this view.
+ *
+ * @param a the allocation to set
+ */
+ protected void setAllocation(Shape a)
+ {
+ if (a instanceof Rectangle)
+ lastAlloc.setBounds((Rectangle) a);
+ else
+ lastAlloc.setBounds(a.getBounds());
+
+ setSize(lastAlloc.width, lastAlloc.height);
+ }
+
+ /**
+ * Returns the index of the view at the specified offset along the major
+ * layout axis.
+ *
+ * @param targetOffset the requested offset
+ *
+ * @return the index of the view at the specified offset along the major
+ * layout axis
+ */
+ protected int getViewIndexAtVisualOffset(float targetOffset)
+ {
+ int n = getViewCount();
+ if (n > 0)
+ {
+ if (lastValidOffset == null)
+ lastValidOffset = getChildState(0);
+ if (targetOffset > majorSpan)
+ return 0;
+ else if (targetOffset > lastValidOffset.getMajorOffset())
+ return updateChildOffsets(targetOffset);
+ else
+ {
+ float offs = 0f;
+ for (int i = 0; i < n; i++)
+ {
+ ChildState cs = getChildState(i);
+ float nextOffs = offs + cs.getMajorSpan();
+ if (targetOffset < nextOffs)
+ return i;
+ offs = nextOffs;
+ }
+ }
+ }
+ return n - 1;
+ }
+
+ /**
+ * Updates all the child view offsets up to the specified targetOffset.
+ *
+ * @param targetOffset the offset up to which the child view offsets are
+ * updated
+ *
+ * @return the index of the view at the specified offset
+ */
+ private int updateChildOffsets(float targetOffset)
+ {
+ int n = getViewCount();
+ int targetIndex = n - 1;;
+ int pos = lastValidOffset.getChildView().getStartOffset();
+ int startIndex = getViewIndexAtPosition(pos, Position.Bias.Forward);
+ float start = lastValidOffset.getMajorOffset();
+ float lastOffset = start;
+ for (int i = startIndex; i < n; i++)
+ {
+ ChildState cs = getChildState(i);
+ cs.setMajorOffset(lastOffset);
+ lastOffset += cs.getMajorSpan();
+ if (targetOffset < lastOffset)
+ {
+ targetIndex = i;
+ lastValidOffset = cs;
+ break;
+ }
+ }
+ return targetIndex;
+ }
+
+ /**
+ * Updates the offsets of the child views up to the specified index.
+ *
+ * @param index the index up to which the offsets are updated
+ */
+ private void updateChildOffsetsToIndex(int index)
+ {
+ int pos = lastValidOffset.getChildView().getStartOffset();
+ int startIndex = getViewIndexAtPosition(pos, Position.Bias.Forward);
+ float lastOffset = lastValidOffset.getMajorOffset();
+ for (int i = startIndex; i <= index; i++)
+ {
+ ChildState cs = getChildState(i);
+ cs.setMajorOffset(lastOffset);
+ lastOffset += cs.getMajorSpan();
+ }
+ }
+ }
+
+ /**
+ * Represents the layout state of a child view.
+ */
+ public class ChildState
+ implements Runnable
+ {
+
+ /**
+ * The child view for this state record.
+ */
+ private View childView;
+
+ /**
+ * Indicates if the minor axis requirements of this child view are valid
+ * or not.
+ */
+ private boolean minorValid;
+
+ /**
+ * Indicates if the major axis requirements of this child view are valid
+ * or not.
+ */
+ private boolean majorValid;
+
+ /**
+ * Indicates if the current child size is valid. This is package private
+ * to avoid synthetic accessor method.
+ */
+ boolean childSizeValid;
+
+ /**
+ * The child views minimumSpan. This is package private to avoid accessor
+ * method.
+ */
+ float minimum;
+
+ /**
+ * The child views preferredSpan. This is package private to avoid accessor
+ * method.
+ */
+ float preferred;
+
+ /**
+ * The current span of the child view along the major axis.
+ */
+ private float majorSpan;
+
+ /**
+ * The current offset of the child view along the major axis.
+ */
+ private float majorOffset;
+
+ /**
+ * The current span of the child view along the minor axis.
+ */
+ private float minorSpan;
+
+ /**
+ * The current offset of the child view along the major axis.
+ */
+ private float minorOffset;
+
+ /**
+ * The child views maximumSpan.
+ */
+ private float maximum;
+
+ /**
+ * Creates a new <code>ChildState</code> object for the specified child
+ * view.
+ *
+ * @param view the child view for which to create the state record
+ */
+ public ChildState(View view)
+ {
+ childView = view;
+ }
+
+ /**
+ * Returns the child view for which this <code>ChildState</code> represents
+ * the layout state.
+ *
+ * @return the child view for this child state object
+ */
+ public View getChildView()
+ {
+ return childView;
+ }
+
+ /**
+ * Returns <code>true</code> if the current layout information is valid,
+ * <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if the current layout information is valid,
+ * <code>false</code> otherwise
+ */
+ public boolean isLayoutValid()
+ {
+ return minorValid && majorValid && childSizeValid;
+ }
+
+ /**
+ * Performs the layout update for the child view managed by this
+ * <code>ChildState</code>.
+ */
+ public void run()
+ {
+ Document doc = getDocument();
+ if (doc instanceof AbstractDocument)
+ {
+ AbstractDocument abstractDoc = (AbstractDocument) doc;
+ abstractDoc.readLock();
+ }
+
+ try
+ {
+
+ if (!(minorValid && majorValid && childSizeValid)
+ && childView.getParent() == AsyncBoxView.this)
+ {
+ synchronized(AsyncBoxView.this)
+ {
+ changing = this;
+ }
+ update();
+ synchronized(AsyncBoxView.this)
+ {
+ changing = null;
+ }
+ // Changing the major axis may cause the minor axis
+ // requirements to have changed, so we need to do this again.
+ update();
+ }
+ }
+ finally
+ {
+ if (doc instanceof AbstractDocument)
+ {
+ AbstractDocument abstractDoc = (AbstractDocument) doc;
+ abstractDoc.readUnlock();
+ }
+ }
+ }
+
+ /**
+ * Performs the actual update after the run methods has made its checks
+ * and locked the document.
+ */
+ private void update()
+ {
+ int majorAxis = getMajorAxis();
+ boolean minorUpdated = false;
+ synchronized (this)
+ {
+ if (! minorValid)
+ {
+ int minorAxis = getMinorAxis();
+ minimum = childView.getMinimumSpan(minorAxis);
+ preferred = childView.getPreferredSpan(minorAxis);
+ maximum = childView.getMaximumSpan(minorAxis);
+ minorValid = true;
+ minorUpdated = true;
+ }
+ }
+ if (minorUpdated)
+ minorRequirementChange(this);
+
+ boolean majorUpdated = false;
+ float delta = 0.0F;
+ synchronized (this)
+ {
+ if (! majorValid)
+ {
+ float oldSpan = majorSpan;
+ majorSpan = childView.getPreferredSpan(majorAxis);
+ delta = majorSpan - oldSpan;
+ majorValid = true;
+ majorUpdated = true;
+ }
+ }
+ if (majorUpdated)
+ {
+ majorRequirementChange(this, delta);
+ locator.childChanged(this);
+ }
+
+ synchronized (this)
+ {
+ if (! childSizeValid)
+ {
+ float w;
+ float h;
+ if (majorAxis == X_AXIS)
+ {
+ w = majorSpan;
+ h = getMinorSpan();
+ }
+ else
+ {
+ w = getMinorSpan();
+ h = majorSpan;
+ }
+ childSizeValid = true;
+ childView.setSize(w, h);
+ }
+ }
+ }
+
+ /**
+ * Returns the span of the child view along the minor layout axis.
+ *
+ * @return the span of the child view along the minor layout axis
+ */
+ public float getMinorSpan()
+ {
+ float retVal;
+ if (maximum < minorSpan)
+ retVal = maximum;
+ else
+ retVal = Math.max(minimum, minorSpan);
+ return retVal;
+ }
+
+ /**
+ * Returns the offset of the child view along the minor layout axis.
+ *
+ * @return the offset of the child view along the minor layout axis
+ */
+ public float getMinorOffset()
+ {
+ float retVal;
+ if (maximum < minorSpan)
+ {
+ float align = childView.getAlignment(getMinorAxis());
+ retVal = ((minorSpan - maximum) * align);
+ }
+ else
+ retVal = 0f;
+
+ return retVal;
+ }
+
+ /**
+ * Returns the span of the child view along the major layout axis.
+ *
+ * @return the span of the child view along the major layout axis
+ */
+
+ public float getMajorSpan()
+ {
+ return majorSpan;
+ }
+
+ /**
+ * Returns the offset of the child view along the major layout axis.
+ *
+ * @return the offset of the child view along the major layout axis
+ */
+ public float getMajorOffset()
+ {
+ return majorOffset;
+ }
+
+ /**
+ * Sets the offset of the child view along the major layout axis. This
+ * should only be called by the ChildLocator of that child view.
+ *
+ * @param offset the offset to set
+ */
+ public void setMajorOffset(float offset)
+ {
+ majorOffset = offset;
+ }
+
+ /**
+ * Mark the preferences changed for that child. This forwards to
+ * {@link AsyncBoxView#preferenceChanged}.
+ *
+ * @param width <code>true</code> if the width preference has changed
+ * @param height <code>true</code> if the height preference has changed
+ */
+ public void preferenceChanged(boolean width, boolean height)
+ {
+ if (getMajorAxis() == X_AXIS)
+ {
+ if (width)
+ majorValid = false;
+ if (height)
+ minorValid = false;
+ }
+ else
+ {
+ if (width)
+ minorValid = false;
+ if (height)
+ majorValid = false;
+ }
+ childSizeValid = false;
+ }
+ }
+
+ /**
+ * Flushes the requirements changes upwards asynchronously.
+ */
+ private class FlushTask implements Runnable
+ {
+ /**
+ * Starts the flush task. This obtains a readLock on the document
+ * and then flushes all the updates using
+ * {@link AsyncBoxView#flushRequirementChanges()} after updating the
+ * requirements.
+ */
+ public void run()
+ {
+ try
+ {
+ // Acquire a lock on the document.
+ Document doc = getDocument();
+ if (doc instanceof AbstractDocument)
+ {
+ AbstractDocument abstractDoc = (AbstractDocument) doc;
+ abstractDoc.readLock();
+ }
+
+ int n = getViewCount();
+ if (minorChanged && (n > 0))
+ {
+ LayoutQueue q = getLayoutQueue();
+ ChildState min = getChildState(0);
+ ChildState pref = getChildState(0);
+ for (int i = 1; i < n; i++)
+ {
+ ChildState cs = getChildState(i);
+ if (cs.minimum > min.minimum)
+ min = cs;
+ if (cs.preferred > pref.preferred)
+ pref = cs;
+ }
+ synchronized (AsyncBoxView.this)
+ {
+ minReq = min;
+ prefReq = pref;
+ }
+ }
+
+ flushRequirementChanges();
+ }
+ finally
+ {
+ // Release the lock on the document.
+ Document doc = getDocument();
+ if (doc instanceof AbstractDocument)
+ {
+ AbstractDocument abstractDoc = (AbstractDocument) doc;
+ abstractDoc.readUnlock();
+ }
+ }
+ }
+
+ }
+
+ /**
+ * The major layout axis.
+ */
+ private int majorAxis;
+
+ /**
+ * The top inset.
+ */
+ private float topInset;
+
+ /**
+ * The bottom inset.
+ */
+ private float bottomInset;
+
+ /**
+ * The left inset.
+ */
+ private float leftInset;
+
+ /**
+ * Indicates if the major span should be treated as beeing estimated or not.
+ */
+ private boolean estimatedMajorSpan;
+
+ /**
+ * The right inset.
+ */
+ private float rightInset;
+
+ /**
+ * The children and their layout statistics.
+ */
+ private ArrayList childStates;
+
+ /**
+ * The currently changing child state. May be null if there is no child state
+ * updating at the moment. This is package private to avoid a synthetic
+ * accessor method inside ChildState.
+ */
+ ChildState changing;
+
+ /**
+ * Represents the minimum requirements. This is used in
+ * {@link #getMinimumSpan(int)}.
+ */
+ ChildState minReq;
+
+ /**
+ * Represents the minimum requirements. This is used in
+ * {@link #getPreferredSpan(int)}.
+ */
+ ChildState prefReq;
+
+ /**
+ * Indicates that the major axis requirements have changed.
+ */
+ private boolean majorChanged;
+
+ /**
+ * Indicates that the minor axis requirements have changed. This is package
+ * private to avoid synthetic accessor method.
+ */
+ boolean minorChanged;
+
+ /**
+ * The current span along the major layout axis. This is package private to
+ * avoid synthetic accessor method.
+ */
+ float majorSpan;
+
+ /**
+ * The current span along the minor layout axis. This is package private to
+ * avoid synthetic accessor method.
+ */
+ float minorSpan;
+
+ /**
+ * This tasked is placed on the layout queue to flush updates up to the
+ * parent view.
+ */
+ private Runnable flushTask;
+
+ /**
+ * The child locator for this view.
+ */
+ protected ChildLocator locator;
+
+ /**
+ * Creates a new <code>AsyncBoxView</code> that represents the specified
+ * element and layouts its children along the specified axis.
+ *
+ * @param elem the element
+ * @param axis the layout axis
+ */
+ public AsyncBoxView(Element elem, int axis)
+ {
+ super(elem);
+ majorAxis = axis;
+ childStates = new ArrayList();
+ flushTask = new FlushTask();
+ locator = new ChildLocator();
+ minorSpan = Short.MAX_VALUE;
+ }
+
+ /**
+ * Returns the major layout axis.
+ *
+ * @return the major layout axis
+ */
+ public int getMajorAxis()
+ {
+ return majorAxis;
+ }
+
+ /**
+ * Returns the minor layout axis, that is the axis orthogonal to the major
+ * layout axis.
+ *
+ * @return the minor layout axis
+ */
+ public int getMinorAxis()
+ {
+ return majorAxis == X_AXIS ? Y_AXIS : X_AXIS;
+ }
+
+ /**
+ * Returns the view at the specified <code>index</code>.
+ *
+ * @param index the index of the requested child view
+ *
+ * @return the view at the specified <code>index</code>
+ */
+ public View getView(int index)
+ {
+ View view = null;
+ synchronized(childStates)
+ {
+ if ((index >= 0) && (index < childStates.size()))
+ {
+ ChildState cs = (ChildState) childStates.get(index);
+ view = cs.getChildView();
+ }
+ }
+ return view;
+ }
+
+ /**
+ * Returns the number of child views.
+ *
+ * @return the number of child views
+ */
+ public int getViewCount()
+ {
+ synchronized(childStates)
+ {
+ return childStates.size();
+ }
+ }
+
+ /**
+ * Returns the view index of the child view that represents the specified
+ * model position.
+ *
+ * @param pos the model position for which we search the view index
+ * @param bias the bias
+ *
+ * @return the view index of the child view that represents the specified
+ * model position
+ */
+ public int getViewIndex(int pos, Position.Bias bias)
+ {
+ int retVal = -1;
+
+ if (bias == Position.Bias.Backward)
+ pos = Math.max(0, pos - 1);
+
+ // TODO: A possible optimization would be to implement a binary search
+ // here.
+ int numChildren = childStates.size();
+ if (numChildren > 0)
+ {
+ for (int i = 0; i < numChildren; ++i)
+ {
+ View child = ((ChildState) childStates.get(i)).getChildView();
+ if (child.getStartOffset() <= pos && child.getEndOffset() > pos)
+ {
+ retVal = i;
+ break;
+ }
+ }
+ }
+ return retVal;
+ }
+
+ /**
+ * Returns the top inset.
+ *
+ * @return the top inset
+ */
+ public float getTopInset()
+ {
+ return topInset;
+ }
+
+ /**
+ * Sets the top inset.
+ *
+ * @param top the top inset
+ */
+ public void setTopInset(float top)
+ {
+ topInset = top;
+ }
+
+ /**
+ * Returns the bottom inset.
+ *
+ * @return the bottom inset
+ */
+ public float getBottomInset()
+ {
+ return bottomInset;
+ }
+
+ /**
+ * Sets the bottom inset.
+ *
+ * @param bottom the bottom inset
+ */
+ public void setBottomInset(float bottom)
+ {
+ bottomInset = bottom;
+ }
+
+ /**
+ * Returns the left inset.
+ *
+ * @return the left inset
+ */
+ public float getLeftInset()
+ {
+ return leftInset;
+ }
+
+ /**
+ * Sets the left inset.
+ *
+ * @param left the left inset
+ */
+ public void setLeftInset(float left)
+ {
+ leftInset = left;
+ }
+
+ /**
+ * Returns the right inset.
+ *
+ * @return the right inset
+ */
+ public float getRightInset()
+ {
+ return rightInset;
+ }
+
+ /**
+ * Sets the right inset.
+ *
+ * @param right the right inset
+ */
+ public void setRightInset(float right)
+ {
+ rightInset = right;
+ }
+
+ /**
+ * Loads the child views of this view. This is triggered by
+ * {@link #setParent(View)}.
+ *
+ * @param f the view factory to build child views with
+ */
+ protected void loadChildren(ViewFactory f)
+ {
+ Element e = getElement();
+ int n = e.getElementCount();
+ if (n > 0)
+ {
+ View[] added = new View[n];
+ for (int i = 0; i < n; i++)
+ {
+ added[i] = f.create(e.getElement(i));
+ }
+ replace(0, 0, added);
+ }
+ }
+
+ /**
+ * Returns the span along an axis that is taken up by the insets.
+ *
+ * @param axis the axis
+ *
+ * @return the span along an axis that is taken up by the insets
+ *
+ * @since 1.4
+ */
+ protected float getInsetSpan(int axis)
+ {
+ float span;
+ if (axis == X_AXIS)
+ span = leftInset + rightInset;
+ else
+ span = topInset + bottomInset;
+ return span;
+ }
+
+ /**
+ * Sets the <code>estimatedMajorSpan</code> property that determines if
+ * the major span should be treated as beeing estimated.
+ *
+ * @param estimated if the major span should be treated as estimated or not
+ *
+ * @since 1.4
+ */
+ protected void setEstimatedMajorSpan(boolean estimated)
+ {
+ estimatedMajorSpan = estimated;
+ }
+
+ /**
+ * Determines whether the major span should be treated as estimated or as
+ * beeing accurate.
+ *
+ * @return <code>true</code> if the major span should be treated as
+ * estimated, <code>false</code> if the major span should be treated
+ * as accurate
+ *
+ * @since 1.4
+ */
+ protected boolean getEstimatedMajorSpan()
+ {
+ return estimatedMajorSpan;
+ }
+
+ /**
+ * Receives notification from the child states that the requirements along
+ * the minor axis have changed.
+ *
+ * @param cs the child state from which this notification is messaged
+ */
+ protected synchronized void minorRequirementChange(ChildState cs)
+ {
+ minorChanged = true;
+ }
+
+ /**
+ * Receives notification from the child states that the requirements along
+ * the major axis have changed.
+ *
+ * @param cs the child state from which this notification is messaged
+ */
+ protected void majorRequirementChange(ChildState cs, float delta)
+ {
+ if (! estimatedMajorSpan)
+ majorSpan += delta;
+ majorChanged = true;
+ }
+
+ /**
+ * Sets the parent for this view. This calls loadChildren if
+ * <code>parent</code> is not <code>null</code> and there have not been any
+ * child views initializes.
+ *
+ * @param parent the new parent view; <code>null</code> if this view is
+ * removed from the view hierarchy
+ *
+ * @see View#setParent(View)
+ */
+ public void setParent(View parent)
+ {
+ super.setParent(parent);
+ if ((parent != null) && (getViewCount() == 0))
+ {
+ ViewFactory f = getViewFactory();
+ loadChildren(f);
+ }
+ }
+
+ /**
+ * Sets the size of this view. This is ususally called before {@link #paint}
+ * is called to make sure the view has a valid layout.
+ *
+ * This implementation queues layout requests for every child view if the
+ * minor axis span has changed. (The major axis span is requested to never
+ * change for this view).
+ *
+ * @param width the width of the view
+ * @param height the height of the view
+ */
+ public void setSize(float width, float height)
+ {
+ float targetSpan;
+ if (majorAxis == X_AXIS)
+ targetSpan = height - getTopInset() - getBottomInset();
+ else
+ targetSpan = width - getLeftInset() - getRightInset();
+
+ if (targetSpan != minorSpan)
+ {
+ minorSpan = targetSpan;
+
+ int n = getViewCount();
+ LayoutQueue q = getLayoutQueue();
+ for (int i = 0; i < n; i++)
+ {
+ ChildState cs = getChildState(i);
+ cs.childSizeValid = false;
+ q.addTask(cs);
+ }
+ q.addTask(flushTask);
+ }
+ }
+
+ /**
+ * Replaces child views with new child views.
+ *
+ * This creates ChildState objects for all the new views and adds layout
+ * requests for them to the layout queue.
+ *
+ * @param offset the offset at which to remove/insert
+ * @param length the number of child views to remove
+ * @param views the new child views to insert
+ */
+ public void replace(int offset, int length, View[] views)
+ {
+ synchronized(childStates)
+ {
+ LayoutQueue q = getLayoutQueue();
+ for (int i = 0; i < length; i++)
+ childStates.remove(offset);
+
+ for (int i = views.length - 1; i >= 0; i--)
+ childStates.add(offset, createChildState(views[i]));
+
+ // We need to go through the new child states _after_ they have been
+ // added to the childStates list, otherwise the layout tasks may find
+ // an incomplete child list. That means we have to loop through
+ // them again, but what else can we do?
+ if (views.length != 0)
+ {
+ for (int i = 0; i < views.length; i++)
+ {
+ ChildState cs = (ChildState) childStates.get(i + offset);
+ cs.getChildView().setParent(this);
+ q.addTask(cs);
+ }
+ q.addTask(flushTask);
+ }
+ }
+ }
+
+ /**
+ * Paints the view. This requests the {@link ChildLocator} to paint the views
+ * after setting the allocation on it.
+ *
+ * @param g the graphics context to use
+ * @param s the allocation for this view
+ */
+ public void paint(Graphics g, Shape s)
+ {
+ synchronized (locator)
+ {
+ locator.setAllocation(s);
+ locator.paintChildren(g);
+ }
+ }
+
+ /**
+ * Returns the preferred span of this view along the specified layout axis.
+ *
+ * @return the preferred span of this view along the specified layout axis
+ */
+ public float getPreferredSpan(int axis)
+ {
+ float retVal;
+ if (majorAxis == axis)
+ retVal = majorSpan;
+
+ else if (prefReq != null)
+ {
+ View child = prefReq.getChildView();
+ retVal = child.getPreferredSpan(axis);
+ }
+
+ // If we have no layout information yet, then return insets + 30 as
+ // an estimation.
+ else
+ {
+ if (axis == X_AXIS)
+ retVal = getLeftInset() + getRightInset() + 30;
+ else
+ retVal = getTopInset() + getBottomInset() + 30;
+ }
+ return retVal;
+ }
+
+ /**
+ * Maps a model location to view coordinates.
+ *
+ * @param pos the model location
+ * @param a the current allocation of this view
+ * @param b the bias
+ *
+ * @return the view allocation for the specified model location
+ */
+ public Shape modelToView(int pos, Shape a, Bias b)
+ throws BadLocationException
+ {
+ int index = getViewIndexAtPosition(pos, b);
+ Shape ca = locator.getChildAllocation(index, a);
+
+ ChildState cs = getChildState(index);
+ synchronized (cs)
+ {
+ View cv = cs.getChildView();
+ Shape v = cv.modelToView(pos, ca, b);
+ return v;
+ }
+ }
+
+ /**
+ * Maps view coordinates to a model location.
+ *
+ * @param x the x coordinate (relative to <code>a</code>)
+ * @param y the y coordinate (relative to <code>a</code>)
+ * @param b holds the bias of the model location on method exit
+ *
+ * @return the model location for the specified view location
+ */
+ public int viewToModel(float x, float y, Shape a, Bias[] b)
+ {
+ int pos;
+ int index;
+ Shape ca;
+
+ synchronized (locator)
+ {
+ index = locator.getViewIndexAtPoint(x, y, a);
+ ca = locator.getChildAllocation(index, a);
+ }
+
+ ChildState cs = getChildState(index);
+ synchronized (cs)
+ {
+ View v = cs.getChildView();
+ pos = v.viewToModel(x, y, ca, b);
+ }
+ return pos;
+ }
+
+ /**
+ * Returns the child allocation for the child view with the specified
+ * <code>index</code>.
+ *
+ * @param index the index of the child view
+ * @param a the current allocation of this view
+ *
+ * @return the allocation of the child view
+ */
+ public Shape getChildAllocation(int index, Shape a)
+ {
+ Shape ca = locator.getChildAllocation(index, a);
+ return ca;
+ }
+
+ /**
+ * Returns the maximum span of this view along the specified axis.
+ * This is implemented to return the <code>preferredSpan</code> for the
+ * major axis (that means the box can't be resized along the major axis) and
+ * {@link Short#MAX_VALUE} for the minor axis.
+ *
+ * @param axis the axis
+ *
+ * @return the maximum span of this view along the specified axis
+ */
+ public float getMaximumSpan(int axis)
+ {
+ float max;
+ if (axis == majorAxis)
+ max = getPreferredSpan(axis);
+ else
+ max = Short.MAX_VALUE;
+ return max;
+ }
+
+ /**
+ * Returns the minimum span along the specified axis.
+ */
+ public float getMinimumSpan(int axis)
+ {
+ float min;
+ if (axis == majorAxis)
+ min = getPreferredSpan(axis);
+ else
+ {
+ if (minReq != null)
+ {
+ View child = minReq.getChildView();
+ min = child.getMinimumSpan(axis);
+ }
+ else
+ {
+ // No layout information yet. Return insets + 5 as some kind of
+ // estimation.
+ if (axis == X_AXIS)
+ min = getLeftInset() + getRightInset() + 5;
+ else
+ min = getTopInset() + getBottomInset() + 5;
+ }
+ }
+ return min;
+ }
+
+ /**
+ * Receives notification that one of the child views has changed its
+ * layout preferences along one or both axis.
+ *
+ * This queues a layout request for that child view if necessary.
+ *
+ * @param view the view that has changed its preferences
+ * @param width <code>true</code> if the width preference has changed
+ * @param height <code>true</code> if the height preference has changed
+ */
+ public synchronized void preferenceChanged(View view, boolean width,
+ boolean height)
+ {
+ if (view == null)
+ getParent().preferenceChanged(this, width, height);
+ else
+ {
+ if (changing != null)
+ {
+ View cv = changing.getChildView();
+ if (cv == view)
+ {
+ changing.preferenceChanged(width, height);
+ return;
+ }
+ }
+ int index = getViewIndexAtPosition(view.getStartOffset(),
+ Position.Bias.Forward);
+ ChildState cs = getChildState(index);
+ cs.preferenceChanged(width, height);
+ LayoutQueue q = getLayoutQueue();
+ q.addTask(cs);
+ q.addTask(flushTask);
+ }
+ }
+
+ /**
+ * Updates the layout for this view. This is implemented to trigger
+ * {@link ChildLocator#childChanged} for the changed view, if there is
+ * any.
+ *
+ * @param ec the element change, may be <code>null</code> if there were
+ * no changes to the element of this view
+ * @param e the document event
+ * @param a the current allocation of this view
+ */
+ protected void updateLayout(DocumentEvent.ElementChange ec,
+ DocumentEvent e, Shape a)
+ {
+ if (ec != null)
+ {
+ int index = Math.max(ec.getIndex() - 1, 0);
+ ChildState cs = getChildState(index);
+ locator.childChanged(cs);
+ }
+ }
+
+
+ /**
+ * Returns the <code>ChildState</code> object associated with the child view
+ * at the specified <code>index</code>.
+ *
+ * @param index the index of the child view for which to query the state
+ *
+ * @return the child state for the specified child view
+ */
+ protected ChildState getChildState(int index) {
+ synchronized (childStates)
+ {
+ return (ChildState) childStates.get(index);
+ }
+ }
+
+ /**
+ * Returns the <code>LayoutQueue</code> used for layouting the box view.
+ * This simply returns {@link LayoutQueue#getDefaultQueue()}.
+ *
+ * @return the <code>LayoutQueue</code> used for layouting the box view
+ */
+ protected LayoutQueue getLayoutQueue()
+ {
+ return LayoutQueue.getDefaultQueue();
+ }
+
+ /**
+ * Returns the child view index of the view that represents the specified
+ * position in the document model.
+ *
+ * @param pos the position in the model
+ * @param b the bias
+ *
+ * @return the child view index of the view that represents the specified
+ * position in the document model
+ */
+ protected synchronized int getViewIndexAtPosition(int pos, Position.Bias b)
+ {
+ if (b == Position.Bias.Backward)
+ pos = Math.max(0, pos - 1);
+ Element elem = getElement();
+ return elem.getElementIndex(pos);
+ }
+
+ /**
+ * Creates a <code>ChildState</code> object for the specified view.
+ *
+ * @param v the view for which to create a child state object
+ *
+ * @return the created child state
+ */
+ protected ChildState createChildState(View v)
+ {
+ return new ChildState(v);
+ }
+
+ /**
+ * Flushes the requirements changes upwards to the parent view. This is
+ * called from the layout thread.
+ */
+ protected synchronized void flushRequirementChanges()
+ {
+ if (majorChanged || minorChanged)
+ {
+ View p = getParent();
+ if (p != null)
+ {
+ boolean horizontal;
+ boolean vertical;
+ if (majorAxis == X_AXIS)
+ {
+ horizontal = majorChanged;
+ vertical = minorChanged;
+ }
+ else
+ {
+ vertical = majorChanged;
+ horizontal = minorChanged;
+ }
+
+ p.preferenceChanged(this, horizontal, vertical);
+ majorChanged = false;
+ minorChanged = false;
+
+ Component c = getContainer();
+ if (c != null)
+ c.repaint();
+ }
+ }
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AttributeSet.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AttributeSet.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AttributeSet.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/AttributeSet.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,195 @@
+/* AttributeSet.java --
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.util.Enumeration;
+
+/**
+ * A set of attributes. An attribute has a key and a value. They typically
+ * describe features of a piece of text that make up its graphical
+ * representation.
+ *
+ * An <code>AttributeSet</code> may have a resolving parent,
+ * that is another <code>AttributeSet</code> that is searched for attribute
+ * keys that are not stored locally in this <code>AttributeSet</code>.
+ *
+ * @author original author unknown
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public interface AttributeSet
+{
+ /**
+ * Used as keys to identify character-run attributes.
+ */
+ static interface CharacterAttribute
+ {
+ // This interface is a marker interface and has no methods.
+ }
+
+ /**
+ * Used as keys to identify color attributes.
+ */
+ static interface ColorAttribute
+ {
+ // This interface is a marker interface and has no methods.
+ }
+
+ /**
+ * Used as keys to identify font attributes.
+ */
+ static interface FontAttribute
+ {
+ // This interface is a marker interface and has no methods.
+ }
+
+ /**
+ * Used as keys to identify paragraph level attributes.
+ */
+ static interface ParagraphAttribute
+ {
+ // This interface is a marker interface and has no methods.
+ }
+
+ /**
+ * Key of the attribute that is used to describe the name of an
+ * <code>AttributeSet</code>.
+ */
+ Object NameAttribute = StyleConstants.NameAttribute;
+
+ /**
+ * Key of the attribute that is used to identify the resolving parent of
+ * an <code>AttributeSet</code>.
+ */
+ Object ResolveAttribute = StyleConstants.ResolveAttribute;
+
+ /**
+ * Returns <code>true</code> if this <code>AttributeSet</code> contains
+ * an attribute with the specified <code>name</code> and <code>value</code>,
+ * <code>false</code> otherwise.
+ *
+ * @param name the name of the requested attribute
+ * @param value the value of the requested attribute
+ *
+ * @return <code>true</code> if this <code>AttributeSet</code> contains
+ * an attribute with the specified <code>name</code> and
+ * <code>value</code>, <code>false</code> otherwise
+ */
+ boolean containsAttribute(Object name, Object value);
+
+ /**
+ * Returns <code>true</code> of this <code>AttributeSet</code> contains all
+ * of the specified <code>attributes</code>.
+ *
+ * @param attributes the requested attributes
+ *
+ * @return <code>true</code> of this <code>AttributeSet</code> contains all
+ * of the specified <code>attributes</code>
+ */
+ boolean containsAttributes(AttributeSet attributes);
+
+ /**
+ * Creates and returns a copy of this <code>AttributeSet</code>.
+ *
+ * @return a copy of this <code>AttributeSet</code>
+ */
+ AttributeSet copyAttributes();
+
+ /**
+ * Returns the attribute with the specified <code>key</code> or
+ * <code>null</code> if no such attribute is defined in this
+ * <code>AttributeSet</code> and its resolving parents.
+ *
+ * @param key the key of the attribute that is looked up
+ *
+ * @return the attribute with the specified <code>key</code> or
+ * <code>null</code> if no such attribute is defined in this
+ * <code>AttributeSet</code> and its resolving parents
+ */
+ Object getAttribute(Object key);
+
+ /**
+ * Returns the number of attributes that are stored locally in this
+ * <code>AttributeSet</code>.
+ *
+ * @return the number of attributes that are stored locally in this
+ * <code>AttributeSet</code>
+ */
+ int getAttributeCount();
+
+ /**
+ * Returns the names of the attributes that are stored in this
+ * <code>AttributeSet</code>.
+ *
+ * @return the names of the attributes that are stored in this
+ * <code>AttributeSet</code>
+ */
+ Enumeration getAttributeNames();
+
+ /**
+ * Returns the resolving parent of this <code>AttributeSet</code>.
+ * If a key is not stored locally, then a {@link #getAttribute(Object)}
+ * request is resolved up in the resolving parent of this
+ * <code>AttributeSet</code>.
+ *
+ * @return the resolving parent of this <code>AttributeSet</code>
+ */
+ AttributeSet getResolveParent();
+
+ /**
+ * Returns <code>true</code> if an attribute with the specified name is
+ * defined locally in this <code>AttributeSet</code>, without resolving
+ * through the resolving parents.
+ *
+ * @return <code>true</code> if an attribute with the specified name is
+ * defined locally in this <code>AttributeSet</code>
+ */
+ boolean isDefined(Object attrName);
+
+ /**
+ * Returns <code>true</code> if all of the attributes in <code>attr</code>
+ * are equal to the attributes in this <code>AttributeSet</code>,
+ * <code>false</code> otherwise.
+ *
+ * @param attr the attributes to be compared to <code>this</code>
+ *
+ * @return <code>true</code> if all of the attributes in <code>attr</code>
+ * are equal to the attributes in this <code>AttributeSet</code>,
+ * <code>false</code> otherwise
+ */
+ boolean isEqual(AttributeSet attr);
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/BadLocationException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/BadLocationException.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/BadLocationException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/BadLocationException.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,78 @@
+/* BadLocationException.java --
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+/**
+ * Indicates that an invalid location within a <code>Document</code> has been
+ * accessed.
+ *
+ * @author original author unknown
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class BadLocationException extends Exception
+{
+ /** The serial version UID for BadLocationException. */
+ private static final long serialVersionUID = -7712259886815656766L;
+
+ /**
+ * The invalid location.
+ */
+ int offset;
+
+ /**
+ * Constructs a <code>BadLocationException</code>
+ *
+ * @param str a string indicating what was wrong with the arguments
+ * @param offset offset within the document that was requested >= 0
+ */
+ public BadLocationException(String str, int offset)
+ {
+ super(str);
+ this.offset = offset;
+ }
+
+ /**
+ * Returns the offset into the document that was not legal.
+ *
+ * @return the offset into the document that was not legal
+ */
+ public int offsetRequested()
+ {
+ return offset;
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/BoxView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/BoxView.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/BoxView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/BoxView.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,1038 @@
+/* BoxView.java -- An composite view
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+import javax.swing.SizeRequirements;
+import javax.swing.event.DocumentEvent;
+
+/**
+ * An implementation of {@link CompositeView} that arranges its children in
+ * a box along one axis. This is comparable to how the <code>BoxLayout</code>
+ * works, but for <code>View</code> children.
+ *
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class BoxView
+ extends CompositeView
+{
+
+ /**
+ * The axis along which this <code>BoxView</code> is laid out.
+ */
+ private int myAxis;
+
+ /**
+ * Indicates if the layout is valid along X_AXIS or Y_AXIS.
+ */
+ private boolean[] layoutValid = new boolean[2];
+
+ /**
+ * Indicates if the requirements for an axis are valid.
+ */
+ private boolean[] requirementsValid = new boolean[2];
+
+ /**
+ * The spans along the X_AXIS and Y_AXIS.
+ */
+ private int[][] spans = new int[2][];
+
+ /**
+ * The offsets of the children along the X_AXIS and Y_AXIS.
+ */
+ private int[][] offsets = new int[2][];
+
+ /**
+ * The size requirements along the X_AXIS and Y_AXIS.
+ */
+ private SizeRequirements[] requirements = new SizeRequirements[2];
+
+ /**
+ * The current span along X_AXIS or Y_AXIS.
+ */
+ private int[] span = new int[2];
+
+ /**
+ * The SizeRequirements of the child views along the X_AXIS and Y_AXIS.
+ */
+ private SizeRequirements[][] childReqs = new SizeRequirements[2][];
+
+ /**
+ * Creates a new <code>BoxView</code> for the given
+ * <code>Element</code> and axis. Valid values for the axis are
+ * {@link View#X_AXIS} and {@link View#Y_AXIS}.
+ *
+ * @param element the element that is rendered by this BoxView
+ * @param axis the axis along which the box is laid out
+ */
+ public BoxView(Element element, int axis)
+ {
+ super(element);
+ myAxis = axis;
+ layoutValid[0] = false;
+ layoutValid[1] = false;
+ span[0] = 0;
+ span[1] = 0;
+ requirements[0] = new SizeRequirements();
+ requirements[1] = new SizeRequirements();
+
+ // Initialize the cache arrays.
+ spans[0] = new int[0];
+ spans[1] = new int[0];
+ offsets[0] = new int[0];
+ offsets[1] = new int[0];
+ }
+
+ /**
+ * Returns the axis along which this <code>BoxView</code> is laid out.
+ *
+ * @return the axis along which this <code>BoxView</code> is laid out
+ *
+ * @since 1.3
+ */
+ public int getAxis()
+ {
+ return myAxis;
+ }
+
+ /**
+ * Sets the axis along which this <code>BoxView</code> is laid out.
+ *
+ * Valid values for the axis are {@link View#X_AXIS} and
+ * {@link View#Y_AXIS}.
+ *
+ * @param axis the axis along which this <code>BoxView</code> is laid out
+ *
+ * @since 1.3
+ */
+ public void setAxis(int axis)
+ {
+ myAxis = axis;
+ }
+
+ /**
+ * Marks the layout along the specified axis as invalid. This is triggered
+ * automatically when any of the child view changes its preferences
+ * via {@link #preferenceChanged(View, boolean, boolean)}.
+ *
+ * The layout will be updated the next time when
+ * {@link #setSize(float, float)} is called, typically from within the
+ * {@link #paint(Graphics, Shape)} method.
+ *
+ * Valid values for the axis are {@link View#X_AXIS} and
+ * {@link View#Y_AXIS}.
+ *
+ * @param axis an <code>int</code> value
+ *
+ * @since 1.3
+ */
+ public void layoutChanged(int axis)
+ {
+ if (axis != X_AXIS && axis != Y_AXIS)
+ throw new IllegalArgumentException("Invalid axis parameter.");
+ layoutValid[axis] = false;
+ }
+
+ /**
+ * Returns <code>true</code> if the layout along the specified
+ * <code>axis</code> is valid, <code>false</code> otherwise.
+ *
+ * Valid values for the axis are {@link View#X_AXIS} and
+ * {@link View#Y_AXIS}.
+ *
+ * @param axis the axis
+ *
+ * @return <code>true</code> if the layout along the specified
+ * <code>axis</code> is valid, <code>false</code> otherwise
+ *
+ * @since 1.4
+ */
+ protected boolean isLayoutValid(int axis)
+ {
+ if (axis != X_AXIS && axis != Y_AXIS)
+ throw new IllegalArgumentException("Invalid axis parameter.");
+ return layoutValid[axis];
+ }
+
+ /**
+ * Paints the child <code>View</code> at the specified <code>index</code>.
+ * This method modifies the actual values in <code>alloc</code> so make
+ * sure you have a copy of the original values if you need them.
+ *
+ * @param g the <code>Graphics</code> context to paint to
+ * @param alloc the allocated region for the child to paint into
+ * @param index the index of the child to be painted
+ *
+ * @see #childAllocation(int, Rectangle)
+ */
+ protected void paintChild(Graphics g, Rectangle alloc, int index)
+ {
+ View child = getView(index);
+ child.paint(g, alloc);
+ }
+
+ /**
+ * Replaces child views by some other child views. If there are no views to
+ * remove (<code>length == 0</code>), the result is a simple insert, if
+ * there are no children to add (<code>view == null</code>) the result
+ * is a simple removal.
+ *
+ * In addition this invalidates the layout and resizes the internal cache
+ * for the child allocations. The old children's cached allocations can
+ * still be accessed (although they are not guaranteed to be valid), and
+ * the new children will have an initial offset and span of 0.
+ *
+ * @param offset the start offset from where to remove children
+ * @param length the number of children to remove
+ * @param views the views that replace the removed children
+ */
+ public void replace(int offset, int length, View[] views)
+ {
+ int numViews = 0;
+ if (views != null)
+ numViews = views.length;
+
+ // Resize and copy data for cache arrays.
+ // The spansX cache.
+ int oldSize = getViewCount();
+
+ int[] newSpansX = new int[oldSize - length + numViews];
+ System.arraycopy(spans[X_AXIS], 0, newSpansX, 0, offset);
+ System.arraycopy(spans[X_AXIS], offset + length, newSpansX,
+ offset + numViews,
+ oldSize - (offset + length));
+ spans[X_AXIS] = newSpansX;
+
+ // The spansY cache.
+ int[] newSpansY = new int[oldSize - length + numViews];
+ System.arraycopy(spans[Y_AXIS], 0, newSpansY, 0, offset);
+ System.arraycopy(spans[Y_AXIS], offset + length, newSpansY,
+ offset + numViews,
+ oldSize - (offset + length));
+ spans[Y_AXIS] = newSpansY;
+
+ // The offsetsX cache.
+ int[] newOffsetsX = new int[oldSize - length + numViews];
+ System.arraycopy(offsets[X_AXIS], 0, newOffsetsX, 0, offset);
+ System.arraycopy(offsets[X_AXIS], offset + length, newOffsetsX,
+ offset + numViews,
+ oldSize - (offset + length));
+ offsets[X_AXIS] = newOffsetsX;
+
+ // The offsetsY cache.
+ int[] newOffsetsY = new int[oldSize - length + numViews];
+ System.arraycopy(offsets[Y_AXIS], 0, newOffsetsY, 0, offset);
+ System.arraycopy(offsets[Y_AXIS], offset + length, newOffsetsY,
+ offset + numViews,
+ oldSize - (offset + length));
+ offsets[Y_AXIS] = newOffsetsY;
+
+ // Actually perform the replace.
+ super.replace(offset, length, views);
+
+ // Invalidate layout information.
+ layoutValid[X_AXIS] = false;
+ requirementsValid[X_AXIS] = false;
+ layoutValid[Y_AXIS] = false;
+ requirementsValid[Y_AXIS] = false;
+ }
+
+ /**
+ * Renders the <code>Element</code> that is associated with this
+ * <code>View</code>.
+ *
+ * @param g the <code>Graphics</code> context to render to
+ * @param a the allocated region for the <code>Element</code>
+ */
+ public void paint(Graphics g, Shape a)
+ {
+ Rectangle alloc;
+ if (a instanceof Rectangle)
+ alloc = (Rectangle) a;
+ else
+ alloc = a.getBounds();
+
+ int x = alloc.x + getLeftInset();
+ int y = alloc.y + getTopInset();
+
+ Rectangle clip = g.getClipBounds();
+ Rectangle tmp = new Rectangle();
+ int count = getViewCount();
+ for (int i = 0; i < count; ++i)
+ {
+ tmp.x = x + getOffset(X_AXIS, i);
+ tmp.y = y + getOffset(Y_AXIS, i);
+ tmp.width = getSpan(X_AXIS, i);
+ tmp.height = getSpan(Y_AXIS, i);
+ if (tmp.intersects(clip))
+ paintChild(g, tmp, i);
+ }
+ }
+
+ /**
+ * Returns the preferred span of the content managed by this
+ * <code>View</code> along the specified <code>axis</code>.
+ *
+ * @param axis the axis
+ *
+ * @return the preferred span of this <code>View</code>.
+ */
+ public float getPreferredSpan(int axis)
+ {
+ updateRequirements(axis);
+ // Add margin.
+ float margin;
+ if (axis == X_AXIS)
+ margin = getLeftInset() + getRightInset();
+ else
+ margin = getTopInset() + getBottomInset();
+ return requirements[axis].preferred + margin;
+ }
+
+ /**
+ * Returns the maximum span of this view along the specified axis.
+ * This returns <code>Integer.MAX_VALUE</code> for the minor axis
+ * and the preferred span for the major axis.
+ *
+ * @param axis the axis
+ *
+ * @return the maximum span of this view along the specified axis
+ */
+ public float getMaximumSpan(int axis)
+ {
+ updateRequirements(axis);
+ // Add margin.
+ float margin;
+ if (axis == X_AXIS)
+ margin = getLeftInset() + getRightInset();
+ else
+ margin = getTopInset() + getBottomInset();
+ return requirements[axis].maximum + margin;
+ }
+
+ /**
+ * Returns the minimum span of this view along the specified axis.
+ * This calculates the minimum span using
+ * {@link #calculateMajorAxisRequirements} or
+ * {@link #calculateMinorAxisRequirements} (depending on the axis) and
+ * returns the resulting minimum span.
+ *
+ * @param axis the axis
+ *
+ * @return the minimum span of this view along the specified axis
+ */
+ public float getMinimumSpan(int axis)
+ {
+ updateRequirements(axis);
+ // Add margin.
+ float margin;
+ if (axis == X_AXIS)
+ margin = getLeftInset() + getRightInset();
+ else
+ margin = getTopInset() + getBottomInset();
+ return requirements[axis].minimum + margin;
+ }
+
+ /**
+ * This method is obsolete and no longer in use. It is replaced by
+ * {@link #calculateMajorAxisRequirements(int, SizeRequirements)} and
+ * {@link #calculateMinorAxisRequirements(int, SizeRequirements)}.
+ *
+ * @param axis the axis that is examined
+ * @param sr the <code>SizeRequirements</code> object to hold the result,
+ * if <code>null</code>, a new one is created
+ *
+ * @return the size requirements for this <code>BoxView</code> along
+ * the specified axis
+ */
+ protected SizeRequirements baselineRequirements(int axis,
+ SizeRequirements sr)
+ {
+ updateChildRequirements(axis);
+
+ SizeRequirements res = sr;
+ if (res == null)
+ res = new SizeRequirements();
+
+ float minLeft = 0;
+ float minRight = 0;
+ float prefLeft = 0;
+ float prefRight = 0;
+ float maxLeft = 0;
+ float maxRight = 0;
+ for (int i = 0; i < childReqs[axis].length; i++)
+ {
+ float myMinLeft = childReqs[axis][i].minimum * childReqs[axis][i].alignment;
+ float myMinRight = childReqs[axis][i].minimum - myMinLeft;
+ minLeft = Math.max(myMinLeft, minLeft);
+ minRight = Math.max(myMinRight, minRight);
+ float myPrefLeft = childReqs[axis][i].preferred * childReqs[axis][i].alignment;
+ float myPrefRight = childReqs[axis][i].preferred - myPrefLeft;
+ prefLeft = Math.max(myPrefLeft, prefLeft);
+ prefRight = Math.max(myPrefRight, prefRight);
+ float myMaxLeft = childReqs[axis][i].maximum * childReqs[axis][i].alignment;
+ float myMaxRight = childReqs[axis][i].maximum - myMaxLeft;
+ maxLeft = Math.max(myMaxLeft, maxLeft);
+ maxRight = Math.max(myMaxRight, maxRight);
+ }
+ int minSize = (int) (minLeft + minRight);
+ int prefSize = (int) (prefLeft + prefRight);
+ int maxSize = (int) (maxLeft + maxRight);
+ float align = prefLeft / (prefRight + prefLeft);
+ if (Float.isNaN(align))
+ align = 0;
+
+ res.alignment = align;
+ res.maximum = maxSize;
+ res.preferred = prefSize;
+ res.minimum = minSize;
+ return res;
+ }
+
+ /**
+ * Calculates the layout of the children of this <code>BoxView</code> along
+ * the specified axis.
+ *
+ * @param span the target span
+ * @param axis the axis that is examined
+ * @param offsets an empty array, filled with the offsets of the children
+ * @param spans an empty array, filled with the spans of the children
+ */
+ protected void baselineLayout(int span, int axis, int[] offsets,
+ int[] spans)
+ {
+ updateChildRequirements(axis);
+ updateRequirements(axis);
+
+ // Calculate the spans and offsets using the SizeRequirements uility
+ // methods.
+ SizeRequirements.calculateAlignedPositions(span, requirements[axis],
+ childReqs[axis], offsets, spans);
+ }
+
+ /**
+ * Calculates the size requirements of this <code>BoxView</code> along
+ * its major axis, that is the axis specified in the constructor.
+ *
+ * @param axis the axis that is examined
+ * @param sr the <code>SizeRequirements</code> object to hold the result,
+ * if <code>null</code>, a new one is created
+ *
+ * @return the size requirements for this <code>BoxView</code> along
+ * the specified axis
+ */
+ protected SizeRequirements calculateMajorAxisRequirements(int axis,
+ SizeRequirements sr)
+ {
+ SizeRequirements res = sr;
+ if (res == null)
+ res = new SizeRequirements();
+
+ float min = 0;
+ float pref = 0;
+ float max = 0;
+
+ int n = getViewCount();
+ for (int i = 0; i < n; i++)
+ {
+ View child = getView(i);
+ min += child.getMinimumSpan(axis);
+ pref = child.getPreferredSpan(axis);
+ max = child.getMaximumSpan(axis);
+ }
+
+ res.minimum = (int) min;
+ res.preferred = (int) pref;
+ res.maximum = (int) max;
+ res.alignment = 0.5F;
+
+ return res;
+ }
+
+ /**
+ * Calculates the size requirements of this <code>BoxView</code> along
+ * its minor axis, that is the axis opposite to the axis specified in the
+ * constructor.
+ *
+ * @param axis the axis that is examined
+ * @param sr the <code>SizeRequirements</code> object to hold the result,
+ * if <code>null</code>, a new one is created
+ *
+ * @return the size requirements for this <code>BoxView</code> along
+ * the specified axis
+ */
+ protected SizeRequirements calculateMinorAxisRequirements(int axis,
+ SizeRequirements sr)
+ {
+ SizeRequirements res = sr;
+ if (res == null)
+ res = new SizeRequirements();
+
+ res.minimum = 0;
+ res.preferred = 0;
+ res.maximum = 0;
+ res.alignment = 0.5F;
+ int n = getViewCount();
+ for (int i = 0; i < n; i++)
+ {
+ View child = getView(i);
+ res.minimum = Math.max((int) child.getMinimumSpan(axis), res.minimum);
+ res.preferred = Math.max((int) child.getPreferredSpan(axis),
+ res.preferred);
+ res.maximum = Math.max((int) child.getMaximumSpan(axis), res.maximum);
+ }
+
+ return res;
+ }
+
+
+ /**
+ * Returns <code>true</code> if the specified point lies before the
+ * given <code>Rectangle</code>, <code>false</code> otherwise.
+ *
+ * "Before" is typically defined as being to the left or above.
+ *
+ * @param x the X coordinate of the point
+ * @param y the Y coordinate of the point
+ * @param r the rectangle to test the point against
+ *
+ * @return <code>true</code> if the specified point lies before the
+ * given <code>Rectangle</code>, <code>false</code> otherwise
+ */
+ protected boolean isBefore(int x, int y, Rectangle r)
+ {
+ boolean result = false;
+
+ if (myAxis == X_AXIS)
+ result = x < r.x;
+ else
+ result = y < r.y;
+
+ return result;
+ }
+
+ /**
+ * Returns <code>true</code> if the specified point lies after the
+ * given <code>Rectangle</code>, <code>false</code> otherwise.
+ *
+ * "After" is typically defined as being to the right or below.
+ *
+ * @param x the X coordinate of the point
+ * @param y the Y coordinate of the point
+ * @param r the rectangle to test the point against
+ *
+ * @return <code>true</code> if the specified point lies after the
+ * given <code>Rectangle</code>, <code>false</code> otherwise
+ */
+ protected boolean isAfter(int x, int y, Rectangle r)
+ {
+ boolean result = false;
+
+ if (myAxis == X_AXIS)
+ result = x > r.x;
+ else
+ result = y > r.y;
+
+ return result;
+ }
+
+ /**
+ * Returns the child <code>View</code> at the specified location.
+ *
+ * @param x the X coordinate
+ * @param y the Y coordinate
+ * @param r the inner allocation of this <code>BoxView</code> on entry,
+ * the allocation of the found child on exit
+ *
+ * @return the child <code>View</code> at the specified location
+ */
+ protected View getViewAtPoint(int x, int y, Rectangle r)
+ {
+ View result = null;
+ int count = getViewCount();
+ Rectangle copy = new Rectangle(r);
+
+ for (int i = 0; i < count; ++i)
+ {
+ copy.setBounds(r);
+ // The next call modifies copy.
+ childAllocation(i, copy);
+ if (copy.contains(x, y))
+ {
+ // Modify r on success.
+ r.setBounds(copy);
+ result = getView(i);
+ break;
+ }
+ }
+
+ if (result == null && count > 0)
+ return getView(count - 1);
+ return result;
+ }
+
+ /**
+ * Computes the allocation for a child <code>View</code>. The parameter
+ * <code>a</code> stores the allocation of this <code>CompositeView</code>
+ * and is then adjusted to hold the allocation of the child view.
+ *
+ * @param index
+ * the index of the child <code>View</code>
+ * @param a
+ * the allocation of this <code>CompositeView</code> before the
+ * call, the allocation of the child on exit
+ */
+ protected void childAllocation(int index, Rectangle a)
+ {
+ if (! isAllocationValid())
+ layout(a.width, a.height);
+
+ a.x += offsets[X_AXIS][index];
+ a.y += offsets[Y_AXIS][index];
+ a.width = spans[X_AXIS][index];
+ a.height = spans[Y_AXIS][index];
+ }
+
+ /**
+ * Lays out the children of this <code>BoxView</code> with the specified
+ * bounds.
+ *
+ * @param width the width of the allocated region for the children (that
+ * is the inner allocation of this <code>BoxView</code>
+ * @param height the height of the allocated region for the children (that
+ * is the inner allocation of this <code>BoxView</code>
+ */
+ protected void layout(int width, int height)
+ {
+ int[] newSpan = new int[]{ width, height };
+ int count = getViewCount();
+
+ // Update minor axis as appropriate. We need to first update the minor
+ // axis layout because that might affect the children's preferences along
+ // the major axis.
+ int minorAxis = myAxis == X_AXIS ? Y_AXIS : X_AXIS;
+ if ((! isLayoutValid(minorAxis)) || newSpan[minorAxis] != span[minorAxis])
+ {
+ layoutValid[minorAxis] = false;
+ span[minorAxis] = newSpan[minorAxis];
+ layoutMinorAxis(span[minorAxis], minorAxis, offsets[minorAxis],
+ spans[minorAxis]);
+
+ // Update the child view's sizes.
+ for (int i = 0; i < count; ++i)
+ {
+ getView(i).setSize(spans[X_AXIS][i], spans[Y_AXIS][i]);
+ }
+ layoutValid[minorAxis] = true;
+ }
+
+
+ // Update major axis as appropriate.
+ if ((! isLayoutValid(myAxis)) || newSpan[myAxis] != span[myAxis])
+ {
+ layoutValid[myAxis] = false;
+ span[myAxis] = newSpan[myAxis];
+ layoutMajorAxis(span[myAxis], myAxis, offsets[myAxis],
+ spans[myAxis]);
+
+ // Update the child view's sizes.
+ for (int i = 0; i < count; ++i)
+ {
+ getView(i).setSize(spans[X_AXIS][i], spans[Y_AXIS][i]);
+ }
+ layoutValid[myAxis] = true;
+ }
+
+ if (layoutValid[myAxis] == false)
+ System.err.println("WARNING: Major axis layout must be valid after layout");
+ if (layoutValid[minorAxis] == false)
+ System.err.println("Minor axis layout must be valid after layout");
+ }
+
+ /**
+ * Performs the layout along the major axis of a <code>BoxView</code>.
+ *
+ * @param targetSpan the (inner) span of the <code>BoxView</code> in which
+ * to layout the children
+ * @param axis the axis along which the layout is performed
+ * @param offsets the array that holds the offsets of the children on exit
+ * @param spans the array that holds the spans of the children on exit
+ */
+ protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets,
+ int[] spans)
+ {
+ // Set the spans to the preferred sizes. Determine the space
+ // that we have to adjust the sizes afterwards.
+ long sumPref = 0;
+ int n = getViewCount();
+ for (int i = 0; i < n; i++)
+ {
+ View child = getView(i);
+ spans[i] = (int) child.getPreferredSpan(axis);
+ sumPref = spans[i];
+ }
+
+ // Try to adjust the spans so that we fill the targetSpan.
+ long diff = targetSpan - sumPref;
+ float factor = 0.0F;
+ int[] diffs = null;
+ if (diff != 0)
+ {
+ long total = 0;
+ diffs = new int[n];
+ for (int i = 0; i < n; i++)
+ {
+ View child = getView(i);
+ int span;
+ if (diff < 0)
+ {
+ span = (int) child.getMinimumSpan(axis);
+ diffs[i] = spans[i] - span;
+ }
+ else
+ {
+ span = (int) child.getMaximumSpan(axis);
+ diffs[i] = span - spans[i];
+ }
+ total += span;
+ }
+
+ float maxAdjust = Math.abs(total - sumPref);
+ factor = diff / maxAdjust;
+ factor = Math.min(factor, 1.0F);
+ factor = Math.max(factor, -1.0F);
+ }
+
+ // Actually perform adjustments.
+ int totalOffs = 0;
+ for (int i = 0; i < n; i++)
+ {
+ offsets[i] = totalOffs;
+ if (diff != 0)
+ {
+ float adjust = factor * diffs[i];
+ spans[i] += Math.round(adjust);
+ }
+ // Avoid overflow here.
+ totalOffs = (int) Math.min((long) totalOffs + (long) spans[i],
+ Integer.MAX_VALUE);
+ }
+ }
+
+ /**
+ * Performs the layout along the minor axis of a <code>BoxView</code>.
+ *
+ * @param targetSpan the (inner) span of the <code>BoxView</code> in which
+ * to layout the children
+ * @param axis the axis along which the layout is performed
+ * @param offsets the array that holds the offsets of the children on exit
+ * @param spans the array that holds the spans of the children on exit
+ */
+ protected void layoutMinorAxis(int targetSpan, int axis, int[] offsets,
+ int[] spans)
+ {
+ int count = getViewCount();
+ for (int i = 0; i < count; i++)
+ {
+ View child = getView(i);
+ int max = (int) child.getMaximumSpan(axis);
+ if (max < targetSpan)
+ {System.err.println("align: " + child);
+ // Align child when it can't be made as wide as the target span.
+ float align = child.getAlignment(axis);
+ offsets[i] = (int) ((targetSpan - max) * align);
+ spans[i] = max;
+ }
+ else
+ {
+ // Expand child to target width if possible.
+ int min = (int) child.getMinimumSpan(axis);
+ offsets[i] = 0;
+ spans[i] = Math.max(min, targetSpan);
+ }
+ }
+ }
+
+ /**
+ * Returns <code>true</code> if the cached allocations for the children
+ * are still valid, <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if the cached allocations for the children
+ * are still valid, <code>false</code> otherwise
+ */
+ protected boolean isAllocationValid()
+ {
+ return isLayoutValid(X_AXIS) && isLayoutValid(Y_AXIS);
+ }
+
+ /**
+ * Return the current width of the box. This is the last allocated width.
+ *
+ * @return the current width of the box
+ */
+ public int getWidth()
+ {
+ return span[X_AXIS];
+ }
+
+ /**
+ * Return the current height of the box. This is the last allocated height.
+ *
+ * @return the current height of the box
+ */
+ public int getHeight()
+ {
+ return span[Y_AXIS];
+ }
+
+ /**
+ * Sets the size of the view. If the actual size has changed, the layout
+ * is updated accordingly.
+ *
+ * @param width the new width
+ * @param height the new height
+ */
+ public void setSize(float width, float height)
+ {
+ layout((int) width, (int) height);
+ }
+
+ /**
+ * Returns the span for the child view with the given index for the specified
+ * axis.
+ *
+ * @param axis the axis to examine, either <code>X_AXIS</code> or
+ * <code>Y_AXIS</code>
+ * @param childIndex the index of the child for for which to return the span
+ *
+ * @return the span for the child view with the given index for the specified
+ * axis
+ */
+ protected int getSpan(int axis, int childIndex)
+ {
+ if (axis != X_AXIS && axis != Y_AXIS)
+ throw new IllegalArgumentException("Illegal axis argument");
+ return spans[axis][childIndex];
+ }
+
+ /**
+ * Returns the offset for the child view with the given index for the
+ * specified axis.
+ *
+ * @param axis the axis to examine, either <code>X_AXIS</code> or
+ * <code>Y_AXIS</code>
+ * @param childIndex the index of the child for for which to return the span
+ *
+ * @return the offset for the child view with the given index for the
+ * specified axis
+ */
+ protected int getOffset(int axis, int childIndex)
+ {
+ if (axis != X_AXIS && axis != Y_AXIS)
+ throw new IllegalArgumentException("Illegal axis argument");
+ return offsets[axis][childIndex];
+ }
+
+ /**
+ * Returns the alignment for this box view for the specified axis. The
+ * axis that is tiled (the major axis) will be requested to be aligned
+ * centered (0.5F). The minor axis alignment depends on the child view's
+ * total alignment.
+ *
+ * @param axis the axis which is examined
+ *
+ * @return the alignment for this box view for the specified axis
+ */
+ public float getAlignment(int axis)
+ {
+ updateRequirements(axis);
+ return requirements[axis].alignment;
+ }
+
+ /**
+ * Called by a child View when its preferred span has changed.
+ *
+ * @param width indicates that the preferred width of the child changed.
+ * @param height indicates that the preferred height of the child changed.
+ * @param child the child View.
+ */
+ public void preferenceChanged(View child, boolean width, boolean height)
+ {
+ if (width)
+ {
+ layoutValid[X_AXIS] = false;
+ requirementsValid[X_AXIS] = false;
+ }
+ if (height)
+ {
+ layoutValid[Y_AXIS] = false;
+ requirementsValid[Y_AXIS] = false;
+ }
+ super.preferenceChanged(child, width, height);
+ }
+
+ /**
+ * Maps the document model position <code>pos</code> to a Shape
+ * in the view coordinate space. This method overrides CompositeView's
+ * method to make sure the children are allocated properly before
+ * calling the super's behaviour.
+ */
+ public Shape modelToView(int pos, Shape a, Position.Bias bias)
+ throws BadLocationException
+ {
+ // Make sure everything is allocated properly and then call super
+ if (! isAllocationValid())
+ {
+ Rectangle bounds = a.getBounds();
+ setSize(bounds.width, bounds.height);
+ }
+ return super.modelToView(pos, a, bias);
+ }
+
+ /**
+ * Returns the resize weight of this view. A value of <code>0</code> or less
+ * means this view is not resizeable. Positive values make the view
+ * resizeable. This implementation returns <code>0</code> for the major
+ * axis and <code>1</code> for the minor axis of this box view.
+ *
+ * @param axis the axis
+ *
+ * @return the resizability of this view along the specified axis
+ *
+ * @throws IllegalArgumentException if <code>axis</code> is invalid
+ */
+ public int getResizeWeight(int axis)
+ {
+ if (axis != X_AXIS && axis != Y_AXIS)
+ throw new IllegalArgumentException("Illegal axis argument");
+ int weight = 1;
+ if (axis == myAxis)
+ weight = 0;
+ return weight;
+ }
+
+ /**
+ * Returns the child allocation for the child view with the specified
+ * <code>index</code>. If the layout is invalid, this returns
+ * <code>null</code>.
+ *
+ * @param index the child view index
+ * @param a the allocation to this view
+ *
+ * @return the child allocation for the child view with the specified
+ * <code>index</code> or <code>null</code> if the layout is invalid
+ * or <code>a</code> is null
+ */
+ public Shape getChildAllocation(int index, Shape a)
+ {
+ Shape ret = null;
+ if (isAllocationValid() && a != null)
+ ret = super.getChildAllocation(index, a);
+ return ret;
+ }
+
+ protected void forwardUpdate(DocumentEvent.ElementChange ec, DocumentEvent e,
+ Shape a, ViewFactory vf)
+ {
+ // FIXME: What to do here?
+ super.forwardUpdate(ec, e, a, vf);
+ }
+
+ public int viewToModel(float x, float y, Shape a, Position.Bias[] bias)
+ {
+ // FIXME: What to do here?
+ return super.viewToModel(x, y, a, bias);
+ }
+
+ protected boolean flipEastAndWestAtEnds(int position, Position.Bias bias)
+ {
+ // FIXME: What to do here?
+ return super.flipEastAndWestAtEnds(position, bias);
+ }
+
+ /**
+ * Updates the child requirements along the specified axis. The requirements
+ * are only updated if the layout for the specified axis is marked as
+ * invalid.
+ *
+ * @param axis the axis to be updated
+ */
+ private void updateChildRequirements(int axis)
+ {
+ if (! isLayoutValid(axis))
+ {
+ int numChildren = getViewCount();
+ if (childReqs[axis] == null || childReqs[axis].length != numChildren)
+ childReqs[axis] = new SizeRequirements[numChildren];
+ for (int i = 0; i < numChildren; ++i)
+ {
+ View child = getView(i);
+ childReqs[axis][i] =
+ new SizeRequirements((int) child.getMinimumSpan(axis),
+ (int) child.getPreferredSpan(axis),
+ (int) child.getMaximumSpan(axis),
+ child.getAlignment(axis));
+ }
+ }
+ }
+
+ /**
+ * Updates the view's cached requirements along the specified axis if
+ * necessary. The requirements are only updated if the layout for the
+ * specified axis is marked as invalid.
+ *
+ * @param axis the axis
+ */
+ private void updateRequirements(int axis)
+ {
+ if (! requirementsValid[axis])
+ {
+ if (axis == myAxis)
+ requirements[axis] = calculateMajorAxisRequirements(axis,
+ requirements[axis]);
+ else
+ requirements[axis] = calculateMinorAxisRequirements(axis,
+ requirements[axis]);
+ requirementsValid[axis] = true;
+ }
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Caret.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Caret.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Caret.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Caret.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,207 @@
+/* Caret.java --
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Graphics;
+import java.awt.Point;
+
+import javax.swing.event.ChangeListener;
+
+/**
+ * Defines the method to be implemented by a caret that can be used in Swing
+ * text components.
+ *
+ * @author original author unknown
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public interface Caret
+{
+ /**
+ * Registers a {@link ChangeListener} that is notified whenever that state
+ * of this <code>Caret</code> changes.
+ *
+ * @param l the listener to register to this caret
+ */
+ void addChangeListener(ChangeListener l);
+
+ /**
+ * Removes a {@link ChangeListener} from the list of registered listeners.
+ *
+ * @param l the listener to remove
+ */
+ void removeChangeListener(ChangeListener l);
+
+ /**
+ * Installs this <code>Caret</code> on the specified text component. This
+ * usually involves setting up listeners.
+ *
+ * This method is called by {@link JTextComponent#setCaret(Caret)} after
+ * this caret has been set on the text component.
+ *
+ * @param c the text component to install this caret to
+ */
+ void install(JTextComponent c);
+
+ /**
+ * Deinstalls this <code>Caret</code> from the specified text component.
+ * This usually involves removing listeners from the text component.
+ *
+ * This method is called by {@link JTextComponent#setCaret(Caret)} before
+ * this caret is removed from the text component.
+ *
+ * @param c the text component to deinstall this caret from
+ */
+ void deinstall(JTextComponent c);
+
+ /**
+ * Returns the blink rate of this <code>Caret</code> in milliseconds.
+ * A value of <code>0</code> means that the caret does not blink.
+ *
+ * @return the blink rate of this <code>Caret</code> or <code>0</code> if
+ * this caret does not blink
+ */
+ int getBlinkRate();
+
+ /**
+ * Sets the blink rate of this <code>Caret</code> in milliseconds.
+ * A value of <code>0</code> means that the caret does not blink.
+ *
+ * @param rate the new blink rate to set
+ */
+ void setBlinkRate(int rate);
+
+ /**
+ * Returns the current position of this <code>Caret</code> within the
+ * <code>Document</code>.
+ *
+ * @return the current position of this <code>Caret</code> within the
+ * <code>Document</code>
+ */
+ int getDot();
+
+ /**
+ * Sets the current position of this <code>Caret</code> within the
+ * <code>Document</code>. This also sets the <code>mark</code> to the
+ * new location.
+ *
+ * @param dot the new position to be set
+ *
+ * @see #moveDot(int)
+ */
+ void setDot(int dot);
+
+ /**
+ * Moves the <code>dot</code> location without touching the
+ * <code>mark</code>. This is used when making a selection.
+ *
+ * @param dot the location where to move the dot
+ *
+ * @see #setDot(int)
+ */
+ void moveDot(int dot);
+
+ /**
+ * Returns the current position of the <code>mark</code>. The
+ * <code>mark</code> marks the location in the <code>Document</code> that
+ * is the end of a selection. If there is no selection, the <code>mark</code>
+ * is the same as the <code>dot</code>.
+ *
+ * @return the current position of the mark
+ */
+ int getMark();
+
+ /**
+ * Returns the current visual position of this <code>Caret</code>.
+ *
+ * @return the current visual position of this <code>Caret</code>
+ *
+ * @see #setMagicCaretPosition
+ */
+ Point getMagicCaretPosition();
+
+ /**
+ * Sets the current visual position of this <code>Caret</code>.
+ *
+ * @param p the Point to use for the saved location. May be <code>null</code>
+ * to indicate that there is no visual location
+ */
+ void setMagicCaretPosition(Point p);
+
+ /**
+ * Returns <code>true</code> if the selection is currently visible,
+ * <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if the selection is currently visible,
+ * <code>false</code> otherwise
+ */
+ boolean isSelectionVisible();
+
+ /**
+ * Sets the visiblity state of the selection.
+ *
+ * @param v <code>true</code> if the selection should be visible,
+ * <code>false</code> otherwise
+ */
+ void setSelectionVisible(boolean v);
+
+ /**
+ * Returns <code>true</code> if this <code>Caret</code> is currently visible,
+ * and <code>false</code> if it is not.
+ *
+ * @return <code>true</code> if this <code>Caret</code> is currently visible,
+ * and <code>false</code> if it is not
+ */
+ boolean isVisible();
+
+ /**
+ * Sets the visibility state of the caret. <code>true</code> shows the
+ * <code>Caret</code>, <code>false</code> hides it.
+ *
+ * @param v the visibility to set
+ */
+ void setVisible(boolean v);
+
+ /**
+ * Paints this <code>Caret</code> to the specified <code>Graphics</code>
+ * context.
+ *
+ * @param g the graphics context to render to
+ */
+ void paint(Graphics g);
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ChangedCharSetException.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ChangedCharSetException.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ChangedCharSetException.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ChangedCharSetException.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,100 @@
+/* ChangedCharSetException.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.io.IOException;
+import java.io.Serializable;
+
+/**
+ * The exception is thrown when the document charset is changed.
+ *
+ * @author Audrius Meskauskas (AudriusA at Bioinformatics.org)
+ */
+public class ChangedCharSetException
+ extends IOException
+ implements Serializable
+{
+ /**
+ * Use serialVersionUID for interoperability.
+ * This value corresponds the version 1.4.
+ */
+ private static final long serialVersionUID = 9119851554465432389L;
+
+ /**
+ * The char set specification.
+ */
+ private final String m_charSetSpec;
+
+ /**
+ * The char set key.
+ */
+ private final boolean m_charSetKey;
+
+ /**
+ * Constructs a new char set exception with two additional parameters,
+ * defining the circumstances under that the exception was raised.
+ */
+ public ChangedCharSetException(String charSetSpec, boolean charSetKey)
+ {
+ m_charSetSpec = charSetSpec;
+ m_charSetKey = charSetKey;
+ }
+
+ /**
+ * Get the value of the first parameter, previously passed to the
+ * constructor.
+ *
+ * @return the value of the first parameter
+ */
+ public String getCharSetSpec()
+ {
+ return m_charSetSpec;
+ }
+
+ /**
+ * Get the value of the second parameter, previously passed to the
+ * constructor.
+ *
+ * @return the value of the second parameter
+ */
+ public boolean keyEqualsCharSet()
+ {
+ return m_charSetKey;
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ComponentView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ComponentView.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ComponentView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ComponentView.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,268 @@
+/* ComponentView.java --
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
+
+/**
+ * A {@link View} implementation that is able to render arbitrary
+ * {@link Component}s. This uses the attribute
+ * {@link StyleConstants#ComponentAttribute} to determine the
+ * <code>Component</code> that should be rendered. This <code>Component</code>
+ * becomes a direct child of the <code>JTextComponent</code> that contains
+ * this <code>ComponentView</code>, so this view must not be shared between
+ * multiple <code>JTextComponent</code>s.
+ *
+ * @author Roman Kennke (kennke at aicas.com)
+ * @author original author unknown
+ */
+public class ComponentView extends View
+{
+
+ /**
+ * The component that is displayed by this view.
+ */
+ private Component comp;
+
+ /**
+ * Creates a new instance of <code>ComponentView</code> for the specified
+ * <code>Element</code>.
+ *
+ * @param elem the element that this <code>View</code> is rendering
+ */
+ public ComponentView(Element elem)
+ {
+ super(elem);
+ }
+
+ /**
+ * Creates the <code>Component</code> that this <code>View</code> is
+ * rendering. The <code>Component</code> is determined using
+ * the {@link StyleConstants#ComponentAttribute} of the associated
+ * <code>Element</code>.
+ *
+ * @return the component that is rendered
+ */
+ protected Component createComponent()
+ {
+ return StyleConstants.getComponent(getElement().getAttributes());
+ }
+
+ /**
+ * Returns the alignment of this <code>View</code> along the specified axis.
+ *
+ * @param axis either {@link View#X_AXIS} or {@link View#Y_AXIS}
+ *
+ * @return the alignment of this <code>View</code> along the specified axis
+ */
+ public float getAlignment(int axis)
+ {
+ float align;
+ if (axis == X_AXIS)
+ align = getComponent().getAlignmentX();
+ else if (axis == Y_AXIS)
+ align = getComponent().getAlignmentY();
+ else
+ throw new IllegalArgumentException();
+ return align;
+ }
+
+ /**
+ * Returns the <code>Component</code> that is rendered by this
+ * <code>ComponentView</code>.
+ *
+ * @return the <code>Component</code> that is rendered by this
+ * <code>ComponentView</code>
+ */
+ public final Component getComponent()
+ {
+ if (comp == null)
+ comp = createComponent();
+ return comp;
+ }
+
+ /**
+ * Returns the maximum span of this <code>View</code> along the specified
+ * axis.
+ *
+ * This will return {@link Component#getMaximumSize()} for the specified
+ * axis.
+ *
+ * @return the maximum span of this <code>View</code> along the specified
+ * axis
+ */
+ public float getMaximumSpan(int axis)
+ {
+ float span;
+ if (axis == X_AXIS)
+ span = getComponent().getMaximumSize().width;
+ else if (axis == Y_AXIS)
+ span = getComponent().getMaximumSize().height;
+ else
+ throw new IllegalArgumentException();
+ return span;
+ }
+
+ public float getMinimumSpan(int axis)
+ {
+ float span;
+ if (axis == X_AXIS)
+ span = getComponent().getMinimumSize().width;
+ else if (axis == Y_AXIS)
+ span = getComponent().getMinimumSize().height;
+ else
+ throw new IllegalArgumentException();
+ return span;
+ }
+
+ public float getPreferredSpan(int axis)
+ {
+ float span;
+ if (axis == X_AXIS)
+ span = getComponent().getPreferredSize().width;
+ else if (axis == Y_AXIS)
+ span = getComponent().getPreferredSize().height;
+ else
+ throw new IllegalArgumentException();
+ return span;
+ }
+
+ public Shape modelToView(int pos, Shape a, Position.Bias b)
+ throws BadLocationException
+ {
+ Element el = getElement();
+ if (pos < el.getStartOffset() || pos >= el.getEndOffset())
+ throw new BadLocationException("Illegal offset for this view", pos);
+ Rectangle r = a.getBounds();
+ Component c = getComponent();
+ return new Rectangle(r.x, r.y, c.getWidth(), c.getHeight());
+ }
+
+ /**
+ * The real painting behavour is performed by normal component painting,
+ * triggered by the text component that hosts this view. This method does
+ * not paint by itself. However, it sets the size of the component according
+ * to the allocation that is passed here.
+ *
+ * @param g the graphics context
+ * @param a the allocation of the child
+ */
+ public void paint(Graphics g, Shape a)
+ {
+ Rectangle r = a.getBounds();
+ getComponent().setBounds(r.x, r.y, r.width, r.height);
+ }
+
+ /**
+ * This sets up the component when the view is added to its parent, or
+ * cleans up the view when it is removed from its parent.
+ *
+ * When this view is added to a parent view, the component of this view
+ * is added to the container that hosts this view. When <code>p</code> is
+ * <code>null</code>, then the view is removed from it's parent and we have
+ * to also remove the component from it's parent container.
+ *
+ * @param p the parent view or <code>null</code> if this view is removed
+ * from it's parent
+ */
+ public void setParent(final View p)
+ {
+ if (SwingUtilities.isEventDispatchThread())
+ setParentImpl(p);
+ else
+ SwingUtilities.invokeLater
+ (new Runnable()
+ {
+ public void run()
+ {
+ setParentImpl(p);
+ }
+ });
+ }
+
+ /**
+ * The implementation of {@link #setParent}. This is package private to
+ * avoid a synthetic accessor method.
+ *
+ * @param p the parent view to set
+ */
+ private void setParentImpl(View p)
+ {
+ super.setParent(p);
+ if (p != null)
+ {
+ Component c = getComponent();
+ p.getContainer().add(c);
+ }
+ else
+ {
+ Component c = getComponent();
+ Container parent = c.getParent();
+ parent.remove(c);
+ comp = null;
+ }
+ }
+
+ /**
+ * Maps coordinates from the <code>View</code>'s space into a position
+ * in the document model.
+ *
+ * @param x the x coordinate in the view space
+ * @param y the y coordinate in the view space
+ * @param a the allocation of this <code>View</code>
+ * @param b the bias to use
+ *
+ * @return the position in the document that corresponds to the screen
+ * coordinates <code>x, y</code>
+ */
+ public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
+ {
+ // The element should only have one character position and it is clear
+ // that this position is the position that best matches the given screen
+ // coordinates, simply because this view has only this one position.
+ Element el = getElement();
+ return el.getStartOffset();
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/CompositeView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/CompositeView.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/CompositeView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/CompositeView.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,799 @@
+/* CompositeView.java -- An abstract view that manages child views
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+import javax.swing.SwingConstants;
+
+/**
+ * An abstract base implementation of {@link View} that manages child
+ * <code>View</code>s.
+ *
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public abstract class CompositeView
+ extends View
+{
+
+ /**
+ * The child views of this <code>CompositeView</code>.
+ */
+ View[] children;
+
+ /**
+ * The allocation of this <code>View</code> minus its insets. This is
+ * initialized in {@link #getInsideAllocation} and reused and modified in
+ * {@link #childAllocation(int, Rectangle)}.
+ */
+ Rectangle insideAllocation;
+
+ /**
+ * The insets of this <code>CompositeView</code>. This is initialized
+ * in {@link #setInsets}.
+ */
+ Insets insets;
+
+ /**
+ * Creates a new <code>CompositeView</code> for the given
+ * <code>Element</code>.
+ *
+ * @param element the element that is rendered by this CompositeView
+ */
+ public CompositeView(Element element)
+ {
+ super(element);
+ children = new View[0];
+ insets = new Insets(0, 0, 0, 0);
+ }
+
+ /**
+ * Loads the child views of this <code>CompositeView</code>. This method
+ * is called from {@link #setParent} to initialize the child views of
+ * this composite view.
+ *
+ * @param f the view factory to use for creating new child views
+ *
+ * @see #setParent
+ */
+ protected void loadChildren(ViewFactory f)
+ {
+ Element el = getElement();
+ int count = el.getElementCount();
+ View[] newChildren = new View[count];
+ for (int i = 0; i < count; ++i)
+ {
+ Element child = el.getElement(i);
+ View view = f.create(child);
+ newChildren[i] = view;
+ }
+ replace(0, getViewCount(), newChildren);
+ }
+
+ /**
+ * Sets the parent of this <code>View</code>.
+ * In addition to setting the parent, this calls {@link #loadChildren}, if
+ * this <code>View</code> does not already have its children initialized.
+ *
+ * @param parent the parent to set
+ */
+ public void setParent(View parent)
+ {
+ super.setParent(parent);
+ if (parent != null && ((children == null) || children.length == 0))
+ loadChildren(getViewFactory());
+ }
+
+ /**
+ * Returns the number of child views.
+ *
+ * @return the number of child views
+ */
+ public int getViewCount()
+ {
+ return children.length;
+ }
+
+ /**
+ * Returns the child view at index <code>n</code>.
+ *
+ * @param n the index of the requested child view
+ *
+ * @return the child view at index <code>n</code>
+ */
+ public View getView(int n)
+ {
+ return children[n];
+ }
+
+ /**
+ * Replaces child views by some other child views. If there are no views to
+ * remove (<code>length == 0</code>), the result is a simple insert, if
+ * there are no children to add (<code>view == null</code>) the result
+ * is a simple removal.
+ *
+ * @param offset the start offset from where to remove children
+ * @param length the number of children to remove
+ * @param views the views that replace the removed children
+ */
+ public void replace(int offset, int length, View[] views)
+ {
+ // Check for null views to add.
+ for (int i = 0; i < views.length; ++i)
+ if (views[i] == null)
+ throw new NullPointerException("Added views must not be null");
+
+ int endOffset = offset + length;
+
+ // First we set the parent of the removed children to null.
+ for (int i = offset; i < endOffset; ++i)
+ children[i].setParent(null);
+
+ View[] newChildren = new View[children.length - length + views.length];
+ System.arraycopy(children, 0, newChildren, 0, offset);
+ System.arraycopy(views, 0, newChildren, offset, views.length);
+ System.arraycopy(children, offset + length, newChildren,
+ offset + views.length,
+ children.length - (offset + length));
+ children = newChildren;
+
+ // Finally we set the parent of the added children to this.
+ for (int i = 0; i < views.length; ++i)
+ views[i].setParent(this);
+ }
+
+ /**
+ * Returns the allocation for the specified child <code>View</code>.
+ *
+ * @param index the index of the child view
+ * @param a the allocation for this view
+ *
+ * @return the allocation for the specified child <code>View</code>
+ */
+ public Shape getChildAllocation(int index, Shape a)
+ {
+ Rectangle r = getInsideAllocation(a);
+ childAllocation(index, r);
+ return r;
+ }
+
+ /**
+ * Maps a position in the document into the coordinate space of the View.
+ * The output rectangle usually reflects the font height but has a width
+ * of zero.
+ *
+ * @param pos the position of the character in the model
+ * @param a the area that is occupied by the view
+ * @param bias either {@link Position.Bias#Forward} or
+ * {@link Position.Bias#Backward} depending on the preferred
+ * direction bias. If <code>null</code> this defaults to
+ * <code>Position.Bias.Forward</code>
+ *
+ * @return a rectangle that gives the location of the document position
+ * inside the view coordinate space
+ *
+ * @throws BadLocationException if <code>pos</code> is invalid
+ * @throws IllegalArgumentException if b is not one of the above listed
+ * valid values
+ */
+ public Shape modelToView(int pos, Shape a, Position.Bias bias)
+ throws BadLocationException
+ {
+ boolean backward = bias == Position.Bias.Backward;
+ int testpos = backward ? Math.max(0, pos - 1) : pos;
+
+ Shape ret = null;
+ if (! backward || testpos >= getStartOffset())
+ {
+ int childIndex = getViewIndexAtPosition(testpos);
+ if (childIndex != -1 && childIndex < getViewCount())
+ {
+ View child = getView(childIndex);
+ if (child != null && testpos >= child.getStartOffset()
+ && testpos < child.getEndOffset())
+ {
+ Shape childAlloc = getChildAllocation(childIndex, a);
+ if (childAlloc != null)
+ {
+ ret = child.modelToView(pos, childAlloc, bias);
+ // Handle corner case.
+ if (ret == null && child.getEndOffset() == pos)
+ {
+ childIndex++;
+ if (childIndex < getViewCount())
+ {
+ child = getView(childIndex);
+ childAlloc = getChildAllocation(childIndex, a);
+ ret = child.modelToView(pos, childAlloc, bias);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ throw new BadLocationException("Position " + pos
+ + " is not represented by view.", pos);
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * A helper method for {@link #modelToView(int, Position.Bias, int,
+ * Position.Bias, Shape)}. This creates a default location when there is
+ * no child view that can take responsibility for mapping the position to
+ * view coordinates. Depending on the specified bias this will be the
+ * left or right edge of this view's allocation.
+ *
+ * @param a the allocation for this view
+ * @param bias the bias
+ *
+ * @return a default location
+ */
+ private Shape createDefaultLocation(Shape a, Position.Bias bias)
+ {
+ Rectangle alloc = a.getBounds();
+ Rectangle location = new Rectangle(alloc.x, alloc.y, 1, alloc.height);
+ if (bias == Position.Bias.Forward)
+ location.x = alloc.x + alloc.width;
+ return location;
+ }
+
+ /**
+ * Maps a region in the document into the coordinate space of the View.
+ *
+ * @param p1 the beginning position inside the document
+ * @param b1 the direction bias for the beginning position
+ * @param p2 the end position inside the document
+ * @param b2 the direction bias for the end position
+ * @param a the area that is occupied by the view
+ *
+ * @return a rectangle that gives the span of the document region
+ * inside the view coordinate space
+ *
+ * @throws BadLocationException if <code>p1</code> or <code>p2</code> are
+ * invalid
+ * @throws IllegalArgumentException if b1 or b2 is not one of the above
+ * listed valid values
+ */
+ public Shape modelToView(int p1, Position.Bias b1,
+ int p2, Position.Bias b2, Shape a)
+ throws BadLocationException
+ {
+ // TODO: This is most likely not 100% ok, figure out what else is to
+ // do here.
+ return super.modelToView(p1, b1, p2, b2, a);
+ }
+
+ /**
+ * Maps coordinates from the <code>View</code>'s space into a position
+ * in the document model.
+ *
+ * @param x the x coordinate in the view space, x >= 0
+ * @param y the y coordinate in the view space, y >= 0
+ * @param a the allocation of this <code>View</code>
+ * @param b the bias to use
+ *
+ * @return the position in the document that corresponds to the screen
+ * coordinates <code>x, y</code> >= 0
+ */
+ public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
+ {
+ if (x >= 0 && y >= 0)
+ {
+ Rectangle r = getInsideAllocation(a);
+ View view = getViewAtPoint((int) x, (int) y, r);
+ return view.viewToModel(x, y, r, b);
+ }
+ return 0;
+ }
+
+ /**
+ * Returns the next model location that is visible in eiter north / south
+ * direction or east / west direction. This is used to determine the placement
+ * of the caret when navigating around the document with the arrow keys. This
+ * is a convenience method for {@link #getNextNorthSouthVisualPositionFrom}
+ * and {@link #getNextEastWestVisualPositionFrom}.
+ *
+ * @param pos
+ * the model position to start search from
+ * @param b
+ * the bias for <code>pos</code>
+ * @param a
+ * the allocated region for this view
+ * @param direction
+ * the direction from the current position, can be one of the
+ * following:
+ * <ul>
+ * <li>{@link SwingConstants#WEST}</li>
+ * <li>{@link SwingConstants#EAST}</li>
+ * <li>{@link SwingConstants#NORTH}</li>
+ * <li>{@link SwingConstants#SOUTH}</li>
+ * </ul>
+ * @param biasRet
+ * the bias of the return value gets stored here
+ * @return the position inside the model that represents the next visual
+ * location
+ * @throws BadLocationException
+ * if <code>pos</code> is not a valid location inside the document
+ * model
+ * @throws IllegalArgumentException
+ * if <code>direction</code> is invalid
+ */
+ public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a,
+ int direction, Position.Bias[] biasRet)
+ throws BadLocationException
+ {
+ int retVal = -1;
+ switch (direction)
+ {
+ case SwingConstants.WEST:
+ case SwingConstants.EAST:
+ retVal = getNextEastWestVisualPositionFrom(pos, b, a, direction,
+ biasRet);
+ break;
+ case SwingConstants.NORTH:
+ case SwingConstants.SOUTH:
+ retVal = getNextNorthSouthVisualPositionFrom(pos, b, a, direction,
+ biasRet);
+ break;
+ default:
+ throw new IllegalArgumentException("Illegal value for direction.");
+ }
+ return retVal;
+ }
+
+ /**
+ * Returns the index of the child view that represents the specified
+ * model location.
+ *
+ * @param pos the model location for which to determine the child view index
+ * @param b the bias to be applied to <code>pos</code>
+ *
+ * @return the index of the child view that represents the specified
+ * model location
+ */
+ public int getViewIndex(int pos, Position.Bias b)
+ {
+ if (b == Position.Bias.Backward && pos != 0)
+ pos -= 1;
+ int i = -1;
+ if (pos >= getStartOffset() && pos < getEndOffset())
+ i = getViewIndexAtPosition(pos);
+ return i;
+ }
+
+ /**
+ * Returns <code>true</code> if the specified point lies before the
+ * given <code>Rectangle</code>, <code>false</code> otherwise.
+ *
+ * "Before" is typically defined as being to the left or above.
+ *
+ * @param x the X coordinate of the point
+ * @param y the Y coordinate of the point
+ * @param r the rectangle to test the point against
+ *
+ * @return <code>true</code> if the specified point lies before the
+ * given <code>Rectangle</code>, <code>false</code> otherwise
+ */
+ protected abstract boolean isBefore(int x, int y, Rectangle r);
+
+ /**
+ * Returns <code>true</code> if the specified point lies after the
+ * given <code>Rectangle</code>, <code>false</code> otherwise.
+ *
+ * "After" is typically defined as being to the right or below.
+ *
+ * @param x the X coordinate of the point
+ * @param y the Y coordinate of the point
+ * @param r the rectangle to test the point against
+ *
+ * @return <code>true</code> if the specified point lies after the
+ * given <code>Rectangle</code>, <code>false</code> otherwise
+ */
+ protected abstract boolean isAfter(int x, int y, Rectangle r);
+
+ /**
+ * Returns the child <code>View</code> at the specified location.
+ *
+ * @param x the X coordinate
+ * @param y the Y coordinate
+ * @param r the inner allocation of this <code>BoxView</code> on entry,
+ * the allocation of the found child on exit
+ *
+ * @return the child <code>View</code> at the specified location
+ */
+ protected abstract View getViewAtPoint(int x, int y, Rectangle r);
+
+ /**
+ * Computes the allocation for a child <code>View</code>. The parameter
+ * <code>a</code> stores the allocation of this <code>CompositeView</code>
+ * and is then adjusted to hold the allocation of the child view.
+ *
+ * @param index the index of the child <code>View</code>
+ * @param a the allocation of this <code>CompositeView</code> before the
+ * call, the allocation of the child on exit
+ */
+ protected abstract void childAllocation(int index, Rectangle a);
+
+ /**
+ * Returns the child <code>View</code> that contains the given model
+ * position. The given <code>Rectangle</code> gives the parent's allocation
+ * and is changed to the child's allocation on exit.
+ *
+ * @param pos the model position to query the child <code>View</code> for
+ * @param a the parent allocation on entry and the child allocation on exit
+ *
+ * @return the child view at the given model position
+ */
+ protected View getViewAtPosition(int pos, Rectangle a)
+ {
+ View view = null;
+ int i = getViewIndexAtPosition(pos);
+ if (i >= 0 && i < getViewCount() && a != null)
+ {
+ view = getView(i);
+ childAllocation(i, a);
+ }
+ return view;
+ }
+
+ /**
+ * Returns the index of the child <code>View</code> for the given model
+ * position.
+ *
+ * @param pos the model position for whicht the child <code>View</code> is
+ * queried
+ *
+ * @return the index of the child <code>View</code> for the given model
+ * position
+ */
+ protected int getViewIndexAtPosition(int pos)
+ {
+ // We have a 1:1 mapping of elements to views here, so we forward
+ // this to the element.
+ Element el = getElement();
+ return el.getElementIndex(pos);
+ }
+
+ /**
+ * Returns the allocation that is given to this <code>CompositeView</code>
+ * minus this <code>CompositeView</code>'s insets.
+ *
+ * Also this translates from an immutable allocation to a mutable allocation
+ * that is typically reused and further narrowed, like in
+ * {@link #childAllocation}.
+ *
+ * @param a the allocation given to this <code>CompositeView</code>
+ *
+ * @return the allocation that is given to this <code>CompositeView</code>
+ * minus this <code>CompositeView</code>'s insets or
+ * <code>null</code> if a was <code>null</code>
+ */
+ protected Rectangle getInsideAllocation(Shape a)
+ {
+ if (a == null)
+ return null;
+
+ Rectangle alloc = a.getBounds();
+ // Initialize the inside allocation rectangle. This is done inside
+ // a synchronized block in order to avoid multiple threads creating
+ // this instance simultanously.
+ Rectangle inside;
+ synchronized(this)
+ {
+ inside = insideAllocation;
+ if (inside == null)
+ {
+ inside = new Rectangle();
+ insideAllocation = inside;
+ }
+ }
+ inside.x = alloc.x + insets.left;
+ inside.y = alloc.y + insets.top;
+ inside.width = alloc.width - insets.left - insets.right;
+ inside.height = alloc.height - insets.top - insets.bottom;
+ return inside;
+ }
+
+ /**
+ * Sets the insets defined by attributes in <code>attributes</code>. This
+ * queries the attribute keys {@link StyleConstants#SpaceAbove},
+ * {@link StyleConstants#SpaceBelow}, {@link StyleConstants#LeftIndent} and
+ * {@link StyleConstants#RightIndent} and calls {@link #setInsets} to
+ * actually set the insets on this <code>CompositeView</code>.
+ *
+ * @param attributes the attributes from which to query the insets
+ */
+ protected void setParagraphInsets(AttributeSet attributes)
+ {
+ Float l = (Float) attributes.getAttribute(StyleConstants.LeftIndent);
+ short left = 0;
+ if (l != null)
+ left = l.shortValue();
+ Float r = (Float) attributes.getAttribute(StyleConstants.RightIndent);
+ short right = 0;
+ if (r != null)
+ right = r.shortValue();
+ Float t = (Float) attributes.getAttribute(StyleConstants.SpaceAbove);
+ short top = 0;
+ if (t != null)
+ top = t.shortValue();
+ Float b = (Float) attributes.getAttribute(StyleConstants.SpaceBelow);
+ short bottom = 0;
+ if (b != null)
+ bottom = b.shortValue();
+ setInsets(top, left, bottom, right);
+ }
+
+ /**
+ * Sets the insets of this <code>CompositeView</code>.
+ *
+ * @param top the top inset
+ * @param left the left inset
+ * @param bottom the bottom inset
+ * @param right the right inset
+ */
+ protected void setInsets(short top, short left, short bottom, short right)
+ {
+ insets.top = top;
+ insets.left = left;
+ insets.bottom = bottom;
+ insets.right = right;
+ }
+
+ /**
+ * Returns the left inset of this <code>CompositeView</code>.
+ *
+ * @return the left inset of this <code>CompositeView</code>
+ */
+ protected short getLeftInset()
+ {
+ return (short) insets.left;
+ }
+
+ /**
+ * Returns the right inset of this <code>CompositeView</code>.
+ *
+ * @return the right inset of this <code>CompositeView</code>
+ */
+ protected short getRightInset()
+ {
+ return (short) insets.right;
+ }
+
+ /**
+ * Returns the top inset of this <code>CompositeView</code>.
+ *
+ * @return the top inset of this <code>CompositeView</code>
+ */
+ protected short getTopInset()
+ {
+ return (short) insets.top;
+ }
+
+ /**
+ * Returns the bottom inset of this <code>CompositeView</code>.
+ *
+ * @return the bottom inset of this <code>CompositeView</code>
+ */
+ protected short getBottomInset()
+ {
+ return (short) insets.bottom;
+ }
+
+ /**
+ * Returns the next model location that is visible in north or south
+ * direction.
+ * This is used to determine the
+ * placement of the caret when navigating around the document with
+ * the arrow keys.
+ *
+ * @param pos the model position to start search from
+ * @param b the bias for <code>pos</code>
+ * @param a the allocated region for this view
+ * @param direction the direction from the current position, can be one of
+ * the following:
+ * <ul>
+ * <li>{@link SwingConstants#NORTH}</li>
+ * <li>{@link SwingConstants#SOUTH}</li>
+ * </ul>
+ * @param biasRet the bias of the return value gets stored here
+ *
+ * @return the position inside the model that represents the next visual
+ * location
+ *
+ * @throws BadLocationException if <code>pos</code> is not a valid location
+ * inside the document model
+ * @throws IllegalArgumentException if <code>direction</code> is invalid
+ */
+ protected int getNextNorthSouthVisualPositionFrom(int pos, Position.Bias b,
+ Shape a, int direction,
+ Position.Bias[] biasRet)
+ throws BadLocationException
+ {
+ // TODO: It is unknown to me how this method has to be implemented and
+ // there is no specification telling me how to do it properly. Therefore
+ // the implementation was done for cases that are known.
+ //
+ // If this method ever happens to act silly for your particular case then
+ // it is likely that it is a cause of not knowing about your case when it
+ // was implemented first. You are free to fix the behavior.
+ //
+ // Here are the assumptions that lead to the implementation:
+ // If direction is NORTH chose the View preceding the one that contains the
+ // offset 'pos' (imagine the views are stacked on top of each other where
+ // the top is 0 and the bottom is getViewCount()-1.
+ // Consecutively when the direction is SOUTH the View following the one
+ // the offset 'pos' lies in is questioned.
+ //
+ // This limitation is described as PR 27345.
+ int index = getViewIndex(pos, b);
+ View v = null;
+
+ if (index == -1)
+ return pos;
+
+ switch (direction)
+ {
+ case NORTH:
+ // If we cannot calculate a proper offset return the one that was
+ // provided.
+ if (index <= 0)
+ return pos;
+
+ v = getView(index - 1);
+ break;
+ case SOUTH:
+ // If we cannot calculate a proper offset return the one that was
+ // provided.
+ if (index >= getViewCount() - 1)
+ return pos;
+
+ v = getView(index + 1);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+
+ return v.getNextVisualPositionFrom(pos, b, a, direction, biasRet);
+ }
+
+ /**
+ * Returns the next model location that is visible in east or west
+ * direction.
+ * This is used to determine the
+ * placement of the caret when navigating around the document with
+ * the arrow keys.
+ *
+ * @param pos the model position to start search from
+ * @param b the bias for <code>pos</code>
+ * @param a the allocated region for this view
+ * @param direction the direction from the current position, can be one of
+ * the following:
+ * <ul>
+ * <li>{@link SwingConstants#EAST}</li>
+ * <li>{@link SwingConstants#WEST}</li>
+ * </ul>
+ * @param biasRet the bias of the return value gets stored here
+ *
+ * @return the position inside the model that represents the next visual
+ * location
+ *
+ * @throws BadLocationException if <code>pos</code> is not a valid location
+ * inside the document model
+ * @throws IllegalArgumentException if <code>direction</code> is invalid
+ */
+ protected int getNextEastWestVisualPositionFrom(int pos, Position.Bias b,
+ Shape a, int direction,
+ Position.Bias[] biasRet)
+ throws BadLocationException
+ {
+ // TODO: It is unknown to me how this method has to be implemented and
+ // there is no specification telling me how to do it properly. Therefore
+ // the implementation was done for cases that are known.
+ //
+ // If this method ever happens to act silly for your particular case then
+ // it is likely that it is a cause of not knowing about your case when it
+ // was implemented first. You are free to fix the behavior.
+ //
+ // Here are the assumptions that lead to the implementation:
+ // If direction is EAST increase the offset by one and ask the View to
+ // which that index belong to calculate the 'next visual position'.
+ // If the direction is WEST do the same with offset 'pos' being decreased
+ // by one.
+ // This behavior will fail in a right-to-left or bidi environment!
+ //
+ // This limitation is described as PR 27346.
+ int index;
+
+ View v = null;
+
+ switch (direction)
+ {
+ case EAST:
+ index = getViewIndex(pos + 1, b);
+ // If we cannot calculate a proper offset return the one that was
+ // provided.
+ if (index == -1)
+ return pos;
+
+ v = getView(index);
+ break;
+ case WEST:
+ index = getViewIndex(pos - 1, b);
+ // If we cannot calculate a proper offset return the one that was
+ // provided.
+ if (index == -1)
+ return pos;
+
+ v = getView(index);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+
+ return v.getNextVisualPositionFrom(pos,
+ b,
+ a,
+ direction,
+ biasRet);
+ }
+
+ /**
+ * Determines if the next view in horinzontal direction is located to
+ * the east or west of the view at position <code>pos</code>. Usually
+ * the <code>View</code>s are laid out from the east to the west, so
+ * we unconditionally return <code>false</code> here. Subclasses that
+ * support bidirectional text may wish to override this method.
+ *
+ * @param pos the position in the document
+ * @param bias the bias to be applied to <code>pos</code>
+ *
+ * @return <code>true</code> if the next <code>View</code> is located
+ * to the EAST, <code>false</code> otherwise
+ */
+ protected boolean flipEastAndWestAtEnds(int pos, Position.Bias bias)
+ {
+ return false;
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DateFormatter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DateFormatter.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DateFormatter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DateFormatter.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,85 @@
+/* DateFormatter.java --
+Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.text.DateFormat;
+
+/**
+ * <code>DateFormatter</code> is an {@link InternationalFormatter}
+ * that implements value to string and string to value conversion via
+ * an instance of {@link DateFormat}.
+ *
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class DateFormatter extends InternationalFormatter
+{
+
+ /** The serialVersoinUID. */
+ private static final long serialVersionUID = 5423279572591848797L;
+
+ /**
+ * Creates a new instance using the default {@link DateFormat} object
+ * returned by {@link DateFormat#getDateInstance()}.
+ */
+ public DateFormatter()
+ {
+ this(DateFormat.getDateInstance());
+ }
+
+ /**
+ * Creates a new instance of <code>DateFormatter</code> using the
+ * specified <code>DateFormat</code>
+ *
+ * @param format the <code>DateFormat</code> to use
+ */
+ public DateFormatter(DateFormat format)
+ {
+ super();
+ setFormat(format);
+ }
+
+ /**
+ * Sets the format that is used by this <code>DateFormatter</code>.
+ *
+ * @param format the <code>DateFormat</code> to use
+ */
+ public void setFormat(DateFormat format)
+ {
+ super.setFormat(format);
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultCaret.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultCaret.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultCaret.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultCaret.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,1286 @@
+/* DefaultCaret.java --
+ Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.EventListener;
+
+import javax.swing.JComponent;
+import javax.swing.SwingUtilities;
+import javax.swing.Timer;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.event.EventListenerList;
+import javax.swing.text.Position.Bias;
+
+/**
+ * The default implementation of the {@link Caret} interface.
+ *
+ * @author original author unknown
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class DefaultCaret extends Rectangle
+ implements Caret, FocusListener, MouseListener, MouseMotionListener
+{
+
+ /** A text component in the current VM which currently has a
+ * text selection or <code>null</code>.
+ */
+ static JTextComponent componentWithSelection;
+
+ /** An implementation of NavigationFilter.FilterBypass which delegates
+ * to the corresponding methods of the <code>DefaultCaret</code>.
+ *
+ * @author Robert Schuster (robertschuster at fsfe.org)
+ */
+ class Bypass extends NavigationFilter.FilterBypass
+ {
+
+ public Caret getCaret()
+ {
+ return DefaultCaret.this;
+ }
+
+ public void moveDot(int dot, Bias bias)
+ {
+ DefaultCaret.this.moveDotImpl(dot);
+ }
+
+ public void setDot(int dot, Bias bias)
+ {
+ DefaultCaret.this.setDotImpl(dot);
+ }
+
+ }
+
+ /**
+ * Controls the blinking of the caret.
+ *
+ * @author Roman Kennke (kennke at aicas.com)
+ * @author Audrius Meskauskas (AudriusA at Bioinformatics.org)
+ */
+ private class BlinkTimerListener implements ActionListener
+ {
+ /**
+ * Forces the next event to be ignored. The next event should be ignored
+ * if we force the caret to appear. We do not know how long will it take
+ * to fire the comming event; this may be near immediately. Better to leave
+ * the caret visible one iteration longer.
+ */
+ boolean ignoreNextEvent;
+
+ /**
+ * Receives notification when the blink timer fires and updates the visible
+ * state of the caret.
+ *
+ * @param event the action event
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ if (ignoreNextEvent)
+ ignoreNextEvent = false;
+ else
+ {
+ visible = !visible;
+ repaint();
+ }
+ }
+ }
+
+ /**
+ * Listens for changes in the text component's document and updates the
+ * caret accordingly.
+ *
+ * @author Roman Kennke (kennke at aicas.com)
+ */
+ private class DocumentHandler implements DocumentListener
+ {
+ /**
+ * Receives notification that some text attributes have changed. No action
+ * is taken here.
+ *
+ * @param event the document event
+ */
+ public void changedUpdate(DocumentEvent event)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Receives notification that some text has been inserted from the text
+ * component. The caret is moved forward accordingly.
+ *
+ * @param event the document event
+ */
+ public void insertUpdate(DocumentEvent event)
+ {
+ if (policy == ALWAYS_UPDATE ||
+ (SwingUtilities.isEventDispatchThread() &&
+ policy == UPDATE_WHEN_ON_EDT))
+ {
+ int dot = getDot();
+ setDot(dot + event.getLength());
+ }
+ }
+
+ /**
+ * Receives notification that some text has been removed into the text
+ * component. The caret is moved backwards accordingly.
+ *
+ * @param event the document event
+ */
+ public void removeUpdate(DocumentEvent event)
+ {
+ if (policy == ALWAYS_UPDATE
+ || (SwingUtilities.isEventDispatchThread()
+ && policy == UPDATE_WHEN_ON_EDT))
+ {
+ int dot = getDot();
+ setDot(dot - event.getLength());
+ }
+ else if (policy == NEVER_UPDATE
+ || (! SwingUtilities.isEventDispatchThread()
+ && policy == UPDATE_WHEN_ON_EDT))
+ {
+ int docLength = event.getDocument().getLength();
+ if (getDot() > docLength)
+ setDot(docLength);
+ }
+ }
+ }
+
+ /**
+ * Listens for property changes on the text document. This is used to add and
+ * remove our document listener, if the document of the text component has
+ * changed.
+ *
+ * @author Roman Kennke (kennke at aicas.com)
+ */
+ private class PropertyChangeHandler implements PropertyChangeListener
+ {
+
+ /**
+ * Receives notification when a property has changed on the text component.
+ * This adds/removes our document listener from the text component's
+ * document when the document changes.
+ *
+ * @param e the property change event
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ String name = e.getPropertyName();
+
+ if (name.equals("document"))
+ {
+ Document oldDoc = (Document) e.getOldValue();
+ if (oldDoc != null)
+ oldDoc.removeDocumentListener(documentListener);
+
+ Document newDoc = (Document) e.getNewValue();
+ if (newDoc != null)
+ newDoc.addDocumentListener(documentListener);
+ }
+ else if (name.equals("editable"))
+ {
+ active = (((Boolean) e.getNewValue()).booleanValue()
+ && textComponent.isEnabled());
+ }
+ else if (name.equals("enabled"))
+ {
+ active = (((Boolean) e.getNewValue()).booleanValue()
+ && textComponent.isEditable());
+ }
+
+ }
+
+ }
+
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 4325555698756477346L;
+
+ /**
+ * Indicates the Caret position should always be updated after Document
+ * changes even if the updates are not performed on the Event Dispatching
+ * thread.
+ *
+ * @since 1.5
+ */
+ public static final int ALWAYS_UPDATE = 2;
+
+ /**
+ * Indicates the Caret position should not be changed unless the Document
+ * length becomes less than the Caret position, in which case the Caret
+ * is moved to the end of the Document.
+ *
+ * @since 1.5
+ */
+ public static final int NEVER_UPDATE = 1;
+
+ /**
+ * Indicates the Caret position should be updated only if Document changes
+ * are made on the Event Dispatcher thread.
+ *
+ * @since 1.5
+ */
+ public static final int UPDATE_WHEN_ON_EDT = 0;
+
+ /** Keeps track of the current update policy **/
+ int policy = UPDATE_WHEN_ON_EDT;
+
+ /**
+ * The <code>ChangeEvent</code> that is fired by {@link #fireStateChanged()}.
+ */
+ protected ChangeEvent changeEvent = new ChangeEvent(this);
+
+ /**
+ * Stores all registered event listeners.
+ */
+ protected EventListenerList listenerList = new EventListenerList();
+
+ /**
+ * Our document listener.
+ */
+ DocumentListener documentListener;
+
+ /**
+ * Our property listener.
+ */
+ PropertyChangeListener propertyChangeListener;
+
+ /**
+ * The text component in which this caret is installed.
+ *
+ * (Package private to avoid synthetic accessor method.)
+ */
+ JTextComponent textComponent;
+
+ /**
+ * Indicates if the selection should be visible or not.
+ */
+ private boolean selectionVisible = true;
+
+ /**
+ * The blink rate of this <code>Caret</code>.
+ */
+ private int blinkRate = 500;
+
+ /**
+ * The current dot position.
+ */
+ private int dot = 0;
+
+ /**
+ * The current mark position.
+ */
+ private int mark = 0;
+
+ /**
+ * The current visual caret position.
+ */
+ private Point magicCaretPosition = null;
+
+ /**
+ * Indicates if this <code>Caret</code> is currently visible or not. This is
+ * package private to avoid an accessor method.
+ */
+ boolean visible = false;
+
+ /** Indicates whether the text component where the caret is installed is
+ * editable and enabled. If either of these properties is <code>false</code>
+ * the caret is not drawn.
+ */
+ boolean active = true;
+
+ /**
+ * The current highlight entry.
+ */
+ private Object highlightEntry;
+
+ private Timer blinkTimer;
+
+ private BlinkTimerListener blinkListener;
+
+ /**
+ * A <code>NavigationFilter.FilterBypass</code> instance which
+ * is provided to the a <code>NavigationFilter</code> to
+ * unconditionally set or move the caret.
+ */
+ NavigationFilter.FilterBypass bypass;
+
+ /**
+ * Creates a new <code>DefaultCaret</code> instance.
+ */
+ public DefaultCaret()
+ {
+ // Nothing to do here.
+ }
+
+ /** Returns the caret's <code>NavigationFilter.FilterBypass</code> instance
+ * and creates it if it does not yet exist.
+ *
+ * @return The caret's <code>NavigationFilter.FilterBypass</code> instance.
+ */
+ private NavigationFilter.FilterBypass getBypass()
+ {
+ return (bypass == null) ? bypass = new Bypass() : bypass;
+ }
+
+ /**
+ * Sets the Caret update policy.
+ *
+ * @param policy the new policy. Valid values are:
+ * ALWAYS_UPDATE: always update the Caret position, even when Document
+ * updates don't occur on the Event Dispatcher thread.
+ * NEVER_UPDATE: don't update the Caret position unless the Document
+ * length becomes less than the Caret position (then update the
+ * Caret to the end of the Document).
+ * UPDATE_WHEN_ON_EDT: update the Caret position when the
+ * Document updates occur on the Event Dispatcher thread. This is the
+ * default.
+ *
+ * @since 1.5
+ * @throws IllegalArgumentException if policy is not one of the above.
+ */
+ public void setUpdatePolicy (int policy)
+ {
+ if (policy != ALWAYS_UPDATE && policy != NEVER_UPDATE
+ && policy != UPDATE_WHEN_ON_EDT)
+ throw new
+ IllegalArgumentException
+ ("policy must be ALWAYS_UPDATE, NEVER__UPDATE, or UPDATE_WHEN_ON_EDT");
+ this.policy = policy;
+ }
+
+ /**
+ * Gets the caret update policy.
+ *
+ * @return the caret update policy.
+ * @since 1.5
+ */
+ public int getUpdatePolicy ()
+ {
+ return policy;
+ }
+
+ /**
+ * Moves the caret position when the mouse is dragged over the text
+ * component, modifying the selectiony.
+ *
+ * <p>When the text component where the caret is installed is disabled,
+ * the selection is not change but you can still scroll the text and
+ * update the caret's location.</p>
+ *
+ * @param event the <code>MouseEvent</code> describing the drag operation
+ */
+ public void mouseDragged(MouseEvent event)
+ {
+ if (event.getButton() == MouseEvent.BUTTON1)
+ {
+ if (textComponent.isEnabled())
+ moveCaret(event);
+ else
+ positionCaret(event);
+ }
+ }
+
+ /**
+ * Indicates a mouse movement over the text component. Does nothing here.
+ *
+ * @param event the <code>MouseEvent</code> describing the mouse operation
+ */
+ public void mouseMoved(MouseEvent event)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * When the click is received from Button 1 then the following actions
+ * are performed here:
+ *
+ * <ul>
+ * <li>If we receive a double click, the caret position (dot) is set
+ * to the position associated to the mouse click and the word at
+ * this location is selected. If there is no word at the pointer
+ * the gap is selected instead.</li>
+ * <li>If we receive a triple click, the caret position (dot) is set
+ * to the position associated to the mouse click and the line at
+ * this location is selected.</li>
+ * </ul>
+ *
+ * @param event the <code>MouseEvent</code> describing the click operation
+ */
+ public void mouseClicked(MouseEvent event)
+ {
+ // Do not modify selection if component is disabled.
+ if (!textComponent.isEnabled())
+ return;
+
+ int count = event.getClickCount();
+
+ if (event.getButton() == MouseEvent.BUTTON1 && count >= 2)
+ {
+ int newDot = getComponent().viewToModel(event.getPoint());
+ JTextComponent t = getComponent();
+
+ try
+ {
+ if (count == 3)
+ {
+ setDot(Utilities.getRowStart(t, newDot));
+ moveDot( Utilities.getRowEnd(t, newDot));
+ }
+ else
+ {
+ int wordStart = Utilities.getWordStart(t, newDot);
+
+ // When the mouse points at the offset of the first character
+ // in a word Utilities().getPreviousWord will not return that
+ // word but we want to select that. We have to use
+ // Utilities.getWordStart() to get it.
+ if (newDot == wordStart)
+ {
+ setDot(wordStart);
+ moveDot(Utilities.getWordEnd(t, wordStart));
+ }
+ else
+ {
+ int nextWord = Utilities.getNextWord(t, newDot);
+ int previousWord = Utilities.getPreviousWord(t, newDot);
+ int previousWordEnd = Utilities.getWordEnd(t, previousWord);
+
+ // If the user clicked in the space between two words,
+ // then select the space.
+ if (newDot >= previousWordEnd && newDot <= nextWord)
+ {
+ setDot(previousWordEnd);
+ moveDot(nextWord);
+ }
+ // Otherwise select the word under the mouse pointer.
+ else
+ {
+ setDot(previousWord);
+ moveDot(previousWordEnd);
+ }
+ }
+ }
+ }
+ catch(BadLocationException ble)
+ {
+ // TODO: Swallowing ok here?
+ }
+ }
+
+ }
+
+ /**
+ * Indicates that the mouse has entered the text component. Nothing is done
+ * here.
+ *
+ * @param event the <code>MouseEvent</code> describing the mouse operation
+ */
+ public void mouseEntered(MouseEvent event)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Indicates that the mouse has exited the text component. Nothing is done
+ * here.
+ *
+ * @param event the <code>MouseEvent</code> describing the mouse operation
+ */
+ public void mouseExited(MouseEvent event)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * If the button 1 is pressed, the caret position is updated to the
+ * position of the mouse click and the text component requests the input
+ * focus if it is enabled. If the SHIFT key is held down, the caret will
+ * be moved, which might select the text between the old and new location.
+ *
+ * @param event the <code>MouseEvent</code> describing the press operation
+ */
+ public void mousePressed(MouseEvent event)
+ {
+
+ // The implementation assumes that consuming the event makes the AWT event
+ // mechanism forget about this event instance and not transfer focus.
+ // By observing how the RI reacts the following behavior has been
+ // implemented (in regard to text components):
+ // - a left-click moves the caret
+ // - a left-click when shift is held down expands the selection
+ // - a right-click or click with any additional mouse button
+ // on a text component is ignored
+ // - a middle-click positions the caret and pastes the clipboard
+ // contents.
+ // - a middle-click when shift is held down is ignored
+
+ if (SwingUtilities.isLeftMouseButton(event))
+ {
+ // Handle the caret.
+ if (event.isShiftDown() && getDot() != -1)
+ {
+ moveCaret(event);
+ }
+ else
+ {
+ positionCaret(event);
+ }
+
+ // Handle the focus.
+ if (textComponent != null && textComponent.isEnabled()
+ && textComponent.isRequestFocusEnabled())
+ {
+ textComponent.requestFocus();
+ }
+
+ // TODO: Handle double click for selecting words.
+ }
+ else if(event.getButton() == MouseEvent.BUTTON2)
+ {
+ // Special handling for X11-style pasting.
+ if (! event.isShiftDown())
+ {
+ positionCaret(event);
+ textComponent.paste();
+ }
+ }
+ }
+
+ /**
+ * Indicates that a mouse button has been released on the text component.
+ * Nothing is done here.
+ *
+ * @param event the <code>MouseEvent</code> describing the mouse operation
+ */
+ public void mouseReleased(MouseEvent event)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Sets the caret to <code>visible</code> if the text component is editable.
+ *
+ * @param event the <code>FocusEvent</code>
+ */
+ public void focusGained(FocusEvent event)
+ {
+ if (textComponent.isEditable())
+ {
+ setVisible(true);
+ updateTimerStatus();
+ }
+ }
+
+ /**
+ * Sets the caret to <code>invisible</code>.
+ *
+ * @param event the <code>FocusEvent</code>
+ */
+ public void focusLost(FocusEvent event)
+ {
+ if (textComponent.isEditable() && event.isTemporary() == false)
+ {
+ setVisible(false);
+
+ // Stop the blinker, if running.
+ if (blinkTimer != null && blinkTimer.isRunning())
+ blinkTimer.stop();
+ }
+ }
+
+ /**
+ * Install (if not present) and start the timer, if the caret must blink. The
+ * caret does not blink if it is invisible, or the component is disabled or
+ * not editable.
+ */
+ private void updateTimerStatus()
+ {
+ if (textComponent.isEnabled() && textComponent.isEditable())
+ {
+ if (blinkTimer == null)
+ initBlinkTimer();
+ if (!blinkTimer.isRunning())
+ blinkTimer.start();
+ }
+ else
+ {
+ if (blinkTimer != null)
+ blinkTimer.stop();
+ }
+ }
+
+ /**
+ * Moves the caret to the position specified in the <code>MouseEvent</code>.
+ * This will cause a selection if the dot and mark are different.
+ *
+ * @param event the <code>MouseEvent</code> from which to fetch the position
+ */
+ protected void moveCaret(MouseEvent event)
+ {
+ int newDot = getComponent().viewToModel(event.getPoint());
+ moveDot(newDot);
+ }
+
+ /**
+ * Repositions the caret to the position specified in the
+ * <code>MouseEvent</code>.
+ *
+ * @param event the <code>MouseEvent</code> from which to fetch the position
+ */
+ protected void positionCaret(MouseEvent event)
+ {
+ int newDot = getComponent().viewToModel(event.getPoint());
+ setDot(newDot);
+ }
+
+ /**
+ * Deinstalls this <code>Caret</code> from the specified
+ * <code>JTextComponent</code>. This removes any listeners that have been
+ * registered by this <code>Caret</code>.
+ *
+ * @param c the text component from which to install this caret
+ */
+ public void deinstall(JTextComponent c)
+ {
+ textComponent.removeFocusListener(this);
+ textComponent.removeMouseListener(this);
+ textComponent.removeMouseMotionListener(this);
+ textComponent.getDocument().removeDocumentListener(documentListener);
+ documentListener = null;
+ textComponent.removePropertyChangeListener(propertyChangeListener);
+ propertyChangeListener = null;
+ textComponent = null;
+
+ // Deinstall blink timer if present.
+ if (blinkTimer != null)
+ blinkTimer.stop();
+ blinkTimer = null;
+ }
+
+ /**
+ * Installs this <code>Caret</code> on the specified
+ * <code>JTextComponent</code>. This registers a couple of listeners
+ * on the text component.
+ *
+ * @param c the text component on which to install this caret
+ */
+ public void install(JTextComponent c)
+ {
+ textComponent = c;
+ textComponent.addFocusListener(this);
+ textComponent.addMouseListener(this);
+ textComponent.addMouseMotionListener(this);
+ propertyChangeListener = new PropertyChangeHandler();
+ textComponent.addPropertyChangeListener(propertyChangeListener);
+ documentListener = new DocumentHandler();
+
+ Document doc = textComponent.getDocument();
+ if (doc != null)
+ doc.addDocumentListener(documentListener);
+
+ active = textComponent.isEditable() && textComponent.isEnabled();
+
+ repaint();
+ }
+
+ /**
+ * Sets the current visual position of this <code>Caret</code>.
+ *
+ * @param p the Point to use for the saved location. May be <code>null</code>
+ * to indicate that there is no visual location
+ */
+ public void setMagicCaretPosition(Point p)
+ {
+ magicCaretPosition = p;
+ }
+
+ /**
+ * Returns the current visual position of this <code>Caret</code>.
+ *
+ * @return the current visual position of this <code>Caret</code>
+ *
+ * @see #setMagicCaretPosition
+ */
+ public Point getMagicCaretPosition()
+ {
+ return magicCaretPosition;
+ }
+
+ /**
+ * Returns the current position of the <code>mark</code>. The
+ * <code>mark</code> marks the location in the <code>Document</code> that
+ * is the end of a selection. If there is no selection, the <code>mark</code>
+ * is the same as the <code>dot</code>.
+ *
+ * @return the current position of the mark
+ */
+ public int getMark()
+ {
+ return mark;
+ }
+
+ private void clearHighlight()
+ {
+ Highlighter highlighter = textComponent.getHighlighter();
+
+ if (highlighter == null)
+ return;
+
+ if (selectionVisible)
+ {
+ try
+ {
+ if (highlightEntry != null)
+ highlighter.changeHighlight(highlightEntry, 0, 0);
+
+ // Free the global variable which stores the text component with an active
+ // selection.
+ if (componentWithSelection == textComponent)
+ componentWithSelection = null;
+ }
+ catch (BadLocationException e)
+ {
+ // This should never happen.
+ throw new InternalError();
+ }
+ }
+ else
+ {
+ if (highlightEntry != null)
+ {
+ highlighter.removeHighlight(highlightEntry);
+ highlightEntry = null;
+ }
+ }
+ }
+
+ private void handleHighlight()
+ {
+ Highlighter highlighter = textComponent.getHighlighter();
+
+ if (highlighter == null)
+ return;
+
+ int p0 = Math.min(dot, mark);
+ int p1 = Math.max(dot, mark);
+
+ if (selectionVisible)
+ {
+ try
+ {
+ if (highlightEntry == null)
+ highlightEntry = highlighter.addHighlight(p0, p1, getSelectionPainter());
+ else
+ highlighter.changeHighlight(highlightEntry, p0, p1);
+
+ // If another component currently has a text selection clear that selection
+ // first.
+ if (componentWithSelection != null)
+ if (componentWithSelection != textComponent)
+ {
+ Caret c = componentWithSelection.getCaret();
+ c.setDot(c.getDot());
+ }
+ componentWithSelection = textComponent;
+
+ }
+ catch (BadLocationException e)
+ {
+ // This should never happen.
+ throw new InternalError();
+ }
+ }
+ else
+ {
+ if (highlightEntry != null)
+ {
+ highlighter.removeHighlight(highlightEntry);
+ highlightEntry = null;
+ }
+ }
+ }
+
+ /**
+ * Sets the visiblity state of the selection.
+ *
+ * @param v <code>true</code> if the selection should be visible,
+ * <code>false</code> otherwise
+ */
+ public void setSelectionVisible(boolean v)
+ {
+ if (selectionVisible == v)
+ return;
+
+ selectionVisible = v;
+ handleHighlight();
+ repaint();
+ }
+
+ /**
+ * Returns <code>true</code> if the selection is currently visible,
+ * <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if the selection is currently visible,
+ * <code>false</code> otherwise
+ */
+ public boolean isSelectionVisible()
+ {
+ return selectionVisible;
+ }
+
+ /**
+ * Causes the <code>Caret</code> to repaint itself.
+ */
+ protected final void repaint()
+ {
+ getComponent().repaint(x, y, width, height);
+ }
+
+ /**
+ * Paints this <code>Caret</code> using the specified <code>Graphics</code>
+ * context.
+ *
+ * @param g the graphics context to use
+ */
+ public void paint(Graphics g)
+ {
+ JTextComponent comp = getComponent();
+ if (comp == null)
+ return;
+
+ // Make sure the dot has a sane position.
+ dot = Math.min(dot, textComponent.getDocument().getLength());
+ dot = Math.max(dot, 0);
+
+ Rectangle rect = null;
+
+ try
+ {
+ rect = textComponent.modelToView(dot);
+ }
+ catch (BadLocationException e)
+ {
+ // Let's ignore that. This shouldn't really occur. But if it
+ // does (it seems that this happens when the model is mutating),
+ // it causes no real damage. Uncomment this for debugging.
+ // e.printStackTrace();
+ }
+
+ if (rect == null)
+ return;
+
+ // Check if paint has possibly been called directly, without a previous
+ // call to damage(). In this case we need to do some cleanup first.
+ if ((x != rect.x) || (y != rect.y))
+ {
+ repaint(); // Erase previous location of caret.
+ x = rect.x;
+ y = rect.y;
+ width = 1;
+ height = rect.height;
+ }
+
+ // Now draw the caret on the new position if visible.
+ if (visible && active)
+ {
+ g.setColor(textComponent.getCaretColor());
+ g.drawLine(rect.x, rect.y, rect.x, rect.y + rect.height - 1);
+ }
+ }
+
+ /**
+ * Returns all registered event listeners of the specified type.
+ *
+ * @param listenerType the type of listener to return
+ *
+ * @return all registered event listeners of the specified type
+ */
+ public EventListener[] getListeners(Class listenerType)
+ {
+ return listenerList.getListeners(listenerType);
+ }
+
+ /**
+ * Registers a {@link ChangeListener} that is notified whenever that state
+ * of this <code>Caret</code> changes.
+ *
+ * @param listener the listener to register to this caret
+ */
+ public void addChangeListener(ChangeListener listener)
+ {
+ listenerList.add(ChangeListener.class, listener);
+ }
+
+ /**
+ * Removes a {@link ChangeListener} from the list of registered listeners.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeChangeListener(ChangeListener listener)
+ {
+ listenerList.remove(ChangeListener.class, listener);
+ }
+
+ /**
+ * Returns all registered {@link ChangeListener}s of this <code>Caret</code>.
+ *
+ * @return all registered {@link ChangeListener}s of this <code>Caret</code>
+ */
+ public ChangeListener[] getChangeListeners()
+ {
+ return (ChangeListener[]) getListeners(ChangeListener.class);
+ }
+
+ /**
+ * Notifies all registered {@link ChangeListener}s that the state
+ * of this <code>Caret</code> has changed.
+ */
+ protected void fireStateChanged()
+ {
+ ChangeListener[] listeners = getChangeListeners();
+
+ for (int index = 0; index < listeners.length; ++index)
+ listeners[index].stateChanged(changeEvent);
+ }
+
+ /**
+ * Returns the <code>JTextComponent</code> on which this <code>Caret</code>
+ * is installed.
+ *
+ * @return the <code>JTextComponent</code> on which this <code>Caret</code>
+ * is installed
+ */
+ protected final JTextComponent getComponent()
+ {
+ return textComponent;
+ }
+
+ /**
+ * Returns the blink rate of this <code>Caret</code> in milliseconds.
+ * A value of <code>0</code> means that the caret does not blink.
+ *
+ * @return the blink rate of this <code>Caret</code> or <code>0</code> if
+ * this caret does not blink
+ */
+ public int getBlinkRate()
+ {
+ return blinkRate;
+ }
+
+ /**
+ * Sets the blink rate of this <code>Caret</code> in milliseconds.
+ * A value of <code>0</code> means that the caret does not blink.
+ *
+ * @param rate the new blink rate to set
+ */
+ public void setBlinkRate(int rate)
+ {
+ if (blinkTimer != null)
+ blinkTimer.setDelay(rate);
+ blinkRate = rate;
+ }
+
+ /**
+ * Returns the current position of this <code>Caret</code> within the
+ * <code>Document</code>.
+ *
+ * @return the current position of this <code>Caret</code> within the
+ * <code>Document</code>
+ */
+ public int getDot()
+ {
+ return dot;
+ }
+
+ /**
+ * Moves the <code>dot</code> location without touching the
+ * <code>mark</code>. This is used when making a selection.
+ *
+ * <p>If the underlying text component has a {@link NavigationFilter}
+ * installed the caret will call the corresponding method of that object.</p>
+ *
+ * @param dot the location where to move the dot
+ *
+ * @see #setDot(int)
+ */
+ public void moveDot(int dot)
+ {
+ NavigationFilter filter = textComponent.getNavigationFilter();
+ if (filter != null)
+ filter.moveDot(getBypass(), dot, Bias.Forward);
+ else
+ moveDotImpl(dot);
+ }
+
+ void moveDotImpl(int dot)
+ {
+ if (dot >= 0)
+ {
+ Document doc = textComponent.getDocument();
+ if (doc != null)
+ this.dot = Math.min(dot, doc.getLength());
+ this.dot = Math.max(this.dot, 0);
+
+ handleHighlight();
+
+ appear();
+
+ adjustVisibility(this);
+ }
+ }
+
+ /**
+ * Sets the current position of this <code>Caret</code> within the
+ * <code>Document</code>. This also sets the <code>mark</code> to the new
+ * location.
+ *
+ * <p>If the underlying text component has a {@link NavigationFilter}
+ * installed the caret will call the corresponding method of that object.</p>
+ *
+ * @param dot
+ * the new position to be set
+ * @see #moveDot(int)
+ */
+ public void setDot(int dot)
+ {
+ NavigationFilter filter = textComponent.getNavigationFilter();
+ if (filter != null)
+ filter.setDot(getBypass(), dot, Bias.Forward);
+ else
+ setDotImpl(dot);
+ }
+
+ void setDotImpl(int dot)
+ {
+ if (dot >= 0)
+ {
+ Document doc = textComponent.getDocument();
+ if (doc != null)
+ this.dot = Math.min(dot, doc.getLength());
+ this.dot = Math.max(this.dot, 0);
+ this.mark = this.dot;
+
+ clearHighlight();
+
+ appear();
+
+ adjustVisibility(this);
+ }
+ }
+
+ /**
+ * Show the caret (may be hidden due blinking) and adjust the timer not to
+ * hide it (possibly immediately).
+ *
+ * @author Audrius Meskauskas (AudriusA at Bioinformatics.org)
+ */
+ void appear()
+ {
+ // All machinery is only required if the carret is blinking.
+ if (blinkListener != null)
+ {
+ blinkListener.ignoreNextEvent = true;
+
+ // If the caret is visible, erase the current position by repainting
+ // over.
+ if (visible)
+ repaint();
+
+ // Draw the caret in the new position.
+ visible = true;
+
+ Rectangle area = null;
+ int dot = getDot();
+ try
+ {
+ area = getComponent().modelToView(dot);
+ }
+ catch (BadLocationException e)
+ {
+ // Let's ignore that. This shouldn't really occur. But if it
+ // does (it seems that this happens when the model is mutating),
+ // it causes no real damage. Uncomment this for debugging.
+ // e.printStackTrace();
+ }
+ if (area != null)
+ damage(area);
+ }
+ repaint();
+ }
+
+ /**
+ * Returns <code>true</code> if this <code>Caret</code> is blinking,
+ * and <code>false</code> if not. The returned value is independent of
+ * the visiblity of this <code>Caret</code> as returned by {@link #isVisible()}.
+ *
+ * @return <code>true</code> if this <code>Caret</code> is blinking,
+ * and <code>false</code> if not.
+ * @see #isVisible()
+ * @since 1.5
+ */
+ public boolean isActive()
+ {
+ if (blinkTimer != null)
+ return blinkTimer.isRunning();
+
+ return false;
+ }
+
+ /**
+ * Returns <code>true</code> if this <code>Caret</code> is currently visible,
+ * and <code>false</code> if it is not.
+ *
+ * @return <code>true</code> if this <code>Caret</code> is currently visible,
+ * and <code>false</code> if it is not
+ */
+ public boolean isVisible()
+ {
+ return visible && active;
+ }
+
+ /**
+ * Sets the visibility state of the caret. <code>true</code> shows the
+ * <code>Caret</code>, <code>false</code> hides it.
+ *
+ * @param v the visibility to set
+ */
+ public void setVisible(boolean v)
+ {
+ if (v != visible)
+ {
+ visible = v;
+ updateTimerStatus();
+ Rectangle area = null;
+ int dot = getDot();
+ try
+ {
+ area = getComponent().modelToView(dot);
+ }
+ catch (BadLocationException e)
+ {
+ AssertionError ae;
+ ae = new AssertionError("Unexpected bad caret location: " + dot);
+ ae.initCause(e);
+ throw ae;
+ }
+ if (area != null)
+ damage(area);
+ }
+ }
+
+ /**
+ * Returns the {@link Highlighter.HighlightPainter} that should be used
+ * to paint the selection.
+ *
+ * @return the {@link Highlighter.HighlightPainter} that should be used
+ * to paint the selection
+ */
+ protected Highlighter.HighlightPainter getSelectionPainter()
+ {
+ return DefaultHighlighter.DefaultPainter;
+ }
+
+ /**
+ * Updates the carets rectangle properties to the specified rectangle and
+ * repaints the caret.
+ *
+ * @param r the rectangle to set as the caret rectangle
+ */
+ protected void damage(Rectangle r)
+ {
+ if (r == null)
+ return;
+ x = r.x;
+ y = r.y;
+ width = 1;
+ // height is normally set in paint and we leave it untouched. However, we
+ // must set a valid value here, since otherwise the painting mechanism
+ // sets a zero clip and never calls paint.
+ if (height <= 0)
+ try
+ {
+ height = textComponent.modelToView(dot).height;
+ }
+ catch (BadLocationException ble)
+ {
+ // Should not happen.
+ throw new InternalError("Caret location not within document range.");
+ }
+
+ repaint();
+ }
+
+ /**
+ * Adjusts the text component so that the caret is visible. This default
+ * implementation simply calls
+ * {@link JComponent#scrollRectToVisible(Rectangle)} on the text component.
+ * Subclasses may wish to change this.
+ */
+ protected void adjustVisibility(Rectangle rect)
+ {
+ getComponent().scrollRectToVisible(rect);
+ }
+
+ /**
+ * Initializes the blink timer.
+ */
+ private void initBlinkTimer()
+ {
+ // Setup the blink timer.
+ blinkListener = new BlinkTimerListener();
+ blinkTimer = new Timer(getBlinkRate(), blinkListener);
+ blinkTimer.setRepeats(true);
+ }
+
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultEditorKit.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultEditorKit.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultEditorKit.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultEditorKit.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,1657 @@
+/* DefaultEditorKit.java --
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Point;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+
+import javax.swing.Action;
+import javax.swing.SwingConstants;
+
+/**
+ * The default implementation of {@link EditorKit}. This <code>EditorKit</code>
+ * a plain text <code>Document</code> and several commands that together
+ * make up a basic editor, like cut / copy + paste.
+ *
+ * @author original author unknown
+ * @author Roman Kennke (roman at kennke.org)
+ * @author Robert Schuster (robertschuster at fsfe.org)
+ */
+public class DefaultEditorKit extends EditorKit
+{
+ static class SelectionPreviousWordAction
+ extends TextAction
+ {
+ SelectionPreviousWordAction()
+ {
+ super(selectionPreviousWordAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ try
+ {
+ JTextComponent t = getTextComponent(event);
+
+ if (t != null)
+ {
+ int offs = Utilities.getPreviousWord(t, t.getCaretPosition());
+
+ Caret c = t.getCaret();
+ c.moveDot(offs);
+ c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+ }
+ }
+ catch(BadLocationException ble)
+ {
+ // Can't happen.
+ }
+ }
+ }
+
+ static class SelectionNextWordAction
+ extends TextAction
+ {
+ SelectionNextWordAction()
+ {
+ super(selectionNextWordAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ try
+ {
+ JTextComponent t = getTextComponent(event);
+
+ if (t != null)
+ {
+ int offs = Utilities.getNextWord(t, t.getCaretPosition());
+
+ Caret c = t.getCaret();
+ c.moveDot(offs);
+ c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+ }
+ }
+ catch(BadLocationException ble)
+ {
+ // Can't happen.
+ }
+ }
+ }
+
+ static class SelectionBeginWordAction extends TextAction
+ {
+ SelectionBeginWordAction()
+ {
+ super(selectionBeginWordAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ try
+ {
+ JTextComponent t = getTextComponent(event);
+
+ if (t != null)
+ {
+ int offs = Utilities.getWordStart(t, t.getCaretPosition());
+
+ Caret c = t.getCaret();
+ c.moveDot(offs);
+ c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+ }
+ }
+ catch(BadLocationException ble)
+ {
+ // Can't happen.
+ }
+ }
+ }
+
+ static class SelectionEndWordAction extends TextAction
+ {
+ SelectionEndWordAction()
+ {
+ super(selectionEndWordAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ try
+ {
+ JTextComponent t = getTextComponent(event);
+
+ if (t != null)
+ {
+ int offs = Utilities.getWordEnd(t, t.getCaretPosition());
+
+ Caret c = t.getCaret();
+ c.moveDot(offs);
+ c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+ }
+ }
+ catch(BadLocationException ble)
+ {
+ // Can't happen.
+ }
+ }
+ }
+
+ static class BeginWordAction extends TextAction
+ {
+ BeginWordAction()
+ {
+ super(beginWordAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ try
+ {
+ JTextComponent t = getTextComponent(event);
+
+ if (t != null)
+ {
+ int offs = Utilities.getWordStart(t, t.getCaretPosition());
+
+ Caret c = t.getCaret();
+ c.setDot(offs);
+ c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+ }
+ }
+ catch(BadLocationException ble)
+ {
+ // Can't happen.
+ }
+ }
+ }
+
+ static class EndWordAction extends TextAction
+ {
+ EndWordAction()
+ {
+ super(endWordAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ try
+ {
+ JTextComponent t = getTextComponent(event);
+
+ if (t != null)
+ {
+ int offs = Utilities.getWordEnd(t, t.getCaretPosition());
+
+ Caret c = t.getCaret();
+ c.setDot(offs);
+ c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+ }
+ }
+ catch(BadLocationException ble)
+ {
+ // Can't happen.
+ }
+ }
+ }
+
+ static class PreviousWordAction
+ extends TextAction
+ {
+ PreviousWordAction()
+ {
+ super(previousWordAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ try
+ {
+ JTextComponent t = getTextComponent(event);
+
+ if (t != null)
+ {
+ int offs = Utilities.getPreviousWord(t, t.getCaretPosition());
+
+ Caret c = t.getCaret();
+ c.setDot(offs);
+ c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+ }
+ }
+ catch(BadLocationException ble)
+ {
+ // Can't happen.
+ }
+ }
+ }
+
+ static class NextWordAction
+ extends TextAction
+ {
+ NextWordAction()
+ {
+ super(nextWordAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ try
+ {
+ JTextComponent t = getTextComponent(event);
+
+ if (t != null)
+ {
+ int offs = Utilities.getNextWord(t, t.getCaretPosition());
+
+ Caret c = t.getCaret();
+ c.setDot(offs);
+ c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+ }
+ }
+ catch(BadLocationException ble)
+ {
+ // Can't happen.
+ }
+ }
+ }
+
+ static class SelectAllAction
+ extends TextAction
+ {
+ SelectAllAction()
+ {
+ super(selectAllAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ JTextComponent t = getTextComponent(event);
+ int offs = t.getDocument().getLength();
+ Caret c = t.getCaret();
+ c.setDot(0);
+ c.moveDot(offs);
+
+ try
+ {
+ c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+ }
+ catch(BadLocationException ble)
+ {
+ // Can't happen.
+ }
+ }
+ }
+
+ static class SelectionBeginAction
+ extends TextAction
+ {
+ SelectionBeginAction()
+ {
+ super(selectionBeginAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ JTextComponent t = getTextComponent(event);
+ Caret c = t.getCaret();
+ c.moveDot(0);
+ try
+ {
+ c.setMagicCaretPosition(t.modelToView(0).getLocation());
+ }
+ catch(BadLocationException ble)
+ {
+ // Can't happen.
+ }
+ }
+ }
+
+ static class SelectionEndAction
+ extends TextAction
+ {
+ SelectionEndAction()
+ {
+ super(selectionEndAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ JTextComponent t = getTextComponent(event);
+ int offs = t.getDocument().getLength();
+ Caret c = t.getCaret();
+ c.moveDot(offs);
+ try
+ {
+ c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+ }
+ catch(BadLocationException ble)
+ {
+ // Can't happen.
+ }
+ }
+ }
+
+ static class SelectionBeginLineAction
+ extends TextAction
+ {
+
+ SelectionBeginLineAction()
+ {
+ super(selectionBeginLineAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ JTextComponent t = getTextComponent(event);
+ Caret c = t.getCaret();
+ try
+ {
+ int offs = Utilities.getRowStart(t, c.getDot());
+ c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+ }
+ catch(BadLocationException ble)
+ {
+ // Can't happen.
+ }
+
+ }
+ }
+
+ static class SelectionEndLineAction
+ extends TextAction
+ {
+ SelectionEndLineAction()
+ {
+ super(selectionEndLineAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ JTextComponent t = getTextComponent(event);
+ Caret c = t.getCaret();
+ try
+ {
+ int offs = Utilities.getRowEnd(t, c.getDot());
+ c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+ }
+ catch(BadLocationException ble)
+ {
+ // Can't happen.
+ }
+
+ }
+ }
+
+ static class SelectLineAction extends TextAction
+ {
+ SelectLineAction()
+ {
+ super(selectLineAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ JTextComponent t = getTextComponent(event);
+ Caret c = t.getCaret();
+ try
+ {
+ int offs1 = Utilities.getRowStart(t, c.getDot());
+ int offs2 = Utilities.getRowEnd(t, c.getDot());
+
+ c.setDot(offs2);
+ c.moveDot(offs1);
+
+ c.setMagicCaretPosition(t.modelToView(offs2).getLocation());
+ }
+ catch(BadLocationException ble)
+ {
+ // Can't happen.
+ }
+ }
+ }
+
+ static class SelectWordAction extends TextAction
+ {
+ SelectWordAction()
+ {
+ super(selectWordAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ JTextComponent t = getTextComponent(event);
+ Caret c = t.getCaret();
+ int dot = c.getDot();
+
+ try
+ {
+ int wordStart = Utilities.getWordStart(t, dot);
+
+ if (dot == wordStart)
+ {
+ // Current cursor position is on the first character in a word.
+ c.setDot(wordStart);
+ c.moveDot(Utilities.getWordEnd(t, wordStart));
+ }
+ else
+ {
+ // Current cursor position is not on the first character
+ // in a word.
+ int nextWord = Utilities.getNextWord(t, dot);
+ int previousWord = Utilities.getPreviousWord(t, dot);
+ int previousWordEnd = Utilities.getWordEnd(t, previousWord);
+
+ // Cursor position is in the space between two words. In such a
+ // situation just select the space.
+ if (dot >= previousWordEnd && dot <= nextWord)
+ {
+ c.setDot(previousWordEnd);
+ c.moveDot(nextWord);
+ }
+ else
+ {
+ // Cursor position is inside a word. Just select it then.
+ c.setDot(previousWord);
+ c.moveDot(previousWordEnd);
+ }
+ }
+
+ // If the position was updated change the magic caret position
+ // as well.
+ if (c.getDot() != dot)
+ c.setMagicCaretPosition(t.modelToView(c.getDot()).getLocation());
+
+ }
+ catch(BadLocationException ble)
+ {
+ // Can't happen.
+ }
+ }
+ }
+
+ static class SelectionDownAction
+ extends TextAction.VerticalMovementAction
+ {
+ SelectionDownAction()
+ {
+ super(selectionDownAction, SwingConstants.SOUTH);
+ }
+
+ protected void actionPerformedImpl(Caret c, int offs)
+ {
+ c.moveDot(offs);
+ }
+
+ }
+
+ static class SelectionUpAction
+ extends TextAction.VerticalMovementAction
+ {
+ SelectionUpAction()
+ {
+ super(selectionUpAction, SwingConstants.NORTH);
+ }
+
+ protected void actionPerformedImpl(Caret c, int offs)
+ {
+ c.moveDot(offs);
+ }
+
+ }
+
+ static class SelectionForwardAction
+ extends TextAction.HorizontalMovementAction
+ {
+ SelectionForwardAction()
+ {
+ super(selectionForwardAction, SwingConstants.EAST);
+ }
+
+ protected void actionPerformedImpl(Caret c, int offs)
+ {
+ c.moveDot(offs);
+ }
+ }
+
+ static class SelectionBackwardAction
+ extends TextAction.HorizontalMovementAction
+ {
+ SelectionBackwardAction()
+ {
+ super(selectionBackwardAction, SwingConstants.WEST);
+ }
+
+ protected void actionPerformedImpl(Caret c, int offs)
+ {
+ c.moveDot(offs);
+ }
+ }
+
+ static class DownAction
+ extends TextAction.VerticalMovementAction
+ {
+ DownAction()
+ {
+ super(downAction, SwingConstants.SOUTH);
+ }
+
+ protected void actionPerformedImpl(Caret c, int offs)
+ {
+ c.setDot(offs);
+ }
+ }
+
+ static class UpAction
+ extends TextAction.VerticalMovementAction
+ {
+ UpAction()
+ {
+ super(upAction, SwingConstants.NORTH);
+ }
+
+ protected void actionPerformedImpl(Caret c, int offs)
+ {
+ c.setDot(offs);
+ }
+
+ }
+
+ static class ForwardAction
+ extends TextAction.HorizontalMovementAction
+ {
+ ForwardAction()
+ {
+ super(forwardAction, SwingConstants.EAST);
+ }
+
+ protected void actionPerformedImpl(Caret c, int offs)
+ {
+ c.setDot(offs);
+ }
+
+ }
+
+ static class BackwardAction
+ extends TextAction.HorizontalMovementAction
+ {
+ BackwardAction()
+ {
+ super(backwardAction, SwingConstants.WEST);
+ }
+
+ protected void actionPerformedImpl(Caret c, int offs)
+ {
+ c.setDot(offs);
+ }
+
+ }
+
+ static class DeletePrevCharAction
+ extends TextAction
+ {
+ DeletePrevCharAction()
+ {
+ super(deletePrevCharAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ JTextComponent t = getTextComponent(event);
+ if (t != null)
+ {
+ try
+ {
+ int pos = t.getSelectionStart();
+ int len = t.getSelectionEnd() - pos;
+
+ if (len > 0)
+ t.getDocument().remove(pos, len);
+ else if (pos > 0)
+ {
+ pos--;
+ t.getDocument().remove(pos, 1);
+ Caret c = t.getCaret();
+ c.setDot(pos);
+ c.setMagicCaretPosition(t.modelToView(pos).getLocation());
+ }
+ }
+ catch (BadLocationException e)
+ {
+ // FIXME: we're not authorized to throw this.. swallow it?
+ }
+ }
+ }
+ }
+
+ static class DeleteNextCharAction
+ extends TextAction
+ {
+ DeleteNextCharAction()
+ {
+ super(deleteNextCharAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ JTextComponent t = getTextComponent(event);
+ if (t != null)
+ {
+ try
+ {
+ int pos = t.getSelectionStart();
+ int len = t.getSelectionEnd() - pos;
+
+ if (len > 0)
+ t.getDocument().remove(pos, len);
+ else if (pos < t.getDocument().getLength())
+ t.getDocument().remove(pos, 1);
+
+ Caret c = t.getCaret();
+ c.setDot(pos);
+ c.setMagicCaretPosition(t.modelToView(pos).getLocation());
+ }
+ catch (BadLocationException e)
+ {
+ // FIXME: we're not authorized to throw this.. swallow it?
+ }
+ }
+ }
+ }
+
+ static class EndLineAction
+ extends TextAction
+ {
+ EndLineAction()
+ {
+ super(endLineAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ JTextComponent t = getTextComponent(event);
+ try
+ {
+ int offs = Utilities.getRowEnd(t, t.getCaretPosition());
+
+ if (offs > -1)
+ {
+ Caret c = t.getCaret();
+ c.setDot(offs);
+ c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+ }
+ }
+ catch (BadLocationException ble)
+ {
+ // Nothing to do here
+ }
+ }
+ }
+
+ static class BeginLineAction
+ extends TextAction
+ {
+ BeginLineAction()
+ {
+ super(beginLineAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ JTextComponent t = getTextComponent(event);
+ try
+ {
+ int offs = Utilities.getRowStart(t, t.getCaretPosition());
+
+ if (offs > -1)
+ {
+ Caret c = t.getCaret();
+ c.setDot(offs);
+ c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+ }
+ }
+ catch (BadLocationException ble)
+ {
+ // Do nothing here.
+ }
+ }
+ }
+
+ static class BeginAction extends TextAction
+ {
+
+ BeginAction()
+ {
+ super(beginAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ JTextComponent t = getTextComponent(event);
+ Caret c = t.getCaret();
+ c.setDot(0);
+ try
+ {
+ c.setMagicCaretPosition(t.modelToView(0).getLocation());
+ }
+ catch(BadLocationException ble)
+ {
+ // Can't happen.
+ }
+ }
+ }
+
+ static class EndAction extends TextAction
+ {
+
+ EndAction()
+ {
+ super(endAction);
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ JTextComponent t = getTextComponent(event);
+ int offs = t.getDocument().getLength();
+ Caret c = t.getCaret();
+ c.setDot(offs);
+ try
+ {
+ c.setMagicCaretPosition(t.modelToView(offs).getLocation());
+ }
+ catch(BadLocationException ble)
+ {
+ // Can't happen.
+ }
+ }
+ }
+
+ /**
+ * Creates a beep on the PC speaker.
+ *
+ * @see Toolkit#beep()
+ */
+ public static class BeepAction extends TextAction
+ {
+ /**
+ * Creates a new <code>BeepAction</code>.
+ */
+ public BeepAction()
+ {
+ super(beepAction);
+ }
+
+ /**
+ * Performs the <code>Action</code>.
+ *
+ * @param event the action event describing the user action
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ Toolkit.getDefaultToolkit().beep();
+ }
+ }
+
+ /**
+ * Copies the selected content into the system clipboard.
+ *
+ * @see Toolkit#getSystemClipboard()
+ * @see CutAction
+ * @see PasteAction
+ */
+ public static class CopyAction extends TextAction
+ {
+
+ /**
+ * Create a new <code>CopyAction</code>.
+ */
+ public CopyAction()
+ {
+ super(copyAction);
+ }
+
+ /**
+ * Performs the <code>Action</code>.
+ *
+ * @param event the action event describing the user action
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ getTextComponent(event).copy();
+ }
+ }
+
+
+ /**
+ * Copies the selected content into the system clipboard and deletes the
+ * selection.
+ *
+ * @see Toolkit#getSystemClipboard()
+ * @see CopyAction
+ * @see PasteAction
+ */
+ public static class CutAction extends TextAction
+ {
+
+ /**
+ * Create a new <code>CutAction</code>.
+ */
+ public CutAction()
+ {
+ super(cutAction);
+ }
+
+ /**
+ * Performs the <code>Action</code>.
+ *
+ * @param event the action event describing the user action
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ getTextComponent(event).cut();
+ }
+ }
+
+ /**
+ * Copies content from the system clipboard into the editor.
+ *
+ * @see Toolkit#getSystemClipboard()
+ * @see CopyAction
+ * @see CutAction
+ */
+ public static class PasteAction extends TextAction
+ {
+
+ /**
+ * Create a new <code>PasteAction</code>.
+ */
+ public PasteAction()
+ {
+ super(pasteAction);
+ }
+
+ /**
+ * Performs the <code>Action</code>.
+ *
+ * @param event the action event describing the user action
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ getTextComponent(event).paste();
+ }
+ }
+
+ /**
+ * This action is executed as default action when a KEY_TYPED
+ * event is received and no keymap entry exists for that. The purpose
+ * of this action is to filter out a couple of characters. This includes
+ * the control characters and characters with the ALT-modifier.
+ *
+ * If an event does not get filtered, it is inserted into the document
+ * of the text component. If there is some text selected in the text
+ * component, this text will be replaced.
+ */
+ public static class DefaultKeyTypedAction
+ extends TextAction
+ {
+
+ /**
+ * Creates a new <code>DefaultKeyTypedAction</code>.
+ */
+ public DefaultKeyTypedAction()
+ {
+ super(defaultKeyTypedAction);
+ }
+
+ /**
+ * Performs the <code>Action</code>.
+ *
+ * @param event the action event describing the user action
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ // first we filter the following events:
+ // - control characters
+ // - key events with the ALT modifier (FIXME: filter that too!)
+ int cp = event.getActionCommand().codePointAt(0);
+ if (Character.isISOControl(cp))
+ return;
+
+ JTextComponent t = getTextComponent(event);
+ if (t != null && t.isEnabled() && t.isEditable())
+ t.replaceSelection(event.getActionCommand());
+ }
+ }
+
+ /**
+ * This action inserts a newline character into the document
+ * of the text component. This is typically triggered by hitting
+ * ENTER on the keyboard.
+ */
+ public static class InsertBreakAction extends TextAction
+ {
+
+ /**
+ * Creates a new <code>InsertBreakAction</code>.
+ */
+ public InsertBreakAction()
+ {
+ super(insertBreakAction);
+ }
+
+ /**
+ * Performs the <code>Action</code>.
+ *
+ * @param event the action event describing the user action
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ JTextComponent t = getTextComponent(event);
+ t.replaceSelection("\n");
+ }
+ }
+
+ /**
+ * Places content into the associated editor. If there currently is a
+ * selection, this selection is replaced.
+ */
+ // FIXME: Figure out what this Action is supposed to do. Obviously text
+ // that is entered by the user is inserted through DefaultKeyTypedAction.
+ public static class InsertContentAction extends TextAction
+ {
+
+ /**
+ * Creates a new <code>InsertContentAction</code>.
+ */
+ public InsertContentAction()
+ {
+ super(insertContentAction);
+ }
+
+ /**
+ * Performs the <code>Action</code>.
+ *
+ * @param event the action event describing the user action
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ // FIXME: Figure out what this Action is supposed to do. Obviously text
+ // that is entered by the user is inserted through DefaultKeyTypedAction.
+ }
+ }
+
+ /**
+ * Inserts a TAB character into the text editor.
+ */
+ public static class InsertTabAction extends TextAction
+ {
+
+ /**
+ * Creates a new <code>TabAction</code>.
+ */
+ public InsertTabAction()
+ {
+ super(insertTabAction);
+ }
+
+ /**
+ * Performs the <code>Action</code>.
+ *
+ * @param event the action event describing the user action
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ JTextComponent t = getTextComponent(event);
+ t.replaceSelection("\t");
+ }
+ }
+
+ /**
+ * The serial version of DefaultEditorKit.
+ */
+ private static final long serialVersionUID = 9017245433028523428L;
+
+ /**
+ * The name of the <code>Action</code> that moves the caret one character
+ * backwards.
+ *
+ * @see #getActions()
+ */
+ public static final String backwardAction = "caret-backward";
+
+ /**
+ * The name of the <code>Action</code> that creates a beep in the speaker.
+ *
+ * @see #getActions()
+ */
+ public static final String beepAction = "beep";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the beginning
+ * of the <code>Document</code>.
+ *
+ * @see #getActions()
+ */
+ public static final String beginAction = "caret-begin";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the beginning
+ * of the current line.
+ *
+ * @see #getActions()
+ */
+ public static final String beginLineAction = "caret-begin-line";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the beginning
+ * of the current paragraph.
+ *
+ * @see #getActions()
+ */
+ public static final String beginParagraphAction = "caret-begin-paragraph";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the beginning
+ * of the current word.
+ *
+ * @see #getActions()
+ */
+ public static final String beginWordAction = "caret-begin-word";
+
+ /**
+ * The name of the <code>Action</code> that copies the selected content
+ * into the system clipboard.
+ *
+ * @see #getActions()
+ */
+ public static final String copyAction = "copy-to-clipboard";
+
+ /**
+ * The name of the <code>Action</code> that copies the selected content
+ * into the system clipboard and removes the selection.
+ *
+ * @see #getActions()
+ */
+ public static final String cutAction = "cut-to-clipboard";
+
+ /**
+ * The name of the <code>Action</code> that is performed by default if
+ * a key is typed and there is no keymap entry.
+ *
+ * @see #getActions()
+ */
+ public static final String defaultKeyTypedAction = "default-typed";
+
+ /**
+ * The name of the <code>Action</code> that deletes the character that
+ * follows the current caret position.
+ *
+ * @see #getActions()
+ */
+ public static final String deleteNextCharAction = "delete-next";
+
+ /**
+ * The name of the <code>Action</code> that deletes the character that
+ * precedes the current caret position.
+ *
+ * @see #getActions()
+ */
+ public static final String deletePrevCharAction = "delete-previous";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret one line down.
+ *
+ * @see #getActions()
+ */
+ public static final String downAction = "caret-down";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the end
+ * of the <code>Document</code>.
+ *
+ * @see #getActions()
+ */
+ public static final String endAction = "caret-end";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the end
+ * of the current line.
+ *
+ * @see #getActions()
+ */
+ public static final String endLineAction = "caret-end-line";
+
+ /**
+ * When a document is read and an CRLF is encountered, then we add a property
+ * with this name and a value of "\r\n".
+ */
+ public static final String EndOfLineStringProperty = "__EndOfLine__";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the end
+ * of the current paragraph.
+ *
+ * @see #getActions()
+ */
+ public static final String endParagraphAction = "caret-end-paragraph";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the end
+ * of the current word.
+ *
+ * @see #getActions()
+ */
+ public static final String endWordAction = "caret-end-word";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret one character
+ * forward.
+ *
+ * @see #getActions()
+ */
+ public static final String forwardAction = "caret-forward";
+
+ /**
+ * The name of the <code>Action</code> that inserts a line break.
+ *
+ * @see #getActions()
+ */
+ public static final String insertBreakAction = "insert-break";
+
+ /**
+ * The name of the <code>Action</code> that inserts some content.
+ *
+ * @see #getActions()
+ */
+ public static final String insertContentAction = "insert-content";
+
+ /**
+ * The name of the <code>Action</code> that inserts a TAB.
+ *
+ * @see #getActions()
+ */
+ public static final String insertTabAction = "insert-tab";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the beginning
+ * of the next word.
+ *
+ * @see #getActions()
+ */
+ public static final String nextWordAction = "caret-next-word";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret one page down.
+ *
+ * @see #getActions()
+ */
+ public static final String pageDownAction = "page-down";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret one page up.
+ *
+ * @see #getActions()
+ */
+ public static final String pageUpAction = "page-up";
+
+ /**
+ * The name of the <code>Action</code> that copies content from the system
+ * clipboard into the document.
+ *
+ * @see #getActions()
+ */
+ public static final String pasteAction = "paste-from-clipboard";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the beginning
+ * of the previous word.
+ *
+ * @see #getActions()
+ */
+ public static final String previousWordAction = "caret-previous-word";
+
+ /**
+ * The name of the <code>Action</code> that sets the editor in read only
+ * mode.
+ *
+ * @see #getActions()
+ */
+ public static final String readOnlyAction = "set-read-only";
+
+ /**
+ * The name of the <code>Action</code> that selects the whole document.
+ *
+ * @see #getActions()
+ */
+ public static final String selectAllAction = "select-all";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret one character
+ * backwards, possibly extending the current selection.
+ *
+ * @see #getActions()
+ */
+ public static final String selectionBackwardAction = "selection-backward";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the beginning
+ * of the document, possibly extending the current selection.
+ *
+ * @see #getActions()
+ */
+ public static final String selectionBeginAction = "selection-begin";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the beginning
+ * of the current line, possibly extending the current selection.
+ *
+ * @see #getActions()
+ */
+ public static final String selectionBeginLineAction = "selection-begin-line";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the beginning
+ * of the current paragraph, possibly extending the current selection.
+ *
+ * @see #getActions()
+ */
+ public static final String selectionBeginParagraphAction =
+ "selection-begin-paragraph";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the beginning
+ * of the current word, possibly extending the current selection.
+ *
+ * @see #getActions()
+ */
+ public static final String selectionBeginWordAction = "selection-begin-word";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret one line down,
+ * possibly extending the current selection.
+ *
+ * @see #getActions()
+ */
+ public static final String selectionDownAction = "selection-down";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the end
+ * of the document, possibly extending the current selection.
+ *
+ * @see #getActions()
+ */
+ public static final String selectionEndAction = "selection-end";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the end
+ * of the current line, possibly extending the current selection.
+ *
+ * @see #getActions()
+ */
+ public static final String selectionEndLineAction = "selection-end-line";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the end
+ * of the current paragraph, possibly extending the current selection.
+ *
+ * @see #getActions()
+ */
+ public static final String selectionEndParagraphAction =
+ "selection-end-paragraph";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the end
+ * of the current word, possibly extending the current selection.
+ *
+ * @see #getActions()
+ */
+ public static final String selectionEndWordAction = "selection-end-word";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret one character
+ * forwards, possibly extending the current selection.
+ *
+ * @see #getActions()
+ */
+ public static final String selectionForwardAction = "selection-forward";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the beginning
+ * of the next word, possibly extending the current selection.
+ *
+ * @see #getActions()
+ */
+ public static final String selectionNextWordAction = "selection-next-word";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret to the beginning
+ * of the previous word, possibly extending the current selection.
+ *
+ * @see #getActions()
+ */
+ public static final String selectionPreviousWordAction =
+ "selection-previous-word";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret one line up,
+ * possibly extending the current selection.
+ *
+ * @see #getActions()
+ */
+ public static final String selectionUpAction = "selection-up";
+
+ /**
+ * The name of the <code>Action</code> that selects the line around the
+ * caret.
+ *
+ * @see #getActions()
+ */
+ public static final String selectLineAction = "select-line";
+
+ /**
+ * The name of the <code>Action</code> that selects the paragraph around the
+ * caret.
+ *
+ * @see #getActions()
+ */
+ public static final String selectParagraphAction = "select-paragraph";
+
+ /**
+ * The name of the <code>Action</code> that selects the word around the
+ * caret.
+ *
+ * @see #getActions()
+ */
+ public static final String selectWordAction = "select-word";
+
+ /**
+ * The name of the <code>Action</code> that moves the caret one line up.
+ *
+ * @see #getActions()
+ */
+ public static final String upAction = "caret-up";
+
+ /**
+ * The name of the <code>Action</code> that sets the editor in read-write
+ * mode.
+ *
+ * @see #getActions()
+ */
+ public static final String writableAction = "set-writable";
+
+ /**
+ * Creates a new <code>DefaultEditorKit</code>.
+ */
+ public DefaultEditorKit()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * The <code>Action</code>s that are supported by the
+ * <code>DefaultEditorKit</code>.
+ */
+ private static Action[] defaultActions =
+ new Action[] {
+ // These classes are public because they are so in the RI.
+ new BeepAction(),
+ new CopyAction(),
+ new CutAction(),
+ new DefaultKeyTypedAction(),
+ new InsertBreakAction(),
+ new InsertContentAction(),
+ new InsertTabAction(),
+ new PasteAction(),
+
+ // These are (package-)private inner classes.
+ new DeleteNextCharAction(),
+ new DeletePrevCharAction(),
+
+ new BeginLineAction(),
+ new SelectionBeginLineAction(),
+
+ new EndLineAction(),
+ new SelectionEndLineAction(),
+
+ new BackwardAction(),
+ new SelectionBackwardAction(),
+
+ new ForwardAction(),
+ new SelectionForwardAction(),
+
+ new UpAction(),
+ new SelectionUpAction(),
+
+ new DownAction(),
+ new SelectionDownAction(),
+
+ new NextWordAction(),
+ new SelectionNextWordAction(),
+
+ new PreviousWordAction(),
+ new SelectionPreviousWordAction(),
+
+ new BeginAction(),
+ new SelectionBeginAction(),
+
+ new EndAction(),
+ new SelectionEndAction(),
+
+ new BeginWordAction(),
+ new SelectionBeginWordAction(),
+
+ new EndWordAction(),
+ new SelectionEndWordAction(),
+
+ new SelectAllAction(),
+ new SelectLineAction(),
+ new SelectWordAction()
+ };
+
+ /**
+ * Creates the <code>Caret</code> for this <code>EditorKit</code>. This
+ * returns a {@link DefaultCaret} in this case.
+ *
+ * @return the <code>Caret</code> for this <code>EditorKit</code>
+ */
+ public Caret createCaret()
+ {
+ return new DefaultCaret();
+ }
+
+ /**
+ * Creates the default {@link Document} that this <code>EditorKit</code>
+ * supports. This is a {@link PlainDocument} in this case.
+ *
+ * @return the default {@link Document} that this <code>EditorKit</code>
+ * supports
+ */
+ public Document createDefaultDocument()
+ {
+ return new PlainDocument();
+ }
+
+ /**
+ * Returns the <code>Action</code>s supported by this <code>EditorKit</code>.
+ *
+ * @return the <code>Action</code>s supported by this <code>EditorKit</code>
+ */
+ public Action[] getActions()
+ {
+ return defaultActions;
+ }
+
+ /**
+ * Returns the content type that this <code>EditorKit</code> supports.
+ * The <code>DefaultEditorKit</code> supports the content type
+ * <code>text/plain</code>.
+ *
+ * @return the content type that this <code>EditorKit</code> supports
+ */
+ public String getContentType()
+ {
+ return "text/plain";
+ }
+
+ /**
+ * Returns a {@link ViewFactory} that is able to create {@link View}s for
+ * the <code>Element</code>s that are used in this <code>EditorKit</code>'s
+ * model. This returns null which lets the UI of the text component supply
+ * <code>View</code>s.
+ *
+ * @return a {@link ViewFactory} that is able to create {@link View}s for
+ * the <code>Element</code>s that are used in this
+ * <code>EditorKit</code>'s model
+ */
+ public ViewFactory getViewFactory()
+ {
+ return null;
+ }
+
+ /**
+ * Reads a document of the supported content type from an {@link InputStream}
+ * into the actual {@link Document} object.
+ *
+ * @param in the stream from which to read the document
+ * @param document the document model into which the content is read
+ * @param offset the offset inside to document where the content is inserted
+ *
+ * @throws BadLocationException if <code>offset</code> is an invalid location
+ * inside <code>document</code>
+ * @throws IOException if something goes wrong while reading from
+ * <code>in</code>
+ */
+ public void read(InputStream in, Document document, int offset)
+ throws BadLocationException, IOException
+ {
+ read(new InputStreamReader(in), document, offset);
+ }
+
+ /**
+ * Reads a document of the supported content type from a {@link Reader}
+ * into the actual {@link Document} object.
+ *
+ * @param in the reader from which to read the document
+ * @param document the document model into which the content is read
+ * @param offset the offset inside to document where the content is inserted
+ *
+ * @throws BadLocationException if <code>offset</code> is an invalid location
+ * inside <code>document</code>
+ * @throws IOException if something goes wrong while reading from
+ * <code>in</code>
+ */
+ public void read(Reader in, Document document, int offset)
+ throws BadLocationException, IOException
+ {
+ BufferedReader reader = new BufferedReader(in);
+
+ String line;
+ StringBuffer content = new StringBuffer();
+
+ while ((line = reader.readLine()) != null)
+ {
+ content.append(line);
+ content.append("\n");
+ }
+
+ document.insertString(offset, content.substring(0, content.length() - 1),
+ SimpleAttributeSet.EMPTY);
+ }
+
+ /**
+ * Writes the <code>Document</code> (or a fragment of the
+ * <code>Document</code>) to an {@link OutputStream} in the
+ * supported content type format.
+ *
+ * @param out the stream to write to
+ * @param document the document that should be written out
+ * @param offset the beginning offset from where to write
+ * @param len the length of the fragment to write
+ *
+ * @throws BadLocationException if <code>offset</code> or
+ * <code>offset + len</code>is an invalid location inside
+ * <code>document</code>
+ * @throws IOException if something goes wrong while writing to
+ * <code>out</code>
+ */
+ public void write(OutputStream out, Document document, int offset, int len)
+ throws BadLocationException, IOException
+ {
+ write(new OutputStreamWriter(out), document, offset, len);
+ }
+
+ /**
+ * Writes the <code>Document</code> (or a fragment of the
+ * <code>Document</code>) to a {@link Writer} in the
+ * supported content type format.
+ *
+ * @param out the writer to write to
+ * @param document the document that should be written out
+ * @param offset the beginning offset from where to write
+ * @param len the length of the fragment to write
+ *
+ * @throws BadLocationException if <code>offset</code> is an
+ * invalid location inside <code>document</code>.
+ * @throws IOException if something goes wrong while writing to
+ * <code>out</code>
+ */
+ public void write(Writer out, Document document, int offset, int len)
+ throws BadLocationException, IOException
+ {
+ // Throw a BLE if offset is invalid
+ if (offset < 0 || offset > document.getLength())
+ throw new BadLocationException("Tried to write to invalid location",
+ offset);
+
+ // If they gave an overly large len, just adjust it
+ if (offset + len > document.getLength())
+ len = document.getLength() - offset;
+
+ out.write(document.getText(offset, len));
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultFormatter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultFormatter.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultFormatter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultFormatter.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,433 @@
+/* DefaultFormatter.java --
+Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.text.ParseException;
+
+import javax.swing.JFormattedTextField;
+
+/**
+ * The <code>DefaultFormatter</code> is a concrete formatter for use in
+ * {@link JFormattedTextField}s.
+ *
+ * It can format arbitrary values by invoking
+ * their {@link Object#toString} method.
+ *
+ * In order to convert a String back to
+ * a value, the value class must provide a single argument constructor that
+ * takes a String object as argument value. If no such constructor is found,
+ * the String itself is passed back by #stringToValue.
+ *
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class DefaultFormatter extends JFormattedTextField.AbstractFormatter
+ implements Cloneable, Serializable
+{
+
+ /**
+ * A {@link DocumentFilter} that intercepts modification of the
+ * JFormattedTextField's Document and commits the value depending
+ * on the value of the <code>commitsOnValidEdit</code> property.
+ *
+ */
+ // FIXME: Handle allowsInvalid and overwriteMode properties
+ private class FormatterDocumentFilter
+ extends DocumentFilter
+ {
+ /**
+ * Invoked when text is removed from a text component.
+ *
+ * @param bypass the FilterBypass to use to mutate the document
+ * @param offset the start position of the modification
+ * @param length the length of the removed text
+ *
+ * @throws BadLocationException if offset or lenght are invalid in
+ * the Document
+ */
+ public void remove(DocumentFilter.FilterBypass bypass, int offset,
+ int length)
+ throws BadLocationException
+ {
+ super.remove(bypass, offset, length);
+ checkValidInput();
+ commitIfAllowed();
+ }
+
+ /**
+ * Invoked when text is inserted into a text component.
+ *
+ * @param bypass the FilterBypass to use to mutate the document
+ * @param offset the start position of the modification
+ * @param text the inserted text
+ * @param attributes the attributes of the inserted text
+ *
+ * @throws BadLocationException if offset or lenght are invalid in
+ * the Document
+ */
+ public void insertString(DocumentFilter.FilterBypass bypass, int offset,
+ String text, AttributeSet attributes)
+ throws BadLocationException
+ {
+ if (overwriteMode == true)
+ replace(bypass, offset, text.length(), text, attributes);
+ else
+ super.insertString(bypass, offset, text, attributes);
+ checkValidInput();
+ commitIfAllowed();
+ }
+
+ /**
+ * Invoked when text is replaced in a text component.
+ *
+ * @param bypass the FilterBypass to use to mutate the document
+ * @param offset the start position of the modification
+ * @param length the length of the removed text
+ * @param text the inserted text
+ * @param attributes the attributes of the inserted text
+ *
+ * @throws BadLocationException if offset or lenght are invalid in
+ * the Document
+ */
+ public void replace(DocumentFilter.FilterBypass bypass, int offset,
+ int length, String text, AttributeSet attributes)
+ throws BadLocationException
+ {
+ super.replace(bypass, offset, length, text, attributes);
+ checkValidInput();
+ commitIfAllowed();
+ }
+
+ /**
+ * Commits the value to the JTextTextField if the property
+ * <code>commitsOnValidEdit</code> is set to <code>true</code>.
+ */
+ private void commitIfAllowed()
+ {
+ if (commitsOnValidEdit == true)
+ try
+ {
+ getFormattedTextField().commitEdit();
+ }
+ catch (ParseException ex)
+ {
+ // ignore invalid edits
+ }
+ }
+
+ /**
+ * Checks if the value in the input field is valid. If the
+ * property allowsInvalid is set to <code>false</code>, then
+ * the string in the input field is not allowed to be entered.
+ */
+ private void checkValidInput()
+ {
+ JFormattedTextField ftf = getFormattedTextField();
+ try
+ {
+ Object newval = stringToValue(ftf.getText());
+ }
+ catch (ParseException ex)
+ {
+ if (!allowsInvalid)
+ {
+ // roll back the input if invalid edits are not allowed
+ try
+ {
+ ftf.setText(valueToString(ftf.getValue()));
+ }
+ catch (ParseException pe)
+ {
+ // if that happens, something serious must be wrong
+ AssertionError ae;
+ ae = new AssertionError("values must be parseable");
+ ae.initCause(pe);
+ throw ae;
+ }
+ }
+ }
+ }
+ }
+
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = -355018354457785329L;
+
+ /**
+ * Indicates if the value should be committed after every
+ * valid modification of the Document.
+ */
+ boolean commitsOnValidEdit;
+
+ /**
+ * If <code>true</code> newly inserted characters overwrite existing
+ * values, otherwise insertion is done the normal way.
+ */
+ boolean overwriteMode;
+
+ /**
+ * If <code>true</code> invalid edits are allowed for a limited
+ * time.
+ */
+ boolean allowsInvalid;
+
+ /**
+ * The class that is used for values.
+ */
+ Class valueClass;
+
+ /**
+ * Creates a new instance of <code>DefaultFormatter</code>.
+ */
+ public DefaultFormatter()
+ {
+ commitsOnValidEdit = true;
+ overwriteMode = true;
+ allowsInvalid = true;
+ }
+
+ /**
+ * Installs the formatter on the specified {@link JFormattedTextField}.
+ *
+ * This method does the following things:
+ * <ul>
+ * <li>Display the value of #valueToString in the
+ * <code>JFormattedTextField</code></li>
+ * <li>Install the Actions from #getActions on the <code>JTextField</code>
+ * </li>
+ * <li>Install the DocumentFilter returned by #getDocumentFilter</li>
+ * <li>Install the NavigationFilter returned by #getNavigationFilter</li>
+ * </ul>
+ *
+ * This method is typically not overridden by subclasses. Instead override
+ * one of the mentioned methods in order to customize behaviour.
+ *
+ * @param ftf the {@link JFormattedTextField} in which this formatter
+ * is installed
+ */
+ public void install(JFormattedTextField ftf)
+ {
+ super.install(ftf);
+ }
+
+ /**
+ * Returns <code>true</code> if the value should be committed after
+ * each valid modification of the input field, <code>false</code> if
+ * it should never be committed by this formatter.
+ *
+ * @return the state of the <code>commitsOnValidEdit</code> property
+ *
+ * @see #setCommitsOnValidEdit
+ */
+ public boolean getCommitsOnValidEdit()
+ {
+ return commitsOnValidEdit;
+ }
+
+ /**
+ * Sets the value of the <code>commitsOnValidEdit</code> property.
+ *
+ * @param commitsOnValidEdit the new state of the
+ * <code>commitsOnValidEdit</code> property
+ *
+ * @see #getCommitsOnValidEdit
+ */
+ public void setCommitsOnValidEdit(boolean commitsOnValidEdit)
+ {
+ this.commitsOnValidEdit = commitsOnValidEdit;
+ }
+
+ /**
+ * Returns the value of the <code>overwriteMode</code> property.
+ * If that is set to <code>true</code> then newly inserted characters
+ * overwrite existing values, otherwise the characters are inserted like
+ * normal. The default is <code>true</code>.
+ *
+ * @return the value of the <code>overwriteMode</code> property
+ */
+ public boolean getOverwriteMode()
+ {
+ return overwriteMode;
+ }
+
+ /**
+ * Sets the value of the <code>overwriteMode</code> property.
+ *
+ * If that is set to <code>true</code> then newly inserted characters
+ * overwrite existing values, otherwise the characters are inserted like
+ * normal. The default is <code>true</code>.
+ *
+ * @param overwriteMode the new value for the <code>overwriteMode</code>
+ * property
+ */
+ public void setOverwriteMode(boolean overwriteMode)
+ {
+ this.overwriteMode = overwriteMode;
+ }
+
+ /**
+ * Returns whether or not invalid edits are allowed or not. If invalid
+ * edits are allowed, the JFormattedTextField may temporarily contain invalid
+ * characters.
+ *
+ * @return the value of the allowsInvalid property
+ */
+ public boolean getAllowsInvalid()
+ {
+ return allowsInvalid;
+ }
+
+ /**
+ * Sets the value of the <code>allowsInvalid</code> property.
+ *
+ * @param allowsInvalid the new value for the property
+ *
+ * @see #getAllowsInvalid()
+ */
+ public void setAllowsInvalid(boolean allowsInvalid)
+ {
+ this.allowsInvalid = allowsInvalid;
+ }
+
+ /**
+ * Returns the class that is used for values. When Strings are converted
+ * back to values, this class is used to create new value objects.
+ *
+ * @return the class that is used for values
+ */
+ public Class getValueClass()
+ {
+ return valueClass;
+ }
+
+ /**
+ * Sets the class that is used for values.
+ *
+ * @param valueClass the class that is used for values
+ *
+ * @see #getValueClass()
+ */
+ public void setValueClass(Class valueClass)
+ {
+ this.valueClass = valueClass;
+ }
+
+ /**
+ * Converts a String (from the JFormattedTextField input) to a value.
+ * In order to achieve this, the formatter tries to instantiate an object
+ * of the class returned by #getValueClass() using a single argument
+ * constructor that takes a String argument. If such a constructor cannot
+ * be found, the String itself is returned.
+ *
+ * @param string the string to convert
+ *
+ * @return the value for the string
+ *
+ * @throws ParseException if the string cannot be converted into
+ * a value object (e.g. invalid input)
+ */
+ public Object stringToValue(String string)
+ throws ParseException
+ {
+ Object value = string;
+ Class valueClass = getValueClass();
+ if (valueClass == null)
+ {
+ JFormattedTextField jft = getFormattedTextField();
+ if (jft != null)
+ valueClass = jft.getValue().getClass();
+ }
+ if (valueClass != null)
+ try
+ {
+ Constructor constr = valueClass.getConstructor
+ (new Class[]{String.class});
+ value = constr.newInstance(new Object[]{ string });
+ }
+ catch (NoSuchMethodException ex)
+ {
+ // leave value as string
+ }
+ catch (Exception ex)
+ {
+ throw new ParseException(string, 0);
+ }
+ return value;
+ }
+
+ /**
+ * Converts a value object into a String. This is done by invoking the
+ * {@link Object#toString()} method on the value.
+ *
+ * @param value the value to be converted
+ *
+ * @return the string representation of the value
+ *
+ * @throws ParseException if the value cannot be converted
+ */
+ public String valueToString(Object value)
+ throws ParseException
+ {
+ if (value == null)
+ return "";
+ return value.toString();
+ }
+
+ /**
+ * Creates and returns a clone of this DefaultFormatter.
+ *
+ * @return a clone of this object
+ *
+ * @throws CloneNotSupportedException not thrown here
+ */
+ public Object clone()
+ throws CloneNotSupportedException
+ {
+ return super.clone();
+ }
+
+ /**
+ * Returns the DocumentFilter that is used to restrict input.
+ *
+ * @return the DocumentFilter that is used to restrict input
+ */
+ protected DocumentFilter getDocumentFilter()
+ {
+ return new FormatterDocumentFilter();
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultFormatterFactory.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultFormatterFactory.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultFormatterFactory.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultFormatterFactory.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,280 @@
+/* DefaultFormatterFactory.java -- FIXME: briefly describe file purpose
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.io.Serializable;
+
+import javax.swing.JFormattedTextField;
+import javax.swing.JFormattedTextField.AbstractFormatter;
+import javax.swing.JFormattedTextField.AbstractFormatterFactory;
+
+/**
+ * This class is Swing's only concrete implementation of
+ * JFormattedTextField.AbstractFormatterFactory. It holds several
+ * formatters and determines the best one to be used based on the
+ * passed-in value from the text field.
+ *
+ * @author Anthony Balkissoon abalkiss at redhat dot com
+ * @since 1.4
+ */
+public class DefaultFormatterFactory extends AbstractFormatterFactory implements
+ Serializable
+{
+ /**
+ * The default formatter.
+ **/
+ AbstractFormatter defaultFormatter;
+
+ /**
+ * The formatter to use when the JFormattedTextField has focus and either the
+ * value isn't null or the value is null but no <code>nullFormatter</code>
+ * has been specified.
+ */
+ AbstractFormatter editFormatter;
+
+ /**
+ * The formatter to use when the JFormattedTextField doesn't havefocus and
+ * either the value isn't null or the value is null but no
+ * <code>nullFormatter</code> has been specified.
+ */
+ AbstractFormatter displayFormatter;
+
+ /**
+ * The formatter to use when the value of the JFormattedTextField is null.
+ */
+ AbstractFormatter nullFormatter;
+
+ /**
+ * Creates a DefaultFormatterFactory with no formatters
+ */
+ public DefaultFormatterFactory()
+ {
+ // Nothing to be done here.
+ }
+
+ /**
+ * Creates a new DefaultFormatterFactory with the specified formatters.
+ * @param defaultFormat the formatter to use if no other appropriate non-null
+ * formatted can be found.
+ */
+ public DefaultFormatterFactory(AbstractFormatter defaultFormat)
+ {
+ defaultFormatter = defaultFormat;
+ }
+
+ /**
+ * Creates a new DefaultFormatterFactory with the specified formatters.
+ * @param defaultFormat the formatter to use if no other appropriate non-null
+ * formatted can be found.
+ * @param displayFormat the formatter to use if the JFormattedTextField
+ * doesn't have focus and either the value is not null or the value is null
+ * but no <code>nullFormatter</code> has been specified.
+ */
+ public DefaultFormatterFactory(AbstractFormatter defaultFormat,
+ AbstractFormatter displayFormat)
+ {
+ defaultFormatter = defaultFormat;
+ displayFormatter = displayFormat;
+ }
+
+ /**
+ * Creates a new DefaultFormatterFactory with the specified formatters.
+ * @param defaultFormat the formatter to use if no other appropriate non-null
+ * formatted can be found.
+ * @param displayFormat the formatter to use if the JFormattedTextField
+ * doesn't have focus and either the value is not null or the value is null
+ * but no <code>nullFormatter</code> has been specified.
+ * @param editFormat the formatter to use if the JFormattedTextField has
+ * focus and either the value is not null or the value is null but not
+ * <code>nullFormatter</code> has been specified.
+ */
+ public DefaultFormatterFactory(AbstractFormatter defaultFormat,
+ AbstractFormatter displayFormat,
+ AbstractFormatter editFormat)
+ {
+ defaultFormatter = defaultFormat;
+ displayFormatter = displayFormat;
+ editFormatter = editFormat;
+ }
+
+ /**
+ * Creates a new DefaultFormatterFactory with the specified formatters.
+ * @param defaultFormat the formatter to use if no other appropriate non-null
+ * formatted can be found.
+ * @param displayFormat the formatter to use if the JFormattedTextField
+ * doesn't have focus and either the value is not null or the value is null
+ * but no <code>nullFormatter</code> has been specified.
+ * @param editFormat the formatter to use if the JFormattedTextField has
+ * focus and either the value is not null or the value is null but not
+ * <code>nullFormatter</code> has been specified.
+ * @param nullFormat the formatter to use when the value of the
+ * JFormattedTextField is null.
+ */
+ public DefaultFormatterFactory(AbstractFormatter defaultFormat,
+ AbstractFormatter displayFormat,
+ AbstractFormatter editFormat,
+ AbstractFormatter nullFormat)
+ {
+ defaultFormatter = defaultFormat;
+ displayFormatter = displayFormat;
+ editFormatter = editFormat;
+ nullFormatter = nullFormat;
+ }
+
+ /**
+ * Returns the formatted to be used if no other appropriate non-null
+ * formatter can be found.
+ * @return the formatted to be used if no other appropriate non-null
+ * formatter can be found.
+ */
+ public AbstractFormatter getDefaultFormatter()
+ {
+ return defaultFormatter;
+ }
+
+ /**
+ * Sets the formatted to be used if no other appropriate non-null formatter
+ * can be found.
+ * @param defaultFormatter the formatted to be used if no other appropriate
+ * non-null formatter can be found.
+ */
+ public void setDefaultFormatter(AbstractFormatter defaultFormatter)
+ {
+ this.defaultFormatter = defaultFormatter;
+ }
+
+ /**
+ * Gets the <code>displayFormatter</code>. This is the formatter to use if
+ * the JFormattedTextField is not being edited and either the value is not
+ * null or the value is null and no <code>nullFormatter<code> has been
+ * specified.
+ * @return the formatter to use if
+ * the JFormattedTextField is not being edited and either the value is not
+ * null or the value is null and no <code>nullFormatter<code> has been
+ * specified.
+ */
+ public AbstractFormatter getDisplayFormatter()
+ {
+ return displayFormatter;
+ }
+
+ /**
+ * Sets the <code>displayFormatter</code>. This is the formatter to use if
+ * the JFormattedTextField is not being edited and either the value is not
+ * null or the value is null and no <code>nullFormatter<code> has been
+ * specified.
+ * @param displayFormatter the formatter to use.
+ */
+ public void setDisplayFormatter(AbstractFormatter displayFormatter)
+ {
+ this.displayFormatter = displayFormatter;
+ }
+
+ /**
+ * Gets the <code>editFormatter</code>. This is the formatter to use if the
+ * JFormattedTextField is being edited and either the value is not null or
+ * the value is null and no <code>nullFormatter<code> has been specified.
+ * @return the formatter to use if the JFormattedTextField is being edited
+ * and the value is not null or the value is null but no nullFormatted has
+ * been specified.
+ */
+ public AbstractFormatter getEditFormatter()
+ {
+ return editFormatter;
+ }
+
+ /**
+ * Sets the <code>editFormatter</code>. This is the formatter to use if the
+ * JFormattedTextField is being edited and either the value is not null or
+ * the value is null and no <code>nullFormatter<code> has been specified.
+ * @param editFormatter the formatter to use.
+ */
+ public void setEditFormatter(AbstractFormatter editFormatter)
+ {
+ this.editFormatter = editFormatter;
+ }
+
+ /**
+ * Gets the formatter to use if the value of the JFormattedTextField is null.
+ * @return the formatter to use for null values.
+ */
+ public AbstractFormatter getNullFormatter()
+ {
+ return nullFormatter;
+ }
+
+ /**
+ * Sets the <code>nullFormatter</code>. This is the formatter to use if the
+ * value of the JFormattedTextField is null.
+ * @param nullFormatter the formatter to use for null values.
+ */
+ public void setNullFormatter(AbstractFormatter nullFormatter)
+ {
+ this.nullFormatter = nullFormatter;
+ }
+
+ /**
+ * Returns the appropriate formatter based on the state of
+ * <code>tf</code>. If <code>tf<code> is null we return null, otherwise
+ * we return one of the following:
+ * 1. Returns <code>nullFormatter</code> if <code>tf.getValue()</code> is
+ * null and <code>nullFormatter</code> is not.
+ * 2. Returns <code>editFormatter</code> if <code>tf.hasFocus()</code> is
+ * true and <code>editFormatter</code> is not null.
+ * 3. Returns <code>displayFormatter</code> if <code>tf.hasFocus()</code> is
+ * false and <code>displayFormatter</code> is not null.
+ * 4. Otherwise returns <code>defaultFormatter</code>.
+ */
+ public AbstractFormatter getFormatter(JFormattedTextField tf)
+ {
+ if (tf == null)
+ return null;
+
+ if (tf.getValue() == null && nullFormatter != null)
+ return nullFormatter;
+
+ if (tf.hasFocus() && editFormatter != null)
+ return editFormatter;
+
+ if (!tf.hasFocus() && displayFormatter != null)
+ return displayFormatter;
+
+ return defaultFormatter;
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultHighlighter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultHighlighter.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultHighlighter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultHighlighter.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,405 @@
+/* DefaultHighlighter.java --
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import gnu.classpath.NotImplementedException;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.util.ArrayList;
+
+import javax.swing.SwingUtilities;
+import javax.swing.plaf.TextUI;
+
+public class DefaultHighlighter extends LayeredHighlighter
+{
+ public static class DefaultHighlightPainter
+ extends LayerPainter
+ {
+ private Color color;
+
+ public DefaultHighlightPainter(Color c)
+ {
+ super();
+ color = c;
+ }
+
+ public Color getColor()
+ {
+ return color;
+ }
+
+ private void paintHighlight(Graphics g, Rectangle rect)
+ {
+ g.fillRect(rect.x, rect.y, rect.width, rect.height);
+ }
+
+ public void paint(Graphics g, int p0, int p1, Shape bounds,
+ JTextComponent t)
+ {
+ if (p0 == p1)
+ return;
+
+ Rectangle rect = bounds.getBounds();
+
+ if (color == null)
+ g.setColor(t.getSelectionColor());
+ else
+ g.setColor(color);
+
+ TextUI ui = t.getUI();
+
+ try
+ {
+
+ Rectangle l0 = ui.modelToView(t, p0, null);
+ Rectangle l1 = ui.modelToView(t, p1, null);
+
+ // Note: The computed locations may lie outside of the allocation
+ // area if the text is scrolled.
+
+ if (l0.y == l1.y)
+ {
+ SwingUtilities.computeUnion(l0.x, l0.y, l0.width, l0.height, l1);
+
+ // Paint only inside the allocation area.
+ SwingUtilities.computeIntersection(rect.x, rect.y, rect.width, rect.height, l1);
+
+ paintHighlight(g, l1);
+ }
+ else
+ {
+ // 1. The line of p0 is painted from the position of p0
+ // to the right border.
+ // 2. All lines between the ones where p0 and p1 lie on
+ // are completely highlighted. The allocation area is used to find
+ // out the bounds.
+ // 3. The final line is painted from the left border to the
+ // position of p1.
+
+ // Highlight first line until the end.
+ // If rect.x is non-zero the calculation will properly adjust the
+ // area to be painted.
+ l0.x -= rect.x;
+ l0.width = rect.width - l0.x - rect.x;
+
+ paintHighlight(g, l0);
+
+ int posBelow = Utilities.getPositionBelow(t, p0, l0.x);
+ int p1RowStart = Utilities.getRowStart(t, p1);
+ if (posBelow != -1
+ && posBelow != p0
+ && Utilities.getRowStart(t, posBelow)
+ != p1RowStart)
+ {
+ Rectangle grow = ui.modelToView(t, posBelow);
+ grow.x = rect.x;
+ grow.width = rect.width;
+
+ // Find further lines which have to be highlighted completely.
+ int nextPosBelow = posBelow;
+ while (nextPosBelow != -1
+ && Utilities.getRowStart(t, nextPosBelow) != p1RowStart)
+ {
+ posBelow = nextPosBelow;
+ nextPosBelow = Utilities.getPositionBelow(t, posBelow, l0.x);
+
+ if (nextPosBelow == posBelow)
+ break;
+ }
+ // Now posBelow is an offset on the last line which has to be painted
+ // completely. (newPosBelow is on the same line as p1)
+
+ // Retrieve the rectangle of posBelow and use its y and height
+ // value to calculate the final height of the multiple line
+ // spanning rectangle.
+ Rectangle end = ui.modelToView(t, posBelow);
+ grow.height = end.y + end.height - grow.y;
+
+ paintHighlight(g, grow);
+ }
+
+ // Paint last line from its beginning to the position of p1.
+ l1.width = l1.x + l1.width - rect.x;
+ l1.x = rect.x;
+ paintHighlight(g, l1);
+ }
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError err = new AssertionError("Unexpected bad location exception");
+ err.initCause(ex);
+ throw err;
+ }
+ }
+
+ public Shape paintLayer(Graphics g, int p0, int p1, Shape bounds,
+ JTextComponent c, View view)
+ {
+ throw new InternalError();
+ }
+ }
+
+ private class HighlightEntry implements Highlighter.Highlight
+ {
+ int p0;
+ int p1;
+ Highlighter.HighlightPainter painter;
+
+ public HighlightEntry(int p0, int p1, Highlighter.HighlightPainter painter)
+ {
+ this.p0 = p0;
+ this.p1 = p1;
+ this.painter = painter;
+ }
+
+ public int getStartOffset()
+ {
+ return p0;
+ }
+
+ public int getEndOffset()
+ {
+ return p1;
+ }
+
+ public Highlighter.HighlightPainter getPainter()
+ {
+ return painter;
+ }
+ }
+
+ /**
+ * @specnote final as of 1.4
+ */
+ public static final LayeredHighlighter.LayerPainter DefaultPainter =
+ new DefaultHighlightPainter(null);
+
+ private JTextComponent textComponent;
+ private ArrayList highlights = new ArrayList();
+ private boolean drawsLayeredHighlights = true;
+
+ public DefaultHighlighter()
+ {
+ // Nothing to do here.
+ }
+
+ public boolean getDrawsLayeredHighlights()
+ {
+ return drawsLayeredHighlights;
+ }
+
+ public void setDrawsLayeredHighlights(boolean newValue)
+ {
+ drawsLayeredHighlights = newValue;
+ }
+
+ private void checkPositions(int p0, int p1)
+ throws BadLocationException
+ {
+ if (p0 < 0)
+ throw new BadLocationException("DefaultHighlighter", p0);
+
+ if (p1 < p0)
+ throw new BadLocationException("DefaultHighlighter", p1);
+ }
+
+ public void install(JTextComponent c)
+ {
+ textComponent = c;
+ removeAllHighlights();
+ }
+
+ public void deinstall(JTextComponent c)
+ {
+ textComponent = null;
+ }
+
+ public Object addHighlight(int p0, int p1, Highlighter.HighlightPainter painter)
+ throws BadLocationException
+ {
+ checkPositions(p0, p1);
+ HighlightEntry entry = new HighlightEntry(p0, p1, painter);
+ highlights.add(entry);
+
+ textComponent.getUI().damageRange(textComponent, p0, p1);
+
+ return entry;
+ }
+
+ public void removeHighlight(Object tag)
+ {
+ highlights.remove(tag);
+
+ HighlightEntry entry = (HighlightEntry) tag;
+ textComponent.getUI().damageRange(textComponent,
+ entry.p0,
+ entry.p1);
+ }
+
+ public void removeAllHighlights()
+ {
+ highlights.clear();
+ }
+
+ public Highlighter.Highlight[] getHighlights()
+ {
+ return (Highlighter.Highlight[])
+ highlights.toArray(new Highlighter.Highlight[highlights.size()]);
+ }
+
+ public void changeHighlight(Object tag, int n0, int n1)
+ throws BadLocationException
+ {
+ int o0, o1;
+
+ checkPositions(n0, n1);
+ HighlightEntry entry = (HighlightEntry) tag;
+ o0 = entry.p0;
+ o1 = entry.p1;
+
+ // Prevent useless write & repaint operations.
+ if (o0 == n0 && o1 == n1)
+ return;
+
+ entry.p0 = n0;
+ entry.p1 = n1;
+
+ TextUI ui = textComponent.getUI();
+
+ // Special situation where the old area has to be cleared simply.
+ if (n0 == n1)
+ ui.damageRange(textComponent, o0, o1);
+ // Calculates the areas where a change is really neccessary
+ else if ((o1 > n0 && o1 <= n1)
+ || (n1 > o0 && n1 <= o1))
+ {
+ // [fds, fde) - the first damage region
+ // [sds, sde] - the second damage region
+ int fds, sds;
+ int fde, sde;
+
+ // Calculate first damaged region.
+ if(o0 < n0)
+ {
+ // Damaged region will be cleared as
+ // the old highlight region starts first.
+ fds = o0;
+ fde = n0;
+ }
+ else
+ {
+ // Damaged region will be painted as
+ // the new highlight region starts first.
+ fds = n0;
+ fde = o0;
+ }
+
+ if (o1 < n1)
+ {
+ // Final region will be painted as the
+ // old highlight region finishes first
+ sds = o1;
+ sde = n1;
+ }
+ else
+ {
+ // Final region will be cleared as the
+ // new highlight region finishes first.
+ sds = n1;
+ sde = o1;
+ }
+
+ // If there is no undamaged region in between
+ // call damageRange only once.
+ if (fde == sds)
+ ui.damageRange(textComponent, fds, sde);
+ else
+ {
+ if (fds != fde)
+ ui.damageRange(textComponent, fds, fde);
+
+ if (sds != sde)
+ ui.damageRange(textComponent, sds, sde);
+ }
+ }
+ else
+ {
+ // The two regions do not overlap. So mark
+ // both areas as damaged.
+ ui.damageRange(textComponent, o0, o1);
+ ui.damageRange(textComponent, n0, n1);
+ }
+
+ }
+
+ public void paintLayeredHighlights(Graphics g, int p0, int p1,
+ Shape viewBounds, JTextComponent editor,
+ View view)
+ throws NotImplementedException
+ {
+ // TODO: Implement this properly.
+ }
+
+ public void paint(Graphics g)
+ {
+ int size = highlights.size();
+
+ // Check if there are any highlights.
+ if (size == 0)
+ return;
+
+ // Prepares the rectangle of the inner drawing area.
+ Insets insets = textComponent.getInsets();
+ Shape bounds =
+ new Rectangle(insets.left,
+ insets.top,
+ textComponent.getWidth() - insets.left - insets.right,
+ textComponent.getHeight() - insets.top - insets.bottom);
+
+ for (int index = 0; index < size; ++index)
+ {
+ HighlightEntry entry = (HighlightEntry) highlights.get(index);
+ entry.painter.paint(g, entry.p0, entry.p1, bounds, textComponent);
+ }
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultStyledDocument.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultStyledDocument.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultStyledDocument.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultStyledDocument.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,2421 @@
+/* DefaultStyledDocument.java --
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.Stack;
+import java.util.Vector;
+
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.UndoableEditEvent;
+import javax.swing.undo.AbstractUndoableEdit;
+import javax.swing.undo.UndoableEdit;
+
+/**
+ * The default implementation of {@link StyledDocument}. The document is
+ * modeled as an {@link Element} tree, which has a {@link SectionElement} as
+ * single root, which has one or more {@link AbstractDocument.BranchElement}s
+ * as paragraph nodes and each paragraph node having one or more
+ * {@link AbstractDocument.LeafElement}s as content nodes.
+ *
+ * @author Michael Koch (konqueror at gmx.de)
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class DefaultStyledDocument extends AbstractDocument implements
+ StyledDocument
+{
+
+ /**
+ * An {@link UndoableEdit} that can undo attribute changes to an element.
+ *
+ * @author Roman Kennke (kennke at aicas.com)
+ */
+ public static class AttributeUndoableEdit extends AbstractUndoableEdit
+ {
+ /**
+ * A copy of the old attributes.
+ */
+ protected AttributeSet copy;
+
+ /**
+ * The new attributes.
+ */
+ protected AttributeSet newAttributes;
+
+ /**
+ * If the new attributes replaced the old attributes or if they only were
+ * added to them.
+ */
+ protected boolean isReplacing;
+
+ /**
+ * The element that has changed.
+ */
+ protected Element element;
+
+ /**
+ * Creates a new <code>AttributeUndoableEdit</code>.
+ *
+ * @param el
+ * the element that changes attributes
+ * @param newAtts
+ * the new attributes
+ * @param replacing
+ * if the new attributes replace the old or only append to them
+ */
+ public AttributeUndoableEdit(Element el, AttributeSet newAtts,
+ boolean replacing)
+ {
+ element = el;
+ newAttributes = newAtts;
+ isReplacing = replacing;
+ copy = el.getAttributes().copyAttributes();
+ }
+
+ /**
+ * Undos the attribute change. The <code>copy</code> field is set as
+ * attributes on <code>element</code>.
+ */
+ public void undo()
+ {
+ super.undo();
+ AttributeSet atts = element.getAttributes();
+ if (atts instanceof MutableAttributeSet)
+ {
+ MutableAttributeSet mutable = (MutableAttributeSet) atts;
+ mutable.removeAttributes(atts);
+ mutable.addAttributes(copy);
+ }
+ }
+
+ /**
+ * Redos an attribute change. This adds <code>newAttributes</code> to the
+ * <code>element</code>'s attribute set, possibly clearing all attributes
+ * if <code>isReplacing</code> is true.
+ */
+ public void redo()
+ {
+ super.undo();
+ AttributeSet atts = element.getAttributes();
+ if (atts instanceof MutableAttributeSet)
+ {
+ MutableAttributeSet mutable = (MutableAttributeSet) atts;
+ if (isReplacing)
+ mutable.removeAttributes(atts);
+ mutable.addAttributes(newAttributes);
+ }
+ }
+ }
+
+ /**
+ * Carries specification information for new {@link Element}s that should be
+ * created in {@link ElementBuffer}. This allows the parsing process to be
+ * decoupled from the <code>Element</code> creation process.
+ */
+ public static class ElementSpec
+ {
+ /**
+ * This indicates a start tag. This is a possible value for {@link #getType}.
+ */
+ public static final short StartTagType = 1;
+
+ /**
+ * This indicates an end tag. This is a possible value for {@link #getType}.
+ */
+ public static final short EndTagType = 2;
+
+ /**
+ * This indicates a content element. This is a possible value for
+ * {@link #getType}.
+ */
+ public static final short ContentType = 3;
+
+ /**
+ * This indicates that the data associated with this spec should be joined
+ * with what precedes it. This is a possible value for {@link #getDirection}.
+ */
+ public static final short JoinPreviousDirection = 4;
+
+ /**
+ * This indicates that the data associated with this spec should be joined
+ * with what follows it. This is a possible value for {@link #getDirection}.
+ */
+ public static final short JoinNextDirection = 5;
+
+ /**
+ * This indicates that the data associated with this spec should be used to
+ * create a new element. This is a possible value for {@link #getDirection}.
+ */
+ public static final short OriginateDirection = 6;
+
+ /**
+ * This indicates that the data associated with this spec should be joined
+ * to the fractured element. This is a possible value for
+ * {@link #getDirection}.
+ */
+ public static final short JoinFractureDirection = 7;
+
+ /**
+ * The type of the tag.
+ */
+ short type;
+
+ /**
+ * The direction of the tag.
+ */
+ short direction;
+
+ /**
+ * The offset of the content.
+ */
+ int offset;
+
+ /**
+ * The length of the content.
+ */
+ int length;
+
+ /**
+ * The actual content.
+ */
+ char[] content;
+
+ /**
+ * The attributes for the tag.
+ */
+ AttributeSet attributes;
+
+ /**
+ * Creates a new <code>ElementSpec</code> with no content, length or
+ * offset. This is most useful for start and end tags.
+ *
+ * @param a
+ * the attributes for the element to be created
+ * @param type
+ * the type of the tag
+ */
+ public ElementSpec(AttributeSet a, short type)
+ {
+ this(a, type, 0);
+ }
+
+ /**
+ * Creates a new <code>ElementSpec</code> that specifies the length but
+ * not the offset of an element. Such <code>ElementSpec</code>s are
+ * processed sequentially from a known starting point.
+ *
+ * @param a
+ * the attributes for the element to be created
+ * @param type
+ * the type of the tag
+ * @param len
+ * the length of the element
+ */
+ public ElementSpec(AttributeSet a, short type, int len)
+ {
+ this(a, type, null, 0, len);
+ }
+
+ /**
+ * Creates a new <code>ElementSpec</code> with document content.
+ *
+ * @param a
+ * the attributes for the element to be created
+ * @param type
+ * the type of the tag
+ * @param txt
+ * the actual content
+ * @param offs
+ * the offset into the <code>txt</code> array
+ * @param len
+ * the length of the element
+ */
+ public ElementSpec(AttributeSet a, short type, char[] txt, int offs, int len)
+ {
+ attributes = a;
+ this.type = type;
+ offset = offs;
+ length = len;
+ content = txt;
+ direction = OriginateDirection;
+ }
+
+ /**
+ * Sets the type of the element.
+ *
+ * @param type
+ * the type of the element to be set
+ */
+ public void setType(short type)
+ {
+ this.type = type;
+ }
+
+ /**
+ * Returns the type of the element.
+ *
+ * @return the type of the element
+ */
+ public short getType()
+ {
+ return type;
+ }
+
+ /**
+ * Sets the direction of the element.
+ *
+ * @param dir
+ * the direction of the element to be set
+ */
+ public void setDirection(short dir)
+ {
+ direction = dir;
+ }
+
+ /**
+ * Returns the direction of the element.
+ *
+ * @return the direction of the element
+ */
+ public short getDirection()
+ {
+ return direction;
+ }
+
+ /**
+ * Returns the attributes of the element.
+ *
+ * @return the attributes of the element
+ */
+ public AttributeSet getAttributes()
+ {
+ return attributes;
+ }
+
+ /**
+ * Returns the actual content of the element.
+ *
+ * @return the actual content of the element
+ */
+ public char[] getArray()
+ {
+ return content;
+ }
+
+ /**
+ * Returns the offset of the content.
+ *
+ * @return the offset of the content
+ */
+ public int getOffset()
+ {
+ return offset;
+ }
+
+ /**
+ * Returns the length of the content.
+ *
+ * @return the length of the content
+ */
+ public int getLength()
+ {
+ return length;
+ }
+
+ /**
+ * Returns a String representation of this <code>ElementSpec</code>
+ * describing the type, direction and length of this
+ * <code>ElementSpec</code>.
+ *
+ * @return a String representation of this <code>ElementSpec</code>
+ */
+ public String toString()
+ {
+ StringBuilder b = new StringBuilder();
+ switch (type)
+ {
+ case StartTagType:
+ b.append("StartTag");
+ break;
+ case EndTagType:
+ b.append("EndTag");
+ break;
+ case ContentType:
+ b.append("Content");
+ break;
+ default:
+ b.append("??");
+ break;
+ }
+
+ b.append(':');
+
+ switch (direction)
+ {
+ case JoinPreviousDirection:
+ b.append("JoinPrevious");
+ break;
+ case JoinNextDirection:
+ b.append("JoinNext");
+ break;
+ case OriginateDirection:
+ b.append("Originate");
+ break;
+ case JoinFractureDirection:
+ b.append("Fracture");
+ break;
+ default:
+ b.append("??");
+ break;
+ }
+
+ b.append(':');
+ b.append(length);
+
+ return b.toString();
+ }
+ }
+
+ /**
+ * Performs all <em>structural</code> changes to the <code>Element</code>
+ * hierarchy. This class was implemented with much help from the document:
+ * http://java.sun.com/products/jfc/tsc/articles/text/element_buffer/index.html.
+ */
+ public class ElementBuffer implements Serializable
+ {
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 1688745877691146623L;
+
+ /** The root element of the hierarchy. */
+ private Element root;
+
+ /** Holds the offset for structural changes. */
+ private int offset;
+
+ /** Holds the end offset for structural changes. */
+ private int endOffset;
+
+ /** Holds the length of structural changes. */
+ private int length;
+
+ /** Holds the position of the change. */
+ private int pos;
+
+ /** Holds the element that was last fractured. */
+ private Element lastFractured;
+
+ /** True if a fracture was not created during a insertFracture call. */
+ private boolean fracNotCreated;
+
+ /**
+ * The current position in the element tree. This is used for bulk inserts
+ * using ElementSpecs.
+ */
+ private Stack elementStack;
+
+ /**
+ * The ElementChange that describes the latest changes.
+ */
+ DefaultDocumentEvent documentEvent;
+
+ /**
+ * Creates a new <code>ElementBuffer</code> for the specified
+ * <code>root</code> element.
+ *
+ * @param root
+ * the root element for this <code>ElementBuffer</code>
+ */
+ public ElementBuffer(Element root)
+ {
+ this.root = root;
+ elementStack = new Stack();
+ }
+
+ /**
+ * Returns the root element of this <code>ElementBuffer</code>.
+ *
+ * @return the root element of this <code>ElementBuffer</code>
+ */
+ public Element getRootElement()
+ {
+ return root;
+ }
+
+ /**
+ * Removes the content. This method sets some internal parameters and
+ * delegates the work to {@link #removeUpdate}.
+ *
+ * @param offs
+ * the offset from which content is remove
+ * @param len
+ * the length of the removed content
+ * @param ev
+ * the document event that records the changes
+ */
+ public void remove(int offs, int len, DefaultDocumentEvent ev)
+ {
+ if (len == 0)
+ return;
+ offset = offs;
+ length = len;
+ pos = offset;
+ documentEvent = ev;
+ removeUpdate();
+ }
+
+ /**
+ * Updates the element structure of the document in response to removal of
+ * content. It removes the affected {@link Element}s from the document
+ * structure.
+ */
+ protected void removeUpdate()
+ {
+ int startParagraph = root.getElementIndex(offset);
+ int endParagraph = root.getElementIndex(offset + length);
+ Element[] empty = new Element[0];
+ int removeStart = -1;
+ int removeEnd = -1;
+ for (int i = startParagraph; i < endParagraph; i++)
+ {
+ BranchElement paragraph = (BranchElement) root.getElement(i);
+ int contentStart = paragraph.getElementIndex(offset);
+ int contentEnd = paragraph.getElementIndex(offset + length);
+ if (contentStart == paragraph.getStartOffset()
+ && contentEnd == paragraph.getEndOffset())
+ {
+ // In this case we only need to remove the whole paragraph. We
+ // do this in one go after this loop and only record the indices
+ // here.
+ if (removeStart == -1)
+ {
+ removeStart = i;
+ removeEnd = i;
+ }
+ else
+ removeEnd = i;
+ }
+ else
+ {
+ // In this case we remove a couple of child elements from this
+ // paragraph.
+ int removeLen = contentEnd - contentStart;
+ Element[] removed = new Element[removeLen];
+ for (int j = contentStart; j < contentEnd; j++)
+ removed[j] = paragraph.getElement(j);
+ Edit edit = getEditForParagraphAndIndex(paragraph, contentStart);
+ edit.addRemovedElements(removed);
+ }
+ }
+ // Now we remove paragraphs from the root that have been tagged for
+ // removal.
+ if (removeStart != -1)
+ {
+ int removeLen = removeEnd - removeStart;
+ Element[] removed = new Element[removeLen];
+ for (int i = removeStart; i < removeEnd; i++)
+ removed[i] = root.getElement(i);
+ Edit edit = getEditForParagraphAndIndex((BranchElement) root,
+ removeStart);
+ edit.addRemovedElements(removed);
+ }
+ }
+
+ /**
+ * Performs the actual work for {@link #change}. The elements at the
+ * interval boundaries are split up (if necessary) so that the interval
+ * boundaries are located at element boundaries.
+ */
+ protected void changeUpdate()
+ {
+ // Split up the element at the start offset if necessary.
+ Element el = getCharacterElement(offset);
+ Element[] res = split(el, offset, 0, el.getElementIndex(offset));
+ BranchElement par = (BranchElement) el.getParentElement();
+ int index = par.getElementIndex(offset);
+ Edit edit = getEditForParagraphAndIndex(par, index);
+ if (res[1] != null)
+ {
+ Element[] removed;
+ Element[] added;
+ if (res[0] == null)
+ {
+ removed = new Element[0];
+ added = new Element[] { res[1] };
+ index++;
+ }
+ else
+ {
+ removed = new Element[] { el };
+ added = new Element[] { res[0], res[1] };
+ }
+ edit.addRemovedElements(removed);
+
+ edit.addAddedElements(added);
+ }
+
+ int endOffset = offset + length;
+ el = getCharacterElement(endOffset);
+ res = split(el, endOffset, 0, el.getElementIndex(endOffset));
+ par = (BranchElement) el.getParentElement();
+ if (res[0] != null)
+ {
+ Element[] removed;
+ Element[] added;
+ if (res[1] == null)
+ {
+ removed = new Element[0];
+ added = new Element[] { res[1] };
+ }
+ else
+ {
+ removed = new Element[] { el };
+ added = new Element[] { res[0], res[1] };
+ }
+ edit.addRemovedElements(removed);
+ edit.addAddedElements(added);
+ }
+ }
+
+ /**
+ * Modifies the element structure so that the specified interval starts and
+ * ends at an element boundary. Content and paragraph elements are split and
+ * created as necessary. This also updates the
+ * <code>DefaultDocumentEvent</code> to reflect the structural changes.
+ * The bulk work is delegated to {@link #changeUpdate()}.
+ *
+ * @param offset
+ * the start index of the interval to be changed
+ * @param length
+ * the length of the interval to be changed
+ * @param ev
+ * the <code>DefaultDocumentEvent</code> describing the change
+ */
+ public void change(int offset, int length, DefaultDocumentEvent ev)
+ {
+ if (length == 0)
+ return;
+ this.offset = offset;
+ this.pos = offset;
+ this.length = length;
+ documentEvent = ev;
+ changeUpdate();
+ }
+
+ /**
+ * Creates and returns a deep clone of the specified <code>clonee</code>
+ * with the specified parent as new parent.
+ *
+ * This method can only clone direct instances of {@link BranchElement}
+ * or {@link LeafElement}.
+ *
+ * @param parent the new parent
+ * @param clonee the element to be cloned
+ *
+ * @return the cloned element with the new parent
+ */
+ public Element clone(Element parent, Element clonee)
+ {
+ Element clone = clonee;
+ // We can only handle AbstractElements here.
+ if (clonee instanceof BranchElement)
+ {
+ BranchElement branchEl = (BranchElement) clonee;
+ BranchElement branchClone =
+ new BranchElement(parent, branchEl.getAttributes());
+ // Also clone all of the children.
+ int numChildren = branchClone.getElementCount();
+ Element[] cloneChildren = new Element[numChildren];
+ for (int i = 0; i < numChildren; ++i)
+ {
+ cloneChildren[i] = clone(branchClone,
+ branchClone.getElement(i));
+ }
+ branchClone.replace(0, 0, cloneChildren);
+ clone = branchClone;
+ }
+ else if (clonee instanceof LeafElement)
+ {
+ clone = new LeafElement(parent, clonee.getAttributes(),
+ clonee.getStartOffset(),
+ clonee.getEndOffset());
+ }
+ return clone;
+ }
+
+ /**
+ * Inserts new <code>Element</code> in the document at the specified
+ * position. Most of the work is done by {@link #insertUpdate}, after some
+ * fields have been prepared for it.
+ *
+ * @param offset
+ * the location in the document at which the content is inserted
+ * @param length
+ * the length of the inserted content
+ * @param data
+ * the element specifications for the content to be inserted
+ * @param ev
+ * the document event that is updated to reflect the structural
+ * changes
+ */
+ public void insert(int offset, int length, ElementSpec[] data,
+ DefaultDocumentEvent ev)
+ {
+ if (length == 0)
+ return;
+
+ this.offset = offset;
+ this.pos = offset;
+ this.endOffset = offset + length;
+ this.length = length;
+ documentEvent = ev;
+
+ edits.removeAllElements();
+ elementStack.removeAllElements();
+ lastFractured = null;
+ fracNotCreated = false;
+ insertUpdate(data);
+ // This for loop applies all the changes that were made and updates the
+ // DocumentEvent.
+ int size = edits.size();
+ for (int i = 0; i < size; i++)
+ {
+ Edit curr = (Edit) edits.get(i);
+ BranchElement e = (BranchElement) curr.e;
+ Element[] removed = curr.getRemovedElements();
+ Element[] added = curr.getAddedElements();
+ // FIXME: We probably shouldn't create the empty Element[] in the
+ // first place.
+ if (removed.length > 0 || added.length > 0)
+ {
+ if (curr.index + removed.length <= e.getElementCount())
+ {
+ e.replace(curr.index, removed.length, added);
+ ElementEdit ee = new ElementEdit(e, curr.index, removed, added);
+ ev.addEdit(ee);
+ }
+ else
+ {
+ System.err.println("WARNING: Tried to replace elements ");
+ System.err.print("beyond boundaries: elementCount: ");
+ System.err.println(e.getElementCount());
+ System.err.print("index: " + curr.index);
+ System.err.println(", removed.length: " + removed.length);
+ }
+ }
+ }
+ }
+
+ /**
+ * Inserts new content
+ *
+ * @param data
+ * the element specifications for the elements to be inserted
+ */
+ protected void insertUpdate(ElementSpec[] data)
+ {
+ // Push the root and the paragraph at offset onto the element stack.
+ Element current = root;
+ int index;
+ while (!current.isLeaf())
+ {
+ index = current.getElementIndex(offset);
+ elementStack.push(current);
+ current = current.getElement(index);
+ }
+
+ int i = 0;
+ int type = data[0].getType();
+ if (type == ElementSpec.ContentType)
+ {
+ // If the first tag is content we must treat it separately to allow
+ // for joining properly to previous Elements and to ensure that
+ // no extra LeafElements are erroneously inserted.
+ insertFirstContentTag(data);
+ pos += data[0].length;
+ i = 1;
+ }
+ else
+ {
+ createFracture(data);
+ i = 0;
+ }
+
+ // Handle each ElementSpec individually.
+ for (; i < data.length; i++)
+ {
+ BranchElement paragraph = (BranchElement) elementStack.peek();
+ switch (data[i].getType())
+ {
+ case ElementSpec.StartTagType:
+ switch (data[i].getDirection())
+ {
+ case ElementSpec.JoinFractureDirection:
+ // Fracture the tree and ensure the appropriate element
+ // is on top of the stack.
+ fracNotCreated = false;
+ insertFracture(data[i]);
+ if (fracNotCreated)
+ {
+ if (lastFractured != null)
+ elementStack.push(lastFractured.getParentElement());
+ else
+ elementStack.push(paragraph.getElement(0));
+ }
+ break;
+ case ElementSpec.JoinNextDirection:
+ // Push the next paragraph element onto the stack so
+ // future insertions are added to it.
+ int ix = paragraph.getElementIndex(pos) + 1;
+ elementStack.push(paragraph.getElement(ix));
+ break;
+ default:
+ Element br = null;
+ if (data.length > i + 1)
+ {
+ // leaves will be added to paragraph later
+ int x = 0;
+ if (paragraph.getElementCount() > 0)
+ x = paragraph.getElementIndex(pos) + 1;
+ Edit e = getEditForParagraphAndIndex(paragraph, x);
+ br = (BranchElement) createBranchElement(paragraph,
+ data[i].getAttributes());
+ e.added.add(br);
+ elementStack.push(br);
+ }
+ else
+ // need to add leaves to paragraph now
+ br = insertParagraph(paragraph, pos);
+ break;
+ }
+ break;
+ case ElementSpec.EndTagType:
+ elementStack.pop();
+ break;
+ case ElementSpec.ContentType:
+ insertContentTag(data[i]);
+ offset = pos;
+ break;
+ }
+ }
+ }
+
+ /**
+ * Inserts a new paragraph.
+ *
+ * @param par -
+ * the parent
+ * @param offset -
+ * the offset
+ * @return the new paragraph
+ */
+ private Element insertParagraph(BranchElement par, int offset)
+ {
+ int index = par.getElementIndex(offset);
+ Element current = par.getElement(index);
+ Element[] res = split(current, offset, 0, 0);
+ Edit e = getEditForParagraphAndIndex(par, index + 1);
+ Element ret;
+ if (res[1] != null)
+ {
+ Element[] removed;
+ Element[] added;
+ if (res[0] == null)
+ {
+ removed = new Element[0];
+ if (res[1] instanceof BranchElement)
+ {
+ added = new Element[] { res[1] };
+ ret = res[1];
+ }
+ else
+ {
+ ret = createBranchElement(par, null);
+ added = new Element[] { ret, res[1] };
+ }
+ index++;
+ }
+ else
+ {
+ removed = new Element[] { current };
+ if (res[1] instanceof BranchElement)
+ {
+ ret = res[1];
+ added = new Element[] { res[0], res[1] };
+ }
+ else
+ {
+ ret = createBranchElement(par, null);
+ added = new Element[] { res[0], ret, res[1] };
+ }
+ }
+
+ e.addAddedElements(added);
+ e.addRemovedElements(removed);
+ }
+ else
+ {
+ ret = createBranchElement(par, null);
+ e.addAddedElement(ret);
+ }
+ return ret;
+ }
+
+ /**
+ * Inserts the first tag into the document.
+ *
+ * @param data -
+ * the data to be inserted.
+ */
+ private void insertFirstContentTag(ElementSpec[] data)
+ {
+ ElementSpec first = data[0];
+ BranchElement paragraph = (BranchElement) elementStack.peek();
+ int index = paragraph.getElementIndex(pos);
+ Element current = paragraph.getElement(index);
+ int newEndOffset = pos + first.length;
+ boolean onlyContent = data.length == 1;
+ Edit edit = getEditForParagraphAndIndex(paragraph, index);
+ switch (first.getDirection())
+ {
+ case ElementSpec.JoinPreviousDirection:
+ if (current.getEndOffset() != newEndOffset && !onlyContent)
+ {
+ Element newEl1 = createLeafElement(paragraph,
+ current.getAttributes(),
+ current.getStartOffset(),
+ newEndOffset);
+ edit.addAddedElement(newEl1);
+ edit.addRemovedElement(current);
+ offset = newEndOffset;
+ }
+ break;
+ case ElementSpec.JoinNextDirection:
+ if (pos != 0)
+ {
+ Element newEl1 = createLeafElement(paragraph,
+ current.getAttributes(),
+ current.getStartOffset(),
+ pos);
+ edit.addAddedElement(newEl1);
+ Element next = paragraph.getElement(index + 1);
+
+ if (onlyContent)
+ newEl1 = createLeafElement(paragraph, next.getAttributes(),
+ pos, next.getEndOffset());
+ else
+ {
+ newEl1 = createLeafElement(paragraph, next.getAttributes(),
+ pos, newEndOffset);
+ pos = newEndOffset;
+ }
+ edit.addAddedElement(newEl1);
+ edit.addRemovedElement(current);
+ edit.addRemovedElement(next);
+ }
+ break;
+ default:
+ if (current.getStartOffset() != pos)
+ {
+ Element newEl = createLeafElement(paragraph,
+ current.getAttributes(),
+ current.getStartOffset(),
+ pos);
+ edit.addAddedElement(newEl);
+ }
+ edit.addRemovedElement(current);
+ Element newEl1 = createLeafElement(paragraph, first.getAttributes(),
+ pos, newEndOffset);
+ edit.addAddedElement(newEl1);
+ if (current.getEndOffset() != endOffset)
+ recreateLeaves(newEndOffset, paragraph, onlyContent);
+ else
+ offset = newEndOffset;
+ break;
+ }
+ }
+
+ /**
+ * Inserts a content element into the document structure.
+ *
+ * @param tag -
+ * the element spec
+ */
+ private void insertContentTag(ElementSpec tag)
+ {
+ BranchElement paragraph = (BranchElement) elementStack.peek();
+ int len = tag.getLength();
+ int dir = tag.getDirection();
+ AttributeSet tagAtts = tag.getAttributes();
+
+ if (dir == ElementSpec.JoinNextDirection)
+ {
+ int index = paragraph.getElementIndex(pos);
+ Element target = paragraph.getElement(index);
+ Edit edit = getEditForParagraphAndIndex(paragraph, index);
+
+ if (paragraph.getStartOffset() > pos)
+ {
+ Element first = paragraph.getElement(0);
+ Element newEl = createLeafElement(paragraph,
+ first.getAttributes(), pos,
+ first.getEndOffset());
+ edit.addAddedElement(newEl);
+ edit.addRemovedElement(first);
+ }
+ else if (paragraph.getElementCount() > (index + 1)
+ && (pos == target.getStartOffset() && !target.equals(lastFractured)))
+ {
+ Element next = paragraph.getElement(index + 1);
+ Element newEl = createLeafElement(paragraph,
+ next.getAttributes(), pos,
+ next.getEndOffset());
+ edit.addAddedElement(newEl);
+ edit.addRemovedElement(next);
+ edit.addRemovedElement(target);
+ }
+ else
+ {
+ BranchElement parent = (BranchElement) paragraph.getParentElement();
+ int i = parent.getElementIndex(pos);
+ BranchElement next = (BranchElement) parent.getElement(i + 1);
+ AttributeSet atts = tag.getAttributes();
+
+ if (next != null)
+ {
+ Element nextLeaf = next.getElement(0);
+ Edit e = getEditForParagraphAndIndex(next, 0);
+ Element newEl2 = createLeafElement(next, atts, pos, nextLeaf.getEndOffset());
+ e.addAddedElement(newEl2);
+ e.addRemovedElement(nextLeaf);
+ }
+ }
+ }
+ else
+ {
+ int end = pos + len;
+ Element leaf = createLeafElement(paragraph, tag.getAttributes(), pos, end);
+
+ // Check for overlap with other leaves/branches
+ if (paragraph.getElementCount() > 0)
+ {
+ int index = paragraph.getElementIndex(pos);
+ Element target = paragraph.getElement(index);
+ boolean onlyContent = target.isLeaf();
+
+ BranchElement toRec = paragraph;
+ if (!onlyContent)
+ toRec = (BranchElement) target;
+
+ // Check if we should place the leaf before or after target
+ if (pos > target.getStartOffset())
+ index++;
+
+ Edit edit = getEditForParagraphAndIndex(paragraph, index);
+ edit.addAddedElement(leaf);
+ }
+ else
+ paragraph.replace(0, 0, new Element[] { leaf });
+ }
+
+ pos += len;
+ }
+
+ /**
+ * This method fractures the child at offset.
+ *
+ * @param data
+ * the ElementSpecs used for the entire insertion
+ */
+ private void createFracture(ElementSpec[] data)
+ {
+ BranchElement paragraph = (BranchElement) elementStack.peek();
+ int index = paragraph.getElementIndex(offset);
+ Element child = paragraph.getElement(index);
+ Edit edit = getEditForParagraphAndIndex(paragraph, index);
+ AttributeSet atts = child.getAttributes();
+
+ if (offset != 0)
+ {
+ Element newEl1 = createLeafElement(paragraph, atts,
+ child.getStartOffset(), offset);
+ edit.addAddedElement(newEl1);
+ edit.addRemovedElement(child);
+ }
+ }
+
+ /**
+ * Recreates a specified part of a the tree after a new leaf
+ * has been inserted.
+ *
+ * @param start - where to start recreating from
+ * @param paragraph - the paragraph to recreate
+ * @param onlyContent - true if this is the only content
+ */
+ private void recreateLeaves(int start, BranchElement paragraph, boolean onlyContent)
+ {
+ int index = paragraph.getElementIndex(start);
+ Element child = paragraph.getElement(index);
+ AttributeSet atts = child.getAttributes();
+
+ if (!onlyContent)
+ {
+ BranchElement newBranch = (BranchElement) createBranchElement(paragraph,
+ atts);
+ Element newLeaf = createLeafElement(newBranch, atts, start,
+ child.getEndOffset());
+ newBranch.replace(0, 0, new Element[] { newLeaf });
+
+ BranchElement parent = (BranchElement) paragraph.getParentElement();
+ int parSize = parent.getElementCount();
+ Edit edit = getEditForParagraphAndIndex(parent, parSize);
+ edit.addAddedElement(newBranch);
+
+ int paragraphSize = paragraph.getElementCount();
+ Element[] removed = new Element[paragraphSize - (index + 1)];
+ int s = 0;
+ for (int j = index + 1; j < paragraphSize; j++)
+ removed[s++] = paragraph.getElement(j);
+
+ edit = getEditForParagraphAndIndex(paragraph, index);
+ edit.addRemovedElements(removed);
+ Element[] added = recreateAfterFracture(removed, newBranch, 0, child.getEndOffset());
+ newBranch.replace(1, 0, added);
+
+ lastFractured = newLeaf;
+ pos = newBranch.getEndOffset();
+ }
+ else
+ {
+ Element newLeaf = createLeafElement(paragraph, atts, start,
+ child.getEndOffset());
+ Edit edit = getEditForParagraphAndIndex(paragraph, index);
+ edit.addAddedElement(newLeaf);
+ }
+ }
+
+ /**
+ * Splits an element if <code>offset</code> is not already at its
+ * boundary.
+ *
+ * @param el
+ * the Element to possibly split
+ * @param offset
+ * the offset at which to possibly split
+ * @param space
+ * the amount of space to create between the splitted parts
+ * @param editIndex
+ * the index of the edit to use
+ * @return An array of elements which represent the split result. This array
+ * has two elements, the two parts of the split. The first element
+ * might be null, which means that the element which should be
+ * splitted can remain in place. The second element might also be
+ * null, which means that the offset is already at an element
+ * boundary and the element doesn't need to be splitted.
+ */
+ private Element[] split(Element el, int offset, int space, int editIndex)
+ {
+ // If we are at an element boundary, then return an empty array.
+ if ((offset == el.getStartOffset() || offset == el.getEndOffset())
+ && space == 0 && el.isLeaf())
+ return new Element[2];
+
+ // If the element is an instance of BranchElement, then we
+ // recursivly
+ // call this method to perform the split.
+ Element[] res = new Element[2];
+ if (el instanceof BranchElement)
+ {
+ int index = el.getElementIndex(offset);
+ Element child = el.getElement(index);
+ Element[] result = split(child, offset, space, editIndex);
+ Element[] removed;
+ Element[] added;
+ Element[] newAdded;
+
+ int count = el.getElementCount();
+ if (result[1] != null)
+ {
+ // This is the case when we can keep the first element.
+ if (result[0] == null)
+ {
+ removed = new Element[count - index - 1];
+ newAdded = new Element[count - index - 1];
+ added = new Element[] {};
+
+ }
+ // This is the case when we may not keep the first
+ // element.
+ else
+ {
+ removed = new Element[count - index];
+ newAdded = new Element[count - index];
+ added = new Element[] { result[0] };
+ }
+ newAdded[0] = result[1];
+ for (int i = index; i < count; i++)
+ {
+ Element el2 = el.getElement(i);
+ int ind = i - count + removed.length;
+ removed[ind] = el2;
+ if (ind != 0)
+ newAdded[ind] = el2;
+ }
+
+ Edit edit = getEditForParagraphAndIndex((BranchElement) el, editIndex);
+ edit.addRemovedElements(removed);
+ edit.addAddedElements(added);
+
+ BranchElement newPar =
+ (BranchElement) createBranchElement(el.getParentElement(),
+ el.getAttributes());
+ newPar.replace(0, 0, newAdded);
+ res = new Element[] { null, newPar };
+ }
+ else
+ {
+ removed = new Element[count - index];
+ for (int i = index; i < count; ++i)
+ removed[i - index] = el.getElement(i);
+
+ Edit edit = getEditForParagraphAndIndex((BranchElement) el, editIndex);
+ edit.addRemovedElements(removed);
+
+ BranchElement newPar = (BranchElement) createBranchElement(el.getParentElement(),
+ el.getAttributes());
+ newPar.replace(0, 0, removed);
+ res = new Element[] { null, newPar };
+ }
+ }
+ else if (el instanceof LeafElement)
+ {
+ BranchElement par = (BranchElement) el.getParentElement();
+ Element el1 = createLeafElement(par, el.getAttributes(),
+ el.getStartOffset(), offset);
+
+ Element el2 = createLeafElement(par, el.getAttributes(),
+ offset + space,
+ el.getEndOffset());
+ res = new Element[] { el1, el2 };
+ }
+ return res;
+ }
+
+ /**
+ * Inserts a fracture into the document structure.
+ *
+ * @param tag -
+ * the element spec.
+ */
+ private void insertFracture(ElementSpec tag)
+ {
+ // insert the fracture at offset.
+ BranchElement parent = (BranchElement) elementStack.peek();
+ int parentIndex = parent.getElementIndex(pos);
+ AttributeSet parentAtts = parent.getAttributes();
+ Element toFracture = parent.getElement(parentIndex);
+ int parSize = parent.getElementCount();
+ Edit edit = getEditForParagraphAndIndex(parent, parentIndex);
+ Element frac = toFracture;
+ int leftIns = 0;
+ int indexOfFrac = toFracture.getElementIndex(pos);
+ int size = toFracture.getElementCount();
+
+ // gets the leaf that falls along the fracture
+ frac = toFracture.getElement(indexOfFrac);
+ while (!frac.isLeaf())
+ frac = frac.getElement(frac.getElementIndex(pos));
+
+ AttributeSet atts = frac.getAttributes();
+ int fracStart = frac.getStartOffset();
+ int fracEnd = frac.getEndOffset();
+ if (pos >= fracStart && pos < fracEnd)
+ {
+ // recreate left-side of branch and all its children before offset
+ // add the fractured leaves to the right branch
+ BranchElement rightBranch =
+ (BranchElement) createBranchElement(parent, parentAtts);
+
+ // Check if left branch has already been edited. If so, we only
+ // need to create the right branch.
+ BranchElement leftBranch = null;
+ Element[] added = null;
+ if (edit.added.size() > 0 || edit.removed.size() > 0)
+ {
+ added = new Element[] { rightBranch };
+
+ // don't try to remove left part of tree
+ parentIndex++;
+ }
+ else
+ {
+ leftBranch =
+ (BranchElement) createBranchElement(parent, parentAtts);
+ added = new Element[] { leftBranch, rightBranch };
+
+ // add fracture to leftBranch
+ if (fracStart != pos)
+ {
+ Element leftFracturedLeaf =
+ createLeafElement(leftBranch, atts, fracStart, pos);
+ leftBranch.replace(leftIns, 0,
+ new Element[] { leftFracturedLeaf });
+ }
+ }
+
+ if (!toFracture.isLeaf())
+ {
+ // add all non-fracture elements to the branches
+ if (indexOfFrac > 0 && leftBranch != null)
+ {
+ Element[] add = new Element[indexOfFrac];
+ for (int i = 0; i < indexOfFrac; i++)
+ add[i] = toFracture.getElement(i);
+ leftIns = add.length;
+ leftBranch.replace(0, 0, add);
+ }
+
+ int count = size - indexOfFrac - 1;
+ if (count > 0)
+ {
+ Element[] add = new Element[count];
+ int j = 0;
+ int i = indexOfFrac + 1;
+ while (j < count)
+ add[j++] = toFracture.getElement(i++);
+ rightBranch.replace(0, 0, add);
+ }
+ }
+
+ // add to fracture to rightBranch
+ // Check if we can join the right frac leaf with the next leaf
+ int rm = 0;
+ int end = fracEnd;
+ Element next = rightBranch.getElement(0);
+ if (next != null && next.isLeaf()
+ && next.getAttributes().isEqual(atts))
+ {
+ end = next.getEndOffset();
+ rm = 1;
+ }
+
+ Element rightFracturedLeaf = createLeafElement(rightBranch, atts,
+ pos, end);
+ rightBranch.replace(0, rm, new Element[] { rightFracturedLeaf });
+
+ // recreate those elements after parentIndex and add/remove all
+ // new/old elements to parent
+ int remove = parSize - parentIndex;
+ Element[] removed = new Element[0];
+ Element[] added2 = new Element[0];
+ if (remove > 0)
+ {
+ removed = new Element[remove];
+ int s = 0;
+ for (int j = parentIndex; j < parSize; j++)
+ removed[s++] = parent.getElement(j);
+ edit.addRemovedElements(removed);
+ added2 = recreateAfterFracture(removed, parent, 1,
+ rightBranch.getEndOffset());
+ }
+
+ edit.addAddedElements(added);
+ edit.addAddedElements(added2);
+ elementStack.push(rightBranch);
+ lastFractured = rightFracturedLeaf;
+ }
+ else
+ fracNotCreated = true;
+ }
+
+ /**
+ * Recreates all the elements from the parent to the element on the top of
+ * the stack, starting from startFrom with the starting offset of
+ * startOffset.
+ *
+ * @param recreate -
+ * the elements to recreate
+ * @param parent -
+ * the element to add the new elements to
+ * @param startFrom -
+ * where to start recreating from
+ * @param startOffset -
+ * the offset of the first element
+ * @return the array of added elements
+ */
+ private Element[] recreateAfterFracture(Element[] recreate,
+ BranchElement parent, int startFrom,
+ int startOffset)
+ {
+ Element[] added = new Element[recreate.length - startFrom];
+ int j = 0;
+ for (int i = startFrom; i < recreate.length; i++)
+ {
+ Element curr = recreate[i];
+ int len = curr.getEndOffset() - curr.getStartOffset();
+ if (curr instanceof LeafElement)
+ added[j] = createLeafElement(parent, curr.getAttributes(),
+ startOffset, startOffset + len);
+ else
+ {
+ BranchElement br =
+ (BranchElement) createBranchElement(parent,
+ curr.getAttributes());
+ int bSize = curr.getElementCount();
+ for (int k = 0; k < bSize; k++)
+ {
+ Element bCurr = curr.getElement(k);
+ Element[] add = recreateAfterFracture(new Element[] { bCurr }, br, 0,
+ startOffset);
+ br.replace(0, 0, add);
+
+ }
+ added[j] = br;
+ }
+ startOffset += len;
+ j++;
+ }
+
+ return added;
+ }
+ }
+
+ /**
+ * This method looks through the Vector of Edits to see if there is already an
+ * Edit object associated with the given paragraph. If there is, then we
+ * return it. Otherwise we create a new Edit object, add it to the vector, and
+ * return it. Note: this method is package private to avoid accessors.
+ *
+ * @param index
+ * the index associated with the Edit we want to create
+ * @param para
+ * the paragraph associated with the Edit we want
+ * @return the found or created Edit object
+ */
+ Edit getEditForParagraphAndIndex(BranchElement para, int index)
+ {
+ Edit curr;
+ int size = edits.size();
+ for (int i = 0; i < size; i++)
+ {
+ curr = (Edit) edits.elementAt(i);
+ if (curr.e.equals(para))
+ return curr;
+ }
+ curr = new Edit(para, index, null, null);
+ edits.add(curr);
+
+ return curr;
+ }
+ /**
+ * Instance of all editing information for an object in the Vector. This class
+ * is used to add information to the DocumentEvent associated with an
+ * insertion/removal/change as well as to store the changes that need to be
+ * made so they can be made all at the same (appropriate) time.
+ */
+ class Edit
+ {
+ /** The element to edit . */
+ Element e;
+
+ /** The index of the change. */
+ int index;
+
+ /** The removed elements. */
+ Vector removed = new Vector();
+
+ /** The added elements. */
+ Vector added = new Vector();
+
+ /**
+ * Return an array containing the Elements that have been removed from the
+ * paragraph associated with this Edit.
+ *
+ * @return an array of removed Elements
+ */
+ public Element[] getRemovedElements()
+ {
+ int size = removed.size();
+ Element[] removedElements = new Element[size];
+ for (int i = 0; i < size; i++)
+ removedElements[i] = (Element) removed.elementAt(i);
+ return removedElements;
+ }
+
+ /**
+ * Return an array containing the Elements that have been added to the
+ * paragraph associated with this Edit.
+ *
+ * @return an array of added Elements
+ */
+ public Element[] getAddedElements()
+ {
+ int size = added.size();
+ Element[] addedElements = new Element[size];
+ for (int i = 0; i < size; i++)
+ addedElements[i] = (Element) added.elementAt(i);
+ return addedElements;
+ }
+
+ /**
+ * Checks if e is already in the vector.
+ *
+ * @param e - the Element to look for
+ * @param v - the vector to search
+ * @return true if e is in v.
+ */
+ private boolean contains(Vector v, Element e)
+ {
+ if (e == null)
+ return false;
+
+ int i = v.size();
+ for (int j = 0; j < i; j++)
+ {
+ Element e1 = (Element) v.get(j);
+ if ((e1 != null) && (e1.getAttributes().isEqual(e.getAttributes()))
+ && (e1.getName().equals(e.getName()))
+ && (e1.getStartOffset() == e.getStartOffset())
+ && (e1.getEndOffset() == e.getEndOffset())
+ && (e1.getParentElement().equals(e.getParentElement()))
+ && (e1.getElementCount() == e.getElementCount()))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Adds one Element to the vector of removed Elements.
+ *
+ * @param e
+ * the Element to add
+ */
+ public void addRemovedElement(Element e)
+ {
+ if (!contains(removed, e))
+ removed.add(e);
+ }
+
+ /**
+ * Adds each Element in the given array to the vector of removed Elements
+ *
+ * @param e
+ * the array containing the Elements to be added
+ */
+ public void addRemovedElements(Element[] e)
+ {
+ if (e == null || e.length == 0)
+ return;
+ for (int i = 0; i < e.length; i++)
+ {
+ if (!contains(removed, e[i]))
+ removed.add(e[i]);
+ }
+ }
+
+ /**
+ * Adds one Element to the vector of added Elements.
+ *
+ * @param e
+ * the Element to add
+ */
+ public void addAddedElement(Element e)
+ {
+ if (!contains(added, e))
+ added.add(e);
+ }
+
+ /**
+ * Adds each Element in the given array to the vector of added Elements.
+ *
+ * @param e
+ * the array containing the Elements to be added
+ */
+ public void addAddedElements(Element[] e)
+ {
+ if (e == null || e.length == 0)
+ return;
+ for (int i = 0; i < e.length; i++)
+ {
+ if (!contains(added, e[i]))
+ added.add(e[i]);
+ }
+ }
+
+ /**
+ * Creates a new Edit object with the given parameters
+ *
+ * @param e
+ * the paragraph Element associated with this Edit
+ * @param i
+ * the index within the paragraph where changes are started
+ * @param removed
+ * an array containing Elements that should be removed from the
+ * paragraph Element
+ * @param added
+ * an array containing Elements that should be added to the
+ * paragraph Element
+ */
+ public Edit(Element e, int i, Element[] removed, Element[] added)
+ {
+ this.e = e;
+ this.index = i;
+ addRemovedElements(removed);
+ addAddedElements(added);
+ }
+ }
+
+ /**
+ * An element type for sections. This is a simple BranchElement with a unique
+ * name.
+ */
+ protected class SectionElement extends BranchElement
+ {
+ /**
+ * Creates a new SectionElement.
+ */
+ public SectionElement()
+ {
+ super(null, null);
+ }
+
+ /**
+ * Returns the name of the element. This method always returns
+ * "section".
+ *
+ * @return the name of the element
+ */
+ public String getName()
+ {
+ return SectionElementName;
+ }
+ }
+
+ /**
+ * Receives notification when any of the document's style changes and calls
+ * {@link DefaultStyledDocument#styleChanged(Style)}.
+ *
+ * @author Roman Kennke (kennke at aicas.com)
+ */
+ private class StyleChangeListener implements ChangeListener
+ {
+
+ /**
+ * Receives notification when any of the document's style changes and calls
+ * {@link DefaultStyledDocument#styleChanged(Style)}.
+ *
+ * @param event
+ * the change event
+ */
+ public void stateChanged(ChangeEvent event)
+ {
+ Style style = (Style) event.getSource();
+ styleChanged(style);
+ }
+ }
+
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 940485415728614849L;
+
+ /**
+ * The default size to use for new content buffers.
+ */
+ public static final int BUFFER_SIZE_DEFAULT = 4096;
+
+ /**
+ * The <code>EditorBuffer</code> that is used to manage to
+ * <code>Element</code> hierarchy.
+ */
+ protected DefaultStyledDocument.ElementBuffer buffer;
+
+ /**
+ * Listens for changes on this document's styles and notifies styleChanged().
+ */
+ private StyleChangeListener styleChangeListener;
+
+ /**
+ * Vector that contains all the edits. Maybe replace by a HashMap.
+ */
+ Vector edits = new Vector();
+
+ /**
+ * Creates a new <code>DefaultStyledDocument</code>.
+ */
+ public DefaultStyledDocument()
+ {
+ this(new GapContent(BUFFER_SIZE_DEFAULT), new StyleContext());
+ }
+
+ /**
+ * Creates a new <code>DefaultStyledDocument</code> that uses the specified
+ * {@link StyleContext}.
+ *
+ * @param context
+ * the <code>StyleContext</code> to use
+ */
+ public DefaultStyledDocument(StyleContext context)
+ {
+ this(new GapContent(BUFFER_SIZE_DEFAULT), context);
+ }
+
+ /**
+ * Creates a new <code>DefaultStyledDocument</code> that uses the specified
+ * {@link StyleContext} and {@link Content} buffer.
+ *
+ * @param content
+ * the <code>Content</code> buffer to use
+ * @param context
+ * the <code>StyleContext</code> to use
+ */
+ public DefaultStyledDocument(AbstractDocument.Content content,
+ StyleContext context)
+ {
+ super(content, context);
+ buffer = new ElementBuffer(createDefaultRoot());
+ setLogicalStyle(0, context.getStyle(StyleContext.DEFAULT_STYLE));
+ }
+
+ /**
+ * Adds a style into the style hierarchy. Unspecified style attributes can be
+ * resolved in the <code>parent</code> style, if one is specified. While it
+ * is legal to add nameless styles (<code>nm == null</code),
+ * you must be aware that the client application is then responsible
+ * for managing the style hierarchy, since unnamed styles cannot be
+ * looked up by their name.
+ *
+ * @param nm the name of the style or <code>null</code> if the style should
+ * be unnamed
+ * @param parent the parent in which unspecified style attributes are
+ * resolved, or <code>null</code> if that is not necessary
+ *
+ * @return the newly created <code>Style</code>
+ */
+ public Style addStyle(String nm, Style parent)
+ {
+ StyleContext context = (StyleContext) getAttributeContext();
+ Style newStyle = context.addStyle(nm, parent);
+
+ // Register change listener.
+ if (styleChangeListener == null)
+ styleChangeListener = new StyleChangeListener();
+ newStyle.addChangeListener(styleChangeListener);
+
+ return newStyle;
+ }
+
+ /**
+ * Create the default root element for this kind of <code>Document</code>.
+ *
+ * @return the default root element for this kind of <code>Document</code>
+ */
+ protected AbstractDocument.AbstractElement createDefaultRoot()
+ {
+ Element[] tmp;
+ SectionElement section = new SectionElement();
+
+ BranchElement paragraph = new BranchElement(section, null);
+ tmp = new Element[1];
+ tmp[0] = paragraph;
+ section.replace(0, 0, tmp);
+
+ Element leaf = new LeafElement(paragraph, null, 0, 1);
+ tmp = new Element[1];
+ tmp[0] = leaf;
+ paragraph.replace(0, 0, tmp);
+
+ return section;
+ }
+
+ /**
+ * Returns the <code>Element</code> that corresponds to the character at the
+ * specified position.
+ *
+ * @param position
+ * the position of which we query the corresponding
+ * <code>Element</code>
+ * @return the <code>Element</code> that corresponds to the character at the
+ * specified position
+ */
+ public Element getCharacterElement(int position)
+ {
+ Element element = getDefaultRootElement();
+
+ while (!element.isLeaf())
+ {
+ int index = element.getElementIndex(position);
+ element = element.getElement(index);
+ }
+
+ return element;
+ }
+
+ /**
+ * Extracts a background color from a set of attributes.
+ *
+ * @param attributes
+ * the attributes from which to get a background color
+ * @return the background color that correspond to the attributes
+ */
+ public Color getBackground(AttributeSet attributes)
+ {
+ StyleContext context = (StyleContext) getAttributeContext();
+ return context.getBackground(attributes);
+ }
+
+ /**
+ * Returns the default root element.
+ *
+ * @return the default root element
+ */
+ public Element getDefaultRootElement()
+ {
+ return buffer.getRootElement();
+ }
+
+ /**
+ * Extracts a font from a set of attributes.
+ *
+ * @param attributes
+ * the attributes from which to get a font
+ * @return the font that correspond to the attributes
+ */
+ public Font getFont(AttributeSet attributes)
+ {
+ StyleContext context = (StyleContext) getAttributeContext();
+ return context.getFont(attributes);
+ }
+
+ /**
+ * Extracts a foreground color from a set of attributes.
+ *
+ * @param attributes
+ * the attributes from which to get a foreground color
+ * @return the foreground color that correspond to the attributes
+ */
+ public Color getForeground(AttributeSet attributes)
+ {
+ StyleContext context = (StyleContext) getAttributeContext();
+ return context.getForeground(attributes);
+ }
+
+ /**
+ * Returns the logical <code>Style</code> for the specified position.
+ *
+ * @param position
+ * the position from which to query to logical style
+ * @return the logical <code>Style</code> for the specified position
+ */
+ public Style getLogicalStyle(int position)
+ {
+ Element paragraph = getParagraphElement(position);
+ AttributeSet attributes = paragraph.getAttributes();
+ AttributeSet a = attributes.getResolveParent();
+ // If the resolve parent is not of type Style, we return null.
+ if (a instanceof Style)
+ return (Style) a;
+ return null;
+ }
+
+ /**
+ * Returns the paragraph element for the specified position. If the position
+ * is outside the bounds of the document's root element, then the closest
+ * element is returned. That is the last paragraph if
+ * <code>position >= endIndex</code> or the first paragraph if
+ * <code>position < startIndex</code>.
+ *
+ * @param position
+ * the position for which to query the paragraph element
+ * @return the paragraph element for the specified position
+ */
+ public Element getParagraphElement(int position)
+ {
+ Element e = getDefaultRootElement();
+ while (!e.isLeaf())
+ e = e.getElement(e.getElementIndex(position));
+
+ if (e != null)
+ return e.getParentElement();
+ return e;
+ }
+
+ /**
+ * Looks up and returns a named <code>Style</code>.
+ *
+ * @param nm
+ * the name of the <code>Style</code>
+ * @return the found <code>Style</code> of <code>null</code> if no such
+ * <code>Style</code> exists
+ */
+ public Style getStyle(String nm)
+ {
+ StyleContext context = (StyleContext) getAttributeContext();
+ return context.getStyle(nm);
+ }
+
+ /**
+ * Removes a named <code>Style</code> from the style hierarchy.
+ *
+ * @param nm
+ * the name of the <code>Style</code> to be removed
+ */
+ public void removeStyle(String nm)
+ {
+ StyleContext context = (StyleContext) getAttributeContext();
+ context.removeStyle(nm);
+ }
+
+ /**
+ * Sets text attributes for the fragment specified by <code>offset</code>
+ * and <code>length</code>.
+ *
+ * @param offset
+ * the start offset of the fragment
+ * @param length
+ * the length of the fragment
+ * @param attributes
+ * the text attributes to set
+ * @param replace
+ * if <code>true</code>, the attributes of the current selection
+ * are overridden, otherwise they are merged
+ */
+ public void setCharacterAttributes(int offset, int length,
+ AttributeSet attributes, boolean replace)
+ {
+ // Exit early if length is 0, so no DocumentEvent is created or fired.
+ if (length == 0)
+ return;
+ try
+ {
+ // Must obtain a write lock for this method. writeLock() and
+ // writeUnlock() should always be in try/finally block to make
+ // sure that locking happens in a balanced manner.
+ writeLock();
+ DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
+ length,
+ DocumentEvent.EventType.CHANGE);
+
+ // Modify the element structure so that the interval begins at an
+ // element
+ // start and ends at an element end.
+ buffer.change(offset, length, ev);
+
+ Element root = getDefaultRootElement();
+ // Visit all paragraph elements within the specified interval
+ int end = offset + length;
+ Element curr;
+ for (int pos = offset; pos < end;)
+ {
+ // Get the CharacterElement at offset pos.
+ curr = getCharacterElement(pos);
+ if (pos == curr.getEndOffset())
+ break;
+
+ MutableAttributeSet a = (MutableAttributeSet) curr.getAttributes();
+ ev.addEdit(new AttributeUndoableEdit(curr, attributes, replace));
+ // If replace is true, remove all the old attributes.
+ if (replace)
+ a.removeAttributes(a);
+ // Add all the new attributes.
+ a.addAttributes(attributes);
+ // Increment pos so we can check the next CharacterElement.
+ pos = curr.getEndOffset();
+ }
+ fireChangedUpdate(ev);
+ fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
+ }
+ finally
+ {
+ writeUnlock();
+ }
+ }
+
+ /**
+ * Sets the logical style for the paragraph at the specified position.
+ *
+ * @param position
+ * the position at which the logical style is added
+ * @param style
+ * the style to set for the current paragraph
+ */
+ public void setLogicalStyle(int position, Style style)
+ {
+ Element el = getParagraphElement(position);
+ // getParagraphElement doesn't return null but subclasses might so
+ // we check for null here.
+ if (el == null)
+ return;
+ try
+ {
+ writeLock();
+ if (el instanceof AbstractElement)
+ {
+ AbstractElement ael = (AbstractElement) el;
+ ael.setResolveParent(style);
+ int start = el.getStartOffset();
+ int end = el.getEndOffset();
+ DefaultDocumentEvent ev = new DefaultDocumentEvent(start,
+ end - start,
+ DocumentEvent.EventType.CHANGE);
+ fireChangedUpdate(ev);
+ fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
+ }
+ else
+ throw new AssertionError(
+ "paragraph elements are expected to be"
+ + "instances of AbstractDocument.AbstractElement");
+ }
+ finally
+ {
+ writeUnlock();
+ }
+ }
+
+ /**
+ * Sets text attributes for the paragraph at the specified fragment.
+ *
+ * @param offset
+ * the beginning of the fragment
+ * @param length
+ * the length of the fragment
+ * @param attributes
+ * the text attributes to set
+ * @param replace
+ * if <code>true</code>, the attributes of the current selection
+ * are overridden, otherwise they are merged
+ */
+ public void setParagraphAttributes(int offset, int length,
+ AttributeSet attributes, boolean replace)
+ {
+ try
+ {
+ // Must obtain a write lock for this method. writeLock() and
+ // writeUnlock() should always be in try/finally blocks to make
+ // sure that locking occurs in a balanced manner.
+ writeLock();
+
+ // Create a DocumentEvent to use for changedUpdate().
+ DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
+ length,
+ DocumentEvent.EventType.CHANGE);
+
+ // Have to iterate through all the _paragraph_ elements that are
+ // contained or partially contained in the interval
+ // (offset, offset + length).
+ Element rootElement = getDefaultRootElement();
+ int startElement = rootElement.getElementIndex(offset);
+ int endElement = rootElement.getElementIndex(offset + length - 1);
+ if (endElement < startElement)
+ endElement = startElement;
+
+ for (int i = startElement; i <= endElement; i++)
+ {
+ Element par = rootElement.getElement(i);
+ MutableAttributeSet a = (MutableAttributeSet) par.getAttributes();
+ // Add the change to the DocumentEvent.
+ ev.addEdit(new AttributeUndoableEdit(par, attributes, replace));
+ // If replace is true remove the old attributes.
+ if (replace)
+ a.removeAttributes(a);
+ // Add the new attributes.
+ a.addAttributes(attributes);
+ }
+ fireChangedUpdate(ev);
+ fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
+ }
+ finally
+ {
+ writeUnlock();
+ }
+ }
+
+ /**
+ * Called in response to content insert actions. This is used to update the
+ * element structure.
+ *
+ * @param ev
+ * the <code>DocumentEvent</code> describing the change
+ * @param attr
+ * the attributes for the change
+ */
+ protected void insertUpdate(DefaultDocumentEvent ev, AttributeSet attr)
+ {
+ super.insertUpdate(ev, attr);
+ // If the attribute set is null, use an empty attribute set.
+ if (attr == null)
+ attr = SimpleAttributeSet.EMPTY;
+ int offset = ev.getOffset();
+ int length = ev.getLength();
+ int endOffset = offset + length;
+ AttributeSet paragraphAttributes = getParagraphElement(endOffset).getAttributes();
+ Segment txt = new Segment();
+ try
+ {
+ getText(offset, length, txt);
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError ae = new AssertionError("Unexpected bad location");
+ ae.initCause(ex);
+ throw ae;
+ }
+
+ int len = 0;
+ Vector specs = new Vector();
+ ElementSpec finalStartTag = null;
+ short finalStartDirection = ElementSpec.OriginateDirection;
+ boolean prevCharWasNewline = false;
+ Element prev = getCharacterElement(offset);
+ Element next = getCharacterElement(endOffset);
+ Element prevParagraph = getParagraphElement(offset);
+ Element paragraph = getParagraphElement(endOffset);
+
+ int segmentEnd = txt.offset + txt.count;
+
+ // Check to see if we're inserting immediately after a newline.
+ if (offset > 0)
+ {
+ try
+ {
+ String s = getText(offset - 1, 1);
+ if (s.equals("\n"))
+ {
+ finalStartDirection = handleInsertAfterNewline(specs, offset,
+ endOffset,
+ prevParagraph,
+ paragraph,
+ paragraphAttributes);
+
+ prevCharWasNewline = true;
+ // Find the final start tag from the ones just created.
+ for (int i = 0; i < specs.size(); i++)
+ if (((ElementSpec) specs.get(i)).getType() == ElementSpec.StartTagType)
+ finalStartTag = (ElementSpec) specs.get(i);
+ }
+ }
+ catch (BadLocationException ble)
+ {
+ // This shouldn't happen.
+ AssertionError ae = new AssertionError();
+ ae.initCause(ble);
+ throw ae;
+ }
+ }
+
+ for (int i = txt.offset; i < segmentEnd; ++i)
+ {
+ len++;
+ if (txt.array[i] == '\n')
+ {
+ // Add the ElementSpec for the content.
+ specs.add(new ElementSpec(attr, ElementSpec.ContentType, len));
+
+ // Add ElementSpecs for the newline.
+ specs.add(new ElementSpec(null, ElementSpec.EndTagType));
+ finalStartTag = new ElementSpec(paragraphAttributes,
+ ElementSpec.StartTagType);
+ specs.add(finalStartTag);
+ len = 0;
+ }
+ }
+
+ // Create last element if last character hasn't been a newline.
+ if (len > 0)
+ specs.add(new ElementSpec(attr, ElementSpec.ContentType, len));
+
+ // Set the direction of the last spec of type StartTagType.
+ // If we are inserting after a newline then this value comes from
+ // handleInsertAfterNewline.
+ if (finalStartTag != null)
+ {
+ if (prevCharWasNewline)
+ finalStartTag.setDirection(finalStartDirection);
+ else if (prevParagraph.getEndOffset() != endOffset)
+ finalStartTag.setDirection(ElementSpec.JoinFractureDirection);
+ else
+ {
+ // If there is an element AFTER this one, then set the
+ // direction to JoinNextDirection.
+ Element parent = prevParagraph.getParentElement();
+ int index = parent.getElementIndex(offset);
+ if (index + 1 < parent.getElementCount()
+ && !parent.getElement(index + 1).isLeaf())
+ finalStartTag.setDirection(ElementSpec.JoinNextDirection);
+ }
+ }
+
+ // If we are at the last index, then check if we could probably be
+ // joined with the next element.
+ // This means:
+ // - we must be a ContentTag
+ // - if there is a next Element, we must have the same attributes
+ // - if there is no next Element, but one will be created,
+ // we must have the same attributes as the higher-level run.
+ ElementSpec last = (ElementSpec) specs.lastElement();
+ if (last.getType() == ElementSpec.ContentType)
+ {
+ Element currentRun = prevParagraph.getElement(prevParagraph.getElementIndex(offset));
+ if (currentRun.getEndOffset() == endOffset)
+ {
+ if (endOffset < getLength() && next.getAttributes().isEqual(attr)
+ && last.getType() == ElementSpec.ContentType)
+ last.setDirection(ElementSpec.JoinNextDirection);
+ }
+ else
+ {
+ if (finalStartTag != null
+ && finalStartTag.getDirection() == ElementSpec.JoinFractureDirection
+ && currentRun.getAttributes().isEqual(attr))
+ {
+ last.setDirection(ElementSpec.JoinNextDirection);
+ }
+ }
+ }
+
+ // If we are at the first new element, then check if it could be
+ // joined with the previous element.
+ ElementSpec first = (ElementSpec) specs.firstElement();
+ if (prev.getAttributes().isEqual(attr)
+ && first.getType() == ElementSpec.ContentType)
+ first.setDirection(ElementSpec.JoinPreviousDirection);
+
+ ElementSpec[] elSpecs = (ElementSpec[]) specs.toArray(new ElementSpec[specs.size()]);
+ buffer.insert(offset, length, elSpecs, ev);
+ }
+
+ /**
+ * A helper method to set up the ElementSpec buffer for the special case of an
+ * insertion occurring immediately after a newline.
+ *
+ * @param specs
+ * the ElementSpec buffer to initialize.
+ */
+ short handleInsertAfterNewline(Vector specs, int offset, int endOffset,
+ Element prevParagraph, Element paragraph,
+ AttributeSet a)
+ {
+ if (prevParagraph.getParentElement() == paragraph.getParentElement())
+ {
+ specs.add(new ElementSpec(a, ElementSpec.EndTagType));
+ specs.add(new ElementSpec(a, ElementSpec.StartTagType));
+ if (paragraph.getStartOffset() != endOffset)
+ return ElementSpec.JoinFractureDirection;
+ // If there is an Element after this one, use JoinNextDirection.
+ Element parent = paragraph.getParentElement();
+ if (parent.getElementCount() > (parent.getElementIndex(offset) + 1))
+ return ElementSpec.JoinNextDirection;
+ }
+ return ElementSpec.OriginateDirection;
+ }
+
+ /**
+ * Updates the document structure in response to text removal. This is
+ * forwarded to the {@link ElementBuffer} of this document. Any changes to the
+ * document structure are added to the specified document event and sent to
+ * registered listeners.
+ *
+ * @param ev
+ * the document event that records the changes to the document
+ */
+ protected void removeUpdate(DefaultDocumentEvent ev)
+ {
+ super.removeUpdate(ev);
+ buffer.remove(ev.getOffset(), ev.getLength(), ev);
+ }
+
+ /**
+ * Returns an enumeration of all style names.
+ *
+ * @return an enumeration of all style names
+ */
+ public Enumeration getStyleNames()
+ {
+ StyleContext context = (StyleContext) getAttributeContext();
+ return context.getStyleNames();
+ }
+
+ /**
+ * Called when any of this document's styles changes.
+ *
+ * @param style
+ * the style that changed
+ */
+ protected void styleChanged(Style style)
+ {
+ // Nothing to do here. This is intended to be overridden by subclasses.
+ }
+
+ /**
+ * Inserts a bulk of structured content at once.
+ *
+ * @param offset
+ * the offset at which the content should be inserted
+ * @param data
+ * the actual content spec to be inserted
+ */
+ protected void insert(int offset, ElementSpec[] data)
+ throws BadLocationException
+ {
+ if (data == null || data.length == 0)
+ return;
+ try
+ {
+ // writeLock() and writeUnlock() should always be in a try/finally
+ // block so that locking balance is guaranteed even if some
+ // exception is thrown.
+ writeLock();
+
+ // First we collect the content to be inserted.
+ StringBuffer contentBuffer = new StringBuffer();
+ for (int i = 0; i < data.length; i++)
+ {
+ // Collect all inserts into one so we can get the correct
+ // ElementEdit
+ ElementSpec spec = data[i];
+ if (spec.getArray() != null && spec.getLength() > 0)
+ contentBuffer.append(spec.getArray(), spec.getOffset(),
+ spec.getLength());
+ }
+
+ int length = contentBuffer.length();
+
+ // If there was no content inserted then exit early.
+ if (length == 0)
+ return;
+
+ UndoableEdit edit = content.insertString(offset,
+ contentBuffer.toString());
+
+ // Create the DocumentEvent with the ElementEdit added
+ DefaultDocumentEvent ev = new DefaultDocumentEvent(offset,
+ length,
+ DocumentEvent.EventType.INSERT);
+ ev.addEdit(edit);
+
+ // Finally we must update the document structure and fire the insert
+ // update event.
+ buffer.insert(offset, length, data, ev);
+ fireInsertUpdate(ev);
+ fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
+ }
+ finally
+ {
+ writeUnlock();
+ }
+ }
+
+ /**
+ * Initializes the <code>DefaultStyledDocument</code> with the specified
+ * data.
+ *
+ * @param data
+ * the specification of the content with which the document is
+ * initialized
+ */
+ protected void create(ElementSpec[] data)
+ {
+ writeLock();
+ try
+ {
+ // Clear content if there is some.
+ int len = getLength();
+ if (len > 0)
+ remove(0, len);
+
+ // Now we insert the content.
+ StringBuilder b = new StringBuilder();
+ for (int i = 0; i < data.length; ++i)
+ {
+ ElementSpec el = data[i];
+ if (el.getArray() != null && el.getLength() > 0)
+ b.append(el.getArray(), el.getOffset(), el.getLength());
+ }
+ Content content = getContent();
+ UndoableEdit cEdit = content.insertString(0, b.toString());
+
+ DefaultDocumentEvent ev =
+ new DefaultDocumentEvent(0, b.length(),
+ DocumentEvent.EventType.INSERT);
+ ev.addEdit(cEdit);
+
+ // We do a little trick here to get the new structure: We instantiate
+ // a new ElementBuffer with a new root element, insert into that root
+ // and then reparent the newly created elements to the old root
+ // element.
+ BranchElement createRoot =
+ (BranchElement) createBranchElement(null, null);
+ Element dummyLeaf = createLeafElement(createRoot, null, 0, 1);
+ createRoot.replace(0, 0, new Element[]{ dummyLeaf });
+ ElementBuffer createBuffer = new ElementBuffer(createRoot);
+ createBuffer.insert(0, b.length(), data, new DefaultDocumentEvent(0, b.length(), DocumentEvent.EventType.INSERT));
+ // Now the new root is the first child of the createRoot.
+ Element newRoot = createRoot.getElement(0);
+ BranchElement root = (BranchElement) getDefaultRootElement();
+ Element[] added = new Element[newRoot.getElementCount()];
+ for (int i = 0; i < added.length; ++i)
+ {
+ added[i] = newRoot.getElement(i);
+ ((AbstractElement) added[i]).element_parent = root;
+ }
+ Element[] removed = new Element[root.getElementCount()];
+ for (int i = 0; i < removed.length; ++i)
+ removed[i] = root.getElement(i);
+
+ // Replace the old elements in root with the new and update the event.
+ root.replace(0, removed.length, added);
+ ev.addEdit(new ElementEdit(root, 0, removed, added));
+
+ fireInsertUpdate(ev);
+ fireUndoableEditUpdate(new UndoableEditEvent(this, ev));
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError err = new AssertionError("Unexpected bad location");
+ err.initCause(ex);
+ throw err;
+ }
+ finally
+ {
+ writeUnlock();
+ }
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultTextUI.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultTextUI.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultTextUI.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DefaultTextUI.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,62 @@
+/* DefaultTextUI.java -- Deprecated base UI for text components
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import javax.swing.plaf.basic.BasicTextUI;
+
+/**
+ * This class is deprecated and should not be used anymore. The base UI for
+ * all text components is now {@link BasicTextUI}.
+ *
+ * @author Roman Kennke (kennke at aicas.com)
+ * @deprecated as of 1.5 use {@link BasicTextUI} instead
+ */
+public abstract class DefaultTextUI extends BasicTextUI
+{
+ /**
+ * This class is deprecated and should not be used anymore. The base UI for
+ * all text components is now {@link BasicTextUI}.
+ *
+ * @deprecated use {@link BasicTextUI} instead
+ */
+ public DefaultTextUI()
+ {
+ // Nothing to do here.
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Document.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Document.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Document.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Document.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,221 @@
+/* Document.java --
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import javax.swing.event.DocumentListener;
+import javax.swing.event.UndoableEditListener;
+
+/**
+ * A Document is the model that backs up all text components in Swing.
+ * This interface supports different kinds of implementations, from
+ * simple plain text model up to complex styled HTML or RTF models.
+ */
+public interface Document
+{
+ /**
+ * The key for the property that describes the source of a document.
+ */
+ String StreamDescriptionProperty = "stream";
+
+ /**
+ * The key for the property that is the title of a document.
+ */
+ String TitleProperty = "title";
+
+ /**
+ * Adds a {@link DocumentListener} to this document.
+ *
+ * @param listener the DocumentListener to add
+ */
+ void addDocumentListener(DocumentListener listener);
+
+ /**
+ * Adds an {@link UndoableEditListener} to this document.
+ *
+ * @param listener the UndoableEditListener to add
+ */
+ void addUndoableEditListener(UndoableEditListener listener);
+
+ /**
+ * Creates a mark in the character content at the specified offset.
+ *
+ * @param offs the offset where to place the mark
+ *
+ * @return the created Position object
+ *
+ * @throws BadLocationException of the specified offset is not a valid
+ * position in the documents content
+ */
+ Position createPosition(int offs)
+ throws BadLocationException;
+
+ /**
+ * Returns the default root element. Views should be using this element
+ * unless other mechanisms for assigning views to element structure is
+ * provided.
+ *
+ * @return the default root element
+ */
+ Element getDefaultRootElement();
+
+ /**
+ * Returns the position that marks the end of the document.
+ *
+ * @return the position that marks the end of the document
+ */
+ Position getEndPosition();
+
+ /**
+ * Returns the length of the document content.
+ *
+ * @return the length of the document content
+ */
+ int getLength();
+
+ /**
+ * Returns a document property with the specified key.
+ *
+ * @param key the (non-null) key for the property to fetch
+ *
+ * @return the property for <code>key</code> or null if no such property
+ * is stored
+ */
+ Object getProperty(Object key);
+
+ /**
+ * Returns the root elements of the document content.
+ *
+ * @return the root elements of the document content
+ */
+ Element[] getRootElements();
+
+ /**
+ * Returns the position that marks the beginning of the document
+ * content.
+ *
+ * @return the start position
+ */
+ Position getStartPosition();
+
+ /**
+ * Returns the textual content starting at <code>offset</code> with
+ * a length of <code>length</code>.
+ *
+ * @param offset the beginning of the text fragment to fetch
+ * @param length the length of the text fragment to fetch
+ *
+ * @return the text fragment starting at <code>offset</code> with
+ * a length of <code>length</code>
+ *
+ * @throws BadLocationException if <code>offset</code> or <code>length</code>
+ * are no valid locations in the document content
+ */
+ String getText(int offset, int length)
+ throws BadLocationException;
+
+ /**
+ * Fetch the textual content starting at <code>offset</code> with
+ * a length of <code>length</code> and store it in <code>txt</code>.
+ *
+ * @param offset the beginning of the text fragment to fetch
+ * @param length the length of the text fragment to fetch
+ * @param txt the Segment where to store the text fragment
+ *
+ * @throws BadLocationException if <code>offset</code> or <code>length</code>
+ * are no valid locations in the document content
+ */
+ void getText(int offset, int length, Segment txt)
+ throws BadLocationException;
+
+ /**
+ * Inserts a piece of text with an AttributeSet at the specified
+ * <code>offset</code>.
+ *
+ * @param offset the location where to insert the content
+ * @param str the textual content to insert
+ * @param a the Attributes associated with the piece of text
+ *
+ * @throws BadLocationException if <code>offset</code>
+ * is not a valid location in the document content
+ */
+ void insertString(int offset, String str, AttributeSet a)
+ throws BadLocationException;
+
+ /**
+ * Sets a document property.
+ *
+ * @param key the key of the property
+ * @param value the value of the property
+ */
+ void putProperty(Object key, Object value);
+
+ /**
+ * Removes a piece of content.
+ *
+ * @param offs the location of the fragment to remove
+ * @param len the length of the fragment to remove
+ *
+ * @throws BadLocationException if <code>offs</code> or <code>len</code>
+ * are no valid locations in the document content
+ */
+ void remove(int offs, int len)
+ throws BadLocationException;
+
+ /**
+ * Removes a DocumentListener from this Document.
+ *
+ * @param listener the DocumentListener to remove
+ */
+ void removeDocumentListener(DocumentListener listener);
+
+ /**
+ * Removes an UndoableEditListener from this Document.
+ *
+ * @param listener the UndoableEditListener to remove
+ */
+ void removeUndoableEditListener(UndoableEditListener listener);
+
+ /**
+ * This allows the Document to be rendered safely. It is made sure that
+ * the Runnable can read the document without any changes while reading.
+ * The Runnable is not allowed to change the Document itself.
+ *
+ * @param r the Runnable that renders the Document
+ */
+ void render(Runnable r);
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DocumentFilter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DocumentFilter.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DocumentFilter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/DocumentFilter.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,83 @@
+/* DocumentFilter.java --
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+public class DocumentFilter
+{
+ public abstract static class FilterBypass
+ {
+ public FilterBypass()
+ {
+ // Do nothing here.
+ }
+
+ public abstract Document getDocument();
+
+ public abstract void insertString(int offset, String string,
+ AttributeSet attr)
+ throws BadLocationException;
+
+ public abstract void remove(int offset, int length)
+ throws BadLocationException;
+
+ public abstract void replace(int offset, int length, String string,
+ AttributeSet attrs)
+ throws BadLocationException;
+ }
+
+ public void insertString(DocumentFilter.FilterBypass fb, int offset,
+ String string, AttributeSet attr)
+ throws BadLocationException
+ {
+ fb.insertString(offset, string, attr);
+ }
+
+ public void remove(DocumentFilter.FilterBypass fb, int offset, int length)
+ throws BadLocationException
+ {
+ fb.remove(offset, length);
+ }
+
+ public void replace(DocumentFilter.FilterBypass fb, int offset, int length,
+ String text, AttributeSet attr)
+ throws BadLocationException
+ {
+ fb.replace(offset, length, text, attr);
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/EditorKit.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/EditorKit.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/EditorKit.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/EditorKit.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,98 @@
+/* EditorKit.java --
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Serializable;
+import java.io.Writer;
+
+import javax.swing.Action;
+import javax.swing.JEditorPane;
+
+public abstract class EditorKit implements Cloneable, Serializable
+{
+ private static final long serialVersionUID = -5044124649345887822L;
+
+ public EditorKit()
+ {
+ // Nothing to do here.
+ }
+
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Called when the kit is being removed from the JEditorPane.
+ */
+ public void deinstall(JEditorPane c)
+ {
+ // This default implementation does nothing.
+ }
+
+ public void install(JEditorPane c)
+ {
+ // This default implementation does nothing.
+ }
+
+ public abstract Caret createCaret();
+ public abstract Document createDefaultDocument();
+ public abstract Action[] getActions();
+ public abstract String getContentType();
+ public abstract ViewFactory getViewFactory();
+ public abstract void read(InputStream in, Document doc, int pos)
+ throws BadLocationException, IOException;
+ public abstract void read(Reader in, Document doc, int pos)
+ throws BadLocationException, IOException;
+ public abstract void write(OutputStream out, Document doc, int pos, int len)
+ throws BadLocationException, IOException;
+ public abstract void write(Writer out, Document doc, int pos, int len)
+ throws BadLocationException, IOException;
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Element.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Element.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Element.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Element.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,54 @@
+/* Element.java --
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+
+
+public interface Element
+{
+ AttributeSet getAttributes();
+ Document getDocument();
+ Element getElement(int index);
+ int getElementCount();
+ int getElementIndex(int offset);
+ int getEndOffset();
+ String getName();
+ Element getParentElement();
+ int getStartOffset();
+ boolean isLeaf();
+ }
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ElementIterator.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ElementIterator.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ElementIterator.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ElementIterator.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,181 @@
+/* ElementIterator.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+/**
+ * This class can be used to iterate over the {@link Element} tree of
+ * a {@link Document} or an {@link Element}. This iterator performs
+ * an "in-order" traversal -- first it visits a node, then each of the
+ * node's children in order. No locking is performed during the
+ * iteration; that is up to the caller.
+ */
+public class ElementIterator implements Cloneable
+{
+ // The root element.
+ private Element root;
+ // The current element.
+ private Element currentElement;
+ // The depth to which we have descended in the tree.
+ private int currentDepth;
+
+ // This is at least as big as the current depth, and at index N
+ // contains the index of the child element we're currently
+ // examining.
+ private int[] state;
+
+ // The previous item.
+ private Element previousItem;
+
+ /**
+ * Create a new ElementIterator to iterate over the given document.
+ * @param document the Document over which we iterate
+ */
+ public ElementIterator(Document document)
+ {
+ this.root = document.getDefaultRootElement();
+ this.currentElement = root;
+ this.state = new int[5];
+ }
+
+ /**
+ * Create a new ElementIterator to iterate over the given document.
+ * @param root the Document over which we iterate
+ */
+ public ElementIterator(Element root)
+ {
+ this.root = root;
+ this.currentElement = root;
+ this.state = new int[5];
+ }
+
+ /**
+ * Returns a new ElementIterator which is a clone of this
+ * ElementIterator.
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException _)
+ {
+ // Can't happen.
+ return null;
+ }
+ }
+
+ /**
+ * Returns the current element.
+ */
+ public Element current()
+ {
+ return currentElement;
+ }
+
+ /**
+ * Returns the depth to which we have descended in the tree.
+ */
+ public int depth()
+ {
+ return currentDepth;
+ }
+
+ /**
+ * Returns the first element in the tree.
+ */
+ public Element first()
+ {
+ // Reset the iterator.
+ currentElement = root;
+ currentDepth = 0;
+ previousItem = null;
+ return root;
+ }
+
+ /**
+ * Advance the iterator and return the next element of the tree,
+ * performing an "in-order" traversal.
+ */
+ public Element next()
+ {
+ previousItem = currentElement;
+ if (currentElement == null)
+ return null;
+ if (! currentElement.isLeaf())
+ {
+ ++currentDepth;
+ if (currentDepth > state.length)
+ {
+ int[] newState = new int[state.length * 2];
+ System.arraycopy(state, 0, newState, 0, state.length);
+ state = newState;
+ }
+ state[currentDepth] = 0;
+ currentElement = currentElement.getElement(0);
+ return currentElement;
+ }
+
+ while (currentDepth > 0)
+ {
+ // At a leaf, or done with a non-leaf's children, so go up a
+ // level.
+ --currentDepth;
+ currentElement = currentElement.getParentElement();
+ ++state[currentDepth];
+ if (state[currentDepth] < currentElement.getElementCount())
+ {
+ currentElement = currentElement.getElement(state[currentDepth]);
+ return currentElement;
+ }
+ }
+
+ currentElement = null;
+ return currentElement;
+ }
+
+ /**
+ * Returns the previous item. Does not modify the iterator state.
+ */
+ public Element previous()
+ {
+ if (currentElement == null || currentElement == root)
+ return null;
+ return previousItem;
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/EmptyAttributeSet.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/EmptyAttributeSet.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/EmptyAttributeSet.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/EmptyAttributeSet.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,153 @@
+/* EmptyAttributeSet.java -- An empty attribute set
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+/**
+ * An immutable, empty attribute set.
+ *
+ * @see SimpleAttributeSet#EMPTY
+ *
+ * @author Roman Kennke (kennke at aicas.com)
+ */
+final class EmptyAttributeSet
+ implements AttributeSet
+{
+
+ /**
+ * Always return false as this AttributeSet doesn't contain any attributes.
+ */
+ public boolean containsAttribute(Object name, Object value)
+ {
+ return false;
+ }
+
+ /**
+ * Return true only if the attributes argument also contains no attributes.
+ */
+ public boolean containsAttributes(AttributeSet attributes)
+ {
+ return attributes.getAttributeCount() == 0;
+ }
+
+ /**
+ * Return this, as this is immutable.
+ */
+ public AttributeSet copyAttributes()
+ {
+ return this;
+ }
+
+ /**
+ * Always return null as this AttributeSet doesn't contain any attributes.
+ */
+ public Object getAttribute(Object key)
+ {
+ return null;
+ }
+
+ /**
+ * Always return 0.
+ */
+ public int getAttributeCount()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns an empty Enumeration.
+ */
+ public Enumeration getAttributeNames()
+ {
+ return new Enumeration()
+ {
+ public boolean hasMoreElements()
+ {
+ return false;
+ }
+
+ public Object nextElement()
+ {
+ throw new NoSuchElementException("No more elements");
+ }
+
+ };
+ }
+
+ /**
+ * Always return null as this has no resolve parent.
+ */
+ public AttributeSet getResolveParent()
+ {
+ return null;
+ }
+
+ /**
+ * Always return false as this AttributeSet doesn't contain any attributes.
+ */
+ public boolean isDefined(Object attrName)
+ {
+ return false;
+ }
+
+ /**
+ * Other attribute sets are equal if they are empty too.
+ */
+ public boolean isEqual(AttributeSet attr)
+ {
+ return attr.getAttributeCount() == 0;
+ }
+
+ /**
+ * Other objects are equal if it's the same instance as this, or if
+ * it's another attribute set without attributes.
+ */
+ public boolean equals(Object o)
+ {
+ boolean eq = o == this;
+ if (! eq)
+ {
+ eq = (o instanceof AttributeSet)
+ && ((AttributeSet) o).getAttributeCount() == 0;
+ }
+ return eq;
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/FieldView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/FieldView.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/FieldView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/FieldView.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,312 @@
+/* FieldView.java --
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.BoundedRangeModel;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.DocumentEvent;
+
+public class FieldView extends PlainView
+{
+ BoundedRangeModel horizontalVisibility;
+
+ /** Caches the preferred span of the X axis. It is invalidated by
+ * setting it to -1f. This is done when text in the document
+ * is inserted, removed or changed. The value is corrected as
+ * soon as calculateHorizontalSpan() is called.
+ */
+ float cachedSpan = -1f;
+
+ public FieldView(Element elem)
+ {
+ super(elem);
+
+ }
+
+ /** Checks whether the given container is a JTextField. If so
+ * it retrieves the textfield's horizontalVisibility instance.
+ *
+ * <p>This method should be only called when the view's container
+ * is valid. Naturally that would be the setParent() method however
+ * that method is not overridden in the RI and that is why we chose
+ * paint() instead.</p>
+ */
+ private void checkContainer()
+ {
+ Container c = getContainer();
+
+ if (c instanceof JTextField)
+ {
+ horizontalVisibility = ((JTextField) c).getHorizontalVisibility();
+
+ // Provokes a repaint when the BoundedRangeModel's values change
+ // (which is what the RI does).
+ horizontalVisibility.addChangeListener(new ChangeListener(){
+ public void stateChanged(ChangeEvent event) {
+ getContainer().repaint();
+ };
+ });
+
+ // It turned out that the span calculated at this point is wrong
+ // and needs to be recalculated (e.g. a different font setting is
+ // not taken into account).
+ calculateHorizontalSpan();
+
+ // Initializes the BoundedRangeModel properly.
+ updateVisibility();
+ }
+
+ }
+
+ private void updateVisibility()
+ {
+ JTextField tf = (JTextField) getContainer();
+ Insets insets = tf.getInsets();
+
+ int width = tf.getWidth() - insets.left - insets.right;
+
+ horizontalVisibility.setMaximum(Math.max((int) ((cachedSpan != -1f)
+ ? cachedSpan
+ : calculateHorizontalSpan()),
+ width));
+
+ horizontalVisibility.setExtent(width - 1);
+ }
+
+ protected FontMetrics getFontMetrics()
+ {
+ Component container = getContainer();
+ return container.getFontMetrics(container.getFont());
+ }
+
+ /**
+ * Vertically centers the single line of text within the
+ * bounds of the input shape. The returned Rectangle is centered
+ * vertically within <code>shape</code> and has a height of the
+ * preferred span along the Y axis. Horizontal adjustment is done according
+ * to the horizontalAligment property of the component that is rendered.
+ *
+ * @param shape the shape within which the line is beeing centered
+ */
+ protected Shape adjustAllocation(Shape shape)
+ {
+ // Return null when the original allocation is null (like the RI).
+ if (shape == null)
+ return null;
+
+ Rectangle rectIn = shape.getBounds();
+ // vertical adjustment
+ int height = (int) getPreferredSpan(Y_AXIS);
+ int y = rectIn.y + (rectIn.height - height) / 2;
+ // horizontal adjustment
+ JTextField textField = (JTextField) getContainer();
+ int width = (int) ((cachedSpan != -1f) ? cachedSpan : calculateHorizontalSpan());
+ int x;
+ if (horizontalVisibility != null && horizontalVisibility.getExtent() < width)
+ x = rectIn.x - horizontalVisibility.getValue();
+ else
+ switch (textField.getHorizontalAlignment())
+ {
+ case JTextField.CENTER:
+ x = rectIn.x + (rectIn.width - width) / 2;
+ break;
+ case JTextField.RIGHT:
+ x = rectIn.x + (rectIn.width - width - 1);
+ break;
+ case JTextField.TRAILING:
+ if (textField.getComponentOrientation().isLeftToRight())
+ x = rectIn.x + (rectIn.width - width - 1);
+ else
+ x = rectIn.x;
+ break;
+ case JTextField.LEADING:
+ if (textField.getComponentOrientation().isLeftToRight())
+ x = rectIn.x;
+ else
+ x = rectIn.x + (rectIn.width - width - 1);
+ break;
+ case JTextField.LEFT:
+ default:
+ x = rectIn.x;
+ break;
+ }
+
+ return new Rectangle(x, y, width, height);
+ }
+
+ public float getPreferredSpan(int axis)
+ {
+ if (axis != X_AXIS && axis != Y_AXIS)
+ throw new IllegalArgumentException();
+
+
+ if (axis == Y_AXIS)
+ return super.getPreferredSpan(axis);
+
+ if (cachedSpan != -1f)
+ return cachedSpan;
+
+ return calculateHorizontalSpan();
+ }
+
+ /** Calculates and sets the horizontal span and stores the value
+ * in cachedSpan.
+ */
+ private float calculateHorizontalSpan()
+ {
+ Segment s = getLineBuffer();
+ Element elem = getElement();
+
+ try
+ {
+ elem.getDocument().getText(elem.getStartOffset(),
+ elem.getEndOffset() - 1,
+ s);
+
+ return cachedSpan = Utilities.getTabbedTextWidth(s, getFontMetrics(), 0, this, s.offset);
+ }
+ catch (BadLocationException e)
+ {
+ // Should never happen
+ AssertionError ae = new AssertionError();
+ ae.initCause(e);
+ throw ae;
+ }
+ }
+
+ public int getResizeWeight(int axis)
+ {
+ return axis = axis == X_AXIS ? 1 : 0;
+ }
+
+ public Shape modelToView(int pos, Shape a, Position.Bias bias)
+ throws BadLocationException
+ {
+ Shape newAlloc = adjustAllocation(a);
+ return super.modelToView(pos, newAlloc, bias);
+ }
+
+ public void paint(Graphics g, Shape s)
+ {
+ if (horizontalVisibility == null)
+ checkContainer();
+
+ Shape newAlloc = adjustAllocation(s);
+
+ Shape clip = g.getClip();
+ if (clip != null)
+ {
+ // Reason for this: The allocation area is always determined by the
+ // size of the component (and its insets) regardless of whether
+ // parts of the component are invisible or not (e.g. when the
+ // component is part of a JScrollPane and partly moved out of
+ // the user-visible range). However the clip of the Graphics
+ // instance may be adjusted properly to that condition but
+ // does not handle insets. By calculating the intersection
+ // we get the correct clip to paint the text in all cases.
+ Rectangle r = s.getBounds();
+ Rectangle cb = clip.getBounds();
+ SwingUtilities.computeIntersection(r.x, r.y, r.width, r.height, cb);
+
+ g.setClip(cb);
+ }
+ else
+ g.setClip(s);
+
+ super.paint(g, newAlloc);
+ g.setClip(clip);
+
+ }
+
+ public void insertUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
+ {
+ cachedSpan = -1f;
+
+ if (horizontalVisibility != null)
+ updateVisibility();
+
+ Shape newAlloc = adjustAllocation(shape);
+
+ super.insertUpdate(ev, newAlloc, vf);
+ getContainer().repaint();
+ }
+
+ public void removeUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
+ {
+ cachedSpan = -1f;
+
+ if (horizontalVisibility != null)
+ updateVisibility();
+
+ Shape newAlloc = adjustAllocation(shape);
+ super.removeUpdate(ev, newAlloc, vf);
+ getContainer().repaint();
+ }
+
+ public void changedUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
+ {
+ cachedSpan = -1f;
+
+ if (horizontalVisibility != null)
+ updateVisibility();
+
+ Shape newAlloc = adjustAllocation(shape);
+ super.changedUpdate(ev, newAlloc, vf);
+ getContainer().repaint();
+ }
+
+ public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias)
+ {
+ return super.viewToModel(fx, fy, adjustAllocation(a), bias);
+ }
+
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/FlowView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/FlowView.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/FlowView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/FlowView.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,612 @@
+/* FlowView.java -- A composite View
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+import javax.swing.SizeRequirements;
+import javax.swing.event.DocumentEvent;
+
+/**
+ * A <code>View</code> that can flows it's children into it's layout space.
+ *
+ * The <code>FlowView</code> manages a set of logical views (that are
+ * the children of the {@link #layoutPool} field). These are translated
+ * at layout time into a set of physical views. These are the views that
+ * are managed as the real child views. Each of these child views represents
+ * a row and are laid out within a box using the superclasses behaviour.
+ * The concrete implementation of the rows must be provided by subclasses.
+ *
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public abstract class FlowView extends BoxView
+{
+ /**
+ * A strategy for translating the logical views of a <code>FlowView</code>
+ * into the real views.
+ */
+ public static class FlowStrategy
+ {
+ /**
+ * Creates a new instance of <code>FlowStragegy</code>.
+ */
+ public FlowStrategy()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Receives notification from a <code>FlowView</code> that some content
+ * has been inserted into the document at a location that the
+ * <code>FlowView</code> is responsible for.
+ *
+ * The default implementation simply calls {@link #layout}.
+ *
+ * @param fv the flow view that sends the notification
+ * @param e the document event describing the change
+ * @param alloc the current allocation of the flow view
+ */
+ public void insertUpdate(FlowView fv, DocumentEvent e, Rectangle alloc)
+ {
+ // The default implementation does nothing.
+ }
+
+ /**
+ * Receives notification from a <code>FlowView</code> that some content
+ * has been removed from the document at a location that the
+ * <code>FlowView</code> is responsible for.
+ *
+ * The default implementation simply calls {@link #layout}.
+ *
+ * @param fv the flow view that sends the notification
+ * @param e the document event describing the change
+ * @param alloc the current allocation of the flow view
+ */
+ public void removeUpdate(FlowView fv, DocumentEvent e, Rectangle alloc)
+ {
+ // The default implementation does nothing.
+ }
+
+ /**
+ * Receives notification from a <code>FlowView</code> that some attributes
+ * have changed in the document at a location that the
+ * <code>FlowView</code> is responsible for.
+ *
+ * The default implementation simply calls {@link #layout}.
+ *
+ * @param fv the flow view that sends the notification
+ * @param e the document event describing the change
+ * @param alloc the current allocation of the flow view
+ */
+ public void changedUpdate(FlowView fv, DocumentEvent e, Rectangle alloc)
+ {
+ // The default implementation does nothing.
+ }
+
+ /**
+ * Returns the logical view of the managed <code>FlowView</code>.
+ *
+ * @param fv the flow view for which to return the logical view
+ *
+ * @return the logical view of the managed <code>FlowView</code>
+ */
+ protected View getLogicalView(FlowView fv)
+ {
+ return fv.layoutPool;
+ }
+
+ /**
+ * Performs the layout for the whole view. By default this rebuilds
+ * all the physical views from the logical views of the managed FlowView.
+ *
+ * This is called by {@link FlowView#layout} to update the layout of
+ * the view.
+ *
+ * @param fv the flow view for which we perform the layout
+ */
+ public void layout(FlowView fv)
+ {
+ fv.removeAll();
+ Element el = fv.getElement();
+
+ int rowStart = el.getStartOffset();
+ int end = el.getEndOffset();
+ int rowIndex = 0;
+ while (rowStart >= 0 && rowStart < end)
+ {
+ View row = fv.createRow();
+ fv.append(row);
+ rowStart = layoutRow(fv, rowIndex, rowStart);
+ rowIndex++;
+ }
+ }
+
+ /**
+ * Lays out one row of the flow view. This is called by {@link #layout} to
+ * fill one row with child views until the available span is exhausted. The
+ * default implementation fills the row by calling
+ * {@link #createView(FlowView, int, int, int)} until the available space is
+ * exhausted, a forced break is encountered or there are no more views in
+ * the logical view. If the available space is exhausted,
+ * {@link #adjustRow(FlowView, int, int, int)} is called to fit the row into
+ * the available span.
+ *
+ * @param fv the flow view for which we perform the layout
+ * @param rowIndex the index of the row
+ * @param pos the model position for the beginning of the row
+ * @return the start position of the next row
+ */
+ protected int layoutRow(FlowView fv, int rowIndex, int pos)
+ {
+ View row = fv.getView(rowIndex);
+ int axis = fv.getFlowAxis();
+ int span = fv.getFlowSpan(rowIndex);
+ int x = fv.getFlowStart(rowIndex);
+ int offset = pos;
+ View logicalView = getLogicalView(fv);
+ // Special case when span == 0. We need to layout the row as if it had
+ // a span of Integer.MAX_VALUE.
+ if (span == 0)
+ span = Integer.MAX_VALUE;
+
+ Row: while (span > 0)
+ {
+ if (logicalView.getViewIndex(offset, Position.Bias.Forward) == - 1)
+ break;
+ View view = createView(fv, offset, span, rowIndex);
+ if (view == null)
+ break;
+
+ int viewSpan = (int) view.getPreferredSpan(axis);
+ int breakWeight = view.getBreakWeight(axis, x, span);
+
+ row.append(view);
+ offset += (view.getEndOffset() - view.getStartOffset());
+ x += viewSpan;
+ span -= viewSpan;
+
+ // Break if the line if the view does not fit in this row or the
+ // line just must be broken.
+ if (span < 0 || breakWeight >= View.ForcedBreakWeight)
+ {
+ int flowStart = fv.getFlowStart(axis);
+ int flowSpan = fv.getFlowSpan(axis);
+ adjustRow(fv, rowIndex, flowSpan, flowStart);
+ int rowViewCount = row.getViewCount();
+ if (rowViewCount > 0)
+ offset = row.getView(rowViewCount - 1).getEndOffset();
+ else
+ offset = - 1;
+ break Row;
+ }
+ }
+
+ return offset != pos ? offset : - 1;
+ }
+
+ /**
+ * Creates physical views that form the rows of the flow view. This
+ * can be an entire view from the logical view (if it fits within the
+ * available span), a fragment of such a view (if it doesn't fit in the
+ * available span and can be broken down) or <code>null</code> (if it does
+ * not fit in the available span and also cannot be broken down).
+ *
+ * The default implementation fetches the logical view at the specified
+ * <code>startOffset</code>. If that view has a different startOffset than
+ * specified in the argument, a fragment is created using
+ * {@link View#createFragment(int, int)} that has the correct startOffset
+ * and the logical view's endOffset.
+ *
+ * @param fv the flow view
+ * @param startOffset the start offset for the view to be created
+ * @param spanLeft the available span
+ * @param rowIndex the index of the row
+ *
+ * @return a view to fill the row with, or <code>null</code> if there
+ * is no view or view fragment that fits in the available span
+ */
+ protected View createView(FlowView fv, int startOffset, int spanLeft,
+ int rowIndex)
+ {
+ View logicalView = getLogicalView(fv);
+ // FIXME: Handle the bias thing correctly.
+ int index = logicalView.getViewIndex(startOffset, Position.Bias.Forward);
+ View retVal = null;
+ if (index >= 0)
+ {
+ retVal = logicalView.getView(index);
+ if (retVal.getStartOffset() != startOffset)
+ retVal = retVal.createFragment(startOffset, retVal.getEndOffset());
+ }
+ return retVal;
+ }
+
+ /**
+ * Tries to adjust the specified row to fit within the desired span. The
+ * default implementation iterates through the children of the specified
+ * row to find the view that has the highest break weight and - if there
+ * is more than one view with such a break weight - which is nearest to
+ * the end of the row. If there is such a view that has a break weight >
+ * {@link View#BadBreakWeight}, this view is broken using the
+ * {@link View#breakView(int, int, float, float)} method and this view and
+ * all views after the now broken view are replaced by the broken view.
+ *
+ * @param fv the flow view
+ * @param rowIndex the index of the row to be adjusted
+ * @param desiredSpan the layout span
+ * @param x the X location at which the row starts
+ */
+ protected void adjustRow(FlowView fv, int rowIndex, int desiredSpan, int x) {
+ // Determine the last view that has the highest break weight.
+ int axis = fv.getFlowAxis();
+ View row = fv.getView(rowIndex);
+ int count = row.getViewCount();
+ int breakIndex = -1;
+ int maxBreakWeight = View.BadBreakWeight;
+ int breakX = x;
+ int breakSpan = desiredSpan;
+ int currentX = x;
+ int currentSpan = desiredSpan;
+ for (int i = 0; i < count; ++i)
+ {
+ View view = row.getView(i);
+ int weight = view.getBreakWeight(axis, currentX, currentSpan);
+ if (weight >= maxBreakWeight)
+ {
+ breakIndex = i;
+ breakX = currentX;
+ breakSpan = currentSpan;
+ maxBreakWeight = weight;
+ }
+ int size = (int) view.getPreferredSpan(axis);
+ currentX += size;
+ currentSpan -= size;
+ }
+
+ // If there is a potential break location found, break the row at
+ // this location.
+ if (breakIndex > -1)
+ {
+ View toBeBroken = row.getView(breakIndex);
+ View brokenView = toBeBroken.breakView(axis,
+ toBeBroken.getStartOffset(),
+ breakX, breakSpan);
+ row.replace(breakIndex, count - breakIndex,
+ new View[]{brokenView});
+ }
+ }
+ }
+
+ /**
+ * This special subclass of <code>View</code> is used to represent
+ * the logical representation of this view. It does not support any
+ * visual representation, this is handled by the physical view implemented
+ * in the <code>FlowView</code>.
+ */
+ class LogicalView extends BoxView
+ {
+ /**
+ * Creates a new LogicalView instance.
+ */
+ LogicalView(Element el, int axis)
+ {
+ super(el, axis);
+ }
+ }
+
+ /**
+ * The shared instance of FlowStrategy.
+ */
+ static final FlowStrategy sharedStrategy = new FlowStrategy();
+
+ /**
+ * The span of the <code>FlowView</code> that should be flowed.
+ */
+ protected int layoutSpan;
+
+ /**
+ * Represents the logical child elements of this view, encapsulated within
+ * one parent view (an instance of a package private <code>LogicalView</code>
+ * class). These will be translated to a set of real views that are then
+ * displayed on screen. This translation is performed by the inner class
+ * {@link FlowStrategy}.
+ */
+ protected View layoutPool;
+
+ /**
+ * The <code>FlowStrategy</code> to use for translating between the
+ * logical and physical view.
+ */
+ protected FlowStrategy strategy;
+
+ /**
+ * Indicates if the flow should be rebuild during the next layout.
+ */
+ private boolean layoutDirty;
+
+ /**
+ * Creates a new <code>FlowView</code> for the given
+ * <code>Element</code> and <code>axis</code>.
+ *
+ * @param element the element that is rendered by this FlowView
+ * @param axis the axis along which the view is tiled, either
+ * <code>View.X_AXIS</code> or <code>View.Y_AXIS</code>, the flow
+ * axis is orthogonal to this one
+ */
+ public FlowView(Element element, int axis)
+ {
+ super(element, axis);
+ strategy = sharedStrategy;
+ layoutDirty = true;
+ }
+
+ /**
+ * Returns the axis along which the view should be flowed. This is
+ * orthogonal to the axis along which the boxes are tiled.
+ *
+ * @return the axis along which the view should be flowed
+ */
+ public int getFlowAxis()
+ {
+ int axis = getAxis();
+ int flowAxis;
+
+ if (axis == X_AXIS)
+ flowAxis = Y_AXIS;
+ else
+ flowAxis = X_AXIS;
+
+ return flowAxis;
+
+ }
+
+ /**
+ * Returns the span of the flow for the specified child view. A flow
+ * layout can be shaped by providing different span values for different
+ * child indices. The default implementation returns the entire available
+ * span inside the view.
+ *
+ * @param index the index of the child for which to return the span
+ *
+ * @return the span of the flow for the specified child view
+ */
+ public int getFlowSpan(int index)
+ {
+ return layoutSpan;
+ }
+
+ /**
+ * Returns the location along the flow axis where the flow span starts
+ * given a child view index. The flow can be shaped by providing
+ * different values here.
+ *
+ * @param index the index of the child for which to return the flow location
+ *
+ * @return the location along the flow axis where the flow span starts
+ */
+ public int getFlowStart(int index)
+ {
+ return getLeftInset(); // TODO: Is this correct?
+ }
+
+ /**
+ * Creates a new view that represents a row within a flow.
+ *
+ * @return a view for a new row
+ */
+ protected abstract View createRow();
+
+ /**
+ * Loads the children of this view. The <code>FlowView</code> does not
+ * directly load its children. Instead it creates a logical view
+ * ({@link #layoutPool}) which is filled by the logical child views.
+ * The real children are created at layout time and each represent one
+ * row.
+ *
+ * This method is called by {@link View#setParent} in order to initialize
+ * the view.
+ *
+ * @param vf the view factory to use for creating the child views
+ */
+ protected void loadChildren(ViewFactory vf)
+ {
+ if (layoutPool == null)
+ {
+ layoutPool = new LogicalView(getElement(), getAxis());
+ layoutPool.setParent(this);
+ }
+ }
+
+ /**
+ * Performs the layout of this view. If the span along the flow axis changed,
+ * this first calls {@link FlowStrategy#layout} in order to rebuild the
+ * rows of this view. Then the superclass's behaviour is called to arrange
+ * the rows within the box.
+ *
+ * @param width the width of the view
+ * @param height the height of the view
+ */
+ protected void layout(int width, int height)
+ {
+ int flowAxis = getFlowAxis();
+ if (flowAxis == X_AXIS)
+ {
+ if (layoutSpan != width)
+ {
+ layoutChanged(Y_AXIS);
+ layoutSpan = width;
+ }
+ }
+ else
+ {
+ if (layoutSpan != height)
+ {
+ layoutChanged(X_AXIS);
+ layoutSpan = height;
+ }
+ }
+
+ if (layoutDirty)
+ {
+ strategy.layout(this);
+ layoutDirty = false;
+ }
+
+ if (getPreferredSpan(getAxis()) != height)
+ preferenceChanged(this, false, true);
+
+ super.layout(width, height);
+ }
+
+ /**
+ * Receice notification that some content has been inserted in the region
+ * that this view is responsible for. This calls
+ * {@link FlowStrategy#insertUpdate}.
+ *
+ * @param changes the document event describing the changes
+ * @param a the current allocation of the view
+ * @param vf the view factory that is used for creating new child views
+ */
+ public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory vf)
+ {
+ // First we must send the insertUpdate to the logical view so it can
+ // be updated accordingly.
+ layoutPool.insertUpdate(changes, a, vf);
+ strategy.insertUpdate(this, changes, getInsideAllocation(a));
+ layoutDirty = true;
+ }
+
+ /**
+ * Receice notification that some content has been removed from the region
+ * that this view is responsible for. This calls
+ * {@link FlowStrategy#removeUpdate}.
+ *
+ * @param changes the document event describing the changes
+ * @param a the current allocation of the view
+ * @param vf the view factory that is used for creating new child views
+ */
+ public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory vf)
+ {
+ layoutPool.removeUpdate(changes, a, vf);
+ strategy.removeUpdate(this, changes, getInsideAllocation(a));
+ layoutDirty = true;
+ }
+
+ /**
+ * Receice notification that some attributes changed in the region
+ * that this view is responsible for. This calls
+ * {@link FlowStrategy#changedUpdate}.
+ *
+ * @param changes the document event describing the changes
+ * @param a the current allocation of the view
+ * @param vf the view factory that is used for creating new child views
+ */
+ public void changedUpdate(DocumentEvent changes, Shape a, ViewFactory vf)
+ {
+ layoutPool.changedUpdate(changes, a, vf);
+ strategy.changedUpdate(this, changes, getInsideAllocation(a));
+ layoutDirty = true;
+ }
+
+ /**
+ * Returns the index of the child <code>View</code> for the given model
+ * position.
+ *
+ * This is implemented to iterate over the children of this
+ * view (the rows) and return the index of the first view that contains
+ * the given position.
+ *
+ * @param pos the model position for whicht the child <code>View</code> is
+ * queried
+ *
+ * @return the index of the child <code>View</code> for the given model
+ * position
+ */
+ protected int getViewIndexAtPosition(int pos)
+ {
+ // First make sure we have a valid layout.
+ if (!isAllocationValid())
+ layout(getWidth(), getHeight());
+
+ int count = getViewCount();
+ int result = -1;
+
+ for (int i = 0; i < count; ++i)
+ {
+ View child = getView(i);
+ int start = child.getStartOffset();
+ int end = child.getEndOffset();
+ if (start <= pos && end > pos)
+ {
+ result = i;
+ break;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Calculates the size requirements of this <code>BoxView</code> along
+ * its minor axis, that is the axis opposite to the axis specified in the
+ * constructor.
+ *
+ * This is overridden and forwards the request to the logical view.
+ *
+ * @param axis the axis that is examined
+ * @param r the <code>SizeRequirements</code> object to hold the result,
+ * if <code>null</code>, a new one is created
+ *
+ * @return the size requirements for this <code>BoxView</code> along
+ * the specified axis
+ */
+ protected SizeRequirements calculateMinorAxisRequirements(int axis,
+ SizeRequirements r)
+ {
+ SizeRequirements res = r;
+ if (res == null)
+ res = new SizeRequirements();
+ res.minimum = (int) layoutPool.getMinimumSpan(axis);
+ res.preferred = Math.max(res.minimum,
+ (int) layoutPool.getMinimumSpan(axis));
+ res.maximum = Integer.MAX_VALUE;
+ res.alignment = 0.5F;
+ return res;
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/GapContent.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/GapContent.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/GapContent.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/GapContent.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,944 @@
+/* GapContent.java --
+ Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.io.Serializable;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.Vector;
+import java.util.WeakHashMap;
+
+import javax.swing.undo.AbstractUndoableEdit;
+import javax.swing.undo.CannotRedoException;
+import javax.swing.undo.CannotUndoException;
+import javax.swing.undo.UndoableEdit;
+
+/**
+ * This implementation of {@link AbstractDocument.Content} uses a gapped buffer.
+ * This takes advantage of the fact that text area content is mostly inserted
+ * sequentially. The buffer is a char array that maintains a gap at the current
+ * insertion point. If characters a inserted at gap boundaries, the cost is
+ * minimal (simple array access). The array only has to be shifted around when
+ * the insertion point moves (then the gap also moves and one array copy is
+ * necessary) or when the gap is filled up and the buffer has to be enlarged.
+ */
+public class GapContent
+ implements AbstractDocument.Content, Serializable
+{
+
+ /**
+ * A {@link Position} implementation for <code>GapContent</code>.
+ */
+ private class GapContentPosition
+ implements Position
+ {
+
+ /**
+ * The index to the positionMarks array entry, which in turn holds the
+ * mark into the buffer array.
+ */
+ Mark mark;
+
+ /**
+ * Creates a new GapContentPosition object.
+ *
+ * @param offset the offset of this Position
+ */
+ GapContentPosition(int offset)
+ {
+ // Try to find the mark in the positionMarks array, and store the index
+ // to it.
+ synchronized (GapContent.this)
+ {
+ // Try to make space.
+ garbageCollect();
+ Mark m = new Mark(offset);
+ int i = search(marks, m);
+ if (i >= 0) // mark found
+ {
+ m = (Mark) marks.get(i);
+ }
+ else
+ {
+ i = -i - 1;
+ marks.add(i, m);
+ }
+ m.refCount++;
+ mark = m;
+ }
+
+ // Register this position in the death queue, so we can cleanup the marks
+ // when this position object gets GC'ed.
+ new WeakReference(this, queueOfDeath);
+ }
+
+ /**
+ * Returns the current offset of this Position within the content.
+ *
+ * @return the current offset of this Position within the content.
+ */
+ public int getOffset()
+ {
+ return mark.getOffset();
+ }
+ }
+
+ /**
+ * Holds a mark into the buffer that is used by GapContentPosition to find
+ * the actual offset of the position. This is pulled out of the
+ * GapContentPosition object so that the mark and position can be handled
+ * independently, and most important, so that the GapContentPosition can
+ * be garbage collected while we still hold a reference to the Mark object.
+ */
+ private class Mark
+ implements Comparable
+ {
+ /**
+ * The actual mark into the buffer.
+ */
+ int mark;
+
+ /**
+ * The number of GapContentPosition object that reference this mark. If
+ * it reaches zero, it get's deleted by {@link GapContent#garbageCollect()}.
+ */
+ int refCount;
+
+ /**
+ * Creates a new Mark object for the specified offset.
+ *
+ * @param offset the offset
+ */
+ Mark(int offset)
+ {
+ mark = offset;
+ if (mark >= gapStart && mark != 0)
+ mark += (gapEnd - gapStart);
+ }
+
+ /**
+ * Returns the offset of the mark.
+ *
+ * @return the offset of the mark
+ */
+ int getOffset()
+ {
+ assert mark == 0 || mark < gapStart || mark >= gapEnd :
+ "Invalid mark: " + mark + ", gapStart: " + gapStart
+ + ", gapEnd: " + gapEnd;
+
+ int res = mark;
+ if (mark >= gapEnd)
+ res -= (gapEnd - gapStart);
+ return res;
+ }
+
+ /**
+ * Implementation of Comparable.
+ */
+ public int compareTo(Object o)
+ {
+ Mark other = (Mark) o;
+ return mark - other.mark;
+ }
+ /**
+ * Adjustment for equals().
+ */
+ public boolean equals(Object o)
+ {
+ if (o == null || !(o instanceof Mark))
+ return false;
+ else
+ return ((Mark) o).mark == mark;
+ }
+ }
+
+ private class InsertUndo extends AbstractUndoableEdit
+ {
+ public int where, length;
+ String text;
+ public InsertUndo(int start, int len)
+ {
+ where = start;
+ length = len;
+ }
+
+ public void undo () throws CannotUndoException
+ {
+ super.undo();
+ try
+ {
+ text = getString(where, length);
+ remove(where, length);
+ }
+ catch (BadLocationException ble)
+ {
+ throw new CannotUndoException();
+ }
+ }
+
+ public void redo () throws CannotUndoException
+ {
+ super.redo();
+ try
+ {
+ insertString(where, text);
+ }
+ catch (BadLocationException ble)
+ {
+ throw new CannotRedoException();
+ }
+ }
+
+ }
+
+ private class UndoRemove extends AbstractUndoableEdit
+ {
+ public int where;
+ String text;
+ public UndoRemove(int start, String removedText)
+ {
+ where = start;
+ text = removedText;
+ }
+
+ public void undo () throws CannotUndoException
+ {
+ super.undo();
+ try
+ {
+ insertString(where, text);
+ }
+ catch (BadLocationException ble)
+ {
+ throw new CannotUndoException();
+ }
+ }
+
+ public void redo () throws CannotUndoException
+ {
+ super.redo();
+ try
+ {
+ remove(where, text.length());
+ }
+ catch (BadLocationException ble)
+ {
+ throw new CannotRedoException();
+ }
+ }
+
+ }
+
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = -6226052713477823730L;
+
+ /**
+ * This is the default buffer size and the amount of bytes that a buffer is
+ * extended if it is full.
+ */
+ static final int DEFAULT_BUFSIZE = 10;
+
+ /**
+ * The text buffer.
+ */
+ char[] buffer;
+
+ /**
+ * The index of the first character of the gap.
+ */
+ int gapStart;
+
+ /**
+ * The index of the character after the last character of the gap.
+ */
+ int gapEnd;
+
+ // FIXME: We might want to track GC'ed GapContentPositions and remove their
+ // corresponding marks, or alternativly, perform some regular cleanup of
+ // the positionMarks array.
+
+ /**
+ * Holds the marks for positions. These marks are referenced by the
+ * GapContentPosition instances by an index into this array.
+ *
+ * This is package private to avoid accessor synthetic methods.
+ */
+ ArrayList marks;
+
+ WeakHashMap positions;
+
+ /**
+ * Queues all references to GapContentPositions that are about to be
+ * GC'ed. This is used to remove the corresponding marks from the
+ * positionMarks array if the number of references to that mark reaches zero.
+ *
+ * This is package private to avoid accessor synthetic methods.
+ */
+ ReferenceQueue queueOfDeath;
+
+ /**
+ * Creates a new GapContent object.
+ */
+ public GapContent()
+ {
+ this(DEFAULT_BUFSIZE);
+ }
+
+ /**
+ * Creates a new GapContent object with a specified initial size.
+ *
+ * @param size the initial size of the buffer
+ */
+ public GapContent(int size)
+ {
+ size = Math.max(size, 2);
+ buffer = (char[]) allocateArray(size);
+ gapStart = 1;
+ gapEnd = size;
+ buffer[0] = '\n';
+ positions = new WeakHashMap();
+ marks = new ArrayList();
+ queueOfDeath = new ReferenceQueue();
+ }
+
+ /**
+ * Allocates an array of the specified length that can then be used as
+ * buffer.
+ *
+ * @param size the size of the array to be allocated
+ *
+ * @return the allocated array
+ */
+ protected Object allocateArray(int size)
+ {
+ return new char[size];
+ }
+
+ /**
+ * Returns the length of the allocated buffer array.
+ *
+ * @return the length of the allocated buffer array
+ */
+ protected int getArrayLength()
+ {
+ return buffer.length;
+ }
+
+ /**
+ * Returns the length of the content.
+ *
+ * @return the length of the content
+ */
+ public int length()
+ {
+ return buffer.length - (gapEnd - gapStart);
+ }
+
+ /**
+ * Inserts a string at the specified position.
+ *
+ * @param where the position where the string is inserted
+ * @param str the string that is to be inserted
+ *
+ * @return an UndoableEdit object
+ *
+ * @throws BadLocationException if <code>where</code> is not a valid
+ * location in the buffer
+ */
+ public UndoableEdit insertString(int where, String str)
+ throws BadLocationException
+ {
+ // check arguments
+ int length = length();
+ int strLen = str.length();
+
+ if (where < 0)
+ throw new BadLocationException("The where argument cannot be smaller"
+ + " than the zero", where);
+
+ if (where > length)
+ throw new BadLocationException("The where argument cannot be greater"
+ + " than the content length", where);
+
+ replace(where, 0, str.toCharArray(), strLen);
+
+ return new InsertUndo(where, strLen);
+ }
+
+ /**
+ * Removes a piece of content at th specified position.
+ *
+ * @param where the position where the content is to be removed
+ * @param nitems number of characters to be removed
+ *
+ * @return an UndoableEdit object
+ *
+ * @throws BadLocationException if <code>where</code> is not a valid
+ * location in the buffer
+ */
+ public UndoableEdit remove(int where, int nitems) throws BadLocationException
+ {
+ // check arguments
+ int length = length();
+
+ if ((where + nitems) >= length)
+ throw new BadLocationException("where + nitems cannot be greater"
+ + " than the content length", where + nitems);
+
+ String removedText = getString(where, nitems);
+ replace(where, nitems, null, 0);
+
+ return new UndoRemove(where, removedText);
+ }
+
+ /**
+ * Returns a piece of content as String.
+ *
+ * @param where the start location of the fragment
+ * @param len the length of the fragment
+ *
+ * @throws BadLocationException if <code>where</code> or
+ * <code>where + len</code> are no valid locations in the buffer
+ */
+ public String getString(int where, int len) throws BadLocationException
+ {
+ Segment seg = new Segment();
+ try
+ {
+ getChars(where, len, seg);
+ return new String(seg.array, seg.offset, seg.count);
+ }
+ catch (StringIndexOutOfBoundsException ex)
+ {
+ int invalid = 0;
+ if (seg.offset < 0 || seg.offset >= seg.array.length)
+ invalid = seg.offset;
+ else
+ invalid = seg.offset + seg.count;
+ throw new BadLocationException("Illegal location: array.length = "
+ + seg.array.length + ", offset = "
+ + seg.offset + ", count = "
+ + seg.count, invalid);
+ }
+ }
+
+ /**
+ * Fetches a piece of content and stores it in a {@link Segment} object.
+ *
+ * If the requested piece of text spans the gap, the content is copied into a
+ * new array. If it doesn't then it is contiguous and the actual content
+ * store is returned.
+ *
+ * @param where the start location of the fragment
+ * @param len the length of the fragment
+ * @param txt the Segment object to store the fragment in
+ *
+ * @throws BadLocationException if <code>where</code> or
+ * <code>where + len</code> are no valid locations in the buffer
+ */
+ public void getChars(int where, int len, Segment txt)
+ throws BadLocationException
+ {
+ // check arguments
+ int length = length();
+ if (where < 0)
+ throw new BadLocationException("the where argument may not be below zero", where);
+ if (where >= length)
+ throw new BadLocationException("the where argument cannot be greater"
+ + " than the content length", where);
+ if ((where + len) > length)
+ throw new BadLocationException("len plus where cannot be greater"
+ + " than the content length", len + where);
+ if (len < 0)
+ throw new BadLocationException("negative length not allowed: ", len);
+
+ // check if requested segment is contiguous
+ if ((where < gapStart) && ((gapStart - where) < len))
+ {
+ // requested segment is not contiguous -> copy the pieces together
+ char[] copy = new char[len];
+ int lenFirst = gapStart - where; // the length of the first segment
+ System.arraycopy(buffer, where, copy, 0, lenFirst);
+ System.arraycopy(buffer, gapEnd, copy, lenFirst, len - lenFirst);
+ txt.array = copy;
+ txt.offset = 0;
+ txt.count = len;
+ }
+ else
+ {
+ // requested segment is contiguous -> we can simply return the
+ // actual content
+ txt.array = buffer;
+ if (where < gapStart)
+ txt.offset = where;
+ else
+ txt.offset = where + (gapEnd - gapStart);
+ txt.count = len;
+ }
+ }
+
+ /**
+ * Creates and returns a mark at the specified position.
+ *
+ * @param offset the position at which to create the mark
+ *
+ * @return the create Position object for the mark
+ *
+ * @throws BadLocationException if the offset is not a valid position in the
+ * buffer
+ */
+ public Position createPosition(final int offset) throws BadLocationException
+ {
+ // Implementation note: We used to perform explicit check on the offset
+ // here. However, this makes some Mauve and Intel/Harmony tests fail
+ // and luckily enough the GapContent can very well deal with offsets
+ // outside the buffer bounds. So I removed that check.
+
+ // We try to find a GapContentPosition at the specified offset and return
+ // that. Otherwise we must create a new one.
+ GapContentPosition pos = null;
+ Set positionSet = positions.keySet();
+ for (Iterator i = positionSet.iterator(); i.hasNext();)
+ {
+ GapContentPosition p = (GapContentPosition) i.next();
+ if (p.getOffset() == offset)
+ {
+ pos = p;
+ break;
+ }
+ }
+
+ // If none was found, then create and return a new one.
+ if (pos == null)
+ {
+ pos = new GapContentPosition(offset);
+ positions.put(pos, null);
+ }
+
+ return pos;
+ }
+
+ /**
+ * Enlarges the gap. This allocates a new bigger buffer array, copy the
+ * segment before the gap as it is and the segment after the gap at the end
+ * of the new buffer array. This does change the gapEnd mark but not the
+ * gapStart mark.
+ *
+ * @param newSize the new size of the gap
+ */
+ protected void shiftEnd(int newSize)
+ {
+ assert newSize > (gapEnd - gapStart) : "The new gap size must be greater "
+ + "than the old gap size";
+
+ int delta = newSize - gapEnd + gapStart;
+ // Update the marks after the gapEnd.
+ adjustPositionsInRange(gapEnd, -1, delta);
+
+ // Copy the data around.
+ char[] newBuf = (char[]) allocateArray(length() + newSize);
+ System.arraycopy(buffer, 0, newBuf, 0, gapStart);
+ System.arraycopy(buffer, gapEnd, newBuf, gapStart + newSize, buffer.length
+ - gapEnd);
+ gapEnd = gapStart + newSize;
+ buffer = newBuf;
+
+ }
+
+ /**
+ * Shifts the gap to the specified position.
+ *
+ * @param newGapStart the new start position of the gap
+ */
+ protected void shiftGap(int newGapStart)
+ {
+ if (newGapStart == gapStart)
+ return;
+ int newGapEnd = newGapStart + gapEnd - gapStart;
+ if (newGapStart < gapStart)
+ {
+ // Update the positions between newGapStart and (old) gapStart. The marks
+ // must be shifted by (gapEnd - gapStart).
+ adjustPositionsInRange(newGapStart, gapStart, gapEnd - gapStart);
+ System.arraycopy(buffer, newGapStart, buffer, newGapEnd, gapStart
+ - newGapStart);
+ gapStart = newGapStart;
+ gapEnd = newGapEnd;
+ }
+ else
+ {
+ // Update the positions between newGapEnd and (old) gapEnd. The marks
+ // must be shifted by (gapEnd - gapStart).
+ adjustPositionsInRange(gapEnd, newGapEnd, -(gapEnd - gapStart));
+ System.arraycopy(buffer, gapEnd, buffer, gapStart, newGapStart
+ - gapStart);
+ gapStart = newGapStart;
+ gapEnd = newGapEnd;
+ }
+ resetMarksAtZero();
+ }
+
+ /**
+ * Shifts the gap start downwards. This does not affect the content of the
+ * buffer. This only updates the gap start and all the marks that are between
+ * the old gap start and the new gap start. They all are squeezed to the start
+ * of the gap, because their location has been removed.
+ *
+ * @param newGapStart the new gap start
+ */
+ protected void shiftGapStartDown(int newGapStart)
+ {
+ if (newGapStart == gapStart)
+ return;
+
+ assert newGapStart < gapStart : "The new gap start must be less than the "
+ + "old gap start.";
+ setPositionsInRange(newGapStart, gapStart, false);
+ gapStart = newGapStart;
+ resetMarksAtZero();
+ }
+
+ /**
+ * Shifts the gap end upwards. This does not affect the content of the
+ * buffer. This only updates the gap end and all the marks that are between
+ * the old gap end and the new end start. They all are squeezed to the end
+ * of the gap, because their location has been removed.
+ *
+ * @param newGapEnd the new gap start
+ */
+ protected void shiftGapEndUp(int newGapEnd)
+ {
+ if (newGapEnd == gapEnd)
+ return;
+
+ assert newGapEnd > gapEnd : "The new gap end must be greater than the "
+ + "old gap end.";
+ setPositionsInRange(gapEnd, newGapEnd, false);
+ gapEnd = newGapEnd;
+ resetMarksAtZero();
+ }
+
+ /**
+ * Returns the allocated buffer array.
+ *
+ * @return the allocated buffer array
+ */
+ protected final Object getArray()
+ {
+ return buffer;
+ }
+
+ /**
+ * Replaces a portion of the storage with the specified items.
+ *
+ * @param position the position at which to remove items
+ * @param rmSize the number of items to remove
+ * @param addItems the items to add at location
+ * @param addSize the number of items to add
+ */
+ protected void replace(int position, int rmSize, Object addItems,
+ int addSize)
+ {
+ if (gapStart != position)
+ shiftGap(position);
+
+ // Remove content
+ if (rmSize > 0)
+ shiftGapEndUp(gapEnd + rmSize);
+
+ // If gap is too small, enlarge the gap.
+ if ((gapEnd - gapStart) <= addSize)
+ shiftEnd((addSize - gapEnd + gapStart + 1) * 2 + gapEnd + DEFAULT_BUFSIZE);
+
+ // Add new items to the buffer.
+ if (addItems != null)
+ {
+ System.arraycopy(addItems, 0, buffer, gapStart, addSize);
+ gapStart += addSize;
+ }
+ }
+
+ /**
+ * Returns the start index of the gap within the buffer array.
+ *
+ * @return the start index of the gap within the buffer array
+ */
+ protected final int getGapStart()
+ {
+ return gapStart;
+ }
+
+ /**
+ * Returns the end index of the gap within the buffer array.
+ *
+ * @return the end index of the gap within the buffer array
+ */
+ protected final int getGapEnd()
+ {
+ return gapEnd;
+ }
+
+ /**
+ * Returns all <code>Position</code>s that are in the range specified by
+ * <code>offset</code> and </code>length</code> within the buffer array.
+ *
+ * @param v the vector to use; if <code>null</code>, a new Vector is allocated
+ * @param offset the start offset of the range to search
+ * @param length the length of the range to search
+ *
+ * @return the positions within the specified range
+ */
+ protected Vector getPositionsInRange(Vector v, int offset, int length)
+ {
+ Vector res = v;
+ if (res == null)
+ res = new Vector();
+ else
+ res.clear();
+
+ int endOffs = offset + length;
+
+ Set positionSet = positions.keySet();
+ for (Iterator i = positionSet.iterator(); i.hasNext();)
+ {
+ GapContentPosition p = (GapContentPosition) i.next();
+ int offs = p.getOffset();
+ if (offs >= offset && offs < endOffs)
+ res.add(p);
+ }
+
+ return res;
+ }
+
+ /**
+ * Crunches all positions in the specified range to either the start or
+ * end of that interval. The interval boundaries are meant to be inclusive
+ * [start, end].
+ *
+ * @param start the start offset of the range
+ * @param end the end offset of the range
+ * @param toStart a boolean indicating if the positions should be crunched
+ * to the start (true) or to the end (false)
+ */
+ private void setPositionsInRange(int start, int end, boolean toStart)
+ {
+ synchronized (this)
+ {
+ // Find the start and end indices in the positionMarks array.
+ Mark m = new Mark(0); // For comparison / search only.
+ m.mark = start;
+ int startIndex = search(marks, m);
+ if (startIndex < 0) // Translate to insertion index, if not found.
+ startIndex = - startIndex - 1;
+ m.mark = end;
+ int endIndex = search(marks, m);
+ if (endIndex < 0) // Translate to insertion index - 1, if not found.
+ endIndex = - endIndex - 2;
+
+ // Actually adjust the marks.
+ for (int i = startIndex; i <= endIndex; i++)
+ ((Mark) marks.get(i)).mark = toStart ? start : end;
+ }
+
+ }
+
+ /**
+ * Adjusts the mark of all <code>Position</code>s that are in the range
+ * specified by <code>offset</code> and </code>length</code> within
+ * the buffer array by <code>increment</code>
+ *
+ * @param startOffs the start offset of the range to search
+ * @param endOffs the length of the range to search, -1 means all to the end
+ * @param incr the increment
+ */
+ private void adjustPositionsInRange(int startOffs, int endOffs, int incr)
+ {
+ synchronized (this)
+ {
+ // Find the start and end indices in the positionMarks array.
+ Mark m = new Mark(0); // For comparison / search only.
+
+ m.mark = startOffs;
+ int startIndex = search(marks, m);
+ if (startIndex < 0) // Translate to insertion index, if not found.
+ startIndex = - startIndex - 1;
+
+ m.mark = endOffs;
+ int endIndex;
+ if (endOffs == -1)
+ endIndex = marks.size() - 1;
+ else
+ {
+ endIndex = search(marks, m);
+ if (endIndex < 0) // Translate to insertion index - 1, if not found.
+ endIndex = - endIndex - 2;
+ }
+ // Actually adjust the marks.
+ for (int i = startIndex; i <= endIndex; i++) {
+ ((Mark) marks.get(i)).mark += incr;
+ }
+ }
+
+ }
+
+ /**
+ * Resets all <code>Position</code> that have an offset of <code>0</code>,
+ * to also have an array index of <code>0</code>. This might be necessary
+ * after a call to <code>shiftGap(0)</code>, since then the marks at offset
+ * <code>0</code> get shifted to <code>gapEnd</code>.
+ */
+ protected void resetMarksAtZero()
+ {
+ if (gapStart != 0)
+ return;
+
+ for (int i = 0; i < marks.size(); i++)
+ {
+ Mark m = (Mark) marks.get(i);
+ if (m.mark <= gapEnd)
+ m.mark = 0;
+ }
+ }
+
+ /**
+ * @specnote This method is not very well specified and the positions vector
+ * is implementation specific. The undo positions are managed
+ * differently in this implementation, this method is only here
+ * for binary compatibility.
+ */
+ protected void updateUndoPositions(Vector positions, int offset, int length)
+ {
+ // We do nothing here.
+ }
+
+ /**
+ * Outputs debugging info to System.err. It prints out the buffer array,
+ * the gapStart is marked by a < sign, the gapEnd is marked by a >
+ * sign and each position is marked by a # sign.
+ */
+ private void dump()
+ {
+ System.err.println("GapContent debug information");
+ System.err.println("buffer length: " + buffer.length);
+ System.err.println("gap start: " + gapStart);
+ System.err.println("gap end: " + gapEnd);
+ for (int i = 0; i < buffer.length; i++)
+ {
+ if (i == gapStart)
+ System.err.print('<');
+ if (i == gapEnd)
+ System.err.print('>');
+
+ if (!Character.isISOControl(buffer[i]))
+ System.err.print(buffer[i]);
+ else
+ System.err.print('.');
+ }
+ System.err.println();
+ }
+
+ /**
+ * Prints out the position marks.
+ */
+ private void dumpMarks()
+ {
+ System.out.print("positionMarks: ");
+ for (int i = 0; i < marks.size(); i++)
+ System.out.print(((Mark) marks.get(i)).mark + ", ");
+ System.out.println();
+ }
+
+ /**
+ * Polls the queue of death for GapContentPositions, updates the
+ * corresponding reference count and removes the corresponding mark
+ * if the refcount reaches zero.
+ *
+ * This is package private to avoid accessor synthetic methods.
+ */
+ void garbageCollect()
+ {
+ Reference ref = queueOfDeath.poll();
+ while (ref != null)
+ {
+ if (ref != null)
+ {
+ GapContentPosition pos = (GapContentPosition) ref.get();
+ Mark m = pos.mark;
+ m.refCount--;
+ if (m.refCount == 0)
+ marks.remove(m);
+ }
+ ref = queueOfDeath.poll();
+ }
+ }
+
+ /**
+ * Searches the first occurance of object <code>o</code> in list
+ * <code>l</code>. This performs a binary search by calling
+ * {@link Collections#binarySearch(List, Object)} and when an object has been
+ * found, it searches backwards to the first occurance of that object in the
+ * list. The meaning of the return value is the same as in
+ * <code>Collections.binarySearch()</code>.
+ *
+ * @param l the list to search through
+ * @param o the object to be searched
+ *
+ * @return the index of the first occurance of o in l, or -i + 1 if not found
+ */
+ private int search(List l, Object o)
+ {
+ int i = Collections.binarySearch(l, o);
+ while (i > 0)
+ {
+ Object o2 = l.get(i - 1);
+ if (o2.equals(o))
+ i--;
+ else
+ break;
+ }
+ return i;
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/GlyphView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/GlyphView.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/GlyphView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/GlyphView.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,1078 @@
+/* GlyphView.java -- A view to render styled text
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.Toolkit;
+import java.text.BreakIterator;
+
+import javax.swing.SwingConstants;
+import javax.swing.event.DocumentEvent;
+import javax.swing.text.Position.Bias;
+
+/**
+ * Renders a run of styled text. This {@link View} subclass paints the
+ * characters of the <code>Element</code> it is responsible for using
+ * the style information from that <code>Element</code>.
+ *
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class GlyphView extends View implements TabableView, Cloneable
+{
+
+ /**
+ * An abstract base implementation for a glyph painter for
+ * <code>GlyphView</code>.
+ */
+ public abstract static class GlyphPainter
+ {
+ /**
+ * Creates a new <code>GlyphPainer</code>.
+ */
+ public GlyphPainter()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns the ascent of the font that is used by this glyph painter.
+ *
+ * @param v the glyph view
+ *
+ * @return the ascent of the font that is used by this glyph painter
+ */
+ public abstract float getAscent(GlyphView v);
+
+ /**
+ * Returns the descent of the font that is used by this glyph painter.
+ *
+ * @param v the glyph view
+ *
+ * @return the descent of the font that is used by this glyph painter
+ */
+ public abstract float getDescent(GlyphView v);
+
+ /**
+ * Returns the full height of the rendered text.
+ *
+ * @return the full height of the rendered text
+ */
+ public abstract float getHeight(GlyphView view);
+
+ /**
+ * Determines the model offset, so that the text between <code>p0</code>
+ * and this offset fits within the span starting at <code>x</code> with
+ * the length of <code>len</code>.
+ *
+ * @param v the glyph view
+ * @param p0 the starting offset in the model
+ * @param x the start location in the view
+ * @param len the length of the span in the view
+ */
+ public abstract int getBoundedPosition(GlyphView v, int p0, float x,
+ float len);
+
+ /**
+ * Paints the glyphs.
+ *
+ * @param view the glyph view to paint
+ * @param g the graphics context to use for painting
+ * @param a the allocation of the glyph view
+ * @param p0 the start position (in the model) from which to paint
+ * @param p1 the end position (in the model) to which to paint
+ */
+ public abstract void paint(GlyphView view, Graphics g, Shape a, int p0,
+ int p1);
+
+ /**
+ * Maps a position in the document into the coordinate space of the View.
+ * The output rectangle usually reflects the font height but has a width
+ * of zero.
+ *
+ * @param view the glyph view
+ * @param pos the position of the character in the model
+ * @param a the area that is occupied by the view
+ * @param b either {@link Position.Bias#Forward} or
+ * {@link Position.Bias#Backward} depending on the preferred
+ * direction bias. If <code>null</code> this defaults to
+ * <code>Position.Bias.Forward</code>
+ *
+ * @return a rectangle that gives the location of the document position
+ * inside the view coordinate space
+ *
+ * @throws BadLocationException if <code>pos</code> is invalid
+ * @throws IllegalArgumentException if b is not one of the above listed
+ * valid values
+ */
+ public abstract Shape modelToView(GlyphView view, int pos, Position.Bias b,
+ Shape a)
+ throws BadLocationException;
+
+ /**
+ * Maps a visual position into a document location.
+ *
+ * @param v the glyph view
+ * @param x the X coordinate of the visual position
+ * @param y the Y coordinate of the visual position
+ * @param a the allocated region
+ * @param biasRet filled with the bias of the model location on method exit
+ *
+ * @return the model location that represents the specified view location
+ */
+ public abstract int viewToModel(GlyphView v, float x, float y, Shape a,
+ Position.Bias[] biasRet);
+
+ /**
+ * Determine the span of the glyphs from location <code>p0</code> to
+ * location <code>p1</code>. If <code>te</code> is not <code>null</code>,
+ * then TABs are expanded using this <code>TabExpander</code>.
+ * The parameter <code>x</code> is the location at which the view is
+ * located (this is important when using TAB expansion).
+ *
+ * @param view the glyph view
+ * @param p0 the starting location in the document model
+ * @param p1 the end location in the document model
+ * @param te the tab expander to use
+ * @param x the location at which the view is located
+ *
+ * @return the span of the glyphs from location <code>p0</code> to
+ * location <code>p1</code>, possibly using TAB expansion
+ */
+ public abstract float getSpan(GlyphView view, int p0, int p1,
+ TabExpander te, float x);
+
+
+ /**
+ * Returns the model location that should be used to place a caret when
+ * moving the caret through the document.
+ *
+ * @param v the glyph view
+ * @param pos the current model location
+ * @param b the bias for <code>p</code>
+ * @param a the allocated region for the glyph view
+ * @param direction the direction from the current position; Must be one of
+ * {@link SwingConstants#EAST}, {@link SwingConstants#WEST},
+ * {@link SwingConstants#NORTH} or {@link SwingConstants#SOUTH}
+ * @param biasRet filled with the bias of the resulting location when method
+ * returns
+ *
+ * @return the location within the document that should be used to place the
+ * caret when moving the caret around the document
+ *
+ * @throws BadLocationException if <code>pos</code> is an invalid model
+ * location
+ * @throws IllegalArgumentException if <code>d</code> is invalid
+ */
+ public int getNextVisualPositionFrom(GlyphView v, int pos, Position.Bias b,
+ Shape a, int direction,
+ Position.Bias[] biasRet)
+ throws BadLocationException
+
+ {
+ int result = pos;
+ switch (direction)
+ {
+ case SwingConstants.EAST:
+ result = pos + 1;
+ break;
+ case SwingConstants.WEST:
+ result = pos - 1;
+ break;
+ case SwingConstants.NORTH:
+ case SwingConstants.SOUTH:
+ default:
+ // This should be handled in enclosing view, since the glyph view
+ // does not layout vertically.
+ break;
+ }
+ return result;
+ }
+
+ /**
+ * Returns a painter that can be used to render the specified glyph view.
+ * If this glyph painter is stateful, then it should return a new instance.
+ * However, if this painter is stateless it should return itself. The
+ * default behaviour is to return itself.
+ *
+ * @param v the glyph view for which to create a painter
+ * @param p0 the start offset of the rendered area
+ * @param p1 the end offset of the rendered area
+ *
+ * @return a painter that can be used to render the specified glyph view
+ */
+ public GlyphPainter getPainter(GlyphView v, int p0, int p1)
+ {
+ return this;
+ }
+ }
+
+ /**
+ * The default <code>GlyphPainter</code> used in <code>GlyphView</code>.
+ */
+ static class DefaultGlyphPainter extends GlyphPainter
+ {
+ /**
+ * Returns the full height of the rendered text.
+ *
+ * @return the full height of the rendered text
+ */
+ public float getHeight(GlyphView view)
+ {
+ Font font = view.getFont();
+ FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
+ float height = metrics.getHeight();
+ return height;
+ }
+
+ /**
+ * Paints the glyphs.
+ *
+ * @param view the glyph view to paint
+ * @param g the graphics context to use for painting
+ * @param a the allocation of the glyph view
+ * @param p0 the start position (in the model) from which to paint
+ * @param p1 the end position (in the model) to which to paint
+ */
+ public void paint(GlyphView view, Graphics g, Shape a, int p0,
+ int p1)
+ {
+ Color oldColor = g.getColor();
+ int height = (int) getHeight(view);
+ Segment txt = view.getText(p0, p1);
+ Rectangle bounds = a.getBounds();
+ TabExpander tabEx = null;
+ View parent = view.getParent();
+ if (parent instanceof TabExpander)
+ tabEx = (TabExpander) parent;
+
+ int width = Utilities.getTabbedTextWidth(txt, g.getFontMetrics(),
+ bounds.x, tabEx, txt.offset);
+ // Fill the background of the text run.
+ Color background = view.getBackground();
+ if (background != null)
+ {
+ g.setColor(background);
+ g.fillRect(bounds.x, bounds.y, width, height);
+ }
+ // Draw the actual text.
+ g.setColor(view.getForeground());
+ g.setFont(view.getFont());
+ int ascent = g.getFontMetrics().getAscent();
+ if (view.isSuperscript())
+ // TODO: Adjust font for superscripting.
+ Utilities.drawTabbedText(txt, bounds.x, bounds.y + ascent - height / 2,
+ g, tabEx, txt.offset);
+ else if (view.isSubscript())
+ // TODO: Adjust font for subscripting.
+ Utilities.drawTabbedText(txt, bounds.x, bounds.y + ascent + height / 2,
+ g, tabEx, txt.offset);
+ else
+ Utilities.drawTabbedText(txt, bounds.x, bounds.y + ascent, g, tabEx,
+ txt.offset);
+
+ if (view.isStrikeThrough())
+ {
+ int strikeHeight = (int) (getAscent(view) / 2);
+ g.drawLine(bounds.x, bounds.y + strikeHeight, bounds.height + width,
+ bounds.y + strikeHeight);
+ }
+ if (view.isUnderline())
+ {
+ int lineHeight = (int) getAscent(view);
+ g.drawLine(bounds.x, bounds.y + lineHeight, bounds.height + width,
+ bounds.y + lineHeight);
+ }
+ g.setColor(oldColor);
+ }
+
+ /**
+ * Maps a position in the document into the coordinate space of the View.
+ * The output rectangle usually reflects the font height but has a width
+ * of zero.
+ *
+ * @param view the glyph view
+ * @param pos the position of the character in the model
+ * @param a the area that is occupied by the view
+ * @param b either {@link Position.Bias#Forward} or
+ * {@link Position.Bias#Backward} depending on the preferred
+ * direction bias. If <code>null</code> this defaults to
+ * <code>Position.Bias.Forward</code>
+ *
+ * @return a rectangle that gives the location of the document position
+ * inside the view coordinate space
+ *
+ * @throws BadLocationException if <code>pos</code> is invalid
+ * @throws IllegalArgumentException if b is not one of the above listed
+ * valid values
+ */
+ public Shape modelToView(GlyphView view, int pos, Position.Bias b,
+ Shape a)
+ throws BadLocationException
+ {
+ Element el = view.getElement();
+ Font font = view.getFont();
+ FontMetrics fm = view.getContainer().getFontMetrics(font);
+ Segment txt = view.getText(el.getStartOffset(), pos);
+ int width = fm.charsWidth(txt.array, txt.offset, txt.count);
+ int height = fm.getHeight();
+ Rectangle bounds = a.getBounds();
+ Rectangle result = new Rectangle(bounds.x + width, bounds.y,
+ bounds.x + width, height);
+ return result;
+ }
+
+ /**
+ * Determine the span of the glyphs from location <code>p0</code> to
+ * location <code>p1</code>. If <code>te</code> is not <code>null</code>,
+ * then TABs are expanded using this <code>TabExpander</code>.
+ * The parameter <code>x</code> is the location at which the view is
+ * located (this is important when using TAB expansion).
+ *
+ * @param view the glyph view
+ * @param p0 the starting location in the document model
+ * @param p1 the end location in the document model
+ * @param te the tab expander to use
+ * @param x the location at which the view is located
+ *
+ * @return the span of the glyphs from location <code>p0</code> to
+ * location <code>p1</code>, possibly using TAB expansion
+ */
+ public float getSpan(GlyphView view, int p0, int p1,
+ TabExpander te, float x)
+ {
+ Element el = view.getElement();
+ Font font = view.getFont();
+ FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
+ Segment txt = view.getText(p0, p1);
+ int span = Utilities.getTabbedTextWidth(txt, fm, (int) x, te, p0);
+ return span;
+ }
+
+ /**
+ * Returns the ascent of the text run that is rendered by this
+ * <code>GlyphPainter</code>.
+ *
+ * @param v the glyph view
+ *
+ * @return the ascent of the text run that is rendered by this
+ * <code>GlyphPainter</code>
+ *
+ * @see FontMetrics#getAscent()
+ */
+ public float getAscent(GlyphView v)
+ {
+ Font font = v.getFont();
+ FontMetrics fm = v.getContainer().getFontMetrics(font);
+ return fm.getAscent();
+ }
+
+ /**
+ * Returns the descent of the text run that is rendered by this
+ * <code>GlyphPainter</code>.
+ *
+ * @param v the glyph view
+ *
+ * @return the descent of the text run that is rendered by this
+ * <code>GlyphPainter</code>
+ *
+ * @see FontMetrics#getDescent()
+ */
+ public float getDescent(GlyphView v)
+ {
+ Font font = v.getFont();
+ FontMetrics fm = v.getContainer().getFontMetrics(font);
+ return fm.getDescent();
+ }
+
+ /**
+ * Determines the model offset, so that the text between <code>p0</code>
+ * and this offset fits within the span starting at <code>x</code> with
+ * the length of <code>len</code>.
+ *
+ * @param v the glyph view
+ * @param p0 the starting offset in the model
+ * @param x the start location in the view
+ * @param len the length of the span in the view
+ */
+ public int getBoundedPosition(GlyphView v, int p0, float x, float len)
+ {
+ TabExpander te = v.getTabExpander();
+ Segment txt = v.getText(p0, v.getEndOffset());
+ Font font = v.getFont();
+ FontMetrics fm = v.getContainer().getFontMetrics(font);
+ int pos = Utilities.getTabbedTextOffset(txt, fm, (int) x,
+ (int) (x + len), te, p0, false);
+ return pos;
+ }
+
+ /**
+ * Maps a visual position into a document location.
+ *
+ * @param v the glyph view
+ * @param x the X coordinate of the visual position
+ * @param y the Y coordinate of the visual position
+ * @param a the allocated region
+ * @param biasRet filled with the bias of the model location on method exit
+ *
+ * @return the model location that represents the specified view location
+ */
+ public int viewToModel(GlyphView v, float x, float y, Shape a,
+ Bias[] biasRet)
+ {
+ Rectangle b = a.getBounds();
+ int pos = getBoundedPosition(v, v.getStartOffset(), b.x, x - b.x);
+ return pos;
+ }
+ }
+
+ /**
+ * The GlyphPainer used for painting the glyphs.
+ */
+ GlyphPainter glyphPainter;
+
+ /**
+ * The start offset within the document for this view.
+ */
+ private int startOffset;
+
+ /**
+ * The end offset within the document for this view.
+ */
+ private int endOffset;
+
+ /**
+ * Creates a new <code>GlyphView</code> for the given <code>Element</code>.
+ *
+ * @param element the element that is rendered by this GlyphView
+ */
+ public GlyphView(Element element)
+ {
+ super(element);
+ startOffset = -1;
+ endOffset = -1;
+ }
+
+ /**
+ * Returns the <code>GlyphPainter</code> that is used by this
+ * <code>GlyphView</code>. If no <code>GlyphPainer</code> has been installed
+ * <code>null</code> is returned.
+ *
+ * @return the glyph painter that is used by this
+ * glyph view or <code>null</code> if no glyph painter has been
+ * installed
+ */
+ public GlyphPainter getGlyphPainter()
+ {
+ return glyphPainter;
+ }
+
+ /**
+ * Sets the {@link GlyphPainter} to be used for this <code>GlyphView</code>.
+ *
+ * @param painter the glyph painter to be used for this glyph view
+ */
+ public void setGlyphPainter(GlyphPainter painter)
+ {
+ glyphPainter = painter;
+ }
+
+ /**
+ * Checks if a <code>GlyphPainer</code> is installed. If this is not the
+ * case, a default painter is installed.
+ */
+ protected void checkPainter()
+ {
+ if (glyphPainter == null)
+ glyphPainter = new DefaultGlyphPainter();
+ }
+
+ /**
+ * Renders the <code>Element</code> that is associated with this
+ * <code>View</code>.
+ *
+ * @param g the <code>Graphics</code> context to render to
+ * @param a the allocated region for the <code>Element</code>
+ */
+ public void paint(Graphics g, Shape a)
+ {
+ Element el = getElement();
+ checkPainter();
+ getGlyphPainter().paint(this, g, a, getStartOffset(), getEndOffset());
+ }
+
+
+ /**
+ * Returns the preferred span of the content managed by this
+ * <code>View</code> along the specified <code>axis</code>.
+ *
+ * @param axis the axis
+ *
+ * @return the preferred span of this <code>View</code>.
+ */
+ public float getPreferredSpan(int axis)
+ {
+ float span = 0;
+ checkPainter();
+ GlyphPainter painter = getGlyphPainter();
+ if (axis == X_AXIS)
+ {
+ Element el = getElement();
+ TabExpander tabEx = null;
+ View parent = getParent();
+ if (parent instanceof TabExpander)
+ tabEx = (TabExpander) parent;
+ span = painter.getSpan(this, getStartOffset(), getEndOffset(),
+ tabEx, 0.F);
+ }
+ else
+ span = painter.getHeight(this);
+
+ return span;
+ }
+
+ /**
+ * Maps a position in the document into the coordinate space of the View.
+ * The output rectangle usually reflects the font height but has a width
+ * of zero.
+ *
+ * @param pos the position of the character in the model
+ * @param a the area that is occupied by the view
+ * @param b either {@link Position.Bias#Forward} or
+ * {@link Position.Bias#Backward} depending on the preferred
+ * direction bias. If <code>null</code> this defaults to
+ * <code>Position.Bias.Forward</code>
+ *
+ * @return a rectangle that gives the location of the document position
+ * inside the view coordinate space
+ *
+ * @throws BadLocationException if <code>pos</code> is invalid
+ * @throws IllegalArgumentException if b is not one of the above listed
+ * valid values
+ */
+ public Shape modelToView(int pos, Shape a, Position.Bias b)
+ throws BadLocationException
+ {
+ GlyphPainter p = getGlyphPainter();
+ return p.modelToView(this, pos, b, a);
+ }
+
+ /**
+ * Maps coordinates from the <code>View</code>'s space into a position
+ * in the document model.
+ *
+ * @param x the x coordinate in the view space
+ * @param y the y coordinate in the view space
+ * @param a the allocation of this <code>View</code>
+ * @param b the bias to use
+ *
+ * @return the position in the document that corresponds to the screen
+ * coordinates <code>x, y</code>
+ */
+ public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
+ {
+ checkPainter();
+ GlyphPainter painter = getGlyphPainter();
+ return painter.viewToModel(this, x, y, a, b);
+ }
+
+ /**
+ * Return the {@link TabExpander} to use.
+ *
+ * @return the {@link TabExpander} to use
+ */
+ public TabExpander getTabExpander()
+ {
+ TabExpander te = null;
+ View parent = getParent();
+
+ if (parent instanceof TabExpander)
+ te = (TabExpander) parent;
+
+ return te;
+ }
+
+ /**
+ * Returns the preferred span of this view for tab expansion.
+ *
+ * @param x the location of the view
+ * @param te the tab expander to use
+ *
+ * @return the preferred span of this view for tab expansion
+ */
+ public float getTabbedSpan(float x, TabExpander te)
+ {
+ Element el = getElement();
+ return getGlyphPainter().getSpan(this, el.getStartOffset(),
+ el.getEndOffset(), te, x);
+ }
+
+ /**
+ * Returns the span of a portion of the view. This is used in TAB expansion
+ * for fragments that don't contain TABs.
+ *
+ * @param p0 the start index
+ * @param p1 the end index
+ *
+ * @return the span of the specified portion of the view
+ */
+ public float getPartialSpan(int p0, int p1)
+ {
+ Element el = getElement();
+ Document doc = el.getDocument();
+ Segment seg = new Segment();
+ try
+ {
+ doc.getText(p0, p1 - p0, seg);
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError ae;
+ ae = new AssertionError("BadLocationException must not be thrown "
+ + "here");
+ ae.initCause(ex);
+ throw ae;
+ }
+ FontMetrics fm = null; // Fetch font metrics somewhere.
+ return Utilities.getTabbedTextWidth(seg, fm, 0, null, p0);
+ }
+
+ /**
+ * Returns the start offset in the document model of the portion
+ * of text that this view is responsible for.
+ *
+ * @return the start offset in the document model of the portion
+ * of text that this view is responsible for
+ */
+ public int getStartOffset()
+ {
+ int start = startOffset;
+ if (start < 0)
+ start = super.getStartOffset();
+ return start;
+ }
+
+ /**
+ * Returns the end offset in the document model of the portion
+ * of text that this view is responsible for.
+ *
+ * @return the end offset in the document model of the portion
+ * of text that this view is responsible for
+ */
+ public int getEndOffset()
+ {
+ int end = endOffset;
+ if (end < 0)
+ end = super.getEndOffset();
+ return end;
+ }
+
+ /**
+ * Returns the text segment that this view is responsible for.
+ *
+ * @param p0 the start index in the document model
+ * @param p1 the end index in the document model
+ *
+ * @return the text segment that this view is responsible for
+ */
+ public Segment getText(int p0, int p1)
+ {
+ Segment txt = new Segment();
+ try
+ {
+ getDocument().getText(p0, p1 - p0, txt);
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError ae;
+ ae = new AssertionError("BadLocationException should not be "
+ + "thrown here. p0 = " + p0 + ", p1 = " + p1);
+ ae.initCause(ex);
+ throw ae;
+ }
+
+ return txt;
+ }
+
+ /**
+ * Returns the font for the text run for which this <code>GlyphView</code>
+ * is responsible.
+ *
+ * @return the font for the text run for which this <code>GlyphView</code>
+ * is responsible
+ */
+ public Font getFont()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ String family = StyleConstants.getFontFamily(atts);
+ int size = StyleConstants.getFontSize(atts);
+ int style = Font.PLAIN;
+ if (StyleConstants.isBold(atts))
+ style |= Font.BOLD;
+ if (StyleConstants.isItalic(atts))
+ style |= Font.ITALIC;
+ Font font = new Font(family, style, size);
+ return font;
+ }
+
+ /**
+ * Returns the foreground color which should be used to paint the text.
+ * This is fetched from the associated element's text attributes using
+ * {@link StyleConstants#getForeground}.
+ *
+ * @return the foreground color which should be used to paint the text
+ */
+ public Color getForeground()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ return StyleConstants.getForeground(atts);
+ }
+
+ /**
+ * Returns the background color which should be used to paint the text.
+ * This is fetched from the associated element's text attributes using
+ * {@link StyleConstants#getBackground}.
+ *
+ * @return the background color which should be used to paint the text
+ */
+ public Color getBackground()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ // We cannot use StyleConstants.getBackground() here, because that returns
+ // BLACK as default (when background == null). What we need is the
+ // background setting of the text component instead, which is what we get
+ // when background == null anyway.
+ return (Color) atts.getAttribute(StyleConstants.Background);
+ }
+
+ /**
+ * Determines whether the text should be rendered strike-through or not. This
+ * is determined using the method
+ * {@link StyleConstants#isStrikeThrough(AttributeSet)} on the element of
+ * this view.
+ *
+ * @return whether the text should be rendered strike-through or not
+ */
+ public boolean isStrikeThrough()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ return StyleConstants.isStrikeThrough(atts);
+ }
+
+ /**
+ * Determines whether the text should be rendered as subscript or not. This
+ * is determined using the method
+ * {@link StyleConstants#isSubscript(AttributeSet)} on the element of
+ * this view.
+ *
+ * @return whether the text should be rendered as subscript or not
+ */
+ public boolean isSubscript()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ return StyleConstants.isSubscript(atts);
+ }
+
+ /**
+ * Determines whether the text should be rendered as superscript or not. This
+ * is determined using the method
+ * {@link StyleConstants#isSuperscript(AttributeSet)} on the element of
+ * this view.
+ *
+ * @return whether the text should be rendered as superscript or not
+ */
+ public boolean isSuperscript()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ return StyleConstants.isSuperscript(atts);
+ }
+
+ /**
+ * Determines whether the text should be rendered as underlined or not. This
+ * is determined using the method
+ * {@link StyleConstants#isUnderline(AttributeSet)} on the element of
+ * this view.
+ *
+ * @return whether the text should be rendered as underlined or not
+ */
+ public boolean isUnderline()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ return StyleConstants.isUnderline(atts);
+ }
+
+ /**
+ * Creates and returns a shallow clone of this GlyphView. This is used by
+ * the {@link #createFragment} and {@link #breakView} methods.
+ *
+ * @return a shallow clone of this GlyphView
+ */
+ protected final Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException ex)
+ {
+ AssertionError err = new AssertionError("CloneNotSupportedException "
+ + "must not be thrown here");
+ err.initCause(ex);
+ throw err;
+ }
+ }
+
+ /**
+ * Tries to break the view near the specified view span <code>len</code>.
+ * The glyph view can only be broken in the X direction. For Y direction it
+ * returns itself.
+ *
+ * @param axis the axis for breaking, may be {@link View#X_AXIS} or
+ * {@link View#Y_AXIS}
+ * @param p0 the model location where the fragment should start
+ * @param pos the view position along the axis where the fragment starts
+ * @param len the desired length of the fragment view
+ *
+ * @return the fragment view, or <code>this</code> if breaking was not
+ * possible
+ */
+ public View breakView(int axis, int p0, float pos, float len)
+ {
+ if (axis == Y_AXIS)
+ return this;
+
+ checkPainter();
+ GlyphPainter painter = getGlyphPainter();
+
+ // Try to find a suitable line break.
+ BreakIterator lineBreaker = BreakIterator.getLineInstance();
+ Segment txt = new Segment();
+ try
+ {
+ int start = getStartOffset();
+ int length = getEndOffset() - start;
+ getDocument().getText(start, length, txt);
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError err = new AssertionError("BadLocationException must not "
+ + "be thrown here.");
+ err.initCause(ex);
+ throw err;
+ }
+ int breakLocation =
+ Utilities.getBreakLocation(txt, getContainer().getFontMetrics(getFont()),
+ (int) pos, (int) (pos + len),
+ getTabExpander(), p0);
+ View brokenView = createFragment(p0, breakLocation);
+ return brokenView;
+ }
+
+ /**
+ * Determines how well the specified view location is suitable for inserting
+ * a line break. If <code>axis</code> is <code>View.Y_AXIS</code>, then
+ * this method forwards to the superclass, if <code>axis</code> is
+ * <code>View.X_AXIS</code> then this method returns
+ * {@link View#ExcellentBreakWeight} if there is a suitable break location
+ * (usually whitespace) within the specified view span, or
+ * {@link View#GoodBreakWeight} if not.
+ *
+ * @param axis the axis along which the break weight is requested
+ * @param pos the starting view location
+ * @param len the length of the span at which the view should be broken
+ *
+ * @return the break weight
+ */
+ public int getBreakWeight(int axis, float pos, float len)
+ {
+ int weight;
+ if (axis == Y_AXIS)
+ weight = super.getBreakWeight(axis, pos, len);
+ else
+ {
+ // FIXME: Commented out because the Utilities.getBreakLocation method
+ // is still buggy. The GoodBreakWeight is a reasonable workaround for
+ // now.
+// int startOffset = getStartOffset();
+// int endOffset = getEndOffset() - 1;
+// Segment s = getText(startOffset, endOffset);
+// Container c = getContainer();
+// FontMetrics fm = c.getFontMetrics(c.getFont());
+// int x0 = (int) pos;
+// int x = (int) (pos + len);
+// int breakLoc = Utilities.getBreakLocation(s, fm, x0, x,
+// getTabExpander(),
+// startOffset);
+// if (breakLoc == startOffset || breakLoc == endOffset)
+// weight = GoodBreakWeight;
+// else
+// weight = ExcellentBreakWeight;
+ weight = GoodBreakWeight;
+ }
+ return weight;
+ }
+
+ /**
+ * Receives notification that some text attributes have changed within the
+ * text fragment that this view is responsible for. This calls
+ * {@link View#preferenceChanged(View, boolean, boolean)} on the parent for
+ * both width and height.
+ *
+ * @param e the document event describing the change; not used here
+ * @param a the view allocation on screen; not used here
+ * @param vf the view factory; not used here
+ */
+ public void changedUpdate(DocumentEvent e, Shape a, ViewFactory vf)
+ {
+ preferenceChanged(this, true, true);
+ }
+
+ /**
+ * Receives notification that some text has been inserted within the
+ * text fragment that this view is responsible for. This calls
+ * {@link View#preferenceChanged(View, boolean, boolean)} for the
+ * direction in which the glyphs are rendered.
+ *
+ * @param e the document event describing the change; not used here
+ * @param a the view allocation on screen; not used here
+ * @param vf the view factory; not used here
+ */
+ public void insertUpdate(DocumentEvent e, Shape a, ViewFactory vf)
+ {
+ preferenceChanged(this, true, false);
+ }
+
+ /**
+ * Receives notification that some text has been removed within the
+ * text fragment that this view is responsible for. This calls
+ * {@link View#preferenceChanged(View, boolean, boolean)} on the parent for
+ * width.
+ *
+ * @param e the document event describing the change; not used here
+ * @param a the view allocation on screen; not used here
+ * @param vf the view factory; not used here
+ */
+ public void removeUpdate(DocumentEvent e, Shape a, ViewFactory vf)
+ {
+ preferenceChanged(this, true, false);
+ }
+
+ /**
+ * Creates a fragment view of this view that starts at <code>p0</code> and
+ * ends at <code>p1</code>.
+ *
+ * @param p0 the start location for the fragment view
+ * @param p1 the end location for the fragment view
+ *
+ * @return the fragment view
+ */
+ public View createFragment(int p0, int p1)
+ {
+ GlyphView fragment = (GlyphView) clone();
+ if (p0 != getStartOffset())
+ fragment.startOffset = p0;
+ if (p1 != getEndOffset())
+ fragment.endOffset = p1;
+ return fragment;
+ }
+
+ /**
+ * Returns the alignment of this view along the specified axis. For the Y
+ * axis this is <code>(height - descent) / height</code> for the used font,
+ * so that it is aligned along the baseline.
+ * For the X axis the superclass is called.
+ */
+ public float getAlignment(int axis)
+ {
+ float align;
+ if (axis == Y_AXIS)
+ {
+ checkPainter();
+ GlyphPainter painter = getGlyphPainter();
+ float height = painter.getHeight(this);
+ float descent = painter.getDescent(this);
+ align = (height - descent) / height;
+ }
+ else
+ align = super.getAlignment(axis);
+
+ return align;
+ }
+
+ /**
+ * Returns the model location that should be used to place a caret when
+ * moving the caret through the document.
+ *
+ * @param pos the current model location
+ * @param bias the bias for <code>p</code>
+ * @param a the allocated region for the glyph view
+ * @param direction the direction from the current position; Must be one of
+ * {@link SwingConstants#EAST}, {@link SwingConstants#WEST},
+ * {@link SwingConstants#NORTH} or {@link SwingConstants#SOUTH}
+ * @param biasRet filled with the bias of the resulting location when method
+ * returns
+ *
+ * @return the location within the document that should be used to place the
+ * caret when moving the caret around the document
+ *
+ * @throws BadLocationException if <code>pos</code> is an invalid model
+ * location
+ * @throws IllegalArgumentException if <code>d</code> is invalid
+ */
+ public int getNextVisualPositionFrom(int pos, Position.Bias bias, Shape a,
+ int direction, Position.Bias[] biasRet)
+ throws BadLocationException
+ {
+ checkPainter();
+ GlyphPainter painter = getGlyphPainter();
+ return painter.getNextVisualPositionFrom(this, pos, bias, a, direction,
+ biasRet);
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Highlighter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Highlighter.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Highlighter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Highlighter.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,79 @@
+/* Highlighter.java --
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Graphics;
+import java.awt.Shape;
+
+
+public interface Highlighter
+{
+ public interface Highlight
+ {
+ int getEndOffset();
+
+ int getStartOffset();
+
+ HighlightPainter getPainter();
+ }
+
+ public interface HighlightPainter
+ {
+ void paint(Graphics g, int p0, int p1, Shape bounds, JTextComponent c);
+ }
+
+ void install(JTextComponent c);
+
+ void deinstall(JTextComponent c);
+
+ Object addHighlight(int p0, int p1, HighlightPainter p)
+ throws BadLocationException;
+
+ void removeAllHighlights();
+
+ void removeHighlight(Object tag);
+
+ void changeHighlight(Object tag, int p0, int p1)
+ throws BadLocationException;
+
+ Highlight[] getHighlights();
+
+ void paint(Graphics g);
+}
+
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/IconView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/IconView.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/IconView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/IconView.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,175 @@
+/* IconView.java -- A view to render icons
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+import javax.swing.Icon;
+import javax.swing.JTextPane;
+
+/**
+ * A View that can render an icon. This view is created by the
+ * {@link StyledEditorKit}'s view factory for all elements that have name
+ * {@link StyleConstants#IconElementName}. This is usually created by
+ * inserting an icon into <code>JTextPane</code> using
+ * {@link JTextPane#insertIcon(Icon)}
+ *
+ * The icon is determined using the attribute
+ * {@link StyleConstants#IconAttribute}, which's value must be an {@link Icon}.
+ *
+ * @author Roman Kennke (kennke at aicas.com)
+ */
+public class IconView
+ extends View
+{
+
+ /**
+ * Creates a new <code>IconView</code> for the given <code>Element</code>.
+ *
+ * @param element the element that is rendered by this IconView
+ */
+ public IconView(Element element)
+ {
+ super(element);
+ }
+
+ /**
+ * Renders the <code>Element</code> that is associated with this
+ * <code>View</code>.
+ *
+ * @param g the <code>Graphics</code> context to render to
+ * @param a the allocated region for the <code>Element</code>
+ */
+ public void paint(Graphics g, Shape a)
+ {
+ Icon icon = StyleConstants.getIcon(getElement().getAttributes());
+ Rectangle b = a.getBounds();
+ icon.paintIcon(getContainer(), g, b.x, b.y);
+ }
+
+ /**
+ * Returns the preferred span of the content managed by this
+ * <code>View</code> along the specified <code>axis</code>.
+ *
+ * @param axis the axis
+ *
+ * @return the preferred span of this <code>View</code>.
+ */
+ public float getPreferredSpan(int axis)
+ {
+ Icon icon = StyleConstants.getIcon(getElement().getAttributes());
+ float span;
+ if (axis == X_AXIS)
+ span = icon.getIconWidth();
+ else if (axis == Y_AXIS)
+ span = icon.getIconHeight();
+ else
+ throw new IllegalArgumentException();
+ return span;
+ }
+
+ /**
+ * Maps a position in the document into the coordinate space of the View.
+ * The output rectangle usually reflects the font height but has a width
+ * of zero.
+ *
+ * @param pos the position of the character in the model
+ * @param a the area that is occupied by the view
+ * @param b either {@link Position.Bias#Forward} or
+ * {@link Position.Bias#Backward} depending on the preferred
+ * direction bias. If <code>null</code> this defaults to
+ * <code>Position.Bias.Forward</code>
+ *
+ * @return a rectangle that gives the location of the document position
+ * inside the view coordinate space
+ *
+ * @throws BadLocationException if <code>pos</code> is invalid
+ * @throws IllegalArgumentException if b is not one of the above listed
+ * valid values
+ */
+ public Shape modelToView(int pos, Shape a, Position.Bias b)
+ throws BadLocationException
+ {
+ Element el = getElement();
+ Rectangle r = a.getBounds();
+ Icon icon = StyleConstants.getIcon(el.getAttributes());
+ return new Rectangle(r.x, r.y, icon.getIconWidth(), icon.getIconHeight());
+ }
+
+ /**
+ * Maps coordinates from the <code>View</code>'s space into a position
+ * in the document model.
+ *
+ * @param x the x coordinate in the view space
+ * @param y the y coordinate in the view space
+ * @param a the allocation of this <code>View</code>
+ * @param b the bias to use
+ *
+ * @return the position in the document that corresponds to the screen
+ * coordinates <code>x, y</code>
+ */
+ public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
+ {
+ // The element should only have one character position and it is clear
+ // that this position is the position that best matches the given screen
+ // coordinates, simply because this view has only this one position.
+ Element el = getElement();
+ return el.getStartOffset();
+ }
+
+ /**
+ * Returns the alignment for this view. This will be 1.0 for the Y_AXIS,
+ * and the super behaviour for the X_AXIS.
+ *
+ * @param axis the axis for which to calculate the alignment
+ *
+ * @return the alignment
+ */
+ public float getAlignment(int axis)
+ {
+ float align;
+ if (axis == Y_AXIS)
+ align = 1.0F;
+ else
+ align = super.getAlignment(axis);
+ return align;
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/InternationalFormatter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/InternationalFormatter.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/InternationalFormatter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/InternationalFormatter.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,357 @@
+/* InternationalFormatter.java --
+Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.text.AttributedCharacterIterator;
+import java.text.Format;
+import java.text.ParseException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.swing.Action;
+import javax.swing.JFormattedTextField;
+
+/**
+ * This extends {@link DefaultFormatter} so that the value to string
+ * conversion is done via a {@link Format} object. This allows
+ * various additional formats to be handled by JFormattedField.
+ *
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class InternationalFormatter
+ extends DefaultFormatter
+{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 2436068675711756856L;
+
+ /** The format that handles value to string conversion. */
+ Format format;
+
+ /** The minimal permissable value. */
+ Comparable minimum;
+
+ /** The maximal permissable value. */
+ Comparable maximum;
+
+ /**
+ * Creates a new InternationalFormatter with no Format specified.
+ */
+ public InternationalFormatter()
+ {
+ super();
+ minimum = null;
+ maximum = null;
+ format = null;
+ setCommitsOnValidEdit(false);
+ setOverwriteMode(false);
+ }
+
+ /**
+ * Creates a new InternationalFormatter that uses the specified
+ * Format object for value to string conversion.
+ *
+ * @param format the Format object to use for value to string conversion
+ */
+ public InternationalFormatter(Format format)
+ {
+ this();
+ setFormat(format);
+ }
+
+ /**
+ * Sets the Format object that is used to convert values to strings.
+ *
+ * @param format the Format to use for value to string conversion
+ *
+ * @see Format
+ */
+ public void setFormat(Format format)
+ {
+ this.format = format;
+ }
+
+ /**
+ * Returns the currently used Format object that is used to format
+ * the JFormattedField.
+ *
+ * @return the current Format
+ */
+ public Format getFormat()
+ {
+ return format;
+ }
+
+ /**
+ * Sets the minimum value that is allowed by this Formatter. The minimum
+ * value is given as an object that implements the {@link Comparable}
+ * interface.
+ *
+ * If <code>minValue</code> is null, then the Formatter has no restrictions
+ * at the lower end.
+ *
+ * If value class is not yet specified and <code>minValue</code> is not
+ * null, then <code>valueClass</code> is set to the class of the minimum
+ * value.
+ *
+ * @param minValue the minimum permissable value
+ *
+ * @see Comparable
+ */
+ public void setMinimum(Comparable minValue)
+ {
+ minimum = minValue;
+ if (valueClass == null && minValue != null)
+ valueClass = minValue.getClass();
+ }
+
+ /**
+ * Returns the minimal value that is allowed by this Formatter.
+ *
+ * A <code>null</code> value means that there is no restriction.
+ *
+ * @return the minimal value that is allowed by this Formatter or
+ * <code>null</code> if there is no restriction
+ */
+ public Comparable getMinimum()
+ {
+ return minimum;
+ }
+
+ /**
+ * Sets the maximum value that is allowed by this Formatter. The maximum
+ * value is given as an object that implements the {@link Comparable}
+ * interface.
+ *
+ * If <code>maxValue</code> is null, then the Formatter has no restrictions
+ * at the upper end.
+ *
+ * If value class is not yet specified and <code>maxValue</code> is not
+ * null, then <code>valueClass</code> is set to the class of the maximum
+ * value.
+ *
+ * @param maxValue the maximum permissable value
+ *
+ * @see Comparable
+ */
+ public void setMaximum(Comparable maxValue)
+ {
+ maximum = maxValue;
+ if (valueClass == null && maxValue != null)
+ valueClass = maxValue.getClass();
+ }
+
+ /**
+ * Returns the maximal value that is allowed by this Formatter.
+ *
+ * A <code>null</code> value means that there is no restriction.
+ *
+ * @return the maximal value that is allowed by this Formatter or
+ * <code>null</code> if there is no restriction
+ */
+ public Comparable getMaximum()
+ {
+ return maximum;
+ }
+
+ /**
+ * Installs the formatter on the specified {@link JFormattedTextField}.
+ *
+ * This method does the following things:
+ * <ul>
+ * <li>Display the value of #valueToString in the
+ * <code>JFormattedTextField</code></li>
+ * <li>Install the Actions from #getActions on the <code>JTextField</code>
+ * </li>
+ * <li>Install the DocumentFilter returned by #getDocumentFilter</li>
+ * <li>Install the NavigationFilter returned by #getNavigationFilter</li>
+ * </ul>
+ *
+ * This method is typically not overridden by subclasses. Instead override
+ * one of the mentioned methods in order to customize behaviour.
+ *
+ * @param ftf the {@link JFormattedTextField} in which this formatter
+ * is installed
+ */
+ public void install(JFormattedTextField ftf)
+ {
+ super.install(ftf);
+ }
+
+ /**
+ * Converts a value object into a String. This is done by invoking
+ * {@link Format#format(Object)} on the specified <code>Format</code> object.
+ * If no format is set, then {@link DefaultFormatter#valueToString(Object)}
+ * is called as a fallback.
+ *
+ * @param value the value to be converted
+ *
+ * @return the string representation of the value
+ *
+ * @throws ParseException if the value cannot be converted
+ */
+ public String valueToString(Object value)
+ throws ParseException
+ {
+ if (value == null)
+ return "";
+ if (format != null)
+ return format.format(value);
+ else
+ return super.valueToString(value);
+ }
+
+ /**
+ * Converts a String (from the JFormattedTextField input) to a value.
+ * This is achieved by invoking {@link Format#parseObject(String)} on
+ * the specified <code>Format</code> object.
+ *
+ * This implementation differs slightly from {@link DefaultFormatter},
+ * it does:
+ * <ol>
+ * <li>Convert the string to an <code>Object</code> using the
+ * <code>Formatter</code>.</li>
+ * <li>If a <code>valueClass</code> has been set, this object is passed to
+ * {@link DefaultFormatter#stringToValue(String)} so that the value
+ * has the correct type. This may or may not work correctly, depending on
+ * the implementation of toString() in the value class and if the class
+ * implements a constructor that takes one String as argument.</li>
+ * <li>If no {@link ParseException} has been thrown so far, we check if the
+ * value exceeds either <code>minimum</code> or <code>maximum</code> if
+ * one of those has been specified and throw a <code>ParseException</code>
+ * if it does.</li>
+ * <li>Return the value.</li>
+ * </ol>
+ *
+ * If no format has been specified, then
+ * {@link DefaultFormatter#stringToValue(String)} is invoked as fallback.
+ *
+ * @param string the string to convert
+ *
+ * @return the value for the string
+ *
+ * @throws ParseException if the string cannot be converted into
+ * a value object (e.g. invalid input)
+ */
+ public Object stringToValue(String string)
+ throws ParseException
+ {
+ if (format != null)
+ {
+ Object o = format.parseObject(string);
+
+ // If a value class has been set, call super in order to get
+ // the class right. That is what the JDK API docs suggest, so we do
+ // it that way.
+ if (valueClass != null)
+ o = super.stringToValue(o.toString());
+
+ // Check for minimum and maximum bounds
+ if (minimum != null && minimum.compareTo(o) > 0)
+ throw new ParseException("The value may not be less than the"
+ + " specified minimum", 0);
+ if (maximum != null && minimum.compareTo(o) < 0)
+ throw new ParseException("The value may not be greater than the"
+ + " specified maximum", 0);
+ return o;
+ }
+ else
+ return super.stringToValue(string);
+ }
+
+ /**
+ * Returns the {@link Format.Field} constants that are associated with
+ * the specified position in the text.
+ *
+ * If <code>offset</code> is not a valid location in the input field,
+ * an empty array of fields is returned.
+ *
+ * @param offset the position in the text from which we want to fetch
+ * the fields constants
+ *
+ * @return the field values associated with the specified position in
+ * the text
+ */
+ public Format.Field[] getFields(int offset)
+ {
+ // TODO: don't know if this is correct
+ AttributedCharacterIterator aci = format.formatToCharacterIterator
+ (getFormattedTextField().getValue());
+ aci.setIndex(offset);
+ Map atts = aci.getAttributes();
+ Set keys = atts.keySet();
+ Format.Field[] fields = new Format.Field[keys.size()];
+ int index = 0;
+ for (Iterator i = keys.iterator(); i.hasNext(); index++)
+ fields[index] = (Format.Field) i.next();
+ return fields;
+ }
+
+ /**
+ * This creates and returns a clone of this Formatter.
+ *
+ * @return a clone of this formatter
+ *
+ * @throws CloneNotSupportedException not thrown here, since cloning is
+ * supported
+ * XXX - FIXME - Whole method disabled as workaround for gcj bug #22060.
+ public Object clone()
+ throws CloneNotSupportedException
+ {
+ // TODO: it has to be considered, if we should return a deep or shallow
+ // clone here. for now we return a shallow clone
+ Object clone = super.clone();
+ return clone;
+ }
+ */
+
+ /**
+ * Returns the Actions that are supported by this Formatter.
+ *
+ * @specnote the JDK API docs say here: <cite>If
+ * <code>getSupportsIncrement</code> returns true, this returns two
+ * Actions suitable for incrementing/decrementing the value.</cite>
+ * The questsion is, which method <code>getSupportsIncrement</code>?
+ * There is no such method in the whole API! So we just call
+ * super.getActions here.
+ */
+ protected Action[] getActions()
+ {
+ return super.getActions();
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/JTextComponent.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/JTextComponent.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/JTextComponent.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/JTextComponent.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,1905 @@
+/* JTextComponent.java --
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import gnu.classpath.NotImplementedException;
+
+import java.awt.AWTEvent;
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.event.ActionEvent;
+import java.awt.event.InputMethodListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleAction;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleEditableText;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleStateSet;
+import javax.accessibility.AccessibleText;
+import javax.swing.Action;
+import javax.swing.ActionMap;
+import javax.swing.InputMap;
+import javax.swing.JComponent;
+import javax.swing.JViewport;
+import javax.swing.KeyStroke;
+import javax.swing.Scrollable;
+import javax.swing.SwingConstants;
+import javax.swing.TransferHandler;
+import javax.swing.UIManager;
+import javax.swing.event.CaretEvent;
+import javax.swing.event.CaretListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.plaf.ActionMapUIResource;
+import javax.swing.plaf.InputMapUIResource;
+import javax.swing.plaf.TextUI;
+
+public abstract class JTextComponent extends JComponent
+ implements Scrollable, Accessible
+{
+ /**
+ * AccessibleJTextComponent implements accessibility hooks for
+ * JTextComponent. It allows an accessibility driver to read and
+ * manipulate the text component's contents as well as update UI
+ * elements such as the caret.
+ */
+ public class AccessibleJTextComponent extends AccessibleJComponent implements
+ AccessibleText, CaretListener, DocumentListener, AccessibleAction,
+ AccessibleEditableText
+ {
+ private static final long serialVersionUID = 7664188944091413696L;
+
+ /**
+ * The caret's offset.
+ */
+ int dot = 0;
+
+ /**
+ * The current JTextComponent.
+ */
+ JTextComponent textComp = JTextComponent.this;
+
+ /**
+ * Construct an AccessibleJTextComponent.
+ */
+ public AccessibleJTextComponent()
+ {
+ super();
+ textComp.addCaretListener(this);
+ }
+
+ /**
+ * Retrieve the current caret position. The index of the first
+ * caret position is 0.
+ *
+ * @return caret position
+ */
+ public int getCaretPosition()
+ {
+ dot = textComp.getCaretPosition();
+ return dot;
+ }
+
+ /**
+ * Retrieve the current text selection. If no text is selected
+ * this method returns null.
+ *
+ * @return the currently selected text or null
+ */
+ public String getSelectedText()
+ {
+ return textComp.getSelectedText();
+ }
+
+ /**
+ * Retrieve the index of the first character in the current text
+ * selection. If there is no text in the text component, this
+ * method returns 0. If there is text in the text component, but
+ * there is no selection, this method returns the current caret
+ * position.
+ *
+ * @return the index of the first character in the selection, the
+ * current caret position or 0
+ */
+ public int getSelectionStart()
+ {
+ if (getSelectedText() == null || (textComp.getText().equals("")))
+ return 0;
+ return textComp.getSelectionStart();
+ }
+
+ /**
+ * Retrieve the index of the last character in the current text
+ * selection. If there is no text in the text component, this
+ * method returns 0. If there is text in the text component, but
+ * there is no selection, this method returns the current caret
+ * position.
+ *
+ * @return the index of the last character in the selection, the
+ * current caret position or 0
+ */
+ public int getSelectionEnd()
+ {
+ if (getSelectedText() == null || (textComp.getText().equals("")))
+ return 0;
+ return textComp.getSelectionEnd();
+ }
+
+ /**
+ * Handle a change in the caret position and fire any applicable
+ * property change events.
+ *
+ * @param e - the caret update event
+ */
+ public void caretUpdate(CaretEvent e)
+ throws NotImplementedException
+ {
+ // TODO: fire appropriate event.
+ dot = e.getDot();
+ }
+
+ /**
+ * Retreive the accessible state set of this component.
+ *
+ * @return the accessible state set of this component
+ */
+ public AccessibleStateSet getAccessibleStateSet()
+ throws NotImplementedException
+ {
+ AccessibleStateSet state = super.getAccessibleStateSet();
+ // TODO: Figure out what state must be added here to the super's state.
+ return state;
+ }
+
+ /**
+ * Retrieve the accessible role of this component.
+ *
+ * @return the accessible role of this component
+ *
+ * @see AccessibleRole
+ */
+ public AccessibleRole getAccessibleRole()
+ {
+ return AccessibleRole.TEXT;
+ }
+
+ /**
+ * Retrieve an AccessibleEditableText object that controls this
+ * text component.
+ *
+ * @return this
+ */
+ public AccessibleEditableText getAccessibleEditableText()
+ {
+ return this;
+ }
+
+ /**
+ * Retrieve an AccessibleText object that controls this text
+ * component.
+ *
+ * @return this
+ *
+ * @see AccessibleText
+ */
+ public AccessibleText getAccessibleText()
+ {
+ return this;
+ }
+
+ /**
+ * Handle a text insertion event and fire an
+ * AccessibleContext.ACCESSIBLE_TEXT_PROPERTY property change
+ * event.
+ *
+ * @param e - the insertion event
+ */
+ public void insertUpdate(DocumentEvent e)
+ throws NotImplementedException
+ {
+ // TODO
+ }
+
+ /**
+ * Handle a text removal event and fire an
+ * AccessibleContext.ACCESSIBLE_TEXT_PROPERTY property change
+ * event.
+ *
+ * @param e - the removal event
+ */
+ public void removeUpdate(DocumentEvent e)
+ throws NotImplementedException
+ {
+ // TODO
+ }
+
+ /**
+ * Handle a text change event and fire an
+ * AccessibleContext.ACCESSIBLE_TEXT_PROPERTY property change
+ * event.
+ *
+ * @param e - text change event
+ */
+ public void changedUpdate(DocumentEvent e)
+ throws NotImplementedException
+ {
+ // TODO
+ }
+
+ /**
+ * Get the index of the character at the given point, in component
+ * pixel co-ordinates. If the point argument is invalid this
+ * method returns -1.
+ *
+ * @param p - a point in component pixel co-ordinates
+ *
+ * @return a character index, or -1
+ */
+ public int getIndexAtPoint(Point p)
+ throws NotImplementedException
+ {
+ return 0; // TODO
+ }
+
+ /**
+ * Calculate the bounding box of the character at the given index.
+ * The returned x and y co-ordinates are relative to this text
+ * component's top-left corner. If the index is invalid this
+ * method returns null.
+ *
+ * @param index - the character index
+ *
+ * @return a character's bounding box, or null
+ */
+ public Rectangle getCharacterBounds(int index)
+ throws NotImplementedException
+ {
+ return null; // TODO
+ }
+
+ /**
+ * Return the length of the text in this text component.
+ *
+ * @return a character length
+ */
+ public int getCharCount()
+ {
+ return textComp.getText().length();
+ }
+
+ /**
+ * Gets the character attributes of the character at index. If
+ * the index is out of bounds, null is returned.
+ *
+ * @param index - index of the character
+ *
+ * @return the character's attributes
+ */
+ public AttributeSet getCharacterAttribute(int index)
+ throws NotImplementedException
+ {
+ return null; // TODO
+ }
+
+ /**
+ * Gets the text located at index. null is returned if the index
+ * or part is invalid.
+ *
+ * @param part - {@link #CHARACTER}, {@link #WORD}, or {@link #SENTENCE}
+ * @param index - index of the part
+ *
+ * @return the part of text at that index, or null
+ */
+ public String getAtIndex(int part, int index)
+ throws NotImplementedException
+ {
+ return null; // TODO
+ }
+
+ /**
+ * Gets the text located after index. null is returned if the index
+ * or part is invalid.
+ *
+ * @param part - {@link #CHARACTER}, {@link #WORD}, or {@link #SENTENCE}
+ * @param index - index after the part
+ *
+ * @return the part of text after that index, or null
+ */
+ public String getAfterIndex(int part, int index)
+ throws NotImplementedException
+ {
+ return null; // TODO
+ }
+
+ /**
+ * Gets the text located before index. null is returned if the index
+ * or part is invalid.
+ *
+ * @param part - {@link #CHARACTER}, {@link #WORD}, or {@link #SENTENCE}
+ * @param index - index before the part
+ *
+ * @return the part of text before that index, or null
+ */
+ public String getBeforeIndex(int part, int index)
+ throws NotImplementedException
+ {
+ return null; // TODO
+ }
+
+ /**
+ * Returns the number of actions for this object. The zero-th
+ * object represents the default action.
+ *
+ * @return the number of actions (0-based).
+ */
+ public int getAccessibleActionCount()
+ throws NotImplementedException
+ {
+ return 0; // TODO
+ }
+
+ /**
+ * Returns the description of the i-th action. Null is returned if
+ * i is out of bounds.
+ *
+ * @param i - the action to get the description for
+ *
+ * @return description of the i-th action
+ */
+ public String getAccessibleActionDescription(int i)
+ throws NotImplementedException
+ {
+ // TODO: Not implemented fully
+ return super.getAccessibleDescription();
+ }
+
+ /**
+ * Performs the i-th action. Nothing happens if i is
+ * out of bounds.
+ *
+ * @param i - the action to perform
+ *
+ * @return true if the action was performed successfully
+ */
+ public boolean doAccessibleAction(int i)
+ throws NotImplementedException
+ {
+ return false; // TODO
+ }
+
+ /**
+ * Sets the text contents.
+ *
+ * @param s - the new text contents.
+ */
+ public void setTextContents(String s)
+ throws NotImplementedException
+ {
+ // TODO
+ }
+
+ /**
+ * Inserts the text at the given index.
+ *
+ * @param index - the index to insert the new text at.
+ * @param s - the new text
+ */
+ public void insertTextAtIndex(int index, String s)
+ throws NotImplementedException
+ {
+ replaceText(index, index, s);
+ }
+
+ /**
+ * Gets the text between two indexes.
+ *
+ * @param start - the starting index (inclusive)
+ * @param end - the ending index (exclusive)
+ */
+ public String getTextRange(int start, int end)
+ {
+ try
+ {
+ return textComp.getText(start, end - start);
+ }
+ catch (BadLocationException ble)
+ {
+ return "";
+ }
+ }
+
+ /**
+ * Deletes the text between two indexes.
+ *
+ * @param start - the starting index (inclusive)
+ * @param end - the ending index (exclusive)
+ */
+ public void delete(int start, int end)
+ {
+ replaceText(start, end, "");
+ }
+
+ /**
+ * Cuts the text between two indexes. The text is put
+ * into the system clipboard.
+ *
+ * @param start - the starting index (inclusive)
+ * @param end - the ending index (exclusive)
+ */
+ public void cut(int start, int end)
+ {
+ textComp.select(start, end);
+ textComp.cut();
+ }
+
+ /**
+ * Pastes the text from the system clipboard to the given index.
+ *
+ * @param start - the starting index
+ */
+ public void paste(int start)
+ {
+ textComp.setCaretPosition(start);
+ textComp.paste();
+ }
+
+ /**
+ * Replaces the text between two indexes with the given text.
+ *
+ *
+ * @param start - the starting index (inclusive)
+ * @param end - the ending index (exclusive)
+ * @param s - the text to paste
+ */
+ public void replaceText(int start, int end, String s)
+ {
+ textComp.select(start, end);
+ textComp.replaceSelection(s);
+ }
+
+ /**
+ * Selects the text between two indexes.
+ *
+ * @param start - the starting index (inclusive)
+ * @param end - the ending index (exclusive)
+ */
+ public void selectText(int start, int end)
+ {
+ textComp.select(start, end);
+ }
+
+ /**
+ * Sets the attributes of all the text between two indexes.
+ *
+ * @param start - the starting index (inclusive)
+ * @param end - the ending index (exclusive)
+ * @param s - the new attribute set for the text in the range
+ */
+ public void setAttributes(int start, int end, AttributeSet s)
+ throws NotImplementedException
+ {
+ // TODO
+ }
+ }
+
+ public static class KeyBinding
+ {
+ public KeyStroke key;
+ public String actionName;
+
+ /**
+ * Creates a new <code>KeyBinding</code> instance.
+ *
+ * @param key a <code>KeyStroke</code> value
+ * @param actionName a <code>String</code> value
+ */
+ public KeyBinding(KeyStroke key, String actionName)
+ {
+ this.key = key;
+ this.actionName = actionName;
+ }
+ }
+
+ /**
+ * According to <a
+ * href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html">this
+ * report</a>, a pair of private classes wraps a {@link
+ * javax.swing.text.Keymap} in the new {@link InputMap} / {@link
+ * ActionMap} interfaces, such that old Keymap-using code can make use of
+ * the new framework.
+ *
+ * <p>A little bit of experimentation with these classes reveals the following
+ * structure:
+ *
+ * <ul>
+ *
+ * <li>KeymapWrapper extends {@link InputMap} and holds a reference to
+ * the underlying {@link Keymap}.</li>
+ *
+ * <li>KeymapWrapper maps {@link KeyStroke} objects to {@link Action}
+ * objects, by delegation to the underlying {@link Keymap}.</li>
+ *
+ * <li>KeymapActionMap extends {@link ActionMap} also holds a reference to
+ * the underlying {@link Keymap} but only appears to use it for listing
+ * its keys. </li>
+ *
+ * <li>KeymapActionMap maps all {@link Action} objects to
+ * <em>themselves</em>, whether they exist in the underlying {@link
+ * Keymap} or not, and passes other objects to the parent {@link
+ * ActionMap} for resolving.
+ *
+ * </ul>
+ */
+
+ private class KeymapWrapper extends InputMap
+ {
+ Keymap map;
+
+ public KeymapWrapper(Keymap k)
+ {
+ map = k;
+ }
+
+ public int size()
+ {
+ return map.getBoundKeyStrokes().length + super.size();
+ }
+
+ public Object get(KeyStroke ks)
+ {
+ Action mapped = null;
+ Keymap m = map;
+ while(mapped == null && m != null)
+ {
+ mapped = m.getAction(ks);
+ if (mapped == null && ks.getKeyEventType() == KeyEvent.KEY_TYPED)
+ mapped = m.getDefaultAction();
+ if (mapped == null)
+ m = m.getResolveParent();
+ }
+
+ if (mapped == null)
+ return super.get(ks);
+ else
+ return mapped;
+ }
+
+ public KeyStroke[] keys()
+ {
+ KeyStroke[] superKeys = super.keys();
+ KeyStroke[] mapKeys = map.getBoundKeyStrokes();
+ KeyStroke[] bothKeys = new KeyStroke[superKeys.length + mapKeys.length];
+ for (int i = 0; i < superKeys.length; ++i)
+ bothKeys[i] = superKeys[i];
+ for (int i = 0; i < mapKeys.length; ++i)
+ bothKeys[i + superKeys.length] = mapKeys[i];
+ return bothKeys;
+ }
+
+ public KeyStroke[] allKeys()
+ {
+ KeyStroke[] superKeys = super.allKeys();
+ KeyStroke[] mapKeys = map.getBoundKeyStrokes();
+ int skl = 0;
+ int mkl = 0;
+ if (superKeys != null)
+ skl = superKeys.length;
+ if (mapKeys != null)
+ mkl = mapKeys.length;
+ KeyStroke[] bothKeys = new KeyStroke[skl + mkl];
+ for (int i = 0; i < skl; ++i)
+ bothKeys[i] = superKeys[i];
+ for (int i = 0; i < mkl; ++i)
+ bothKeys[i + skl] = mapKeys[i];
+ return bothKeys;
+ }
+ }
+
+ private class KeymapActionMap extends ActionMap
+ {
+ Keymap map;
+
+ public KeymapActionMap(Keymap k)
+ {
+ map = k;
+ }
+
+ public Action get(Object cmd)
+ {
+ if (cmd instanceof Action)
+ return (Action) cmd;
+ else
+ return super.get(cmd);
+ }
+
+ public int size()
+ {
+ return map.getBoundKeyStrokes().length + super.size();
+ }
+
+ public Object[] keys()
+ {
+ Object[] superKeys = super.keys();
+ Object[] mapKeys = map.getBoundKeyStrokes();
+ Object[] bothKeys = new Object[superKeys.length + mapKeys.length];
+ for (int i = 0; i < superKeys.length; ++i)
+ bothKeys[i] = superKeys[i];
+ for (int i = 0; i < mapKeys.length; ++i)
+ bothKeys[i + superKeys.length] = mapKeys[i];
+ return bothKeys;
+ }
+
+ public Object[] allKeys()
+ {
+ Object[] superKeys = super.allKeys();
+ Object[] mapKeys = map.getBoundKeyStrokes();
+ Object[] bothKeys = new Object[superKeys.length + mapKeys.length];
+ for (int i = 0; i < superKeys.length; ++i)
+ bothKeys[i] = superKeys[i];
+ for (int i = 0; i < mapKeys.length; ++i)
+ bothKeys[i + superKeys.length] = mapKeys[i];
+ return bothKeys;
+ }
+
+ }
+
+ static class DefaultKeymap implements Keymap
+ {
+ String name;
+ Keymap parent;
+ Hashtable map;
+ Action defaultAction;
+
+ public DefaultKeymap(String name)
+ {
+ this.name = name;
+ this.map = new Hashtable();
+ }
+
+ public void addActionForKeyStroke(KeyStroke key, Action a)
+ {
+ map.put(key, a);
+ }
+
+ /**
+ * Looks up a KeyStroke either in the current map or the parent Keymap;
+ * does <em>not</em> return the default action if lookup fails.
+ *
+ * @param key The KeyStroke to look up an Action for.
+ *
+ * @return The mapping for <code>key</code>, or <code>null</code>
+ * if no mapping exists in this Keymap or any of its parents.
+ */
+ public Action getAction(KeyStroke key)
+ {
+ if (map.containsKey(key))
+ return (Action) map.get(key);
+ else if (parent != null)
+ return parent.getAction(key);
+ else
+ return null;
+ }
+
+ public Action[] getBoundActions()
+ {
+ Action [] ret = new Action[map.size()];
+ Enumeration e = map.elements();
+ int i = 0;
+ while (e.hasMoreElements())
+ {
+ ret[i++] = (Action) e.nextElement();
+ }
+ return ret;
+ }
+
+ public KeyStroke[] getBoundKeyStrokes()
+ {
+ KeyStroke [] ret = new KeyStroke[map.size()];
+ Enumeration e = map.keys();
+ int i = 0;
+ while (e.hasMoreElements())
+ {
+ ret[i++] = (KeyStroke) e.nextElement();
+ }
+ return ret;
+ }
+
+ public Action getDefaultAction()
+ {
+ return defaultAction;
+ }
+
+ public KeyStroke[] getKeyStrokesForAction(Action a)
+ {
+ int i = 0;
+ Enumeration e = map.keys();
+ while (e.hasMoreElements())
+ {
+ if (map.get(e.nextElement()).equals(a))
+ ++i;
+ }
+ KeyStroke [] ret = new KeyStroke[i];
+ i = 0;
+ e = map.keys();
+ while (e.hasMoreElements())
+ {
+ KeyStroke k = (KeyStroke) e.nextElement();
+ if (map.get(k).equals(a))
+ ret[i++] = k;
+ }
+ return ret;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public Keymap getResolveParent()
+ {
+ return parent;
+ }
+
+ public boolean isLocallyDefined(KeyStroke key)
+ {
+ return map.containsKey(key);
+ }
+
+ public void removeBindings()
+ {
+ map.clear();
+ }
+
+ public void removeKeyStrokeBinding(KeyStroke key)
+ {
+ map.remove(key);
+ }
+
+ public void setDefaultAction(Action a)
+ {
+ defaultAction = a;
+ }
+
+ public void setResolveParent(Keymap p)
+ {
+ parent = p;
+ }
+ }
+
+ class DefaultTransferHandler extends TransferHandler
+ {
+ public boolean canImport(JComponent component, DataFlavor[] flavors)
+ {
+ JTextComponent textComponent = (JTextComponent) component;
+
+ if (! (textComponent.isEnabled()
+ && textComponent.isEditable()
+ && flavors != null))
+ return false;
+
+ for (int i = 0; i < flavors.length; ++i)
+ if (flavors[i].equals(DataFlavor.stringFlavor))
+ return true;
+
+ return false;
+ }
+
+ public void exportToClipboard(JComponent component, Clipboard clipboard,
+ int action)
+ {
+ JTextComponent textComponent = (JTextComponent) component;
+ int start = textComponent.getSelectionStart();
+ int end = textComponent.getSelectionEnd();
+
+ if (start == end)
+ return;
+
+ try
+ {
+ // Copy text to clipboard.
+ String data = textComponent.getDocument().getText(start, end);
+ StringSelection selection = new StringSelection(data);
+ clipboard.setContents(selection, null);
+
+ // Delete selected text on cut action.
+ if (action == MOVE)
+ doc.remove(start, end - start);
+ }
+ catch (BadLocationException e)
+ {
+ // Ignore this and do nothing.
+ }
+ }
+
+ public int getSourceActions()
+ {
+ return NONE;
+ }
+
+ public boolean importData(JComponent component, Transferable transferable)
+ {
+ DataFlavor flavor = null;
+ DataFlavor[] flavors = transferable.getTransferDataFlavors();
+
+ if (flavors == null)
+ return false;
+
+ for (int i = 0; i < flavors.length; ++i)
+ if (flavors[i].equals(DataFlavor.stringFlavor))
+ flavor = flavors[i];
+
+ if (flavor == null)
+ return false;
+
+ try
+ {
+ JTextComponent textComponent = (JTextComponent) component;
+ String data = (String) transferable.getTransferData(flavor);
+ textComponent.replaceSelection(data);
+ return true;
+ }
+ catch (IOException e)
+ {
+ // Ignored.
+ }
+ catch (UnsupportedFlavorException e)
+ {
+ // Ignored.
+ }
+
+ return false;
+ }
+ }
+
+ private static final long serialVersionUID = -8796518220218978795L;
+
+ public static final String DEFAULT_KEYMAP = "default";
+ public static final String FOCUS_ACCELERATOR_KEY = "focusAcceleratorKey";
+
+ private static DefaultTransferHandler defaultTransferHandler;
+ private static Hashtable keymaps = new Hashtable();
+ private Keymap keymap;
+ private char focusAccelerator = '\0';
+ private NavigationFilter navigationFilter;
+
+ /**
+ * Get a Keymap from the global keymap table, by name.
+ *
+ * @param n The name of the Keymap to look up
+ *
+ * @return A Keymap associated with the provided name, or
+ * <code>null</code> if no such Keymap exists
+ *
+ * @see #addKeymap
+ * @see #removeKeymap
+ * @see #keymaps
+ */
+ public static Keymap getKeymap(String n)
+ {
+ return (Keymap) keymaps.get(n);
+ }
+
+ /**
+ * Remove a Keymap from the global Keymap table, by name.
+ *
+ * @param n The name of the Keymap to remove
+ *
+ * @return The keymap removed from the global table
+ *
+ * @see #addKeymap
+ * @see #getKeymap()
+ * @see #keymaps
+ */
+ public static Keymap removeKeymap(String n)
+ {
+ Keymap km = (Keymap) keymaps.get(n);
+ keymaps.remove(n);
+ return km;
+ }
+
+ /**
+ * Create a new Keymap with a specific name and parent, and add the new
+ * Keymap to the global keymap table. The name may be <code>null</code>,
+ * in which case the new Keymap will <em>not</em> be added to the global
+ * Keymap table. The parent may also be <code>null</code>, which is
+ * harmless.
+ *
+ * @param n The name of the new Keymap, or <code>null</code>
+ * @param parent The parent of the new Keymap, or <code>null</code>
+ *
+ * @return The newly created Keymap
+ *
+ * @see #removeKeymap
+ * @see #getKeymap()
+ * @see #keymaps
+ */
+ public static Keymap addKeymap(String n, Keymap parent)
+ {
+ Keymap k = new DefaultKeymap(n);
+ k.setResolveParent(parent);
+ if (n != null)
+ keymaps.put(n, k);
+ return k;
+ }
+
+ /**
+ * Get the current Keymap of this component.
+ *
+ * @return The component's current Keymap
+ *
+ * @see #setKeymap
+ * @see #keymap
+ */
+ public Keymap getKeymap()
+ {
+ return keymap;
+ }
+
+ /**
+ * Set the current Keymap of this component, installing appropriate
+ * {@link KeymapWrapper} and {@link KeymapActionMap} objects in the
+ * {@link InputMap} and {@link ActionMap} parent chains, respectively,
+ * and fire a property change event with name <code>"keymap"</code>.
+ *
+ * @see #getKeymap()
+ * @see #keymap
+ */
+ public void setKeymap(Keymap k)
+ {
+
+ // phase 1: replace the KeymapWrapper entry in the InputMap chain.
+ // the goal here is to always maintain the following ordering:
+ //
+ // [InputMap]? -> [KeymapWrapper]? -> [InputMapUIResource]*
+ //
+ // that is to say, component-specific InputMaps need to remain children
+ // of Keymaps, and Keymaps need to remain children of UI-installed
+ // InputMaps (and the order of each group needs to be preserved, of
+ // course).
+
+ KeymapWrapper kw = (k == null ? null : new KeymapWrapper(k));
+ InputMap childInputMap = getInputMap(JComponent.WHEN_FOCUSED);
+ if (childInputMap == null)
+ setInputMap(JComponent.WHEN_FOCUSED, kw);
+ else
+ {
+ while (childInputMap.getParent() != null
+ && !(childInputMap.getParent() instanceof KeymapWrapper)
+ && !(childInputMap.getParent() instanceof InputMapUIResource))
+ childInputMap = childInputMap.getParent();
+
+ // option 1: there is nobody to replace at the end of the chain
+ if (childInputMap.getParent() == null)
+ childInputMap.setParent(kw);
+
+ // option 2: there is already a KeymapWrapper in the chain which
+ // needs replacing (possibly with its own parents, possibly without)
+ else if (childInputMap.getParent() instanceof KeymapWrapper)
+ {
+ if (kw == null)
+ childInputMap.setParent(childInputMap.getParent().getParent());
+ else
+ {
+ kw.setParent(childInputMap.getParent().getParent());
+ childInputMap.setParent(kw);
+ }
+ }
+
+ // option 3: there is an InputMapUIResource in the chain, which marks
+ // the place where we need to stop and insert ourselves
+ else if (childInputMap.getParent() instanceof InputMapUIResource)
+ {
+ if (kw != null)
+ {
+ kw.setParent(childInputMap.getParent());
+ childInputMap.setParent(kw);
+ }
+ }
+ }
+
+ // phase 2: replace the KeymapActionMap entry in the ActionMap chain
+
+ KeymapActionMap kam = (k == null ? null : new KeymapActionMap(k));
+ ActionMap childActionMap = getActionMap();
+ if (childActionMap == null)
+ setActionMap(kam);
+ else
+ {
+ while (childActionMap.getParent() != null
+ && !(childActionMap.getParent() instanceof KeymapActionMap)
+ && !(childActionMap.getParent() instanceof ActionMapUIResource))
+ childActionMap = childActionMap.getParent();
+
+ // option 1: there is nobody to replace at the end of the chain
+ if (childActionMap.getParent() == null)
+ childActionMap.setParent(kam);
+
+ // option 2: there is already a KeymapActionMap in the chain which
+ // needs replacing (possibly with its own parents, possibly without)
+ else if (childActionMap.getParent() instanceof KeymapActionMap)
+ {
+ if (kam == null)
+ childActionMap.setParent(childActionMap.getParent().getParent());
+ else
+ {
+ kam.setParent(childActionMap.getParent().getParent());
+ childActionMap.setParent(kam);
+ }
+ }
+
+ // option 3: there is an ActionMapUIResource in the chain, which marks
+ // the place where we need to stop and insert ourselves
+ else if (childActionMap.getParent() instanceof ActionMapUIResource)
+ {
+ if (kam != null)
+ {
+ kam.setParent(childActionMap.getParent());
+ childActionMap.setParent(kam);
+ }
+ }
+ }
+
+ // phase 3: update the explicit keymap field
+
+ Keymap old = keymap;
+ keymap = k;
+ firePropertyChange("keymap", old, k);
+ }
+
+ /**
+ * Resolves a set of bindings against a set of actions and inserts the
+ * results into a {@link Keymap}. Specifically, for each provided binding
+ * <code>b</code>, if there exists a provided action <code>a</code> such
+ * that <code>a.getValue(Action.NAME) == b.ActionName</code> then an
+ * entry is added to the Keymap mapping <code>b</code> to
+ * <code>a</code>.
+ *
+ * @param map The Keymap to add new mappings to
+ * @param bindings The set of bindings to add to the Keymap
+ * @param actions The set of actions to resolve binding names against
+ *
+ * @see Action#NAME
+ * @see Action#getValue
+ * @see KeyBinding#actionName
+ */
+ public static void loadKeymap(Keymap map,
+ JTextComponent.KeyBinding[] bindings,
+ Action[] actions)
+ {
+ Hashtable acts = new Hashtable(actions.length);
+ for (int i = 0; i < actions.length; ++i)
+ acts.put(actions[i].getValue(Action.NAME), actions[i]);
+ for (int i = 0; i < bindings.length; ++i)
+ if (acts.containsKey(bindings[i].actionName))
+ map.addActionForKeyStroke(bindings[i].key, (Action) acts.get(bindings[i].actionName));
+ }
+
+ /**
+ * Returns the set of available Actions this component's associated
+ * editor can run. Equivalent to calling
+ * <code>getUI().getEditorKit().getActions()</code>. This set of Actions
+ * is a reasonable value to provide as a parameter to {@link
+ * #loadKeymap}, when resolving a set of {@link KeyBinding} objects
+ * against this component.
+ *
+ * @return The set of available Actions on this component's {@link EditorKit}
+ *
+ * @see TextUI#getEditorKit
+ * @see EditorKit#getActions()
+ */
+ public Action[] getActions()
+ {
+ return getUI().getEditorKit(this).getActions();
+ }
+
+ // These are package-private to avoid an accessor method.
+ Document doc;
+ Caret caret;
+ boolean editable;
+
+ private Highlighter highlighter;
+ private Color caretColor;
+ private Color disabledTextColor;
+ private Color selectedTextColor;
+ private Color selectionColor;
+ private Insets margin;
+ private boolean dragEnabled;
+
+ /**
+ * Creates a new <code>JTextComponent</code> instance.
+ */
+ public JTextComponent()
+ {
+ Keymap defkeymap = getKeymap(DEFAULT_KEYMAP);
+ if (defkeymap == null)
+ {
+ defkeymap = addKeymap(DEFAULT_KEYMAP, null);
+ defkeymap.setDefaultAction(new DefaultEditorKit.DefaultKeyTypedAction());
+ }
+
+ setFocusable(true);
+ setEditable(true);
+ enableEvents(AWTEvent.KEY_EVENT_MASK);
+ setOpaque(true);
+ updateUI();
+ }
+
+ public void setDocument(Document newDoc)
+ {
+ Document oldDoc = doc;
+ try
+ {
+ if (oldDoc instanceof AbstractDocument)
+ ((AbstractDocument) oldDoc).readLock();
+
+ doc = newDoc;
+ firePropertyChange("document", oldDoc, newDoc);
+ }
+ finally
+ {
+ if (oldDoc instanceof AbstractDocument)
+ ((AbstractDocument) oldDoc).readUnlock();
+ }
+ revalidate();
+ repaint();
+ }
+
+ public Document getDocument()
+ {
+ return doc;
+ }
+
+ /**
+ * Get the <code>AccessibleContext</code> of this object.
+ *
+ * @return an <code>AccessibleContext</code> object
+ */
+ public AccessibleContext getAccessibleContext()
+ {
+ return new AccessibleJTextComponent();
+ }
+
+ public void setMargin(Insets m)
+ {
+ margin = m;
+ }
+
+ public Insets getMargin()
+ {
+ return margin;
+ }
+
+ public void setText(String text)
+ {
+ try
+ {
+ if (doc instanceof AbstractDocument)
+ ((AbstractDocument) doc).replace(0, doc.getLength(), text, null);
+ else
+ {
+ doc.remove(0, doc.getLength());
+ doc.insertString(0, text, null);
+ }
+ }
+ catch (BadLocationException e)
+ {
+ // This can never happen.
+ throw (InternalError) new InternalError().initCause(e);
+ }
+ }
+
+ /**
+ * Retrieves the current text in this text document.
+ *
+ * @return the text
+ *
+ * @exception NullPointerException if the underlaying document is null
+ */
+ public String getText()
+ {
+ if (doc == null)
+ return null;
+
+ try
+ {
+ return doc.getText(0, doc.getLength());
+ }
+ catch (BadLocationException e)
+ {
+ // This should never happen.
+ return "";
+ }
+ }
+
+ /**
+ * Retrieves a part of the current text in this document.
+ *
+ * @param offset the postion of the first character
+ * @param length the length of the text to retrieve
+ *
+ * @return the text
+ *
+ * @exception BadLocationException if arguments do not hold pre-conditions
+ */
+ public String getText(int offset, int length)
+ throws BadLocationException
+ {
+ return getDocument().getText(offset, length);
+ }
+
+ /**
+ * Retrieves the currently selected text in this text document.
+ *
+ * @return the selected text
+ *
+ * @exception NullPointerException if the underlaying document is null
+ */
+ public String getSelectedText()
+ {
+ int start = getSelectionStart();
+ int offset = getSelectionEnd() - start;
+
+ if (offset <= 0)
+ return null;
+
+ try
+ {
+ return doc.getText(start, offset);
+ }
+ catch (BadLocationException e)
+ {
+ // This should never happen.
+ return null;
+ }
+ }
+
+ /**
+ * Returns a string that specifies the name of the Look and Feel class
+ * that renders this component.
+ *
+ * @return the string "TextComponentUI"
+ */
+ public String getUIClassID()
+ {
+ return "TextComponentUI";
+ }
+
+ /**
+ * Returns a string representation of this JTextComponent.
+ */
+ protected String paramString()
+ {
+ // TODO: Do something useful here.
+ return super.paramString();
+ }
+
+ /**
+ * This method returns the label's UI delegate.
+ *
+ * @return The label's UI delegate.
+ */
+ public TextUI getUI()
+ {
+ return (TextUI) ui;
+ }
+
+ /**
+ * This method sets the label's UI delegate.
+ *
+ * @param newUI The label's UI delegate.
+ */
+ public void setUI(TextUI newUI)
+ {
+ super.setUI(newUI);
+ }
+
+ /**
+ * This method resets the label's UI delegate to the default UI for the
+ * current look and feel.
+ */
+ public void updateUI()
+ {
+ setUI((TextUI) UIManager.getUI(this));
+ }
+
+ public Dimension getPreferredScrollableViewportSize()
+ {
+ return getPreferredSize();
+ }
+
+ public int getScrollableUnitIncrement(Rectangle visible, int orientation,
+ int direction)
+ {
+ // We return 1/10 of the visible area as documented in Sun's API docs.
+ if (orientation == SwingConstants.HORIZONTAL)
+ return visible.width / 10;
+ else if (orientation == SwingConstants.VERTICAL)
+ return visible.height / 10;
+ else
+ throw new IllegalArgumentException("orientation must be either "
+ + "javax.swing.SwingConstants.VERTICAL "
+ + "or "
+ + "javax.swing.SwingConstants.HORIZONTAL"
+ );
+ }
+
+ public int getScrollableBlockIncrement(Rectangle visible, int orientation,
+ int direction)
+ {
+ // We return the whole visible area as documented in Sun's API docs.
+ if (orientation == SwingConstants.HORIZONTAL)
+ return visible.width;
+ else if (orientation == SwingConstants.VERTICAL)
+ return visible.height;
+ else
+ throw new IllegalArgumentException("orientation must be either "
+ + "javax.swing.SwingConstants.VERTICAL "
+ + "or "
+ + "javax.swing.SwingConstants.HORIZONTAL"
+ );
+ }
+
+ /**
+ * Checks whether this text component it editable.
+ *
+ * @return true if editable, false otherwise
+ */
+ public boolean isEditable()
+ {
+ return editable;
+ }
+
+ /**
+ * Enables/disabled this text component's editability.
+ *
+ * @param newValue true to make it editable, false otherwise.
+ */
+ public void setEditable(boolean newValue)
+ {
+ if (editable == newValue)
+ return;
+
+ boolean oldValue = editable;
+ editable = newValue;
+ firePropertyChange("editable", oldValue, newValue);
+ }
+
+ /**
+ * The <code>Caret</code> object used in this text component.
+ *
+ * @return the caret object
+ */
+ public Caret getCaret()
+ {
+ return caret;
+ }
+
+ /**
+ * Sets a new <code>Caret</code> for this text component.
+ *
+ * @param newCaret the new <code>Caret</code> to set
+ */
+ public void setCaret(Caret newCaret)
+ {
+ if (caret != null)
+ caret.deinstall(this);
+
+ Caret oldCaret = caret;
+ caret = newCaret;
+
+ if (caret != null)
+ caret.install(this);
+
+ firePropertyChange("caret", oldCaret, newCaret);
+ }
+
+ public Color getCaretColor()
+ {
+ return caretColor;
+ }
+
+ public void setCaretColor(Color newColor)
+ {
+ Color oldCaretColor = caretColor;
+ caretColor = newColor;
+ firePropertyChange("caretColor", oldCaretColor, newColor);
+ }
+
+ public Color getDisabledTextColor()
+ {
+ return disabledTextColor;
+ }
+
+ public void setDisabledTextColor(Color newColor)
+ {
+ Color oldColor = disabledTextColor;
+ disabledTextColor = newColor;
+ firePropertyChange("disabledTextColor", oldColor, newColor);
+ }
+
+ public Color getSelectedTextColor()
+ {
+ return selectedTextColor;
+ }
+
+ public void setSelectedTextColor(Color newColor)
+ {
+ Color oldColor = selectedTextColor;
+ selectedTextColor = newColor;
+ firePropertyChange("selectedTextColor", oldColor, newColor);
+ }
+
+ public Color getSelectionColor()
+ {
+ return selectionColor;
+ }
+
+ public void setSelectionColor(Color newColor)
+ {
+ Color oldColor = selectionColor;
+ selectionColor = newColor;
+ firePropertyChange("selectionColor", oldColor, newColor);
+ }
+
+ /**
+ * Retrisves the current caret position.
+ *
+ * @return the current position
+ */
+ public int getCaretPosition()
+ {
+ return caret.getDot();
+ }
+
+ /**
+ * Sets the caret to a new position.
+ *
+ * @param position the new position
+ */
+ public void setCaretPosition(int position)
+ {
+ if (doc == null)
+ return;
+
+ if (position < 0 || position > doc.getLength())
+ throw new IllegalArgumentException();
+
+ caret.setDot(position);
+ }
+
+ /**
+ * Moves the caret to a given position. This selects the text between
+ * the old and the new position of the caret.
+ */
+ public void moveCaretPosition(int position)
+ {
+ if (doc == null)
+ return;
+
+ if (position < 0 || position > doc.getLength())
+ throw new IllegalArgumentException();
+
+ caret.moveDot(position);
+ }
+
+ public Highlighter getHighlighter()
+ {
+ return highlighter;
+ }
+
+ public void setHighlighter(Highlighter newHighlighter)
+ {
+ if (highlighter != null)
+ highlighter.deinstall(this);
+
+ Highlighter oldHighlighter = highlighter;
+ highlighter = newHighlighter;
+
+ if (highlighter != null)
+ highlighter.install(this);
+
+ firePropertyChange("highlighter", oldHighlighter, newHighlighter);
+ }
+
+ /**
+ * Returns the start postion of the currently selected text.
+ *
+ * @return the start postion
+ */
+ public int getSelectionStart()
+ {
+ return Math.min(caret.getDot(), caret.getMark());
+ }
+
+ /**
+ * Selects the text from the given postion to the selection end position.
+ *
+ * @param start the start positon of the selected text.
+ */
+ public void setSelectionStart(int start)
+ {
+ select(start, getSelectionEnd());
+ }
+
+ /**
+ * Returns the end postion of the currently selected text.
+ *
+ * @return the end postion
+ */
+ public int getSelectionEnd()
+ {
+ return Math.max(caret.getDot(), caret.getMark());
+ }
+
+ /**
+ * Selects the text from the selection start postion to the given position.
+ *
+ * @param end the end positon of the selected text.
+ */
+ public void setSelectionEnd(int end)
+ {
+ select(getSelectionStart(), end);
+ }
+
+ /**
+ * Selects a part of the content of the text component.
+ *
+ * @param start the start position of the selected text
+ * @param end the end position of the selected text
+ */
+ public void select(int start, int end)
+ {
+ int length = doc.getLength();
+
+ start = Math.max(start, 0);
+ start = Math.min(start, length);
+
+ end = Math.max(end, start);
+ end = Math.min(end, length);
+
+ setCaretPosition(start);
+ moveCaretPosition(end);
+ }
+
+ /**
+ * Selects the whole content of the text component.
+ */
+ public void selectAll()
+ {
+ select(0, doc.getLength());
+ }
+
+ public synchronized void replaceSelection(String content)
+ {
+ int dot = caret.getDot();
+ int mark = caret.getMark();
+
+ // If content is empty delete selection.
+ if (content == null)
+ {
+ caret.setDot(dot);
+ return;
+ }
+
+ try
+ {
+ int start = getSelectionStart();
+ int end = getSelectionEnd();
+
+ // Remove selected text.
+ if (dot != mark)
+ doc.remove(start, end - start);
+
+ // Insert new text.
+ doc.insertString(start, content, null);
+
+ // Set dot to new position,
+ dot = start + content.length();
+ setCaretPosition(dot);
+
+ // and update it's magic position.
+ caret.setMagicCaretPosition(modelToView(dot).getLocation());
+ }
+ catch (BadLocationException e)
+ {
+ // This should never happen.
+ }
+ }
+
+ public boolean getScrollableTracksViewportHeight()
+ {
+ if (getParent() instanceof JViewport)
+ return getParent().getHeight() > getPreferredSize().height;
+
+ return false;
+ }
+
+ public boolean getScrollableTracksViewportWidth()
+ {
+ boolean res = false;;
+ Container c = getParent();
+ if (c instanceof JViewport)
+ res = ((JViewport) c).getExtentSize().width > getPreferredSize().width;
+
+ return res;
+ }
+
+ /**
+ * Adds a <code>CaretListener</code> object to this text component.
+ *
+ * @param listener the listener to add
+ */
+ public void addCaretListener(CaretListener listener)
+ {
+ listenerList.add(CaretListener.class, listener);
+ }
+
+ /**
+ * Removed a <code>CaretListener</code> object from this text component.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeCaretListener(CaretListener listener)
+ {
+ listenerList.remove(CaretListener.class, listener);
+ }
+
+ /**
+ * Returns all added <code>CaretListener</code> objects.
+ *
+ * @return an array of listeners
+ */
+ public CaretListener[] getCaretListeners()
+ {
+ return (CaretListener[]) getListeners(CaretListener.class);
+ }
+
+ /**
+ * Notifies all registered <code>CaretListener</code> objects that the caret
+ * was updated.
+ *
+ * @param event the event to send
+ */
+ protected void fireCaretUpdate(CaretEvent event)
+ {
+ CaretListener[] listeners = getCaretListeners();
+
+ for (int index = 0; index < listeners.length; ++index)
+ listeners[index].caretUpdate(event);
+ }
+
+ /**
+ * Adds an <code>InputListener</code> object to this text component.
+ *
+ * @param listener the listener to add
+ */
+ public void addInputMethodListener(InputMethodListener listener)
+ {
+ listenerList.add(InputMethodListener.class, listener);
+ }
+
+ /**
+ * Removes an <code>InputListener</code> object from this text component.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeInputMethodListener(InputMethodListener listener)
+ {
+ listenerList.remove(InputMethodListener.class, listener);
+ }
+
+ /**
+ * Returns all added <code>InputMethodListener</code> objects.
+ *
+ * @return an array of listeners
+ */
+ public InputMethodListener[] getInputMethodListeners()
+ {
+ return (InputMethodListener[]) getListeners(InputMethodListener.class);
+ }
+
+ public Rectangle modelToView(int position) throws BadLocationException
+ {
+ return getUI().modelToView(this, position);
+ }
+
+ public boolean getDragEnabled()
+ {
+ return dragEnabled;
+ }
+
+ public void setDragEnabled(boolean enabled)
+ {
+ dragEnabled = enabled;
+ }
+
+ public int viewToModel(Point pt)
+ {
+ return getUI().viewToModel(this, pt);
+ }
+
+ public void copy()
+ {
+ if (isEnabled())
+ doTransferAction("copy", TransferHandler.getCopyAction());
+ }
+
+ public void cut()
+ {
+ if (editable && isEnabled())
+ doTransferAction("cut", TransferHandler.getCutAction());
+ }
+
+ public void paste()
+ {
+ if (editable && isEnabled())
+ doTransferAction("paste", TransferHandler.getPasteAction());
+ }
+
+ private void doTransferAction(String name, Action action)
+ {
+ // Install default TransferHandler if none set.
+ if (getTransferHandler() == null)
+ {
+ if (defaultTransferHandler == null)
+ defaultTransferHandler = new DefaultTransferHandler();
+
+ setTransferHandler(defaultTransferHandler);
+ }
+
+ // Perform action.
+ ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
+ action.getValue(Action.NAME).toString());
+ action.actionPerformed(event);
+ }
+
+ public void setFocusAccelerator(char newKey)
+ {
+ if (focusAccelerator == newKey)
+ return;
+
+ char oldKey = focusAccelerator;
+ focusAccelerator = newKey;
+ firePropertyChange(FOCUS_ACCELERATOR_KEY, oldKey, newKey);
+ }
+
+ public char getFocusAccelerator()
+ {
+ return focusAccelerator;
+ }
+
+ /**
+ * @since 1.4
+ */
+ public NavigationFilter getNavigationFilter()
+ {
+ return navigationFilter;
+ }
+
+ /**
+ * @since 1.4
+ */
+ public void setNavigationFilter(NavigationFilter filter)
+ {
+ navigationFilter = filter;
+ }
+
+ /**
+ * Read and set the content this component. If not overridden, the
+ * method reads the component content as a plain text.
+ *
+ * The second parameter of this method describes the input stream. It can
+ * be String, URL, File and so on. If not null, this object is added to
+ * the properties of the associated document under the key
+ * {@link Document#StreamDescriptionProperty}.
+ *
+ * @param input an input stream to read from.
+ * @param streamDescription an object, describing the stream.
+ *
+ * @throws IOException if the reader throws it.
+ *
+ * @see #getDocument()
+ * @see Document#getProperty(Object)
+ */
+ public void read(Reader input, Object streamDescription)
+ throws IOException
+ {
+ if (streamDescription != null)
+ {
+ Document d = getDocument();
+ if (d != null)
+ d.putProperty(Document.StreamDescriptionProperty, streamDescription);
+ }
+
+ StringBuffer b = new StringBuffer();
+ int c;
+
+ // Read till -1 (EOF).
+ while ((c = input.read()) >= 0)
+ b.append((char) c);
+
+ setText(b.toString());
+ }
+
+ /**
+ * Write the content of this component to the given stream. If not
+ * overridden, the method writes the component content as a plain text.
+ *
+ * @param output the writer to write into.
+ *
+ * @throws IOException if the writer throws it.
+ */
+ public void write(Writer output)
+ throws IOException
+ {
+ output.write(getText());
+ }
+
+ /**
+ * Returns the tooltip text for this text component for the given mouse
+ * event. This forwards the call to
+ * {@link TextUI#getToolTipText(JTextComponent, Point)}.
+ *
+ * @param ev the mouse event
+ *
+ * @return the tooltip text for this text component for the given mouse
+ * event
+ */
+ public String getToolTipText(MouseEvent ev)
+ {
+ return getUI().getToolTipText(this, ev.getPoint());
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Keymap.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Keymap.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Keymap.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Keymap.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,60 @@
+/* Keymap.java --
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import javax.swing.Action;
+import javax.swing.KeyStroke;
+
+public interface Keymap
+{
+ void addActionForKeyStroke(KeyStroke key, Action a);
+ Action getAction(KeyStroke key);
+ Action[] getBoundActions();
+ KeyStroke[] getBoundKeyStrokes();
+ Action getDefaultAction();
+ KeyStroke[] getKeyStrokesForAction(Action a);
+ String getName();
+ Keymap getResolveParent();
+ boolean isLocallyDefined(KeyStroke key);
+ void removeBindings();
+ void removeKeyStrokeBinding(KeyStroke keys);
+ void setDefaultAction(Action a);
+ void setResolveParent(Keymap parent);
+}
+
+
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LabelView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LabelView.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LabelView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LabelView.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,294 @@
+/* LabelView.java -- A view to render styled text
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Shape;
+
+import javax.swing.event.DocumentEvent;
+
+/**
+ * A {@link GlyphView} that caches the textattributes for most effective
+ * rendering.
+ *
+ * @author Roman Kennke (kennke at aicas.com)
+ */
+public class LabelView extends GlyphView
+{
+
+ /**
+ * The background color.
+ */
+ Color background;
+
+ /**
+ * The foreground color.
+ */
+ Color foreground;
+
+ /**
+ * The background color.
+ */
+ Font font;
+
+ /**
+ * The strikethrough flag.
+ */
+ boolean strikeThrough;
+
+ /**
+ * The underline flag.
+ */
+ boolean underline;
+
+ /**
+ * The subscript flag.
+ */
+ boolean subscript;
+
+ /**
+ * The superscript flag.
+ */
+ boolean superscript;
+
+ /**
+ * Creates a new <code>GlyphView</code> for the given <code>Element</code>.
+ *
+ * @param element the element that is rendered by this GlyphView
+ */
+ public LabelView(Element element)
+ {
+ super(element);
+ setPropertiesFromAttributes();
+ }
+
+ /**
+ * Loads the properties of this label view from the element's text
+ * attributes. This method is called from the constructor and the
+ * {@link #changedUpdate} method
+ */
+ protected void setPropertiesFromAttributes()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ // We cannot use StyleConstants.getBackground() here, because that returns
+ // BLACK as default (when background == null). What we need is the
+ // background setting of the text component instead, which is what we get
+ // when background == null anyway.
+ background = (Color) atts.getAttribute(StyleConstants.Background);
+ foreground = StyleConstants.getForeground(atts);
+ strikeThrough = StyleConstants.isStrikeThrough(atts);
+ subscript = StyleConstants.isSubscript(atts);
+ superscript = StyleConstants.isSuperscript(atts);
+ underline = StyleConstants.isUnderline(atts);
+
+ // Determine the font.
+ String family = StyleConstants.getFontFamily(atts);
+ int size = StyleConstants.getFontSize(atts);
+ int style = Font.PLAIN;
+ if (StyleConstants.isBold(atts))
+ style |= Font.BOLD;
+ if (StyleConstants.isItalic(atts))
+ style |= Font.ITALIC;
+ font = new Font(family, style, size);
+ }
+
+ /**
+ * Receives notification when text attributes change in the chunk of
+ * text that this view is responsible for. This simply calls
+ * {@link #setPropertiesFromAttributes()}.
+ *
+ * @param e the document event
+ * @param a the allocation of this view
+ * @param vf the view factory to use for creating new views
+ */
+ public void changedUpdate(DocumentEvent e, Shape a, ViewFactory vf)
+ {
+ setPropertiesFromAttributes();
+ }
+
+ /**
+ * Returns the background color for the glyphs.
+ *
+ * @return the background color for the glyphs
+ */
+ public Color getBackground()
+ {
+ return background;
+ }
+
+ /**
+ * Sets the background color for the glyphs. A value of <code>null</code>
+ * means the background of the parent view should shine through.
+ *
+ * @param bg the background to set or <code>null</code>
+ *
+ * @since 1.5
+ */
+ protected void setBackground(Color bg)
+ {
+ background = bg;
+ }
+
+ /**
+ * Returns the foreground color for the glyphs.
+ *
+ * @return the foreground color for the glyphs
+ */
+ public Color getForeground()
+ {
+ return foreground;
+ }
+
+ /**
+ * Returns the font for the glyphs.
+ *
+ * @return the font for the glyphs
+ */
+ public Font getFont()
+ {
+ return font;
+ }
+
+ /**
+ * Returns the font metrics of the current font.
+ *
+ * @return the font metrics of the current font
+ *
+ * @deprecated this is not used anymore
+ */
+ protected FontMetrics getFontMetrics()
+ {
+ return getContainer().getGraphics().getFontMetrics(font);
+ }
+
+ /**
+ * Returns <code>true</code> if the glyphs are rendered underlined,
+ * <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if the glyphs are rendered underlined,
+ * <code>false</code> otherwise
+ */
+ public boolean isUnderline()
+ {
+ return underline;
+ }
+
+ /**
+ * Sets the underline flag.
+ *
+ * @param flag <code>true</code> if the glyphs are rendered underlined,
+ * <code>false</code> otherwise
+ */
+ protected void setUnderline(boolean flag)
+ {
+ underline = flag;
+ }
+
+ /**
+ * Returns <code>true</code> if the glyphs are rendered as subscript,
+ * <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if the glyphs are rendered as subscript,
+ * <code>false</code> otherwise
+ */
+ public boolean isSubscript()
+ {
+ return subscript;
+ }
+
+ /**
+ * Sets the subscript flag.
+ *
+ * @param flag <code>true</code> if the glyphs are rendered as subscript,
+ * <code>false</code> otherwise
+ */
+ protected void setSubscript(boolean flag)
+ {
+ subscript = flag;
+ }
+
+ /**
+ * Returns <code>true</code> if the glyphs are rendered as superscript,
+ * <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if the glyphs are rendered as superscript,
+ * <code>false</code> otherwise
+ */
+ public boolean isSuperscript()
+ {
+ return superscript;
+ }
+
+ /**
+ * Sets the superscript flag.
+ *
+ * @param flag <code>true</code> if the glyphs are rendered as superscript,
+ * <code>false</code> otherwise
+ */
+ protected void setSuperscript(boolean flag)
+ {
+ superscript = flag;
+ }
+
+ /**
+ * Returns <code>true</code> if the glyphs are rendered strike-through,
+ * <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if the glyphs are rendered strike-through,
+ * <code>false</code> otherwise
+ */
+ public boolean isStrikeThrough()
+ {
+ return strikeThrough;
+ }
+
+ /**
+ * Sets the strike-through flag.
+ *
+ * @param flag <code>true</code> if the glyphs are rendered strike-through,
+ * <code>false</code> otherwise
+ */
+ protected void setStrikeThrough(boolean flag)
+ {
+ strikeThrough = flag;
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LayeredHighlighter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LayeredHighlighter.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LayeredHighlighter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LayeredHighlighter.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,57 @@
+/* LayeredHighlighter.java --
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.awt.Graphics;
+import java.awt.Shape;
+
+public abstract class LayeredHighlighter
+ implements Highlighter
+{
+ public abstract static class LayerPainter
+ implements Highlighter.HighlightPainter
+ {
+ public abstract Shape paintLayer(Graphics g, int p0, int p1,
+ Shape viewBounds, JTextComponent editor,
+ View view);
+ }
+
+ public abstract void paintLayeredHighlights(Graphics g, int p0, int p1,
+ Shape viewBounds,
+ JTextComponent editor, View view);
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LayoutQueue.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LayoutQueue.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LayoutQueue.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/LayoutQueue.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,116 @@
+/* LayoutQueue.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.util.LinkedList;
+
+/**
+ * This is a queue which holds {@link Runnable} objects. It is
+ * intended for deferring layout operations.
+ */
+public class LayoutQueue
+{
+ // The default layout queue.
+ private static LayoutQueue defaultQueue = new LayoutQueue();
+
+ // The queue of tasks.
+ private LinkedList list = new LinkedList();
+
+ /**
+ * Create a new layout queue.
+ */
+ public LayoutQueue()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Add a layout task to the queue.
+ */
+ public void addTask(Runnable task)
+ {
+ synchronized (list)
+ {
+ list.addLast(task);
+ list.notify();
+ }
+ }
+
+ /**
+ * Called by a worker thread to retrieve the next layout task. This
+ * will block until a new task is available. This method will
+ * return null if the thread is interrupted while waiting.
+ */
+ protected Runnable waitForWork()
+ {
+ synchronized (list)
+ {
+ while (list.size() == 0)
+ {
+ try
+ {
+ list.wait();
+ }
+ catch (InterruptedException _)
+ {
+ // This seemed like a good idea, but it has not been
+ // tested on the JDK.
+ return null;
+ }
+ }
+ return (Runnable) list.removeFirst();
+ }
+ }
+
+ /**
+ * Return the default layout queue.
+ */
+ public static synchronized LayoutQueue getDefaultQueue()
+ {
+ return defaultQueue;
+ }
+
+ /**
+ * Set the default layout queue.
+ */
+ public static synchronized void setDefaultQueue(LayoutQueue q)
+ {
+ defaultQueue = q;
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/MaskFormatter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/MaskFormatter.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/MaskFormatter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/MaskFormatter.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,583 @@
+/* MaskFormatter.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.text.ParseException;
+
+import javax.swing.JFormattedTextField;
+
+/**
+ * @author Anthony Balkissoon abalkiss at redhat dot com
+ *
+ */
+public class MaskFormatter extends DefaultFormatter
+{
+ // The declaration of the valid mask characters
+ private static final char NUM_CHAR = '#';
+ private static final char ESCAPE_CHAR = '\'';
+ private static final char UPPERCASE_CHAR = 'U';
+ private static final char LOWERCASE_CHAR = 'L';
+ private static final char ALPHANUM_CHAR = 'A';
+ private static final char LETTER_CHAR = '?';
+ private static final char ANYTHING_CHAR = '*';
+ private static final char HEX_CHAR = 'H';
+
+ /** The mask for this MaskFormatter **/
+ private String mask;
+
+ /**
+ * A String made up of the characters that are not valid for input for
+ * this MaskFormatter.
+ */
+ private String invalidChars;
+
+ /**
+ * A String made up of the characters that are valid for input for
+ * this MaskFormatter.
+ */
+ private String validChars;
+
+ /** A String used in place of missing chracters if the value does not
+ * completely fill in the spaces in the mask.
+ */
+ private String placeHolder;
+
+ /** A character used in place of missing characters if the value does
+ * not completely fill in the spaces in the mask.
+ */
+ private char placeHolderChar = ' ';
+
+ /**
+ * Whether or not stringToValue should return literal characters in the mask.
+ */
+ private boolean valueContainsLiteralCharacters = true;
+
+ /** A String used for easy access to valid HEX characters **/
+ private static String hexString = "0123456789abcdefABCDEF";
+
+ /** An int to hold the length of the mask, accounting for escaped characters **/
+ int maskLength = 0;
+
+ public MaskFormatter ()
+ {
+ // Override super's default behaviour, in MaskFormatter the default
+ // is not to allow invalid values
+ setAllowsInvalid(false);
+ }
+
+ /**
+ * Creates a MaskFormatter with the specified mask.
+ * @specnote doesn't actually throw a ParseException although it
+ * is declared to do so
+ * @param mask
+ * @throws java.text.ParseException
+ */
+ public MaskFormatter (String mask) throws java.text.ParseException
+ {
+ // Override super's default behaviour, in MaskFormatter the default
+ // is not to allow invalid values
+ setAllowsInvalid(false);
+ setMask (mask);
+ }
+
+ /**
+ * Returns the mask used in this MaskFormatter.
+ * @return the mask used in this MaskFormatter.
+ */
+ public String getMask()
+ {
+ return mask;
+ }
+
+ /**
+ * Returns a String containing the characters that are not valid for input
+ * for this MaskFormatter.
+ * @return a String containing the invalid characters.
+ */
+ public String getInvalidCharacters()
+ {
+ return invalidChars;
+ }
+
+ /**
+ * Sets characters that are not valid for input. If
+ * <code>invalidCharacters</code> is non-null then no characters contained
+ * in it will be allowed to be input.
+ *
+ * @param invalidCharacters the String specifying invalid characters.
+ */
+ public void setInvalidCharacters (String invalidCharacters)
+ {
+ this.invalidChars = invalidCharacters;
+ }
+
+ /**
+ * Returns a String containing the characters that are valid for input
+ * for this MaskFormatter.
+ * @return a String containing the valid characters.
+ */
+ public String getValidCharacters()
+ {
+ return validChars;
+ }
+
+ /**
+ * Sets characters that are valid for input. If
+ * <code>validCharacters</code> is non-null then no characters that are
+ * not contained in it will be allowed to be input.
+ *
+ * @param validCharacters the String specifying valid characters.
+ */
+ public void setValidCharacters (String validCharacters)
+ {
+ this.validChars = validCharacters;
+ }
+
+ /**
+ * Returns the place holder String that is used in place of missing
+ * characters when the value doesn't completely fill in the spaces
+ * in the mask.
+ * @return the place holder String.
+ */
+ public String getPlaceholder()
+ {
+ return placeHolder;
+ }
+
+ /**
+ * Sets the string to use if the value does not completely fill in the mask.
+ * If this is null, the place holder character will be used instead.
+ * @param placeholder the String to use if the value doesn't completely
+ * fill in the mask.
+ */
+ public void setPlaceholder (String placeholder)
+ {
+ this.placeHolder = placeholder;
+ }
+
+ /**
+ * Returns the character used in place of missing characters when the
+ * value doesn't completely fill the mask.
+ * @return the place holder character
+ */
+ public char getPlaceholderCharacter()
+ {
+ return placeHolderChar;
+ }
+
+ /**
+ * Sets the char to use if the value does not completely fill in the mask.
+ * This is only used if the place holder String has not been set or does
+ * not completely fill in the mask.
+ * @param placeholder the char to use if the value doesn't completely
+ * fill in the mask.
+ */
+ public void setPlaceholderCharacter (char placeholder)
+ {
+ this.placeHolderChar = placeholder;
+ }
+
+ /**
+ * Returns true if stringToValue should return the literal
+ * characters in the mask.
+ * @return true if stringToValue should return the literal
+ * characters in the mask
+ */
+ public boolean getValueContainsLiteralCharacters()
+ {
+ return valueContainsLiteralCharacters;
+ }
+
+ /**
+ * Determines whether stringToValue will return literal characters or not.
+ * @param containsLiteralChars if true, stringToValue will return the
+ * literal characters in the mask, otherwise it will not.
+ */
+ public void setValueContainsLiteralCharacters (boolean containsLiteralChars)
+ {
+ this.valueContainsLiteralCharacters = containsLiteralChars;
+ }
+
+ /**
+ * Sets the mask for this MaskFormatter.
+ * @specnote doesn't actually throw a ParseException even though it is
+ * declared to do so
+ * @param mask the new mask for this MaskFormatter
+ * @throws ParseException if <code>mask</code> is not valid.
+ */
+ public void setMask (String mask) throws ParseException
+ {
+ this.mask = mask;
+
+ // Update the cached maskLength.
+ int end = mask.length() - 1;
+ maskLength = 0;
+ for (int i = 0; i <= end; i++)
+ {
+ // Handle escape characters properly - they don't add to the maskLength
+ // but 2 escape characters in a row is really one escape character and
+ // one literal single quote, so that does add 1 to the maskLength.
+ if (mask.charAt(i) == '\'')
+ {
+ // Escape characters at the end of the mask don't do anything.
+ if (i != end)
+ maskLength++;
+ i++;
+ }
+ else
+ maskLength++;
+ }
+ }
+
+ /**
+ * Installs this MaskFormatter on the JFormattedTextField.
+ * Invokes valueToString to convert the current value from the
+ * JFormattedTextField to a String, then installs the Actions from
+ * getActions, the DocumentFilter from getDocumentFilter, and the
+ * NavigationFilter from getNavigationFilter.
+ *
+ * If valueToString throws a ParseException, this method sets the text
+ * to an empty String and marks the JFormattedTextField as invalid.
+ */
+ public void install (JFormattedTextField ftf)
+ {
+ super.install(ftf);
+ if (ftf != null)
+ {
+ try
+ {
+ valueToString(ftf.getValue());
+ }
+ catch (ParseException pe)
+ {
+ // Set the text to an empty String and mark the JFormattedTextField
+ // as invalid.
+ ftf.setText("");
+ setEditValid(false);
+ }
+ }
+ }
+
+ /**
+ * Parses the text using the mask, valid characters, and invalid characters
+ * to determine the appropriate Object to return. This strips the literal
+ * characters if necessary and invokes super.stringToValue. If the paramter
+ * is invalid for the current mask and valid/invalid character sets this
+ * method will throw a ParseException.
+ *
+ * @param value the String to parse
+ * @throws ParseException if value doesn't match the mask and valid/invalid
+ * character sets
+ */
+ public Object stringToValue (String value) throws ParseException
+ {
+ int vLength = value.length();
+
+ // For value to be a valid it must be the same length as the mask
+ // note this doesn't take into account symbols that occupy more than
+ // one character, this is something we may possibly need to fix.
+ if (maskLength != vLength)
+ throw new ParseException ("stringToValue passed invalid value", vLength);
+
+ // Check if the value is valid according to the mask and valid/invalid
+ // sets.
+ try
+ {
+ convertValue(value, false);
+ }
+ catch (ParseException pe)
+ {
+ throw new ParseException("stringToValue passed invalid value",
+ pe.getErrorOffset());
+ }
+
+ if (!getValueContainsLiteralCharacters())
+ value = stripLiterals(value);
+ return super.stringToValue(value);
+ }
+
+ /**
+ * Strips the literal characters from the given String.
+ * @param value the String to strip
+ * @return the stripped String
+ */
+ String stripLiterals(String value)
+ {
+ StringBuffer result = new StringBuffer();
+ for (int i = 0; i < value.length(); i++)
+ {
+ // Only append the characters that don't correspond to literal
+ // characters in the mask.
+ switch (mask.charAt(i))
+ {
+ case NUM_CHAR:
+ case UPPERCASE_CHAR:
+ case LOWERCASE_CHAR:
+ case ALPHANUM_CHAR:
+ case LETTER_CHAR:
+ case HEX_CHAR:
+ case ANYTHING_CHAR:
+ result.append(value.charAt(i));
+ break;
+ default:
+ }
+ }
+ return result.toString();
+ }
+
+ /**
+ * Returns a String representation of the Object value based on the mask.
+ *
+ * @param value the value to convert
+ * @throws ParseException if value is invalid for this mask and valid/invalid
+ * character sets
+ */
+ public String valueToString (Object value) throws ParseException
+ {
+ String result = super.valueToString(value);
+ int rLength = result.length();
+
+ // If value is longer than the mask, truncate it. Note we may need to
+ // account for symbols that are more than one character long.
+ if (rLength > maskLength)
+ result = result.substring(0, maskLength);
+
+ // Verify the validity and convert to upper/lowercase as needed.
+ result = convertValue(result, true);
+ if (rLength < maskLength)
+ return pad(result, rLength);
+ return result;
+ }
+
+ /**
+ * This method takes in a String and runs it through the mask to make
+ * sure that it is valid. If <code>convert</code> is true, it also
+ * converts letters to upper/lowercase as required by the mask.
+ * @param value the String to convert
+ * @param convert true if we should convert letters to upper/lowercase
+ * @return the converted String
+ * @throws ParseException if the given String isn't valid for the mask
+ */
+ String convertValue(String value, boolean convert) throws ParseException
+ {
+ StringBuffer result = new StringBuffer(value);
+ char markChar;
+ char resultChar;
+ boolean literal;
+
+ // this boolean is specifically to avoid calling the isCharValid method
+ // when neither invalidChars or validChars has been set
+ boolean checkCharSets = (invalidChars != null || validChars != null);
+
+ for (int i = 0, j = 0; i < value.length(); i++, j++)
+ {
+ literal = false;
+ resultChar = result.charAt(i);
+ // This switch block on the mask character checks that the character
+ // within <code>value</code> at that point is valid according to the
+ // mask and also converts to upper/lowercase as needed.
+ switch (mask.charAt(j))
+ {
+ case NUM_CHAR:
+ if (!Character.isDigit(resultChar))
+ throw new ParseException("Number expected", i);
+ break;
+ case UPPERCASE_CHAR:
+ if (!Character.isLetter(resultChar))
+ throw new ParseException("Letter expected", i);
+ if (convert)
+ result.setCharAt(i, Character.toUpperCase(resultChar));
+ break;
+ case LOWERCASE_CHAR:
+ if (!Character.isLetter(resultChar))
+ throw new ParseException("Letter expected", i);
+ if (convert)
+ result.setCharAt(i, Character.toLowerCase(resultChar));
+ break;
+ case ALPHANUM_CHAR:
+ if (!Character.isLetterOrDigit(resultChar))
+ throw new ParseException("Letter or number expected", i);
+ break;
+ case LETTER_CHAR:
+ if (!Character.isLetter(resultChar))
+ throw new ParseException("Letter expected", i);
+ break;
+ case HEX_CHAR:
+ if (hexString.indexOf(resultChar) == -1)
+ throw new ParseException("Hexadecimal character expected", i);
+ break;
+ case ANYTHING_CHAR:
+ break;
+ case ESCAPE_CHAR:
+ // Escape character, check the next character to make sure that
+ // the literals match
+ j++;
+ literal = true;
+ if (resultChar != mask.charAt(j))
+ throw new ParseException ("Invalid character: "+resultChar, i);
+ break;
+ default:
+ literal = true;
+ if (!getValueContainsLiteralCharacters() && convert)
+ throw new ParseException ("Invalid character: "+resultChar, i);
+ else if (resultChar != mask.charAt(j))
+ throw new ParseException ("Invalid character: "+resultChar, i);
+ }
+ // If necessary, check if the character is valid.
+ if (!literal && checkCharSets && !isCharValid(resultChar))
+ throw new ParseException("invalid character: "+resultChar, i);
+
+ }
+ return result.toString();
+ }
+
+ /**
+ * Convenience method used by many other methods to check if a character is
+ * valid according to the mask, the validChars, and the invalidChars. To
+ * be valid a character must:
+ * 1. be allowed by the mask
+ * 2. be present in any non-null validChars String
+ * 3. not be present in any non-null invalidChars String
+ * @param testChar the character to test
+ * @return true if the character is valid
+ */
+ boolean isCharValid(char testChar)
+ {
+ char lower = Character.toLowerCase(testChar);
+ char upper = Character.toUpperCase(testChar);
+ // If validChars isn't null, the character must appear in it.
+ if (validChars != null)
+ if (validChars.indexOf(lower) == -1 && validChars.indexOf(upper) == -1)
+ return false;
+ // If invalidChars isn't null, the character must not appear in it.
+ if (invalidChars != null)
+ if (invalidChars.indexOf(lower) != -1
+ || invalidChars.indexOf(upper) != -1)
+ return false;
+ return true;
+ }
+
+ /**
+ * Pads the value with literals, the placeholder String and/or placeholder
+ * character as appropriate.
+ * @param value the value to pad
+ * @param currLength the current length of the value
+ * @return the padded String
+ */
+ String pad (String value, int currLength)
+ {
+ StringBuffer result = new StringBuffer(value);
+ int index = currLength;
+ while (result.length() < maskLength)
+ {
+ // The character used to pad may be a literal, a character from the
+ // place holder string, or the place holder character. getPadCharAt
+ // will find the proper one for us.
+ result.append (getPadCharAt(index));
+ index++;
+ }
+ return result.toString();
+ }
+
+ /**
+ * Returns the character with which to pad the value at the given index
+ * position. If the mask has a literal at this position, this is returned
+ * otherwise if the place holder string is initialized and is longer than
+ * <code>i</code> characters then the character at position <code>i</code>
+ * from this String is returned. Else, the place holder character is
+ * returned.
+ * @param i the index at which we want to pad the value
+ * @return the character with which we should pad the value
+ */
+ char getPadCharAt(int i)
+ {
+ boolean escaped = false;
+ int target = i;
+ char maskChar;
+ int holderLength = placeHolder == null ? -1 : placeHolder.length();
+ // We must iterate through the mask from the beginning, because the given
+ // index doesn't account for escaped characters. For example, with the
+ // mask "1A'A''A1" index 2 refers to the literalized A, not to the
+ // single quotation.
+ for (int n = 0; n < mask.length(); n++)
+ {
+ maskChar = mask.charAt(n);
+ if (maskChar == ESCAPE_CHAR && !escaped)
+ {
+ target++;
+ escaped = true;
+ }
+ else if (escaped == true)
+ {
+ // Check if target == n which means we've come to the character
+ // we want to return and since it is a literal (because escaped
+ // is true), we return it.
+ if (target == n)
+ return maskChar;
+ escaped = false;
+ }
+ if (target == n)
+ {
+ // We've come to the character we want to return. It wasn't
+ // escaped so if it isn't a literal we should return either
+ // the character from place holder string or the place holder
+ // character, depending on whether or not the place holder
+ // string is long enough.
+ switch (maskChar)
+ {
+ case NUM_CHAR:
+ case UPPERCASE_CHAR:
+ case LOWERCASE_CHAR:
+ case ALPHANUM_CHAR:
+ case LETTER_CHAR:
+ case HEX_CHAR:
+ case ANYTHING_CHAR:
+ if (holderLength > i)
+ return placeHolder.charAt(i);
+ else
+ return placeHolderChar;
+ default:
+ return maskChar;
+ }
+ }
+ }
+ // This shouldn't happen
+ throw new AssertionError("MaskFormatter.getMaskCharAt failed");
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/MutableAttributeSet.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/MutableAttributeSet.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/MutableAttributeSet.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/MutableAttributeSet.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,117 @@
+/* MutableAttributeSet.java --
+ Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.util.Enumeration;
+
+/**
+ * An {@link AttributeSet} that supports modification of the stored
+ * attributes.
+ *
+ * @author Andrew Selkirk
+ * @since 1.2
+ */
+public interface MutableAttributeSet extends AttributeSet
+{
+ /**
+ * Adds an attribute with the given <code>name</code> and <code>value</code>
+ * to the set. If the set already contains an attribute with the given
+ * <code>name</code>, the attribute value is updated.
+ *
+ * @param name the attribute name (<code>null</code> not permitted).
+ * @param value the value (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either argument is <code>null</code>.
+ */
+ void addAttribute(Object name, Object value);
+
+ /**
+ * Adds all the attributes from <code>attributes</code> to this set.
+ *
+ * @param attributes the set of attributes to add (<code>null</code> not
+ * permitted).
+ *
+ * @throws NullPointerException if <code>attributes</code> is
+ * <code>null</code>.
+ */
+ void addAttributes(AttributeSet attributes);
+
+ /**
+ * Removes the attribute with the specified <code>name</code>, if this
+ * attribute is defined. This method will only remove an attribute from
+ * this set, not from the resolving parent.
+ *
+ * @param name the attribute name (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>name</code> is <code>null</code>.
+ */
+ void removeAttribute(Object name);
+
+ /**
+ * Removes the attributes listed in <code>names</code>.
+ *
+ * @param names the attribute names (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>names</code> is <code>null</code>
+ * or contains any <code>null</code> values.
+ */
+ void removeAttributes(Enumeration names);
+
+ /**
+ * Removes attributes from this set if they are found in the
+ * given set. Only attributes whose key AND value are removed.
+ * Removes attributes only from this set, not from the resolving parent.
+ * Since the resolving parent is stored as an attribute, if
+ * <code>attributes</code> has the same resolving parent as this set, the
+ * parent will be removed from this set.
+ *
+ * @param attributes the attributes (<code>null</code> not permitted).
+ */
+ void removeAttributes(AttributeSet attributes);
+
+ /**
+ * Sets the reolving parent for this set. When looking up an attribute, if
+ * it is not found in this set, then the resolving parent is also used for
+ * the lookup.
+ *
+ * @param parent the parent attribute set (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>parent</code> is <code>null</code>.
+ */
+ void setResolveParent(AttributeSet parent);
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/NavigationFilter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/NavigationFilter.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/NavigationFilter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/NavigationFilter.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,98 @@
+/* NavigationFilter.java --
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+public class NavigationFilter
+{
+ public abstract static class FilterBypass
+ {
+ public FilterBypass()
+ {
+ // Do nothing here.
+ }
+
+ public abstract Caret getCaret();
+ public abstract void moveDot(int dot, Position.Bias bias);
+ public abstract void setDot(int dot, Position.Bias bias);
+ }
+
+ public NavigationFilter()
+ {
+ // Do nothing here.
+ }
+
+ public void moveDot(NavigationFilter.FilterBypass fb, int dot,
+ Position.Bias bias)
+ {
+ fb.moveDot(dot, bias);
+ }
+
+ public void setDot(NavigationFilter.FilterBypass fb, int dot,
+ Position.Bias bias)
+ {
+ fb.setDot(dot, bias);
+ }
+
+ /**
+ * Returns the next visual position in the specified direction at which one
+ * would place a caret. The default implementation forwards to the text
+ * component's root view. Subclasses may wish to restrict that more.
+ *
+ * @param c the text component
+ * @param pos the current model position
+ * @param bias the bias of <code>pos</code>
+ * @param dir the direction, one of {@link javax.swing.SwingConstants#NORTH},
+ * {@link javax.swing.SwingConstants#SOUTH},
+ * {@link javax.swing.SwingConstants#WEST} or
+ * {@link javax.swing.SwingConstants#EAST}
+ * @param retBias the bias of the returned position
+ *
+ * @return the next model location to place the caret
+ *
+ * @throws BadLocationException when <code>pos</code> is not a valid model
+ * position
+ */
+ public int getNextVisualPositionFrom(JTextComponent c, int pos,
+ Position.Bias bias, int dir,
+ Position.Bias[] retBias)
+ throws BadLocationException
+ {
+ return c.getUI().getNextVisualPositionFrom(c, pos, bias, dir, retBias);
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/NumberFormatter.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/NumberFormatter.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/NumberFormatter.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/NumberFormatter.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,86 @@
+/* NumberFormatter.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.text.Format;
+import java.text.NumberFormat;
+
+/**
+ * <code>NumberFormatter</code> is an {@link InternationalFormatter}
+ * that implements value to string and string to value conversion via
+ * an instance of {@link NumberFormat}.
+ *
+ * @author Anthony Balkissoon abalkiss at redhat dot com
+ * @since 1.4
+ */
+public class NumberFormatter extends InternationalFormatter
+{
+
+ /**
+ * Creates a NumberFormatter with the default NumberFormat from
+ * NumberFormat.getNumberInstance().
+ */
+ public NumberFormatter ()
+ {
+ this (NumberFormat.getNumberInstance());
+ }
+
+ /**
+ * Creates a NumberFormatter with the specified NumberFormat.
+ * @param format the NumberFormat to use for this NumberFormatter.
+ */
+ public NumberFormatter (NumberFormat format)
+ {
+ super(format);
+ setFormat(format);
+ }
+
+ /**
+ * Sets the NumberFormat that this NumberFormatter will use to determine
+ * legal values for editing and displaying.
+ *
+ * @param format the Format to use to determine legal values.
+ */
+ public void setFormat (Format format)
+ {
+ // TODO: This should be different from the super implementation
+ // but I don't yet know how.
+ super.setFormat(format);
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ParagraphView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ParagraphView.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ParagraphView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/ParagraphView.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,456 @@
+/* ParagraphView.java -- A composite View
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Shape;
+
+import javax.swing.event.DocumentEvent;
+
+/**
+ * A {@link FlowView} that flows it's children horizontally and boxes the rows
+ * vertically.
+ *
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class ParagraphView extends FlowView implements TabExpander
+{
+ /**
+ * A specialized horizontal <code>BoxView</code> that represents exactly
+ * one row in a <code>ParagraphView</code>.
+ */
+ class Row extends BoxView
+ {
+ /**
+ * Creates a new instance of <code>Row</code>.
+ */
+ Row(Element el)
+ {
+ super(el, X_AXIS);
+ }
+
+ public float getAlignment(int axis)
+ {
+ float align;
+ if (axis == X_AXIS)
+ align = 0.0F; // TODO: Implement according to justification
+ else
+ align = super.getAlignment(axis);
+ return align;
+ }
+
+ /**
+ * Allows rows to span the whole parent view.
+ */
+ public float getMaximumSpan(int axis)
+ {
+ float max;
+ if (axis == X_AXIS)
+ max = Float.MAX_VALUE;
+ else
+ max = super.getMaximumSpan(axis);
+ return max;
+ }
+
+ /**
+ * Overridden because child views are not necessarily laid out in model
+ * order.
+ */
+ protected int getViewIndexAtPosition(int pos)
+ {
+ int index = -1;
+ if (pos >= getStartOffset() && pos < getEndOffset())
+ {
+ int nviews = getViewCount();
+ for (int i = 0; i < nviews && index == -1; i++)
+ {
+ View child = getView(i);
+ if (pos >= child.getStartOffset() && pos < child.getEndOffset())
+ index = i;
+ }
+ }
+ return index;
+ }
+
+ protected void loadChildren(ViewFactory vf)
+ {
+ // Do nothing here. The children are added while layouting.
+ }
+ }
+
+ /**
+ * The indentation of the first line of the paragraph.
+ */
+ protected int firstLineIndent;
+
+ /**
+ * The justification of the paragraph.
+ */
+ private int justification;
+
+ /**
+ * The line spacing of this paragraph.
+ */
+ private float lineSpacing;
+
+ /**
+ * The TabSet of this paragraph.
+ */
+ private TabSet tabSet;
+
+ /**
+ * Creates a new <code>ParagraphView</code> for the given
+ * <code>Element</code>.
+ *
+ * @param element the element that is rendered by this ParagraphView
+ */
+ public ParagraphView(Element element)
+ {
+ super(element, Y_AXIS);
+ }
+
+ public float nextTabStop(float x, int tabOffset)
+ {
+ throw new InternalError("Not implemented yet");
+ }
+
+ /**
+ * Creates a new view that represents a row within a flow.
+ *
+ * @return a view for a new row
+ */
+ protected View createRow()
+ {
+ return new Row(getElement());
+ }
+
+ /**
+ * Returns the alignment for this paragraph view for the specified axis.
+ * For the X_AXIS the paragraph view will be aligned at it's left edge
+ * (0.0F). For the Y_AXIS the paragraph view will be aligned at the
+ * center of it's first row.
+ *
+ * @param axis the axis which is examined
+ *
+ * @return the alignment for this paragraph view for the specified axis
+ */
+ public float getAlignment(int axis)
+ {
+ float align;
+ if (axis == X_AXIS)
+ align = 0.5F;
+ else if (getViewCount() > 0)
+ {
+ float prefHeight = getPreferredSpan(Y_AXIS);
+ float firstRowHeight = getView(0).getPreferredSpan(Y_AXIS);
+ align = (firstRowHeight / 2.F) / prefHeight;
+ }
+ else
+ align = 0.5F;
+ return align;
+ }
+
+ /**
+ * Receives notification when some attributes of the displayed element
+ * changes. This triggers a refresh of the cached attributes of this
+ * paragraph.
+ *
+ * @param ev the document event
+ * @param a the allocation of this view
+ * @param fv the view factory to use for creating new child views
+ */
+ public void changedUpdate(DocumentEvent ev, Shape a, ViewFactory fv)
+ {
+ setPropertiesFromAttributes();
+ }
+
+ /**
+ * Fetches the cached properties from the element's attributes.
+ */
+ protected void setPropertiesFromAttributes()
+ {
+ Element el = getElement();
+ AttributeSet atts = el.getAttributes();
+ setFirstLineIndent(StyleConstants.getFirstLineIndent(atts));
+ setLineSpacing(StyleConstants.getLineSpacing(atts));
+ setJustification(StyleConstants.getAlignment(atts));
+ tabSet = StyleConstants.getTabSet(atts);
+ }
+
+ /**
+ * Sets the indentation of the first line of the paragraph.
+ *
+ * @param i the indentation to set
+ */
+ protected void setFirstLineIndent(float i)
+ {
+ firstLineIndent = (int) i;
+ }
+
+ /**
+ * Sets the justification of the paragraph.
+ *
+ * @param j the justification to set
+ */
+ protected void setJustification(int j)
+ {
+ justification = j;
+ }
+
+ /**
+ * Sets the line spacing for this paragraph.
+ *
+ * @param s the line spacing to set
+ */
+ protected void setLineSpacing(float s)
+ {
+ lineSpacing = s;
+ }
+
+ /**
+ * Returns the i-th view from the logical views, before breaking into rows.
+ *
+ * @param i the index of the logical view to return
+ *
+ * @return the i-th view from the logical views, before breaking into rows
+ */
+ protected View getLayoutView(int i)
+ {
+ return layoutPool.getView(i);
+ }
+
+ /**
+ * Returns the number of logical child views.
+ *
+ * @return the number of logical child views
+ */
+ protected int getLayoutViewCount()
+ {
+ return layoutPool.getViewCount();
+ }
+
+ /**
+ * Returns the TabSet used by this ParagraphView.
+ *
+ * @return the TabSet used by this ParagraphView
+ */
+ protected TabSet getTabSet()
+ {
+ return tabSet;
+ }
+
+ /**
+ * Finds the next offset in the document that has one of the characters
+ * specified in <code>string</code>. If there is no such character found,
+ * this returns -1.
+ *
+ * @param string the characters to search for
+ * @param start the start offset
+ *
+ * @return the next offset in the document that has one of the characters
+ * specified in <code>string</code>
+ */
+ protected int findOffsetToCharactersInString(char[] string, int start)
+ {
+ int offset = -1;
+ Document doc = getDocument();
+ Segment text = new Segment();
+ try
+ {
+ doc.getText(start, doc.getLength() - start, text);
+ int index = start;
+
+ searchLoop:
+ while (true)
+ {
+ char ch = text.next();
+ if (ch == Segment.DONE)
+ break;
+
+ for (int j = 0; j < string.length; ++j)
+ {
+ if (string[j] == ch)
+ {
+ offset = index;
+ break searchLoop;
+ }
+ }
+ index++;
+ }
+ }
+ catch (BadLocationException ex)
+ {
+ // Ignore this and return -1.
+ }
+ return offset;
+ }
+
+ protected int getClosestPositionTo(int pos, Position.Bias bias, Shape a,
+ int direction, Position.Bias[] biasRet,
+ int rowIndex, int x)
+ throws BadLocationException
+ {
+ // FIXME: Implement this properly. However, this looks like it might
+ // have been replaced by viewToModel.
+ return pos;
+ }
+
+ /**
+ * Returns the size that is used by this view (or it's child views) between
+ * <code>startOffset</code> and <code>endOffset</code>. If the child views
+ * implement the {@link TabableView} interface, then this is used to
+ * determine the span, otherwise we use the preferred span of the child
+ * views.
+ *
+ * @param startOffset the start offset
+ * @param endOffset the end offset
+ *
+ * @return the span used by the view between <code>startOffset</code> and
+ * <code>endOffset</cod>
+ */
+ protected float getPartialSize(int startOffset, int endOffset)
+ {
+ int startIndex = getViewIndex(startOffset, Position.Bias.Backward);
+ int endIndex = getViewIndex(endOffset, Position.Bias.Forward);
+ float span;
+ if (startIndex == endIndex)
+ {
+ View child = getView(startIndex);
+ if (child instanceof TabableView)
+ {
+ TabableView tabable = (TabableView) child;
+ span = tabable.getPartialSpan(startOffset, endOffset);
+ }
+ else
+ span = child.getPreferredSpan(X_AXIS);
+ }
+ else if (endIndex - startIndex == 1)
+ {
+ View child1 = getView(startIndex);
+ if (child1 instanceof TabableView)
+ {
+ TabableView tabable = (TabableView) child1;
+ span = tabable.getPartialSpan(startOffset, child1.getEndOffset());
+ }
+ else
+ span = child1.getPreferredSpan(X_AXIS);
+ View child2 = getView(endIndex);
+ if (child2 instanceof TabableView)
+ {
+ TabableView tabable = (TabableView) child2;
+ span += tabable.getPartialSpan(child2.getStartOffset(), endOffset);
+ }
+ else
+ span += child2.getPreferredSpan(X_AXIS);
+ }
+ else
+ {
+ // Start with the first view.
+ View child1 = getView(startIndex);
+ if (child1 instanceof TabableView)
+ {
+ TabableView tabable = (TabableView) child1;
+ span = tabable.getPartialSpan(startOffset, child1.getEndOffset());
+ }
+ else
+ span = child1.getPreferredSpan(X_AXIS);
+
+ // Add up the view spans between the start and the end view.
+ for (int i = startIndex + 1; i < endIndex; i++)
+ {
+ View child = getView(i);
+ span += child.getPreferredSpan(X_AXIS);
+ }
+
+ // Add the span of the last view.
+ View child2 = getView(endIndex);
+ if (child2 instanceof TabableView)
+ {
+ TabableView tabable = (TabableView) child2;
+ span += tabable.getPartialSpan(child2.getStartOffset(), endOffset);
+ }
+ else
+ span += child2.getPreferredSpan(X_AXIS);
+ }
+ return span;
+ }
+
+ /**
+ * Returns the location where the tabs are calculated from. This returns
+ * <code>0.0F</code> by default.
+ *
+ * @return the location where the tabs are calculated from
+ */
+ protected float getTabBase()
+ {
+ return 0.0F;
+ }
+
+ /**
+ * @specnote This method is specified to take a Row parameter, which is a
+ * private inner class of that class, which makes it unusable from
+ * application code. Also, this method seems to be replaced by
+ * {@link FlowStrategy#adjustRow(FlowView, int, int, int)}.
+ *
+ */
+ protected void adjustRow(Row r, int desiredSpan, int x)
+ {
+ }
+
+ /**
+ * @specnote This method's signature differs from the one defined in
+ * {@link View} and is therefore never called. It is probably there
+ * for historical reasons.
+ */
+ public View breakView(int axis, float len, Shape a)
+ {
+ // This method is not used.
+ return null;
+ }
+
+ /**
+ * @specnote This method's signature differs from the one defined in
+ * {@link View} and is therefore never called. It is probably there
+ * for historical reasons.
+ */
+ public int getBreakWeight(int axis, float len)
+ {
+ // This method is not used.
+ return 0;
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PasswordView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PasswordView.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PasswordView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PasswordView.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,254 @@
+/* PasswordView.java --
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Color;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+import javax.swing.JPasswordField;
+
+public class PasswordView
+ extends FieldView
+{
+ /**
+ * Buffer for putting the echo char into it and
+ * then using it to draw it into the view.
+ */
+ private char[] oneCharBuffer = new char[1];
+
+ public PasswordView(Element elem)
+ {
+ super(elem);
+ }
+
+ /**
+ * Draws one echo character at a given position.
+ *
+ * @param g the <code>Graphics</code> object to draw to
+ * @param x the x-position
+ * @param y the y-position
+ * @param ch the echo character
+ *
+ * @return the next x position right of the drawn character
+ */
+ protected int drawEchoCharacter(Graphics g, int x, int y, char ch)
+ {
+ // Update font metrics.
+ updateMetrics();
+
+ // Draw character.
+ oneCharBuffer[0] = ch;
+ g.drawChars(oneCharBuffer, 0, 1, x, y);
+
+ // Return new x position right of drawn character.
+ return x + metrics.charWidth(ch);
+ }
+
+ private char getEchoChar()
+ {
+ char ch = ((JPasswordField) getContainer()).getEchoChar();
+
+ if (ch == 0)
+ ch = '*';
+
+ return ch;
+ }
+
+ /**
+ * Draws selected text at a given position.
+ *
+ * @param g the <code>Graphics</code> object to draw to
+ * @param x the x-position
+ * @param y the y-position
+ * @param p0 the position of the first character to draw
+ * @param p1 the position of the first character not to draw
+ *
+ * @return the next x position right of the drawn character
+ */
+ protected int drawSelectedText(Graphics g, int x, int y, int p0, int p1)
+ throws BadLocationException
+ {
+ // Update font metrics.
+ updateMetrics();
+
+ // Get echo character.
+ char ch = getEchoChar();
+
+ // Set color for selected text.
+ g.setColor(selectedColor);
+ g.setColor(Color.BLACK);
+
+ // Draw echo character using drawEchoCharacter() method.
+ for (int index = p0; index < p1; ++index)
+ x = drawEchoCharacter(g, x, y, ch);
+ return x;
+ }
+
+ /**
+ * Draws unselected text at a given position.
+ *
+ * @param g the <code>Graphics</code> object to draw to
+ * @param x the x-position of the start of the baseline
+ * @param y the y-position of the start of the baseline
+ * @param p0 the position of the first character to draw
+ * @param p1 the position of the first character not to draw
+ *
+ * @return the next x position right of the drawn character
+ */
+ protected int drawUnselectedText(Graphics g, int x, int y, int p0, int p1)
+ throws BadLocationException
+ {
+ // Update font metrics.
+ updateMetrics();
+
+ // Get echo character.
+ char ch = getEchoChar();
+
+ // Set color for unselected text.
+ g.setColor(unselectedColor);
+ g.setColor(Color.BLACK);
+
+ // Draw echo character using drawEchoCharacter() method.
+ for (int index = p0; index < p1; ++index)
+ x = drawEchoCharacter(g, x, y, ch);
+ return x;
+ }
+
+ /**
+ * Determines the preferred span for this view along an axis.
+ *
+ * @param axis to get the preferred span of
+ * @return the preferred span of the axis
+ */
+ public float getPreferredSpan(int axis)
+ {
+ if (axis != X_AXIS && axis != Y_AXIS)
+ throw new IllegalArgumentException();
+
+ FontMetrics fm = getFontMetrics();
+
+ if (axis == Y_AXIS)
+ return fm.getHeight();
+
+ String text;
+ Element elem = getElement();
+
+ try
+ {
+ text = elem.getDocument().getText(elem.getStartOffset(),
+ elem.getEndOffset());
+ }
+ catch (BadLocationException e)
+ {
+ // This should never happen.
+ text = "";
+ }
+ return fm.stringWidth(text);
+ }
+
+ /**
+ * Provides a mapping from the document model coordinate space to the
+ * coordinate space of the view mapped to it.
+ *
+ * This method is overridden to provide a correct mapping with respect to the
+ * echo char and not to the real content.
+ *
+ * @param pos - the position to convert >= 0
+ * @param a - the allocated region to render into
+ * @param b - typesafe enumeration to indicate bias to a position in the model.
+ * @return the bounding box of the given position
+ * @throws BadLocationException if the given position does not
+ * represent a valid location in the associated document
+ */
+ public Shape modelToView(int pos, Shape a, Position.Bias b)
+ throws BadLocationException
+ {
+ Shape newAlloc = adjustAllocation(a);
+
+ // Ensure metrics are up-to-date.
+ updateMetrics();
+
+ // Get rectangle of the line containing position.
+ int lineIndex = getElement().getElementIndex(pos);
+ Rectangle rect = lineToRect(newAlloc, lineIndex);
+
+ // Get the rectangle for position.
+ Element line = getElement().getElement(lineIndex);
+ int lineStart = line.getStartOffset();
+ Segment segment = getLineBuffer();
+ segment.array = new char[pos - lineStart];
+ char echoChar = getEchoChar();
+ for (int i = 0; i < segment.array.length; ++i)
+ segment.array[i] = echoChar;
+ segment.offset = 0;
+ segment.count = segment.array.length;
+
+ int xoffset = Utilities.getTabbedTextWidth(segment, metrics, rect.x,
+ this, lineStart);
+
+ // Calc the real rectangle.
+ rect.x += xoffset;
+ rect.width = 1;
+ rect.height = metrics.getHeight();
+
+ return rect;
+ }
+
+ /**
+ * Provides a mapping from the view coordinate space to the logical
+ * coordinate space of the model.
+ *
+ * @param fx - the X coordinate >= 0.0f
+ * @param fy - the Y coordinate >= 0.0f
+ * @param a - the allocated region to render into
+ * @param bias - typesafe enumeration to indicate bias to a position in the model.
+ * @return the location within the model that best represents
+ * the given point in the view
+ *
+ */
+ public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias)
+ {
+ // FIXME: This only provides a view->model mapping for the real text
+ // content and does not respect the echo char.
+ return super.viewToModel(fx, fy, a, bias);
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PlainDocument.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PlainDocument.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PlainDocument.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PlainDocument.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,292 @@
+/* PlainDocument.java --
+ Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.util.ArrayList;
+
+/**
+ * A simple document class which maps lines to {@link Element}s.
+ *
+ * @author Anthony Balkissoon (abalkiss at redhat.com)
+ * @author Graydon Hoare (graydon at redhat.com)
+ * @author Roman Kennke (roman at kennke.org)
+ * @author Michael Koch (konqueror at gmx.de)
+ * @author Robert Schuster (robertschuster at fsfe.org)
+ */
+public class PlainDocument extends AbstractDocument
+{
+ private static final long serialVersionUID = 4758290289196893664L;
+
+ public static final String lineLimitAttribute = "lineLimit";
+ public static final String tabSizeAttribute = "tabSize";
+
+ /**
+ * The default root element of this document. This is made type Element
+ * because the RI seems to accept other types of elements as well from
+ * createDefaultRoot() (when overridden by a subclass).
+ */
+ private Element rootElement;
+
+ public PlainDocument()
+ {
+ this(new GapContent());
+ }
+
+ public PlainDocument(AbstractDocument.Content content)
+ {
+ super(content);
+ rootElement = createDefaultRoot();
+
+ // This property has been determined using a Mauve test.
+ putProperty("tabSize", new Integer(8));
+ }
+
+ private void reindex()
+ {
+ Element[] lines;
+ try
+ {
+ String str = content.getString(0, content.length());
+
+ ArrayList elts = new ArrayList();
+ int j = 0;
+ for (int i = str.indexOf('\n', 0); i != -1; i = str.indexOf('\n', i + 1))
+ {
+ elts.add(createLeafElement(rootElement, SimpleAttributeSet.EMPTY, j, i + 1));
+ j = i + 1;
+ }
+
+ if (j < content.length())
+ elts.add(createLeafElement(rootElement, SimpleAttributeSet.EMPTY, j, content.length()));
+
+ lines = new Element[elts.size()];
+ for (int i = 0; i < elts.size(); ++i)
+ lines[i] = (Element) elts.get(i);
+ }
+ catch (BadLocationException e)
+ {
+ lines = new Element[1];
+ lines[0] = createLeafElement(rootElement, SimpleAttributeSet.EMPTY, 0, 1);
+ }
+
+ ((BranchElement) rootElement).replace(0, rootElement.getElementCount(), lines);
+ }
+
+ protected AbstractDocument.AbstractElement createDefaultRoot()
+ {
+ BranchElement root =
+ (BranchElement) createBranchElement(null, null);
+
+ Element[] array = new Element[1];
+ array[0] = createLeafElement(root, null, 0, 1);
+ root.replace(0, 0, array);
+
+ return root;
+ }
+
+ protected void insertUpdate(DefaultDocumentEvent event,
+ AttributeSet attributes)
+ {
+
+ String text = null;
+ int offset = event.getOffset();
+ int length = event.getLength();
+ try
+ {
+ text = getText(offset, length);
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError err = new AssertionError();
+ err.initCause(ex);
+ throw err;
+ }
+
+ boolean hasLineBreak = text.indexOf('\n') != -1;
+ boolean prevCharIsLineBreak = false;
+ try
+ {
+ prevCharIsLineBreak =
+ offset > 0 && getText(offset - 1, 1).charAt(0) == '\n';
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError err = new AssertionError();
+ err.initCause(ex);
+ throw err;
+ }
+ boolean lastCharIsLineBreak = text.charAt(text.length() - 1) == '\n';
+ int lineIndex = -1;
+ int lineStart = -1;
+ int lineEnd = -1;
+ Element[] removed = null;
+ BranchElement root = (BranchElement) rootElement;
+ boolean updateStructure = true;
+
+ if (prevCharIsLineBreak && ! lastCharIsLineBreak)
+ {
+ // We must fix the structure a little if the previous char
+ // is a linebreak and the last char isn't.
+ lineIndex = root.getElementIndex(offset - 1);
+ Element prevLine = root.getElement(lineIndex);
+ Element nextLine = root.getElement(lineIndex + 1);
+ lineStart = prevLine.getStartOffset();
+ lineEnd = nextLine.getEndOffset();
+ removed = new Element[]{ prevLine, nextLine };
+ }
+ else if (hasLineBreak)
+ {
+ lineIndex = root.getElementIndex(offset);
+ Element line = root.getElement(lineIndex);
+ lineStart = line.getStartOffset();
+ lineEnd = line.getEndOffset();
+ removed = new Element[]{ line };
+ }
+ else
+ {
+ updateStructure = false;
+ }
+
+ if (updateStructure)
+ {
+ // Break the lines between lineStart and lineEnd.
+ ArrayList lines = new ArrayList();
+ int len = lineEnd - lineStart;
+ try
+ {
+ text = getText(lineStart, len);
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError err = new AssertionError();
+ err.initCause(ex);
+ throw err;
+ }
+ int prevLineBreak = 0;
+ int lineBreak = text.indexOf('\n');
+ do
+ {
+ lineBreak++;
+ lines.add(createLeafElement(root, null, lineStart + prevLineBreak,
+ lineStart + lineBreak));
+ prevLineBreak = lineBreak;
+ lineBreak = text.indexOf('\n', prevLineBreak);
+ } while (prevLineBreak < len);
+
+ // Update the element structure and prepare document event.
+ Element[] added = (Element[]) lines.toArray(new Element[lines.size()]);
+ event.addEdit(new ElementEdit(root, lineIndex, removed, added));
+ root.replace(lineIndex, removed.length, added);
+ }
+ super.insertUpdate(event, attributes);
+ }
+
+ protected void removeUpdate(DefaultDocumentEvent event)
+ {
+ super.removeUpdate(event);
+
+ // added and removed are Element arrays used to add an ElementEdit
+ // to the DocumentEvent if there were entire lines added or removed
+ // from the Document
+ Element[] added = new Element[1];
+ Element[] removed;
+ int p0 = event.getOffset();
+
+ // check if we must collapse some elements
+ int i1 = rootElement.getElementIndex(p0);
+ int i2 = rootElement.getElementIndex(p0 + event.getLength());
+ if (i1 != i2)
+ {
+ // If there were lines removed then we have to add an ElementEdit
+ // to the DocumentEvent so we set it up now by filling the Element
+ // arrays "removed" and "added" appropriately
+ removed = new Element [i2 - i1 + 1];
+ for (int i = i1; i <= i2; i++)
+ removed[i-i1] = rootElement.getElement(i);
+
+ int start = rootElement.getElement(i1).getStartOffset();
+ int end = rootElement.getElement(i2).getEndOffset();
+ added[0] = createLeafElement(rootElement,
+ SimpleAttributeSet.EMPTY,
+ start, end);
+
+ // Now create and add the ElementEdit
+ ElementEdit e = new ElementEdit(rootElement, i1, removed, added);
+ event.addEdit(e);
+
+ // collapse elements if the removal spans more than 1 line
+ ((BranchElement) rootElement).replace(i1, i2 - i1 + 1, added);
+ }
+ }
+
+ public Element getDefaultRootElement()
+ {
+ return rootElement;
+ }
+
+ public Element getParagraphElement(int pos)
+ {
+ Element root = getDefaultRootElement();
+ return root.getElement(root.getElementIndex(pos));
+ }
+
+ /**
+ * Inserts a string into the document. If the document property
+ * '<code>filterNewLines</code>' is set to <code>Boolean.TRUE</code>, then
+ * all newlines in the inserted string are replaced by space characters,
+ * otherwise the superclasses behaviour is executed.
+ *
+ * Inserting content causes a write lock to be acquired during this method
+ * call.
+ *
+ * @param offs the offset at which to insert the string
+ * @param str the string to be inserted
+ * @param atts the text attributes of the string to be inserted
+ *
+ * @throws BadLocationException
+ */
+ public void insertString(int offs, String str, AttributeSet atts)
+ throws BadLocationException
+ {
+ String string = str;
+ if (str != null && Boolean.TRUE.equals(getProperty("filterNewlines")))
+ string = str.replaceAll("\n", " ");
+ super.insertString(offs, string, atts);
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PlainView.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PlainView.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PlainView.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/PlainView.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,661 @@
+/* PlainView.java --
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+import javax.swing.SwingUtilities;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentEvent.ElementChange;
+
+public class PlainView extends View implements TabExpander
+{
+ Color selectedColor;
+ Color unselectedColor;
+
+ /**
+ * The color that is used to draw disabled text fields.
+ */
+ Color disabledColor;
+
+ /**
+ * While painting this is the textcomponent's current start index
+ * of the selection.
+ */
+ int selectionStart;
+
+ /**
+ * While painting this is the textcomponent's current end index
+ * of the selection.
+ */
+ int selectionEnd;
+
+ Font font;
+
+ /** The length of the longest line in the Document **/
+ float maxLineLength = -1;
+
+ /** The longest line in the Document **/
+ Element longestLine = null;
+
+ protected FontMetrics metrics;
+
+ /**
+ * The instance returned by {@link #getLineBuffer()}.
+ */
+ private transient Segment lineBuffer;
+
+ public PlainView(Element elem)
+ {
+ super(elem);
+ }
+
+ /**
+ * @since 1.4
+ */
+ protected void updateMetrics()
+ {
+ Component component = getContainer();
+ Font font = component.getFont();
+
+ if (this.font != font)
+ {
+ this.font = font;
+ metrics = component.getFontMetrics(font);
+ }
+ }
+
+ /**
+ * @since 1.4
+ */
+ protected Rectangle lineToRect(Shape a, int line)
+ {
+ // Ensure metrics are up-to-date.
+ updateMetrics();
+
+ Rectangle rect = a.getBounds();
+ int fontHeight = metrics.getHeight();
+ return new Rectangle(rect.x, rect.y + (line * fontHeight),
+ rect.width, fontHeight);
+ }
+
+ public Shape modelToView(int position, Shape a, Position.Bias b)
+ throws BadLocationException
+ {
+ // Ensure metrics are up-to-date.
+ updateMetrics();
+
+ Document document = getDocument();
+
+ // Get rectangle of the line containing position.
+ int lineIndex = getElement().getElementIndex(position);
+ Rectangle rect = lineToRect(a, lineIndex);
+
+ // Get the rectangle for position.
+ Element line = getElement().getElement(lineIndex);
+ int lineStart = line.getStartOffset();
+ Segment segment = getLineBuffer();
+ document.getText(lineStart, position - lineStart, segment);
+ int xoffset = Utilities.getTabbedTextWidth(segment, metrics, rect.x,
+ this, lineStart);
+
+ // Calc the real rectangle.
+ rect.x += xoffset;
+ rect.width = 1;
+ rect.height = metrics.getHeight();
+
+ return rect;
+ }
+
+ /**
+ * Draws a line of text. The X and Y coordinates specify the start of
+ * the <em>baseline</em> of the line.
+ *
+ * @param lineIndex the index of the line
+ * @param g the graphics to use for drawing the text
+ * @param x the X coordinate of the baseline
+ * @param y the Y coordinate of the baseline
+ */
+ protected void drawLine(int lineIndex, Graphics g, int x, int y)
+ {
+ try
+ {
+ Element line = getElement().getElement(lineIndex);
+ int startOffset = line.getStartOffset();
+ int endOffset = line.getEndOffset() - 1;
+
+ if (selectionStart <= startOffset)
+ // Selection starts before the line ...
+ if (selectionEnd <= startOffset)
+ {
+ // end ends before the line: Draw completely unselected text.
+ drawUnselectedText(g, x, y, startOffset, endOffset);
+ }
+ else if (selectionEnd <= endOffset)
+ {
+ // and ends within the line: First part is selected,
+ // second is not.
+ x = drawSelectedText(g, x, y, startOffset, selectionEnd);
+ drawUnselectedText(g, x, y, selectionEnd, endOffset);
+ }
+ else
+ // and ends behind the line: Draw completely selected text.
+ drawSelectedText(g, x, y, startOffset, endOffset);
+ else if (selectionStart < endOffset)
+ // Selection starts within the line ..
+ if (selectionEnd < endOffset)
+ {
+ // and ends within it: First part unselected, second part
+ // selected, third part unselected.
+ x = drawUnselectedText(g, x, y, startOffset, selectionStart);
+ x = drawSelectedText(g, x, y, selectionStart, selectionEnd);
+ drawUnselectedText(g, x, y, selectionEnd, endOffset);
+ }
+ else
+ {
+ // and ends behind the line: First part unselected, second
+ // part selected.
+ x = drawUnselectedText(g, x, y, startOffset, selectionStart);
+ drawSelectedText(g, x, y, selectionStart, endOffset);
+ }
+ else
+ // Selection is behind this line: Draw completely unselected text.
+ drawUnselectedText(g, x, y, startOffset, endOffset);
+ }
+ catch (BadLocationException e)
+ {
+ AssertionError ae = new AssertionError("Unexpected bad location");
+ ae.initCause(e);
+ throw ae;
+ }
+ }
+
+ protected int drawSelectedText(Graphics g, int x, int y, int p0, int p1)
+ throws BadLocationException
+ {
+ g.setColor(selectedColor);
+ Segment segment = getLineBuffer();
+ getDocument().getText(p0, p1 - p0, segment);
+ return Utilities.drawTabbedText(segment, x, y, g, this, segment.offset);
+ }
+
+ /**
+ * Draws a chunk of unselected text.
+ *
+ * @param g the graphics to use for drawing the text
+ * @param x the X coordinate of the baseline
+ * @param y the Y coordinate of the baseline
+ * @param p0 the start position in the text model
+ * @param p1 the end position in the text model
+ *
+ * @return the X location of the end of the range
+ *
+ * @throws BadLocationException if <code>p0</code> or <code>p1</code> are
+ * invalid
+ */
+ protected int drawUnselectedText(Graphics g, int x, int y, int p0, int p1)
+ throws BadLocationException
+ {
+ JTextComponent textComponent = (JTextComponent) getContainer();
+ if (textComponent.isEnabled())
+ g.setColor(unselectedColor);
+ else
+ g.setColor(disabledColor);
+
+ Segment segment = getLineBuffer();
+ getDocument().getText(p0, p1 - p0, segment);
+ return Utilities.drawTabbedText(segment, x, y, g, this, segment.offset);
+ }
+
+ public void paint(Graphics g, Shape s)
+ {
+ // Ensure metrics are up-to-date.
+ updateMetrics();
+
+ JTextComponent textComponent = (JTextComponent) getContainer();
+
+ selectedColor = textComponent.getSelectedTextColor();
+ unselectedColor = textComponent.getForeground();
+ disabledColor = textComponent.getDisabledTextColor();
+ selectionStart = textComponent.getSelectionStart();
+ selectionEnd = textComponent.getSelectionEnd();
+
+ Rectangle rect = s.getBounds();
+
+ // FIXME: Text may be scrolled.
+ Document document = textComponent.getDocument();
+ Element root = document.getDefaultRootElement();
+ int y = rect.y + metrics.getAscent();
+ int height = metrics.getHeight();
+
+ int count = root.getElementCount();
+ for (int i = 0; i < count; i++)
+ {
+ drawLine(i, g, rect.x, y);
+ y += height;
+ }
+ }
+
+ /**
+ * Returns the tab size of a tab. Checks the Document's
+ * properties for PlainDocument.tabSizeAttribute and returns it if it is
+ * defined, otherwise returns 8.
+ *
+ * @return the tab size.
+ */
+ protected int getTabSize()
+ {
+ Object tabSize = getDocument().getProperty(PlainDocument.tabSizeAttribute);
+ if (tabSize == null)
+ return 8;
+ return ((Integer)tabSize).intValue();
+ }
+
+ /**
+ * Returns the next tab stop position after a given reference position.
+ *
+ * This implementation ignores the <code>tabStop</code> argument.
+ *
+ * @param x the current x position in pixels
+ * @param tabStop the position within the text stream that the tab occured at
+ */
+ public float nextTabStop(float x, int tabStop)
+ {
+ float tabSizePixels = getTabSize() * metrics.charWidth('m');
+ return (float) (Math.floor(x / tabSizePixels) + 1) * tabSizePixels;
+ }
+
+ /**
+ * Returns the length of the longest line, used for getting the span
+ * @return the length of the longest line
+ */
+ float determineMaxLineLength()
+ {
+ // if the longest line is cached, return the cached value
+ if (maxLineLength != -1)
+ return maxLineLength;
+
+ // otherwise we have to go through all the lines and find it
+ Element el = getElement();
+ Segment seg = getLineBuffer();
+ float span = 0;
+ for (int i = 0; i < el.getElementCount(); i++)
+ {
+ Element child = el.getElement(i);
+ int start = child.getStartOffset();
+ int end = child.getEndOffset() - 1;
+ try
+ {
+ el.getDocument().getText(start, end - start, seg);
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError ae = new AssertionError("Unexpected bad location");
+ ae.initCause(ex);
+ throw ae;
+ }
+
+ if (seg == null || seg.array == null || seg.count == 0)
+ continue;
+
+ int width = metrics.charsWidth(seg.array, seg.offset, seg.count);
+ if (width > span)
+ {
+ longestLine = child;
+ span = width;
+ }
+ }
+ maxLineLength = span;
+ return maxLineLength;
+ }
+
+ public float getPreferredSpan(int axis)
+ {
+ if (axis != X_AXIS && axis != Y_AXIS)
+ throw new IllegalArgumentException();
+
+ // make sure we have the metrics
+ updateMetrics();
+
+ Element el = getElement();
+ float span;
+
+ switch (axis)
+ {
+ case X_AXIS:
+ span = determineMaxLineLength();
+ break;
+ case Y_AXIS:
+ default:
+ span = metrics.getHeight() * el.getElementCount();
+ break;
+ }
+
+ return span;
+ }
+
+ /**
+ * Maps coordinates from the <code>View</code>'s space into a position
+ * in the document model.
+ *
+ * @param x the x coordinate in the view space
+ * @param y the y coordinate in the view space
+ * @param a the allocation of this <code>View</code>
+ * @param b the bias to use
+ *
+ * @return the position in the document that corresponds to the screen
+ * coordinates <code>x, y</code>
+ */
+ public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
+ {
+ Rectangle rec = a.getBounds();
+ Document doc = getDocument();
+ Element root = doc.getDefaultRootElement();
+
+ // PlainView doesn't support line-wrapping so we can find out which
+ // Element was clicked on just by the y-position.
+ // Since the coordinates may be outside of the coordinate space
+ // of the allocation area (e.g. user dragged mouse outside
+ // the component) we have to limit the values.
+ // This has the nice effect that the user can drag the
+ // mouse above or below the component and it will still
+ // react to the x values (e.g. when selecting).
+ int lineClicked
+ = Math.min(Math.max((int) (y - rec.y) / metrics.getHeight(), 0),
+ root.getElementCount() - 1);
+
+ Element line = root.getElement(lineClicked);
+
+ Segment s = getLineBuffer();
+ int start = line.getStartOffset();
+ // We don't want the \n at the end of the line.
+ int end = line.getEndOffset() - 1;
+ try
+ {
+ doc.getText(start, end - start, s);
+ }
+ catch (BadLocationException ble)
+ {
+ AssertionError ae = new AssertionError("Unexpected bad location");
+ ae.initCause(ble);
+ throw ae;
+ }
+
+ int pos = Utilities.getTabbedTextOffset(s, metrics, rec.x, (int)x, this, start);
+ return Math.max (0, pos);
+ }
+
+ /**
+ * Since insertUpdate and removeUpdate each deal with children
+ * Elements being both added and removed, they both have to perform
+ * the same checks. So they both simply call this method.
+ * @param changes the DocumentEvent for the changes to the Document.
+ * @param a the allocation of the View.
+ * @param f the ViewFactory to use for rebuilding.
+ */
+ protected void updateDamage(DocumentEvent changes, Shape a, ViewFactory f)
+ {
+ // This happens during initialization.
+ if (metrics == null)
+ {
+ updateMetrics();
+ preferenceChanged(null, true, true);
+ return;
+ }
+
+ Element element = getElement();
+
+ // Find longest line if it hasn't been initialized yet.
+ if (longestLine == null)
+ findLongestLine(0, element.getElementCount() - 1);
+
+ ElementChange change = changes.getChange(element);
+ if (changes.getType() == DocumentEvent.EventType.INSERT)
+ {
+ // Handles character/line insertion.
+
+ // Determine if lines have been added. In this case we repaint
+ // differently.
+ boolean linesAdded = true;
+ if (change == null)
+ linesAdded = false;
+
+ // Determine the start line.
+ int start;
+ if (linesAdded)
+ start = change.getIndex();
+ else
+ start = element.getElementIndex(changes.getOffset());
+
+ // Determine the length of the updated region.
+ int length = 0;
+ if (linesAdded)
+ length = change.getChildrenAdded().length - 1;
+
+ // Update the longest line and length.
+ int oldMaxLength = (int) maxLineLength;
+ if (longestLine.getEndOffset() < changes.getOffset()
+ || longestLine.getStartOffset() > changes.getOffset()
+ + changes.getLength())
+ {
+ findLongestLine(start, start + length);
+ }
+ else
+ {
+ findLongestLine(0, element.getElementCount() - 1);
+ }
+
+ // Trigger a preference change so that the layout gets updated
+ // correctly.
+ preferenceChanged(null, maxLineLength != oldMaxLength, linesAdded);
+
+ // Damage the updated line range.
+ int endLine = start;
+ if (linesAdded)
+ endLine = element.getElementCount() - 1;
+ damageLineRange(start, endLine, a, getContainer());
+
+ }
+ else
+ {
+ // Handles character/lines removals.
+
+ // Update the longest line and length and trigger preference changed.
+ int oldMaxLength = (int) maxLineLength;
+ if (change != null)
+ {
+ // Line(s) have been removed.
+ findLongestLine(0, element.getElementCount() - 1);
+ preferenceChanged(null, maxLineLength != oldMaxLength, true);
+ }
+ else
+ {
+ // No line has been removed.
+ int lineNo = getElement().getElementIndex(changes.getOffset());
+ Element line = getElement().getElement(lineNo);
+ if (longestLine == line)
+ {
+ findLongestLine(0, element.getElementCount() - 1);
+ preferenceChanged(null, maxLineLength != oldMaxLength, false);
+ }
+ damageLineRange(lineNo, lineNo, a, getContainer());
+ }
+ }
+ }
+
+ /**
+ * This method is called when something is inserted into the Document
+ * that this View is displaying.
+ *
+ * @param changes the DocumentEvent for the changes.
+ * @param a the allocation of the View
+ * @param f the ViewFactory used to rebuild
+ */
+ public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory f)
+ {
+ updateDamage(changes, a, f);
+ }
+
+ /**
+ * This method is called when something is removed from the Document
+ * that this View is displaying.
+ *
+ * @param changes the DocumentEvent for the changes.
+ * @param a the allocation of the View
+ * @param f the ViewFactory used to rebuild
+ */
+ public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory f)
+ {
+ updateDamage(changes, a, f);
+ }
+
+ /**
+ * This method is called when attributes were changed in the
+ * Document in a location that this view is responsible for.
+ */
+ public void changedUpdate (DocumentEvent changes, Shape a, ViewFactory f)
+ {
+ updateDamage(changes, a, f);
+ }
+
+ /**
+ * Repaint the given line range. This is called from insertUpdate,
+ * changedUpdate, and removeUpdate when no new lines were added
+ * and no lines were removed, to repaint the line that was
+ * modified.
+ *
+ * @param line0 the start of the range
+ * @param line1 the end of the range
+ * @param a the rendering region of the host
+ * @param host the Component that uses this View (used to call repaint
+ * on that Component)
+ *
+ * @since 1.4
+ */
+ protected void damageLineRange (int line0, int line1, Shape a, Component host)
+ {
+ if (a == null)
+ return;
+
+ Rectangle rec0 = lineToRect(a, line0);
+ Rectangle rec1 = lineToRect(a, line1);
+
+ if (rec0 == null || rec1 == null)
+ // something went wrong, repaint the entire host to be safe
+ host.repaint();
+ else
+ {
+ Rectangle repaintRec = SwingUtilities.computeUnion(rec0.x, rec0.y,
+ rec0.width,
+ rec0.height, rec1);
+ host.repaint(repaintRec.x, repaintRec.y, repaintRec.width,
+ repaintRec.height);
+ }
+ }
+
+ /**
+ * Provides a {@link Segment} object, that can be used to fetch text from
+ * the document.
+ *
+ * @returna {@link Segment} object, that can be used to fetch text from
+ * the document
+ */
+ protected final Segment getLineBuffer()
+ {
+ if (lineBuffer == null)
+ lineBuffer = new Segment();
+ return lineBuffer;
+ }
+
+ /**
+ * Finds and updates the longest line in the view inside an interval of
+ * lines.
+ *
+ * @param start the start of the search interval
+ * @param end the end of the search interval
+ */
+ private void findLongestLine(int start, int end)
+ {
+ for (int i = start; i <= end; i++)
+ {
+ int w = getLineLength(i);
+ if (w > maxLineLength)
+ {
+ maxLineLength = w;
+ longestLine = getElement().getElement(i);
+ }
+ }
+ }
+
+ /**
+ * Determines the length of the specified line.
+ *
+ * @param line the number of the line
+ *
+ * @return the length of the line in pixels
+ */
+ private int getLineLength(int line)
+ {
+ Element lineEl = getElement().getElement(line);
+ Segment buffer = getLineBuffer();
+ try
+ {
+ Document doc = getDocument();
+ doc.getText(lineEl.getStartOffset(),
+ lineEl.getEndOffset() - lineEl.getStartOffset() - 1,
+ buffer);
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError err = new AssertionError("Unexpected bad location");
+ err.initCause(ex);
+ throw err;
+ }
+
+ return Utilities.getTabbedTextWidth(buffer, metrics, 0, this,
+ lineEl.getStartOffset());
+ }
+}
+
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Position.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Position.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Position.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Position.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,62 @@
+/* Position.java --
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+
+public interface Position
+{
+ static final class Bias
+ {
+ public static final Bias Backward = new Bias("backward");
+ public static final Bias Forward = new Bias("forward");
+
+ private String name;
+
+ private Bias(String n)
+ {
+ name = n;
+ }
+
+ public String toString()
+ {
+ return name;
+ }
+ }
+
+ int getOffset();
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Segment.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Segment.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Segment.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Segment.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,297 @@
+/* Segment.java --
+ Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.text.CharacterIterator;
+
+/**
+ * A text fragment represented by a sequence of characters stored in an array.
+ */
+public class Segment implements Cloneable, CharacterIterator
+{
+ private boolean partialReturn;
+
+ /** The current index. */
+ private int current;
+
+ /** Storage for the characters (may contain additional characters). */
+ public char[] array;
+
+ /** The number of characters in the segment. */
+ public int count;
+
+ /** The offset of the first character in the segment. */
+ public int offset;
+
+ /**
+ * Creates a new <code>Segment</code>.
+ */
+ public Segment()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Creates a new <code>Segment</code>.
+ *
+ * @param array the underlying character data.
+ * @param offset the offset of the first character in the segment.
+ * @param count the number of characters in the segment.
+ */
+ public Segment(char[] array, int offset, int count)
+ {
+ this.array = array;
+ this.offset = offset;
+ this.count = count;
+ }
+
+ /**
+ * Clones the segment (note that the underlying character array is not cloned,
+ * just the reference to it).
+ *
+ * @return A clone of the segment.
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the character at the current index. If the segment consists of
+ * zero characters, or the current index has passed the end of the
+ * characters in the segment, this method returns {@link #DONE}.
+ *
+ * @return The character at the current index.
+ */
+ public char current()
+ {
+ if (count == 0
+ || current >= getEndIndex())
+ return DONE;
+
+ return array[current];
+ }
+
+ /**
+ * Sets the current index to the first character in the segment and returns
+ * that character. If the segment contains zero characters, this method
+ * returns {@link #DONE}.
+ *
+ * @return The first character in the segment, or {@link #DONE} if the
+ * segment contains zero characters.
+ */
+ public char first()
+ {
+ if (count == 0)
+ return DONE;
+
+ current = getBeginIndex();
+ return array[current];
+ }
+
+ /**
+ * Returns the index of the first character in the segment.
+ *
+ * @return The index of the first character.
+ */
+ public int getBeginIndex()
+ {
+ return offset;
+ }
+
+ /**
+ * Returns the end index for the segment (one position beyond the last
+ * character in the segment - note that this can be outside the range of the
+ * underlying character array).
+ *
+ * @return The end index for the segment.
+ */
+ public int getEndIndex()
+ {
+ return offset + count;
+ }
+
+ /**
+ * Returns the index of the current character in the segment.
+ *
+ * @return The index of the current character.
+ */
+ public int getIndex()
+ {
+ return current;
+ }
+
+ /**
+ * Sets the current index to point to the last character in the segment and
+ * returns that character. If the segment contains zero characters, the
+ * current index is set to {@link #getEndIndex()} and this method returns
+ * {@link #DONE}.
+ *
+ * @return The last character in the segment, or {@link #DONE} if the
+ * segment contains zero characters.
+ */
+ public char last()
+ {
+ if (count == 0)
+ {
+ current = getEndIndex();
+ return DONE;
+ }
+
+ current = getEndIndex() - 1;
+ return array[current];
+ }
+
+ /**
+ * Sets the current index to point to the next character in the segment and
+ * returns that character. If the next character position is past the end of
+ * the segment, the index is set to {@link #getEndIndex()} and the method
+ * returns {@link #DONE}. If the segment contains zero characters, this
+ * method returns {@link #DONE}.
+ *
+ * @return The next character in the segment or {@link #DONE} (if the next
+ * character position is past the end of the segment or if the
+ * segment contains zero characters).
+ */
+ public char next()
+ {
+ if (count == 0)
+ return DONE;
+
+ if ((current + 1) >= getEndIndex())
+ {
+ current = getEndIndex();
+ return DONE;
+ }
+
+ current++;
+ return array[current];
+ }
+
+ /**
+ * Sets the current index to point to the previous character in the segment
+ * and returns that character. If the current index is equal to
+ * {@link #getBeginIndex()}, or if the segment contains zero characters, this
+ * method returns {@link #DONE}.
+ *
+ * @return The previous character in the segment or {@link #DONE} (if the
+ * current character position is at the beginning of the segment or
+ * if the segment contains zero characters).
+ */
+ public char previous()
+ {
+ if (count == 0
+ || current == getBeginIndex())
+ return DONE;
+
+ current--;
+ return array[current];
+ }
+
+ /**
+ * Sets the current index and returns the character at that position (or
+ * {@link #DONE} if the index is equal to {@link #getEndIndex()}.
+ *
+ * @param position the current position.
+ *
+ * @return The character at the specified <code>position</code>, or
+ * {@link #DONE} if <code>position</code> is equal to
+ * {@link #getEndIndex()}.
+ *
+ * @throws IllegalArgumentException if <code>position</code> is not in the
+ * range {@link #getBeginIndex()} to {@link #getEndIndex()}.
+ */
+ public char setIndex(int position)
+ {
+ if (position < getBeginIndex()
+ || position > getEndIndex())
+ throw new IllegalArgumentException("position: " + position
+ + ", beginIndex: " + getBeginIndex()
+ + ", endIndex: " + getEndIndex()
+ + ", text: " + toString());
+
+ current = position;
+
+ if (position == getEndIndex())
+ return DONE;
+
+ return array[current];
+ }
+
+ /**
+ * Returns a <code>String</code> containing the same characters as this
+ * <code>Segment</code>.
+ *
+ * @return A <code>String</code> containing the same characters as this
+ * <code>Segment</code>.
+ */
+ public String toString()
+ {
+ return (array != null) ? new String(array, offset, count) : "";
+ }
+
+ /**
+ * Sets the partial return flag.
+ *
+ * @param p the new value of the flag.
+ *
+ * @since 1.4
+ */
+ public void setPartialReturn(boolean p)
+ {
+ partialReturn = p;
+ }
+
+ /**
+ * Returns the partial return flag.
+ *
+ * @return The partial return flag.
+ * @since 1.4
+ */
+ public boolean isPartialReturn()
+ {
+ return partialReturn;
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/SimpleAttributeSet.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/SimpleAttributeSet.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/SimpleAttributeSet.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/SimpleAttributeSet.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,407 @@
+/* SimpleAttributeSet.java --
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**
+ * A set of attributes.
+ */
+public class SimpleAttributeSet
+ implements MutableAttributeSet, Serializable, Cloneable
+{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 8267656273837665219L;
+
+ /**
+ * An empty attribute set.
+ */
+ public static final AttributeSet EMPTY = new EmptyAttributeSet();
+
+ /** Storage for the attributes. */
+ Hashtable tab;
+
+ /**
+ * Creates a new attribute set that is initially empty.
+ */
+ public SimpleAttributeSet()
+ {
+ tab = new Hashtable();
+ }
+
+ /**
+ * Creates a new <code>SimpleAttributeSet</code> with the same attributes
+ * and resolve parent as the specified set.
+ *
+ * @param a the attributes (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>a</code> is <code>null</code>.
+ */
+ public SimpleAttributeSet(AttributeSet a)
+ {
+ tab = new Hashtable();
+ addAttributes(a);
+ }
+
+ /**
+ * Adds an attribute with the given <code>name</code> and <code>value</code>
+ * to the set. If the set already contains an attribute with the given
+ * <code>name</code>, the attribute value is updated.
+ *
+ * @param name the attribute name (<code>null</code> not permitted).
+ * @param value the value (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either argument is <code>null</code>.
+ */
+ public void addAttribute(Object name, Object value)
+ {
+ tab.put(name, value);
+ }
+
+ /**
+ * Adds all the attributes from <code>attributes</code> to this set.
+ *
+ * @param attributes the set of attributes to add (<code>null</code> not
+ * permitted).
+ *
+ * @throws NullPointerException if <code>attributes</code> is
+ * <code>null</code>.
+ */
+ public void addAttributes(AttributeSet attributes)
+ {
+ Enumeration e = attributes.getAttributeNames();
+ while (e.hasMoreElements())
+ {
+ Object name = e.nextElement();
+ Object val = attributes.getAttribute(name);
+ tab.put(name, val);
+ }
+ }
+
+ /**
+ * Returns a clone of the attribute set.
+ *
+ * @return A clone of the attribute set.
+ */
+ public Object clone()
+ {
+ SimpleAttributeSet s = new SimpleAttributeSet();
+ s.tab = (Hashtable) tab.clone();
+ return s;
+ }
+
+ /**
+ * Returns true if the given name and value represent an attribute
+ * found either in this AttributeSet or in its resolve parent hierarchy.
+ * @param name the key for the attribute
+ * @param value the value for the attribute
+ * @return true if the attribute is found here or in this set's resolve
+ * parent hierarchy
+ */
+ public boolean containsAttribute(Object name, Object value)
+ {
+ if (value == null)
+ throw new NullPointerException("Null 'value' argument.");
+ if (tab.containsKey(name))
+ return tab.get(name).equals(value);
+ else
+ {
+ AttributeSet p = getResolveParent();
+ if (p != null)
+ return p.containsAttribute(name, value);
+ else
+ return false;
+ }
+ }
+
+ /**
+ * Returns true if the given name and value are found in this AttributeSet.
+ * Does not check the resolve parent.
+ * @param name the key for the attribute
+ * @param value the value for the attribute
+ * @return true if the attribute is found in this AttributeSet
+ */
+ boolean containsAttributeLocally(Object name, Object value)
+ {
+ return tab.containsKey(name)
+ && tab.get(name).equals(value);
+ }
+
+ /**
+ * Returns <code>true</code> of this <code>AttributeSet</code> contains all
+ * of the specified <code>attributes</code>.
+ *
+ * @param attributes the requested attributes
+ *
+ * @return <code>true</code> of this <code>AttributeSet</code> contains all
+ * of the specified <code>attributes</code>
+ */
+ public boolean containsAttributes(AttributeSet attributes)
+ {
+ Enumeration e = attributes.getAttributeNames();
+ while (e.hasMoreElements())
+ {
+ Object name = e.nextElement();
+ Object val = attributes.getAttribute(name);
+ if (! containsAttribute(name, val))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Creates and returns a copy of this <code>AttributeSet</code>.
+ *
+ * @return a copy of this <code>AttributeSet</code>
+ */
+ public AttributeSet copyAttributes()
+ {
+ return (AttributeSet) clone();
+ }
+
+ /**
+ * Checks this set for equality with an arbitrary object.
+ *
+ * @param obj the object (<code>null</code> permitted).
+ *
+ * @return <code>true</code> if this set is equal to <code>obj</code>, and
+ * <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj)
+ {
+ return
+ (obj instanceof AttributeSet)
+ && this.isEqual((AttributeSet) obj);
+ }
+
+ /**
+ * Returns the value of the specified attribute, or <code>null</code> if
+ * there is no attribute with that name. If the attribute is not defined
+ * directly in this set, the parent hierarchy (if there is one) will be
+ * used.
+ *
+ * @param name the attribute (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>name</code> is <code>null</code>.
+ */
+ public Object getAttribute(Object name)
+ {
+ Object val = tab.get(name);
+ if (val != null)
+ return val;
+
+ AttributeSet p = getResolveParent();
+ if (p != null)
+ return p.getAttribute(name);
+
+ return null;
+ }
+
+ /**
+ * Returns the number of attributes stored in this set, plus 1 if a parent
+ * has been specified (the reference to the parent is stored as a special
+ * attribute). The attributes stored in the parent do NOT contribute
+ * to the count.
+ *
+ * @return The attribute count.
+ */
+ public int getAttributeCount()
+ {
+ return tab.size();
+ }
+
+ /**
+ * Returns an enumeration of the attribute names.
+ *
+ * @return An enumeration of the attribute names.
+ */
+ public Enumeration getAttributeNames()
+ {
+ return tab.keys();
+ }
+
+ /**
+ * Returns the resolving parent.
+ *
+ * @return The resolving parent (possibly <code>null</code>).
+ *
+ * @see #setResolveParent(AttributeSet)
+ */
+ public AttributeSet getResolveParent()
+ {
+ return (AttributeSet) tab.get(ResolveAttribute);
+ }
+
+ /**
+ * Returns a hash code for this instance.
+ *
+ * @return A hash code.
+ */
+ public int hashCode()
+ {
+ return tab.hashCode();
+ }
+
+ /**
+ * Returns <code>true</code> if the given attribute is defined in this set,
+ * and <code>false</code> otherwise. The parent attribute set is not
+ * checked.
+ *
+ * @param attrName the attribute name (<code>null</code> not permitted).
+ */
+ public boolean isDefined(Object attrName)
+ {
+ return tab.containsKey(attrName);
+ }
+
+ /**
+ * Returns <code>true</code> if the set contains no attributes, and
+ * <code>false</code> otherwise. Note that the resolving parent is
+ * stored as an attribute, so this method will return <code>false</code> if
+ * a resolving parent is set.
+ *
+ * @return <code>true</code> if the set contains no attributes, and
+ * <code>false</code> otherwise.
+ */
+ public boolean isEmpty()
+ {
+ return tab.isEmpty();
+ }
+
+ /**
+ * Returns true if the given set has the same number of attributes
+ * as this set and <code>containsAttributes(attr)</code> returns
+ * <code>true</code>.
+ *
+ * @param attr the attribute set (<code>null</code> not permitted).
+ *
+ * @return A boolean.
+ *
+ * @throws NullPointerException if <code>attr</code> is <code>null</code>.
+ */
+ public boolean isEqual(AttributeSet attr)
+ {
+ return getAttributeCount() == attr.getAttributeCount()
+ && this.containsAttributes(attr);
+ }
+
+ /**
+ * Removes the attribute with the specified <code>name</code>, if this
+ * attribute is defined. This method will only remove an attribute from
+ * this set, not from the resolving parent.
+ *
+ * @param name the attribute name (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>name</code> is <code>null</code>.
+ */
+ public void removeAttribute(Object name)
+ {
+ tab.remove(name);
+ }
+
+ /**
+ * Removes attributes from this set if they are found in the
+ * given set. Only attributes whose key AND value are removed.
+ * Removes attributes only from this set, not from the resolving parent.
+ * Since the resolving parent is stored as an attribute, if
+ * <code>attributes</code> has the same resolving parent as this set, the
+ * parent will be removed from this set.
+ *
+ * @param attributes the attributes (<code>null</code> not permitted).
+ */
+ public void removeAttributes(AttributeSet attributes)
+ {
+ Enumeration e = attributes.getAttributeNames();
+ while (e.hasMoreElements())
+ {
+ Object name = e.nextElement();
+ Object val = attributes.getAttribute(name);
+ if (containsAttributeLocally(name, val))
+ removeAttribute(name);
+ }
+ }
+
+ /**
+ * Removes the attributes listed in <code>names</code>.
+ *
+ * @param names the attribute names (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>names</code> is <code>null</code>
+ * or contains any <code>null</code> values.
+ */
+ public void removeAttributes(Enumeration names)
+ {
+ while (names.hasMoreElements())
+ {
+ removeAttribute(names.nextElement());
+ }
+ }
+
+ /**
+ * Sets the reolving parent for this set. When looking up an attribute, if
+ * it is not found in this set, then the resolving parent is also used for
+ * the lookup.
+ * <p>
+ * Note that the parent is stored as an attribute, and will contribute 1 to
+ * the count returned by {@link #getAttributeCount()}.
+ *
+ * @param parent the parent attribute set (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>parent</code> is <code>null</code>.
+ *
+ * @see #setResolveParent(AttributeSet)
+ */
+ public void setResolveParent(AttributeSet parent)
+ {
+ addAttribute(ResolveAttribute, parent);
+ }
+
+ /**
+ * Returns a string representation of this instance, typically used for
+ * debugging purposes.
+ *
+ * @return A string representation of this instance.
+ */
+ public String toString()
+ {
+ return tab.toString();
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StringContent.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StringContent.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StringContent.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StringContent.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,410 @@
+/* StringContent.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.Vector;
+
+import javax.swing.undo.AbstractUndoableEdit;
+import javax.swing.undo.CannotRedoException;
+import javax.swing.undo.CannotUndoException;
+import javax.swing.undo.UndoableEdit;
+
+/**
+ * An implementation of the <code>AbstractDocument.Content</code>
+ * interface useful for small documents or debugging. The character
+ * content is a simple character array. It's not really efficient.
+ *
+ * <p>Do not use this class for large size.</p>
+ */
+public final class StringContent
+ implements AbstractDocument.Content, Serializable
+{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 4755994433709540381L;
+
+ // This is package-private to avoid an accessor method.
+ char[] content;
+
+ private int count;
+
+ private Vector positions = new Vector();
+
+ private class InsertUndo extends AbstractUndoableEdit
+ {
+ private int start;
+
+ private int length;
+
+ private String redoContent;
+
+ public InsertUndo(int start, int length)
+ {
+ super();
+ this.start = start;
+ this.length = length;
+ }
+
+ public void undo()
+ {
+ super.undo();
+ try
+ {
+ StringContent.this.checkLocation(this.start, this.length);
+ this.redoContent = new String(StringContent.this.content, this.start,
+ this.length);
+ StringContent.this.remove(this.start, this.length);
+ }
+ catch (BadLocationException b)
+ {
+ throw new CannotUndoException();
+ }
+ }
+
+ public void redo()
+ {
+ super.redo();
+ try
+ {
+ StringContent.this.insertString(this.start, this.redoContent);
+ }
+ catch (BadLocationException b)
+ {
+ throw new CannotRedoException();
+ }
+ }
+ }
+
+ private class RemoveUndo extends AbstractUndoableEdit
+ {
+ private int start;
+
+ private String undoString;
+
+ public RemoveUndo(int start, String str)
+ {
+ super();
+ this.start = start;
+ this.undoString = str;
+ }
+
+ public void undo()
+ {
+ super.undo();
+ try
+ {
+ StringContent.this.insertString(this.start, this.undoString);
+ }
+ catch (BadLocationException bad)
+ {
+ throw new CannotUndoException();
+ }
+ }
+
+ public void redo()
+ {
+ super.redo();
+ try
+ {
+ int end = this.undoString.length();
+ StringContent.this.remove(this.start, end);
+ }
+ catch (BadLocationException bad)
+ {
+ throw new CannotRedoException();
+ }
+ }
+ }
+
+ private class StickyPosition implements Position
+ {
+ private int offset = -1;
+
+ public StickyPosition(int offset)
+ {
+ this.offset = offset;
+ }
+
+ // This is package-private to avoid an accessor method.
+ void setOffset(int offset)
+ {
+ this.offset = this.offset >= 0 ? offset : -1;
+ }
+
+ /**
+ * Should be >=0.
+ */
+ public int getOffset()
+ {
+ return offset < 0 ? 0 : offset;
+ }
+ }
+
+ /**
+ * Creates a new instance containing the string "\n". This is equivalent
+ * to calling {@link #StringContent(int)} with an <code>initialLength</code>
+ * of 10.
+ */
+ public StringContent()
+ {
+ this(10);
+ }
+
+ /**
+ * Creates a new instance containing the string "\n".
+ *
+ * @param initialLength the initial length of the underlying character
+ * array used to store the content.
+ */
+ public StringContent(int initialLength)
+ {
+ super();
+ if (initialLength < 1)
+ initialLength = 1;
+ this.content = new char[initialLength];
+ this.content[0] = '\n';
+ this.count = 1;
+ }
+
+ protected Vector getPositionsInRange(Vector v,
+ int offset,
+ int length)
+ {
+ Vector refPos = new Vector();
+ Iterator iter = this.positions.iterator();
+ while(iter.hasNext())
+ {
+ Position p = (Position) iter.next();
+ if ((offset <= p.getOffset())
+ && (p.getOffset() <= (offset + length)))
+ refPos.add(p);
+ }
+ return refPos;
+ }
+
+ /**
+ * Creates a position reference for the character at the given offset. The
+ * position offset will be automatically updated when new characters are
+ * inserted into or removed from the content.
+ *
+ * @param offset the character offset.
+ *
+ * @throws BadLocationException if offset is outside the bounds of the
+ * content.
+ */
+ public Position createPosition(int offset) throws BadLocationException
+ {
+ if (offset < this.count || offset > this.count)
+ checkLocation(offset, 0);
+ StickyPosition sp = new StickyPosition(offset);
+ this.positions.add(sp);
+ return sp;
+ }
+
+ /**
+ * Returns the length of the string content, including the '\n' character at
+ * the end.
+ *
+ * @return The length of the string content.
+ */
+ public int length()
+ {
+ return this.count;
+ }
+
+ /**
+ * Inserts <code>str</code> at the given position and returns an
+ * {@link UndoableEdit} that enables undo/redo support.
+ *
+ * @param where the insertion point (must be less than
+ * <code>length()</code>).
+ * @param str the string to insert (<code>null</code> not permitted).
+ *
+ * @return An object that can undo the insertion.
+ */
+ public UndoableEdit insertString(int where, String str)
+ throws BadLocationException
+ {
+ checkLocation(where, 0);
+ if (where == this.count)
+ throw new BadLocationException("Invalid location", 1);
+ if (str == null)
+ throw new NullPointerException();
+ char[] insert = str.toCharArray();
+ char[] temp = new char[this.content.length + insert.length];
+ this.count += insert.length;
+ // Copy array and insert the string.
+ if (where > 0)
+ System.arraycopy(this.content, 0, temp, 0, where);
+ System.arraycopy(insert, 0, temp, where, insert.length);
+ System.arraycopy(this.content, where, temp, (where + insert.length),
+ (temp.length - where - insert.length));
+ if (this.content.length < temp.length)
+ this.content = new char[temp.length];
+ // Copy the result in the original char array.
+ System.arraycopy(temp, 0, this.content, 0, temp.length);
+ // Move all the positions.
+ Vector refPos = getPositionsInRange(this.positions, where,
+ temp.length - where);
+ Iterator iter = refPos.iterator();
+ while (iter.hasNext())
+ {
+ StickyPosition p = (StickyPosition)iter.next();
+ p.setOffset(p.getOffset() + str.length());
+ }
+ InsertUndo iundo = new InsertUndo(where, insert.length);
+ return iundo;
+ }
+
+ /**
+ * Removes the specified range of characters and returns an
+ * {@link UndoableEdit} that enables undo/redo support.
+ *
+ * @param where the starting index.
+ * @param nitems the number of characters.
+ *
+ * @return An object that can undo the removal.
+ *
+ * @throws BadLocationException if the character range extends outside the
+ * bounds of the content OR includes the last character.
+ */
+ public UndoableEdit remove(int where, int nitems) throws BadLocationException
+ {
+ checkLocation(where, nitems + 1);
+ char[] temp = new char[(this.content.length - nitems)];
+ this.count = this.count - nitems;
+ RemoveUndo rundo = new RemoveUndo(where, new String(this.content, where,
+ nitems));
+ // Copy array.
+ System.arraycopy(this.content, 0, temp, 0, where);
+ System.arraycopy(this.content, where + nitems, temp, where,
+ this.content.length - where - nitems);
+ this.content = new char[temp.length];
+ // Then copy the result in the original char array.
+ System.arraycopy(temp, 0, this.content, 0, this.content.length);
+ // Move all the positions.
+ Vector refPos = getPositionsInRange(this.positions, where,
+ this.content.length + nitems - where);
+ Iterator iter = refPos.iterator();
+ while (iter.hasNext())
+ {
+ StickyPosition p = (StickyPosition)iter.next();
+ int result = p.getOffset() - nitems;
+ p.setOffset(result);
+ if (result < 0)
+ this.positions.remove(p);
+ }
+ return rundo;
+ }
+
+ /**
+ * Returns a new <code>String</code> containing the characters in the
+ * specified range.
+ *
+ * @param where the start index.
+ * @param len the number of characters.
+ *
+ * @return A string.
+ *
+ * @throws BadLocationException if the requested range of characters extends
+ * outside the bounds of the content.
+ */
+ public String getString(int where, int len) throws BadLocationException
+ {
+ checkLocation(where, len);
+ return new String(this.content, where, len);
+ }
+
+ /**
+ * Updates <code>txt</code> to contain a direct reference to the underlying
+ * character array.
+ *
+ * @param where the index of the first character.
+ * @param len the number of characters.
+ * @param txt a carrier for the return result (<code>null</code> not
+ * permitted).
+ *
+ * @throws BadLocationException if the requested character range is not
+ * within the bounds of the content.
+ * @throws NullPointerException if <code>txt</code> is <code>null</code>.
+ */
+ public void getChars(int where, int len, Segment txt)
+ throws BadLocationException
+ {
+ checkLocation(where, len);
+ txt.array = this.content;
+ txt.offset = where;
+ txt.count = len;
+ }
+
+
+ /**
+ * @specnote This method is not very well specified and the positions vector
+ * is implementation specific. The undo positions are managed
+ * differently in this implementation, this method is only here
+ * for binary compatibility.
+ */
+ protected void updateUndoPositions(Vector positions)
+ {
+ // We do nothing here.
+ }
+
+ /**
+ * A utility method that checks the validity of the specified character
+ * range.
+ *
+ * @param where the first character in the range.
+ * @param len the number of characters in the range.
+ *
+ * @throws BadLocationException if the specified range is not within the
+ * bounds of the content.
+ */
+ void checkLocation(int where, int len) throws BadLocationException
+ {
+ if (where < 0)
+ throw new BadLocationException("Invalid location", 1);
+ else if (where > this.count)
+ throw new BadLocationException("Invalid location", this.count);
+ else if ((where + len) > this.count)
+ throw new BadLocationException("Invalid range", this.count);
+ }
+
+}
+
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Style.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Style.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Style.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/Style.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,64 @@
+/* Style.java --
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import javax.swing.event.ChangeListener;
+
+public interface Style extends MutableAttributeSet
+{
+ /**
+ * Returns the name of the style.
+ *
+ * @return the name
+ */
+ String getName();
+
+ /**
+ * Adds a <code>ChangeListener</code> object to the style.
+ *
+ * @param listener the listener object to add
+ */
+ void addChangeListener(ChangeListener listener);
+
+ /**
+ * Removes a <code>ChangeListener</code> from to the style.
+ *
+ * @param listener the listener object to remove,
+ */
+ void removeChangeListener(ChangeListener listener);
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyleConstants.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyleConstants.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyleConstants.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyleConstants.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,1072 @@
+/* StyleConstants.java --
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Color;
+import java.awt.Component;
+
+import javax.swing.Icon;
+
+/**
+ * Represents standard attribute keys. This class also contains a set of
+ * useful static utility methods for querying and populating an
+ * {@link AttributeSet}.
+ *
+ * @since 1.2
+ */
+public class StyleConstants
+{
+ /**
+ * A value representing left alignment for the
+ * {@link ParagraphConstants#Alignment} attribute.
+ */
+ public static final int ALIGN_LEFT = 0;
+
+ /**
+ * A value representing center alignment for the
+ * {@link ParagraphConstants#Alignment} attribute.
+ */
+ public static final int ALIGN_CENTER = 1;
+
+ /**
+ * A value representing right alignment for the
+ * {@link ParagraphConstants#Alignment} attribute.
+ */
+ public static final int ALIGN_RIGHT = 2;
+
+ /**
+ * A value representing ful justification for the
+ * {@link ParagraphConstants#Alignment} attribute.
+ */
+ public static final int ALIGN_JUSTIFIED = 3;
+
+ /** An alias for {@link CharacterConstants#Background}. */
+ public static final Object Background = CharacterConstants.Background;
+
+ /** An alias for {@link CharacterConstants#BidiLevel}. */
+ public static final Object BidiLevel = CharacterConstants.BidiLevel;
+
+ /** An alias for {@link CharacterConstants#Bold}. */
+ public static final Object Bold = CharacterConstants.Bold;
+
+ /** An alias for {@link CharacterConstants#ComponentAttribute}. */
+ public static final Object ComponentAttribute
+ = CharacterConstants.ComponentAttribute;
+
+ /** An alias for {@link CharacterConstants#Family}. */
+ public static final Object Family = CharacterConstants.Family;
+
+ /** An alias for {@link CharacterConstants#Family}. */
+ public static final Object FontFamily = CharacterConstants.Family;
+
+ /** An alias for {@link CharacterConstants#Size}. */
+ public static final Object FontSize = CharacterConstants.Size;
+
+ /** An alias for {@link CharacterConstants#Foreground}. */
+ public static final Object Foreground = CharacterConstants.Foreground;
+
+ /** An alias for {@link CharacterConstants#IconAttribute}. */
+ public static final Object IconAttribute = CharacterConstants.IconAttribute;
+
+ /** An alias for {@link CharacterConstants#Italic}. */
+ public static final Object Italic = CharacterConstants.Italic;
+
+ /** An alias for {@link CharacterConstants#Size}. */
+ public static final Object Size = CharacterConstants.Size;
+
+ /** An alias for {@link CharacterConstants#StrikeThrough}. */
+ public static final Object StrikeThrough = CharacterConstants.StrikeThrough;
+
+ /** An alias for {@link CharacterConstants#Subscript}. */
+ public static final Object Subscript = CharacterConstants.Subscript;
+
+ /** An alias for {@link CharacterConstants#Superscript}. */
+ public static final Object Superscript = CharacterConstants.Superscript;
+
+ /** An alias for {@link CharacterConstants#Underline}. */
+ public static final Object Underline = CharacterConstants.Underline;
+
+ /** An alias for {@link ParagraphConstants#Alignment}. */
+ public static final Object Alignment = ParagraphConstants.Alignment;
+
+ /** An alias for {@link ParagraphConstants#FirstLineIndent}. */
+ public static final Object FirstLineIndent
+ = ParagraphConstants.FirstLineIndent;
+
+ /** An alias for {@link ParagraphConstants#LeftIndent}. */
+ public static final Object LeftIndent = ParagraphConstants.LeftIndent;
+
+ /** An alias for {@link ParagraphConstants#LineSpacing}. */
+ public static final Object LineSpacing = ParagraphConstants.LineSpacing;
+
+ /** An alias for {@link ParagraphConstants#Orientation}. */
+ public static final Object Orientation = ParagraphConstants.Orientation;
+
+ /** An alias for {@link ParagraphConstants#RightIndent}. */
+ public static final Object RightIndent = ParagraphConstants.RightIndent;
+
+ /** An alias for {@link ParagraphConstants#SpaceAbove}. */
+ public static final Object SpaceAbove = ParagraphConstants.SpaceAbove;
+
+ /** An alias for {@link ParagraphConstants#SpaceBelow}. */
+ public static final Object SpaceBelow = ParagraphConstants.SpaceBelow;
+
+ /** An alias for {@link ParagraphConstants#TabSet}. */
+ public static final Object TabSet = ParagraphConstants.TabSet;
+
+ public static final String ComponentElementName = "component";
+
+ public static final String IconElementName = "icon";
+
+ public static final Object ComposedTextAttribute
+ = new StyleConstants("composed text");
+
+ public static final Object ModelAttribute = new StyleConstants("model");
+
+ public static final Object NameAttribute = new StyleConstants("name");
+
+ public static final Object ResolveAttribute = new StyleConstants("resolver");
+
+ String keyname;
+
+ // Package-private to avoid accessor constructor for use by
+ // subclasses.
+ StyleConstants(String k)
+ {
+ keyname = k;
+ }
+
+ /**
+ * Returns a string representation of the attribute key.
+ *
+ * @return A string representation of the attribute key.
+ */
+ public String toString()
+ {
+ return keyname;
+ }
+
+ /**
+ * Returns the alignment specified in the given attributes, or
+ * {@link #ALIGN_LEFT} if no alignment is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The alignment (typically one of {@link #ALIGN_LEFT},
+ * {@link #ALIGN_RIGHT}, {@link #ALIGN_CENTER} or
+ * {@link #ALIGN_JUSTIFIED}).
+ *
+ * @see #setAlignment(MutableAttributeSet, int)
+ */
+ public static int getAlignment(AttributeSet a)
+ {
+ Integer i = (Integer) a.getAttribute(Alignment);
+ if (i != null)
+ return i.intValue();
+ else
+ return ALIGN_LEFT;
+ }
+
+ /**
+ * Returns the background color specified in the given attributes, or
+ * {@link Color#BLACK} if no background color is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The background color.
+ *
+ * @see #setBackground(MutableAttributeSet, Color)
+ */
+ public static Color getBackground(AttributeSet a)
+ {
+ Color c = (Color) a.getAttribute(Background);
+ if (c != null)
+ return c;
+ else
+ return Color.BLACK;
+ }
+
+ /**
+ * Returns the bidi level specified in the given attributes, or
+ * <code>0</code> if no bidi level is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The bidi level.
+ *
+ * @see #setBidiLevel(MutableAttributeSet, int)
+ */
+ public static int getBidiLevel(AttributeSet a)
+ {
+ Integer i = (Integer) a.getAttribute(BidiLevel);
+ if (i != null)
+ return i.intValue();
+ else
+ return 0;
+ }
+
+ /**
+ * Returns the component specified in the given attributes, or
+ * <code>null</code> if no component is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The component (possibly <code>null</code>).
+ *
+ * @see #setComponent(MutableAttributeSet, Component)
+ */
+ public static Component getComponent(AttributeSet a)
+ {
+ Component c = (Component) a.getAttribute(ComponentAttribute);
+ if (c != null)
+ return c;
+ else
+ return null;
+ }
+
+ /**
+ * Returns the indentation specified in the given attributes, or
+ * <code>0.0f</code> if no indentation is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The indentation.
+ *
+ * @see #setFirstLineIndent(MutableAttributeSet, float)
+ */
+ public static float getFirstLineIndent(AttributeSet a)
+ {
+ Float f = (Float) a.getAttribute(FirstLineIndent);
+ if (f != null)
+ return f.floatValue();
+ else
+ return 0.0f;
+ }
+
+ /**
+ * Returns the font family specified in the given attributes, or
+ * <code>Monospaced</code> if no font family is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The font family.
+ *
+ * @see #setFontFamily(MutableAttributeSet, String)
+ */
+ public static String getFontFamily(AttributeSet a)
+ {
+ String ff = (String) a.getAttribute(FontFamily);
+ if (ff != null)
+ return ff;
+ else
+ return "Monospaced";
+ }
+
+ /**
+ * Returns the font size specified in the given attributes, or
+ * <code>12</code> if no font size is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The font size.
+ *
+ * @see #setFontSize(MutableAttributeSet, int)
+ */
+ public static int getFontSize(AttributeSet a)
+ {
+ Integer i = (Integer) a.getAttribute(FontSize);
+ if (i != null)
+ return i.intValue();
+ else
+ return 12;
+ }
+
+ /**
+ * Returns the foreground color specified in the given attributes, or
+ * {@link Color#BLACK} if no foreground color is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The foreground color.
+ *
+ * @see #setForeground(MutableAttributeSet, Color)
+ */
+ public static Color getForeground(AttributeSet a)
+ {
+ Color c = (Color) a.getAttribute(Foreground);
+ if (c != null)
+ return c;
+ else
+ return Color.BLACK;
+ }
+
+ /**
+ * Returns the icon specified in the given attributes, or
+ * <code>null</code> if no icon is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The icon (possibly <code>null</code>).
+ *
+ * @see #setIcon(MutableAttributeSet, Icon)
+ */
+ public static Icon getIcon(AttributeSet a)
+ {
+ return (Icon) a.getAttribute(IconAttribute);
+ }
+
+ /**
+ * Returns the left indentation specified in the given attributes, or
+ * <code>0.0f</code> if no left indentation is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The left indentation.
+ *
+ * @see #setLeftIndent(MutableAttributeSet, float)
+ */
+ public static float getLeftIndent(AttributeSet a)
+ {
+ Float f = (Float) a.getAttribute(LeftIndent);
+ if (f != null)
+ return f.floatValue();
+ else
+ return 0.0f;
+ }
+
+ /**
+ * Returns the line spacing specified in the given attributes, or
+ * <code>0.0f</code> if no line spacing is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The line spacing.
+ *
+ * @see #setLineSpacing(MutableAttributeSet, float)
+ */
+ public static float getLineSpacing(AttributeSet a)
+ {
+ Float f = (Float) a.getAttribute(LineSpacing);
+ if (f != null)
+ return f.floatValue();
+ else
+ return 0.0f;
+ }
+
+ /**
+ * Returns the right indentation specified in the given attributes, or
+ * <code>0.0f</code> if no right indentation is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The right indentation.
+ *
+ * @see #setRightIndent(MutableAttributeSet, float)
+ */
+ public static float getRightIndent(AttributeSet a)
+ {
+ Float f = (Float) a.getAttribute(RightIndent);
+ if (f != null)
+ return f.floatValue();
+ else
+ return 0.0f;
+ }
+
+ /**
+ * Returns the 'space above' specified in the given attributes, or
+ * <code>0.0f</code> if no 'space above' is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The 'space above'.
+ *
+ * @see #setSpaceAbove(MutableAttributeSet, float)
+ */
+ public static float getSpaceAbove(AttributeSet a)
+ {
+ Float f = (Float) a.getAttribute(SpaceAbove);
+ if (f != null)
+ return f.floatValue();
+ else
+ return 0.0f;
+ }
+
+ /**
+ * Returns the 'space below' specified in the given attributes, or
+ * <code>0.0f</code> if no 'space below' is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The 'space below'.
+ *
+ * @see #setSpaceBelow(MutableAttributeSet, float)
+ */
+ public static float getSpaceBelow(AttributeSet a)
+ {
+ Float f = (Float) a.getAttribute(SpaceBelow);
+ if (f != null)
+ return f.floatValue();
+ else
+ return 0.0f;
+ }
+
+ /**
+ * Returns the tab set specified in the given attributes, or
+ * <code>null</code> if no tab set is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The tab set.
+ *
+ * @see #setTabSet(MutableAttributeSet, javax.swing.text.TabSet)
+ */
+ public static javax.swing.text.TabSet getTabSet(AttributeSet a)
+ {
+ // I'm guessing that the fully qualified class name is to differentiate
+ // between the TabSet class and the TabSet (attribute) instance on some
+ // compiler...
+ return (javax.swing.text.TabSet) a.getAttribute(StyleConstants.TabSet);
+ }
+
+ /**
+ * Returns the value of the bold flag in the given attributes, or
+ * <code>false</code> if no bold flag is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The bold flag.
+ *
+ * @see #setBold(MutableAttributeSet, boolean)
+ */
+ public static boolean isBold(AttributeSet a)
+ {
+ Boolean b = (Boolean) a.getAttribute(Bold);
+ if (b != null)
+ return b.booleanValue();
+ else
+ return false;
+ }
+
+ /**
+ * Returns the value of the italic flag in the given attributes, or
+ * <code>false</code> if no italic flag is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The italic flag.
+ *
+ * @see #setItalic(MutableAttributeSet, boolean)
+ */
+ public static boolean isItalic(AttributeSet a)
+ {
+ Boolean b = (Boolean) a.getAttribute(Italic);
+ if (b != null)
+ return b.booleanValue();
+ else
+ return false;
+ }
+
+ /**
+ * Returns the value of the strike-through flag in the given attributes, or
+ * <code>false</code> if no strike-through flag is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The strike-through flag.
+ *
+ * @see #setStrikeThrough(MutableAttributeSet, boolean)
+ */
+ public static boolean isStrikeThrough(AttributeSet a)
+ {
+ Boolean b = (Boolean) a.getAttribute(StrikeThrough);
+ if (b != null)
+ return b.booleanValue();
+ else
+ return false;
+ }
+
+ /**
+ * Returns the value of the subscript flag in the given attributes, or
+ * <code>false</code> if no subscript flag is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The subscript flag.
+ *
+ * @see #setSubscript(MutableAttributeSet, boolean)
+ */
+ public static boolean isSubscript(AttributeSet a)
+ {
+ Boolean b = (Boolean) a.getAttribute(Subscript);
+ if (b != null)
+ return b.booleanValue();
+ else
+ return false;
+ }
+
+ /**
+ * Returns the value of the superscript flag in the given attributes, or
+ * <code>false</code> if no superscript flag is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The superscript flag.
+ *
+ * @see #setSuperscript(MutableAttributeSet, boolean)
+ */
+ public static boolean isSuperscript(AttributeSet a)
+ {
+ Boolean b = (Boolean) a.getAttribute(Superscript);
+ if (b != null)
+ return b.booleanValue();
+ else
+ return false;
+ }
+
+ /**
+ * Returns the value of the underline flag in the given attributes, or
+ * <code>false</code> if no underline flag is specified.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ *
+ * @return The underline flag.
+ *
+ * @see #setUnderline(MutableAttributeSet, boolean)
+ */
+ public static boolean isUnderline(AttributeSet a)
+ {
+ Boolean b = (Boolean) a.getAttribute(Underline);
+ if (b != null)
+ return b.booleanValue();
+ else
+ return false;
+ }
+
+ /**
+ * Adds an alignment attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param align the alignment (typically one of
+ * {@link StyleConstants#ALIGN_LEFT},
+ * {@link StyleConstants#ALIGN_RIGHT},
+ * {@link StyleConstants#ALIGN_CENTER} or
+ * {@link StyleConstants#ALIGN_JUSTIFIED}).
+ *
+ * @throws NullPointerException if <code>a</code> is <code>null</code>.
+ *
+ * @see #getAlignment(AttributeSet)
+ */
+ public static void setAlignment(MutableAttributeSet a, int align)
+ {
+ a.addAttribute(Alignment, new Integer(align));
+ }
+
+ /**
+ * Adds a background attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param bg the background (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either argument is <code>null</code>.
+ *
+ * @see #getBackground(AttributeSet)
+ */
+ public static void setBackground(MutableAttributeSet a, Color bg)
+ {
+ a.addAttribute(Background, bg);
+ }
+
+ /**
+ * Adds a bidi-level attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param lev the level.
+ *
+ * @throws NullPointerException if <code>a</code> is <code>null</code>.
+ *
+ * @see #getBidiLevel(AttributeSet)
+ */
+ public static void setBidiLevel(MutableAttributeSet a, int lev)
+ {
+ a.addAttribute(BidiLevel, new Integer(lev));
+ }
+
+ /**
+ * Adds a bold attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param b the new value of the bold attribute.
+ *
+ * @throws NullPointerException if <code>a</code> is <code>null</code>.
+ *
+ * @see #isBold(AttributeSet)
+ */
+ public static void setBold(MutableAttributeSet a, boolean b)
+ {
+ a.addAttribute(Bold, Boolean.valueOf(b));
+ }
+
+ /**
+ * Adds a component attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param c the component (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either argument is <code>null</code>.
+ *
+ * @see #getComponent(AttributeSet)
+ */
+ public static void setComponent(MutableAttributeSet a, Component c)
+ {
+ a.addAttribute(ComponentAttribute, c);
+ }
+
+ /**
+ * Adds a first line indentation attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param i the indentation.
+ *
+ * @throws NullPointerException if <code>a</code> is <code>null</code>.
+ *
+ * @see #getFirstLineIndent(AttributeSet)
+ */
+ public static void setFirstLineIndent(MutableAttributeSet a, float i)
+ {
+ a.addAttribute(FirstLineIndent, new Float(i));
+ }
+
+ /**
+ * Adds a font family attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param fam the font family name (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either argument is <code>null</code>.
+ *
+ * @see #getFontFamily(AttributeSet)
+ */
+ public static void setFontFamily(MutableAttributeSet a, String fam)
+ {
+ a.addAttribute(FontFamily, fam);
+ }
+
+ /**
+ * Adds a font size attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param s the font size (in points).
+ *
+ * @throws NullPointerException if <code>a</code> is <code>null</code>.
+ *
+ * @see #getFontSize(AttributeSet)
+ */
+ public static void setFontSize(MutableAttributeSet a, int s)
+ {
+ a.addAttribute(FontSize, new Integer(s));
+ }
+
+ /**
+ * Adds a foreground color attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param fg the foreground color (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either argument is <code>null</code>.
+ *
+ * @see #getForeground(AttributeSet)
+ */
+ public static void setForeground(MutableAttributeSet a, Color fg)
+ {
+ a.addAttribute(Foreground, fg);
+ }
+
+ /**
+ * Adds an icon attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param c the icon (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either argument is <code>null</code>.
+ *
+ * @see #getIcon(AttributeSet)
+ */
+ public static void setIcon(MutableAttributeSet a, Icon c)
+ {
+ a.addAttribute(IconAttribute, c);
+ }
+
+ /**
+ * Adds an italic attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param b the new value of the italic attribute.
+ *
+ * @throws NullPointerException if <code>a</code> is <code>null</code>.
+ *
+ * @see #isItalic(AttributeSet)
+ */
+ public static void setItalic(MutableAttributeSet a, boolean b)
+ {
+ a.addAttribute(Italic, Boolean.valueOf(b));
+ }
+
+ /**
+ * Adds a left indentation attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param i the indentation.
+ *
+ * @throws NullPointerException if <code>a</code> is <code>null</code>.
+ *
+ * @see #getLeftIndent(AttributeSet)
+ */
+ public static void setLeftIndent(MutableAttributeSet a, float i)
+ {
+ a.addAttribute(LeftIndent, new Float(i));
+ }
+
+ /**
+ * Adds a line spacing attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param i the line spacing.
+ *
+ * @throws NullPointerException if <code>a</code> is <code>null</code>.
+ *
+ * @see #getLineSpacing(AttributeSet)
+ */
+ public static void setLineSpacing(MutableAttributeSet a, float i)
+ {
+ a.addAttribute(LineSpacing, new Float(i));
+ }
+
+ /**
+ * Adds a right indentation attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param i the right indentation.
+ *
+ * @throws NullPointerException if <code>a</code> is <code>null</code>.
+ *
+ * @see #getRightIndent(AttributeSet)
+ */
+ public static void setRightIndent(MutableAttributeSet a, float i)
+ {
+ a.addAttribute(RightIndent, new Float(i));
+ }
+
+ /**
+ * Adds a 'space above' attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param i the space above attribute value.
+ *
+ * @throws NullPointerException if <code>a</code> is <code>null</code>.
+ *
+ * @see #getSpaceAbove(AttributeSet)
+ */
+ public static void setSpaceAbove(MutableAttributeSet a, float i)
+ {
+ a.addAttribute(SpaceAbove, new Float(i));
+ }
+
+ /**
+ * Adds a 'space below' attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param i the space below attribute value.
+ *
+ * @throws NullPointerException if <code>a</code> is <code>null</code>.
+ *
+ * @see #getSpaceBelow(AttributeSet)
+ */
+ public static void setSpaceBelow(MutableAttributeSet a, float i)
+ {
+ a.addAttribute(SpaceBelow, new Float(i));
+ }
+
+ /**
+ * Adds a strike-through attribue to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param b the strike-through attribute value.
+ *
+ * @throws NullPointerException if <code>a</code> is <code>null</code>.
+ *
+ * @see #isStrikeThrough(AttributeSet)
+ */
+ public static void setStrikeThrough(MutableAttributeSet a, boolean b)
+ {
+ a.addAttribute(StrikeThrough, Boolean.valueOf(b));
+ }
+
+ /**
+ * Adds a subscript attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param b the subscript attribute value.
+ *
+ * @throws NullPointerException if <code>a</code> is <code>null</code>.
+ *
+ * @see #isSubscript(AttributeSet)
+ */
+ public static void setSubscript(MutableAttributeSet a, boolean b)
+ {
+ a.addAttribute(Subscript, Boolean.valueOf(b));
+ }
+
+ /**
+ * Adds a superscript attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param b the superscript attribute value.
+ *
+ * @throws NullPointerException if <code>a</code> is <code>null</code>.
+ *
+ * @see #isSuperscript(AttributeSet)
+ */
+ public static void setSuperscript(MutableAttributeSet a, boolean b)
+ {
+ a.addAttribute(Superscript, Boolean.valueOf(b));
+ }
+
+ /**
+ * Adds a {@link TabSet} attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param tabs the tab set (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either argument is <code>null</code>.
+ *
+ * @see #getTabSet(AttributeSet)
+ */
+ public static void setTabSet(MutableAttributeSet a,
+ javax.swing.text.TabSet tabs)
+ {
+ a.addAttribute(StyleConstants.TabSet, tabs);
+ }
+
+ /**
+ * Adds an underline attribute to the specified set.
+ *
+ * @param a the attribute set (<code>null</code> not permitted).
+ * @param b the underline attribute value.
+ *
+ * @throws NullPointerException if <code>a</code> is <code>null</code>.
+ *
+ * @see #isUnderline(AttributeSet)
+ */
+ public static void setUnderline(MutableAttributeSet a, boolean b)
+ {
+ a.addAttribute(Underline, Boolean.valueOf(b));
+ }
+
+ // The remainder are so-called "typesafe enumerations" which
+ // alias subsets of the above constants.
+
+ /**
+ * A set of keys for attributes that apply to characters.
+ */
+ public static class CharacterConstants
+ extends StyleConstants
+ implements AttributeSet.CharacterAttribute
+ {
+ /**
+ * Private constructor prevents new instances being created.
+ *
+ * @param k the key name.
+ */
+ private CharacterConstants(String k)
+ {
+ super(k);
+ }
+
+ /** An alias for {@link ColorConstants#Background}. */
+ public static final Object Background = ColorConstants.Background;
+
+ /** A key for the bidi level character attribute. */
+ public static final Object BidiLevel = new CharacterConstants("bidiLevel");
+
+ /** An alias for {@link FontConstants#Bold}. */
+ public static final Object Bold = FontConstants.Bold;
+
+ /** A key for the component character attribute. */
+ public static final Object ComponentAttribute
+ = new CharacterConstants("component");
+
+ /** An alias for {@link FontConstants#Family}. */
+ public static final Object Family = FontConstants.Family;
+
+ /** An alias for {@link FontConstants#Size}. */
+ public static final Object Size = FontConstants.Size;
+
+ /** An alias for {@link ColorConstants#Foreground}. */
+ public static final Object Foreground = ColorConstants.Foreground;
+
+ /** A key for the icon character attribute. */
+ public static final Object IconAttribute = new CharacterConstants("icon");
+
+ /** A key for the italic character attribute. */
+ public static final Object Italic = FontConstants.Italic;
+
+ /** A key for the strike through character attribute. */
+ public static final Object StrikeThrough
+ = new CharacterConstants("strikethrough");
+
+ /** A key for the subscript character attribute. */
+ public static final Object Subscript = new CharacterConstants("subscript");
+
+ /** A key for the superscript character attribute. */
+ public static final Object Superscript
+ = new CharacterConstants("superscript");
+
+ /** A key for the underline character attribute. */
+ public static final Object Underline = new CharacterConstants("underline");
+
+ }
+
+ /**
+ * A set of keys for attributes that relate to colors.
+ */
+ public static class ColorConstants
+ extends StyleConstants
+ implements AttributeSet.ColorAttribute, AttributeSet.CharacterAttribute
+ {
+ /**
+ * Private constructor prevents new instances being created.
+ *
+ * @param k the key name.
+ */
+ private ColorConstants(String k)
+ {
+ super(k);
+ }
+
+ /** A key for the foreground color attribute. */
+ public static final Object Foreground = new ColorConstants("foreground");
+
+ /** A key for the background color attribute. */
+ public static final Object Background = new ColorConstants("background");
+ }
+
+ /**
+ * A set of keys for attributes that apply to fonts.
+ */
+ public static class FontConstants
+ extends StyleConstants
+ implements AttributeSet.FontAttribute, AttributeSet.CharacterAttribute
+ {
+ /**
+ * Private constructor prevents new instances being created.
+ *
+ * @param k the key name.
+ */
+ private FontConstants(String k)
+ {
+ super(k);
+ }
+
+ /** A key for the bold font attribute. */
+ public static final Object Bold = new FontConstants("bold");
+
+ /** A key for the family font attribute. */
+ public static final Object Family = new FontConstants("family");
+
+ /** A key for the italic font attribute. */
+ public static final Object Italic = new FontConstants("italic");
+
+ /** A key for the size font attribute. */
+ public static final Object Size = new FontConstants("size");
+ }
+
+ /**
+ * A set of keys for attributes that apply to paragraphs.
+ */
+ public static class ParagraphConstants
+ extends StyleConstants
+ implements AttributeSet.ParagraphAttribute
+ {
+ /**
+ * Private constructor prevents new instances being created.
+ *
+ * @param k the key name.
+ */
+ private ParagraphConstants(String k)
+ {
+ super(k);
+ }
+
+ /** A key for the alignment paragraph attribute. */
+ public static final Object Alignment = new ParagraphConstants("Alignment");
+
+ /** A key for the first line indentation paragraph attribute. */
+ public static final Object FirstLineIndent
+ = new ParagraphConstants("FirstLineIndent");
+
+ /** A key for the left indentation paragraph attribute. */
+ public static final Object LeftIndent
+ = new ParagraphConstants("LeftIndent");
+
+ /** A key for the line spacing paragraph attribute. */
+ public static final Object LineSpacing
+ = new ParagraphConstants("LineSpacing");
+
+ /** A key for the orientation paragraph attribute. */
+ public static final Object Orientation
+ = new ParagraphConstants("Orientation");
+
+ /** A key for the right indentation paragraph attribute. */
+ public static final Object RightIndent
+ = new ParagraphConstants("RightIndent");
+
+ /** A key for the 'space above' paragraph attribute. */
+ public static final Object SpaceAbove
+ = new ParagraphConstants("SpaceAbove");
+
+ /** A key for the 'space below' paragraph attribute. */
+ public static final Object SpaceBelow
+ = new ParagraphConstants("SpaceBelow");
+
+ /** A key for the tabset paragraph attribute. */
+ public static final Object TabSet = new ParagraphConstants("TabSet");
+
+ }
+
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyleContext.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyleContext.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyleContext.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyleContext.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,840 @@
+/* StyleContext.java --
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Toolkit;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.EventListener;
+import java.util.Hashtable;
+
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.EventListenerList;
+
+public class StyleContext
+ implements Serializable, AbstractDocument.AttributeContext
+{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 8042858831190784241L;
+
+ public class NamedStyle
+ implements Serializable, Style
+ {
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = -6690628971806226374L;
+
+ protected ChangeEvent changeEvent;
+ protected EventListenerList listenerList;
+
+ AttributeSet attributes;
+ String name;
+
+ public NamedStyle()
+ {
+ this(null, null);
+ }
+
+ public NamedStyle(Style parent)
+ {
+ this(null, parent);
+ }
+
+ public NamedStyle(String name, Style parent)
+ {
+ this.name = name;
+ this.attributes = getEmptySet();
+ this.changeEvent = new ChangeEvent(this);
+ this.listenerList = new EventListenerList();
+ setResolveParent(parent);
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName(String n)
+ {
+ name = n;
+ fireStateChanged();
+ }
+
+ public void addChangeListener(ChangeListener l)
+ {
+ listenerList.add(ChangeListener.class, l);
+ }
+
+ public void removeChangeListener(ChangeListener l)
+ {
+ listenerList.remove(ChangeListener.class, l);
+ }
+
+ public EventListener[] getListeners(Class listenerType)
+ {
+ return listenerList.getListeners(listenerType);
+ }
+
+ public ChangeListener[] getChangeListeners()
+ {
+ return (ChangeListener[]) getListeners(ChangeListener.class);
+ }
+
+ protected void fireStateChanged()
+ {
+ ChangeListener[] listeners = getChangeListeners();
+ for (int i = 0; i < listeners.length; ++i)
+ {
+ listeners[i].stateChanged(changeEvent);
+ }
+ }
+
+ public void addAttribute(Object name, Object value)
+ {
+ attributes = StyleContext.this.addAttribute(attributes, name, value);
+ fireStateChanged();
+ }
+
+ public void addAttributes(AttributeSet attr)
+ {
+ attributes = StyleContext.this.addAttributes(attributes, attr);
+ fireStateChanged();
+ }
+
+ public boolean containsAttribute(Object name, Object value)
+ {
+ return attributes.containsAttribute(name, value);
+ }
+
+ public boolean containsAttributes(AttributeSet attrs)
+ {
+ return attributes.containsAttributes(attrs);
+ }
+
+ public AttributeSet copyAttributes()
+ {
+ return attributes.copyAttributes();
+ }
+
+ public Object getAttribute(Object attrName)
+ {
+ return attributes.getAttribute(attrName);
+ }
+
+ public int getAttributeCount()
+ {
+ return attributes.getAttributeCount();
+ }
+
+ public Enumeration getAttributeNames()
+ {
+ return attributes.getAttributeNames();
+ }
+
+ public boolean isDefined(Object attrName)
+ {
+ return attributes.isDefined(attrName);
+ }
+
+ public boolean isEqual(AttributeSet attr)
+ {
+ return attributes.isEqual(attr);
+ }
+
+ public void removeAttribute(Object name)
+ {
+ attributes = StyleContext.this.removeAttribute(attributes, name);
+ fireStateChanged();
+ }
+
+ public void removeAttributes(AttributeSet attrs)
+ {
+ attributes = StyleContext.this.removeAttributes(attributes, attrs);
+ fireStateChanged();
+ }
+
+ public void removeAttributes(Enumeration names)
+ {
+ attributes = StyleContext.this.removeAttributes(attributes, names);
+ fireStateChanged();
+ }
+
+
+ public AttributeSet getResolveParent()
+ {
+ return attributes.getResolveParent();
+ }
+
+ public void setResolveParent(AttributeSet parent)
+ {
+ if (parent != null)
+ {
+ attributes = StyleContext.this.addAttribute
+ (attributes, ResolveAttribute, parent);
+ }
+ fireStateChanged();
+ }
+
+ public String toString()
+ {
+ return ("[NamedStyle: name=" + name + ", attrs=" + attributes.toString() + "]");
+ }
+ }
+
+ public class SmallAttributeSet
+ implements AttributeSet
+ {
+ final Object [] attrs;
+ public SmallAttributeSet(AttributeSet a)
+ {
+ if (a == null)
+ attrs = new Object[0];
+ else
+ {
+ int n = a.getAttributeCount();
+ int i = 0;
+ attrs = new Object[n * 2];
+ Enumeration e = a.getAttributeNames();
+ while (e.hasMoreElements())
+ {
+ Object name = e.nextElement();
+ attrs[i++] = name;
+ attrs[i++] = a.getAttribute(name);
+ }
+ }
+ }
+
+ public SmallAttributeSet(Object [] a)
+ {
+ if (a == null)
+ attrs = new Object[0];
+ else
+ {
+ attrs = new Object[a.length];
+ System.arraycopy(a, 0, attrs, 0, a.length);
+ }
+ }
+
+ public Object clone()
+ {
+ return new SmallAttributeSet(this.attrs);
+ }
+
+ public boolean containsAttribute(Object name, Object value)
+ {
+ for (int i = 0; i < attrs.length; i += 2)
+ {
+ if (attrs[i].equals(name) &&
+ attrs[i+1].equals(value))
+ return true;
+ }
+ return false;
+ }
+
+ public boolean containsAttributes(AttributeSet a)
+ {
+ Enumeration e = a.getAttributeNames();
+ while (e.hasMoreElements())
+ {
+ Object name = e.nextElement();
+ Object val = a.getAttribute(name);
+ if (!containsAttribute(name, val))
+ return false;
+ }
+ return true;
+ }
+
+ public AttributeSet copyAttributes()
+ {
+ return (AttributeSet) clone();
+ }
+
+ public boolean equals(Object obj)
+ {
+ return
+ (obj instanceof AttributeSet)
+ && this.isEqual((AttributeSet)obj);
+ }
+
+ public Object getAttribute(Object key)
+ {
+ for (int i = 0; i < attrs.length; i += 2)
+ {
+ if (attrs[i].equals(key))
+ return attrs[i+1];
+ }
+
+ // Check the resolve parent, unless we're looking for the
+ // ResolveAttribute, which would cause an infinite loop
+ if (!(key.equals(ResolveAttribute)))
+ {
+ Object p = getResolveParent();
+ if (p != null && p instanceof AttributeSet)
+ return (((AttributeSet)p).getAttribute(key));
+ }
+
+ return null;
+ }
+
+ public int getAttributeCount()
+ {
+ return attrs.length / 2;
+ }
+
+ public Enumeration getAttributeNames()
+ {
+ return new Enumeration()
+ {
+ int i = 0;
+ public boolean hasMoreElements()
+ {
+ return i < attrs.length;
+ }
+ public Object nextElement()
+ {
+ i += 2;
+ return attrs[i-2];
+ }
+ };
+ }
+
+ public AttributeSet getResolveParent()
+ {
+ return (AttributeSet) getAttribute(ResolveAttribute);
+ }
+
+ public int hashCode()
+ {
+ return java.util.Arrays.asList(attrs).hashCode();
+ }
+
+ public boolean isDefined(Object key)
+ {
+ for (int i = 0; i < attrs.length; i += 2)
+ {
+ if (attrs[i].equals(key))
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isEqual(AttributeSet attr)
+ {
+ return getAttributeCount() == attr.getAttributeCount()
+ && this.containsAttributes(attr);
+ }
+
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append("[StyleContext.SmallattributeSet:");
+ for (int i = 0; i < attrs.length - 1; ++i)
+ {
+ sb.append(" (");
+ sb.append(attrs[i].toString());
+ sb.append("=");
+ sb.append(attrs[i+1].toString());
+ sb.append(")");
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+ }
+
+ // FIXME: official javadocs suggest that these might be more usefully
+ // implemented using a WeakHashMap, but not sure if that works most
+ // places or whether it really matters anyways.
+ //
+ // FIXME: also not sure if these tables ought to be static (singletons),
+ // shared across all StyleContexts. I think so, but it's not clear in
+ // docs. revert to non-shared if you think it matters.
+
+ /**
+ * The name of the default style.
+ */
+ public static final String DEFAULT_STYLE = "default";
+
+ /**
+ * The default style for this style context.
+ */
+ NamedStyle defaultStyle = new NamedStyle(DEFAULT_STYLE, null);
+
+ static Hashtable sharedAttributeSets = new Hashtable();
+ static Hashtable sharedFonts = new Hashtable();
+
+ static StyleContext defaultStyleContext = new StyleContext();
+ static final int compressionThreshold = 9;
+
+ /**
+ * These attribute keys are handled specially in serialization.
+ */
+ private static Hashtable staticAttributeKeys = new Hashtable();
+
+ EventListenerList listenerList;
+ Hashtable styleTable;
+
+ /**
+ * Creates a new instance of the style context. Add the default style
+ * to the style table.
+ */
+ public StyleContext()
+ {
+ listenerList = new EventListenerList();
+ styleTable = new Hashtable();
+ styleTable.put(DEFAULT_STYLE, defaultStyle);
+ }
+
+ protected SmallAttributeSet createSmallAttributeSet(AttributeSet a)
+ {
+ return new SmallAttributeSet(a);
+ }
+
+ protected MutableAttributeSet createLargeAttributeSet(AttributeSet a)
+ {
+ return new SimpleAttributeSet(a);
+ }
+
+ public void addChangeListener(ChangeListener listener)
+ {
+ listenerList.add(ChangeListener.class, listener);
+ }
+
+ public void removeChangeListener(ChangeListener listener)
+ {
+ listenerList.remove(ChangeListener.class, listener);
+ }
+
+ public ChangeListener[] getChangeListeners()
+ {
+ return (ChangeListener[]) listenerList.getListeners(ChangeListener.class);
+ }
+
+ public Style addStyle(String name, Style parent)
+ {
+ Style newStyle = new NamedStyle(name, parent);
+ if (name != null)
+ styleTable.put(name, newStyle);
+ return newStyle;
+ }
+
+ public void removeStyle(String name)
+ {
+ styleTable.remove(name);
+ }
+
+ /**
+ * Get the style from the style table. If the passed name
+ * matches {@link #DEFAULT_STYLE}, returns the default style.
+ * Otherwise returns the previously defined style of
+ * <code>null</code> if the style with the given name is not defined.
+ *
+ * @param name the name of the style.
+ *
+ * @return the style with the given name or null if no such defined.
+ */
+ public Style getStyle(String name)
+ {
+ return (Style) styleTable.get(name);
+ }
+
+ /**
+ * Get the names of the style. The returned enumeration always
+ * contains at least one member, the default style.
+ */
+ public Enumeration getStyleNames()
+ {
+ return styleTable.keys();
+ }
+
+ //
+ // StyleContexts only understand the "simple" model of fonts present in
+ // pre-java2d systems: fonts are a family name, a size (integral number
+ // of points), and a mask of style parameters (plain, bold, italic, or
+ // bold|italic). We have an inner class here called SimpleFontSpec which
+ // holds such triples.
+ //
+ // A SimpleFontSpec can be built for *any* AttributeSet because the size,
+ // family, and style keys in an AttributeSet have default values (defined
+ // over in StyleConstants).
+ //
+ // We keep a static cache mapping SimpleFontSpecs to java.awt.Fonts, so
+ // that we reuse Fonts between styles and style contexts.
+ //
+
+ private static class SimpleFontSpec
+ {
+ String family;
+ int style;
+ int size;
+ public SimpleFontSpec(String family,
+ int style,
+ int size)
+ {
+ this.family = family;
+ this.style = style;
+ this.size = size;
+ }
+ public boolean equals(Object obj)
+ {
+ return (obj != null)
+ && (obj instanceof SimpleFontSpec)
+ && (((SimpleFontSpec)obj).family.equals(this.family))
+ && (((SimpleFontSpec)obj).style == this.style)
+ && (((SimpleFontSpec)obj).size == this.size);
+ }
+ public int hashCode()
+ {
+ return family.hashCode() + style + size;
+ }
+ }
+
+ public Font getFont(AttributeSet attr)
+ {
+ String family = StyleConstants.getFontFamily(attr);
+ int style = Font.PLAIN;
+ if (StyleConstants.isBold(attr))
+ style += Font.BOLD;
+ if (StyleConstants.isItalic(attr))
+ style += Font.ITALIC;
+ int size = StyleConstants.getFontSize(attr);
+ return getFont(family, style, size);
+ }
+
+ public Font getFont(String family, int style, int size)
+ {
+ SimpleFontSpec spec = new SimpleFontSpec(family, style, size);
+ if (sharedFonts.containsKey(spec))
+ return (Font) sharedFonts.get(spec);
+ else
+ {
+ Font tmp = new Font(family, style, size);
+ sharedFonts.put(spec, tmp);
+ return tmp;
+ }
+ }
+
+ public FontMetrics getFontMetrics(Font f)
+ {
+ return Toolkit.getDefaultToolkit().getFontMetrics(f);
+ }
+
+ public Color getForeground(AttributeSet a)
+ {
+ return StyleConstants.getForeground(a);
+ }
+
+ public Color getBackground(AttributeSet a)
+ {
+ return StyleConstants.getBackground(a);
+ }
+
+ protected int getCompressionThreshold()
+ {
+ return compressionThreshold;
+ }
+
+ public static StyleContext getDefaultStyleContext()
+ {
+ return defaultStyleContext;
+ }
+
+ public AttributeSet addAttribute(AttributeSet old, Object name, Object value)
+ {
+ if (old instanceof MutableAttributeSet)
+ {
+ ((MutableAttributeSet)old).addAttribute(name, value);
+ return old;
+ }
+ else
+ {
+ MutableAttributeSet mutable = createLargeAttributeSet(old);
+ mutable.addAttribute(name, value);
+ if (mutable.getAttributeCount() >= getCompressionThreshold())
+ return mutable;
+ else
+ {
+ SmallAttributeSet small = createSmallAttributeSet(mutable);
+ if (sharedAttributeSets.containsKey(small))
+ small = (SmallAttributeSet) sharedAttributeSets.get(small);
+ else
+ sharedAttributeSets.put(small,small);
+ return small;
+ }
+ }
+ }
+
+ public AttributeSet addAttributes(AttributeSet old, AttributeSet attributes)
+ {
+ if (old instanceof MutableAttributeSet)
+ {
+ ((MutableAttributeSet)old).addAttributes(attributes);
+ return old;
+ }
+ else
+ {
+ MutableAttributeSet mutable = createLargeAttributeSet(old);
+ mutable.addAttributes(attributes);
+ if (mutable.getAttributeCount() >= getCompressionThreshold())
+ return mutable;
+ else
+ {
+ SmallAttributeSet small = createSmallAttributeSet(mutable);
+ if (sharedAttributeSets.containsKey(small))
+ small = (SmallAttributeSet) sharedAttributeSets.get(small);
+ else
+ sharedAttributeSets.put(small,small);
+ return small;
+ }
+ }
+ }
+
+ public AttributeSet getEmptySet()
+ {
+ AttributeSet e = createSmallAttributeSet(null);
+ if (sharedAttributeSets.containsKey(e))
+ e = (AttributeSet) sharedAttributeSets.get(e);
+ else
+ sharedAttributeSets.put(e, e);
+ return e;
+ }
+
+ public void reclaim(AttributeSet attributes)
+ {
+ if (sharedAttributeSets.containsKey(attributes))
+ sharedAttributeSets.remove(attributes);
+ }
+
+ public AttributeSet removeAttribute(AttributeSet old, Object name)
+ {
+ if (old instanceof MutableAttributeSet)
+ {
+ ((MutableAttributeSet)old).removeAttribute(name);
+ if (old.getAttributeCount() < getCompressionThreshold())
+ {
+ SmallAttributeSet small = createSmallAttributeSet(old);
+ if (!sharedAttributeSets.containsKey(small))
+ sharedAttributeSets.put(small,small);
+ old = (AttributeSet) sharedAttributeSets.get(small);
+ }
+ return old;
+ }
+ else
+ {
+ MutableAttributeSet mutable = createLargeAttributeSet(old);
+ mutable.removeAttribute(name);
+ SmallAttributeSet small = createSmallAttributeSet(mutable);
+ if (sharedAttributeSets.containsKey(small))
+ small = (SmallAttributeSet) sharedAttributeSets.get(small);
+ else
+ sharedAttributeSets.put(small,small);
+ return small;
+ }
+ }
+
+ public AttributeSet removeAttributes(AttributeSet old, AttributeSet attributes)
+ {
+ return removeAttributes(old, attributes.getAttributeNames());
+ }
+
+ public AttributeSet removeAttributes(AttributeSet old, Enumeration names)
+ {
+ if (old instanceof MutableAttributeSet)
+ {
+ ((MutableAttributeSet)old).removeAttributes(names);
+ if (old.getAttributeCount() < getCompressionThreshold())
+ {
+ SmallAttributeSet small = createSmallAttributeSet(old);
+ if (!sharedAttributeSets.containsKey(small))
+ sharedAttributeSets.put(small,small);
+ old = (AttributeSet) sharedAttributeSets.get(small);
+ }
+ return old;
+ }
+ else
+ {
+ MutableAttributeSet mutable = createLargeAttributeSet(old);
+ mutable.removeAttributes(names);
+ SmallAttributeSet small = createSmallAttributeSet(mutable);
+ if (sharedAttributeSets.containsKey(small))
+ small = (SmallAttributeSet) sharedAttributeSets.get(small);
+ else
+ sharedAttributeSets.put(small,small);
+ return small;
+ }
+ }
+
+ /**
+ * Gets the object previously registered with registerStaticAttributeKey.
+ *
+ * @param key - the key that was registered.
+ * @return the object previously registered with registerStaticAttributeKey.
+ */
+ public static Object getStaticAttribute(Object key)
+ {
+ if (key == null)
+ return null;
+ return staticAttributeKeys.get(key);
+ }
+
+ /**
+ * Returns the String that key will be registered with
+ * registerStaticAttributeKey.
+ *
+ * @param key - the key that will be registered.
+ * @return the string the key will be registered with.
+ */
+ public static Object getStaticAttributeKey(Object key)
+ {
+ return key.getClass().getName() + "." + key.toString();
+ }
+
+ /**
+ * Reads a set of attributes from the given object input stream. This will
+ * attempt to restore keys that were static objects by considering only the
+ * keys that have were registered with registerStaticAttributeKey. The
+ * attributes retrieved will be placed into the given set.
+ *
+ * @param in - the stream to read from
+ * @param a - the set of attributes
+ * @throws ClassNotFoundException - may be encountered when reading from
+ * stream
+ * @throws IOException - any I/O error
+ */
+ public static void readAttributeSet(ObjectInputStream in, MutableAttributeSet a)
+ throws ClassNotFoundException, IOException
+ {
+ if (in == null || a == null)
+ return;
+
+ Object key = in.readObject();
+ Object val = in.readObject();
+ while (key != null && val != null)
+ {
+ Object staticKey = staticAttributeKeys.get(key);
+ Object staticVal = staticAttributeKeys.get(val);
+
+ if (staticKey != null)
+ key = staticKey;
+ if (staticVal != null)
+ val = staticVal;
+
+ a.addAttribute(key, val);
+ key = in.readObject();
+ val = in.readObject();
+ }
+ }
+
+ /**
+ * Serialize an attribute set in a way that is compatible with it
+ * being read in again by {@link #readAttributeSet(ObjectInputStream, MutableAttributeSet)}.
+ * In particular registered static keys are transformed properly.
+ *
+ * @param out - stream to write to
+ * @param a - the attribute set
+ * @throws IOException - any I/O error
+ */
+ public static void writeAttributeSet(ObjectOutputStream out, AttributeSet a)
+ throws IOException
+ {
+ Enumeration e = a.getAttributeNames();
+ while (e.hasMoreElements())
+ {
+ Object oldKey = e.nextElement();
+ Object newKey = getStaticAttribute(oldKey);
+ Object key = (newKey == null) ? oldKey : newKey;
+
+ out.writeObject(key);
+ out.writeObject(a.getAttribute(oldKey));
+ }
+ out.writeObject(null);
+ out.writeObject(null);
+ }
+
+ /**
+ * Handles reading in the attributes.
+ * @see #readAttributeSet(ObjectInputStream, MutableAttributeSet)
+ *
+ * @param in - the stream to read from
+ * @param a - the set of attributes
+ * @throws ClassNotFoundException - may be encountered when reading from stream
+ * @throws IOException - any I/O error
+ */
+ public void readAttributes(ObjectInputStream in, MutableAttributeSet a)
+ throws ClassNotFoundException, IOException
+ {
+ readAttributeSet(in, a);
+ }
+
+ /**
+ * Handles writing of the given attributes.
+ * @see #writeAttributeSet(ObjectOutputStream, AttributeSet)
+ *
+ * @param out - stream to write to
+ * @param a - the attribute set
+ * @throws IOException - any I/O error
+ */
+ public void writeAttributes(ObjectOutputStream out, AttributeSet a)
+ throws IOException
+ {
+ writeAttributeSet(out, a);
+ }
+
+ /**
+ * Registers an attribute key as a well-known keys. When an attribute with
+ * such a key is written to a stream, a special syntax is used so that it
+ * can be recognized when it is read back in. All attribute keys defined
+ * in <code>StyleContext</code> are registered as static keys. If you define
+ * additional attribute keys that you want to exist as nonreplicated objects,
+ * then you should register them using this method.
+ *
+ * @param key the key to register as static attribute key
+ */
+ public static void registerStaticAttributeKey(Object key)
+ {
+ if (key != null)
+ staticAttributeKeys.put(key.getClass().getName() + "." + key.toString(),
+ key);
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyledDocument.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyledDocument.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyledDocument.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyledDocument.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,140 @@
+/* StyledDcoument.java --
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.awt.Color;
+import java.awt.Font;
+
+/**
+ * StyledDocument
+ * @author Andrew Selkirk
+ * @version 1.0
+ */
+public interface StyledDocument extends Document
+{
+ /**
+ * addStyle
+ * @param nm TODO
+ * @param parent TODO
+ * @returns Style
+ */
+ Style addStyle(String nm, Style parent);
+
+ /**
+ * removeStyle
+ * @param nm TODO
+ */
+ void removeStyle(String nm);
+
+ /**
+ * getStyle
+ * @param nm TODO
+ * @returns Style
+ */
+ Style getStyle(String nm);
+
+ /**
+ * setCharacterAttributes
+ * @param offset TODO
+ * @param length TODO
+ * @param set TODO
+ * @param replace TODO
+ */
+ void setCharacterAttributes(int offset, int length, AttributeSet set,
+ boolean replace);
+
+ /**
+ * setParagraphAttributes
+ * @param offset TODO
+ * @param length TODO
+ * @param set TODO
+ * @param replace TODO
+ */
+ void setParagraphAttributes(int offset, int length, AttributeSet set,
+ boolean replace);
+
+ /**
+ * getLogicalStyle
+ * @param position TODO
+ * @returns Style
+ */
+ Style getLogicalStyle(int position);
+
+ /**
+ * setLogicalStyle
+ * @param position TODO
+ * @param style TODO
+ */
+ void setLogicalStyle(int position, Style style);
+
+ /**
+ * getParagraphElement
+ * @param position TODO
+ * @returns Element
+ */
+ Element getParagraphElement(int position);
+
+ /**
+ * getCharacterElement
+ * @param position TODO
+ * @returns Element
+ */
+ Element getCharacterElement(int position);
+
+ /**
+ * getForeground
+ * @param set TODO
+ * @returns Color
+ */
+ Color getForeground(AttributeSet set);
+
+ /**
+ * getBackground
+ * @param set TODO
+ * @returns Color
+ */
+ Color getBackground(AttributeSet set);
+
+ /**
+ * getFont
+ * @param set TODO
+ * @returns Font
+ */
+ Font getFont(AttributeSet set);
+
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyledEditorKit.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyledEditorKit.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyledEditorKit.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/StyledEditorKit.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,721 @@
+/* StyledEditorKit.java --
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text;
+
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+
+import javax.swing.Action;
+import javax.swing.JEditorPane;
+import javax.swing.event.CaretEvent;
+import javax.swing.event.CaretListener;
+
+/**
+ * An {@link EditorKit} that supports editing styled text.
+ *
+ * @author Andrew Selkirk
+ * @author Roman Kennke (roman at kennke.org)
+ */
+public class StyledEditorKit extends DefaultEditorKit
+{
+ /** The serialVersionUID. */
+ private static final long serialVersionUID = 7002391892985555948L;
+
+ /**
+ * Toggles the underline attribute for the selected text.
+ */
+ public static class UnderlineAction extends StyledEditorKit.StyledTextAction
+ {
+ /**
+ * Creates an instance of <code>UnderlineAction</code>.
+ */
+ public UnderlineAction()
+ {
+ super("font-underline");
+ }
+
+ /**
+ * Performs the action.
+ *
+ * @param event the <code>ActionEvent</code> that describes the action
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ JEditorPane editor = getEditor(event);
+ StyledDocument doc = getStyledDocument(editor);
+ Element el = doc.getCharacterElement(editor.getSelectionStart());
+ boolean isUnderline = StyleConstants.isUnderline(el.getAttributes());
+ SimpleAttributeSet atts = new SimpleAttributeSet();
+ StyleConstants.setUnderline(atts, ! isUnderline);
+ setCharacterAttributes(editor, atts, false);
+ }
+ }
+
+ /**
+ * Toggles the italic attribute for the selected text.
+ */
+ public static class ItalicAction extends StyledEditorKit.StyledTextAction
+ {
+ /**
+ * Creates an instance of <code>ItalicAction</code>.
+ */
+ public ItalicAction()
+ {
+ super("font-italic");
+ }
+
+ /**
+ * Performs the action.
+ *
+ * @param event the <code>ActionEvent</code> that describes the action
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ JEditorPane editor = getEditor(event);
+ StyledDocument doc = getStyledDocument(editor);
+ Element el = doc.getCharacterElement(editor.getSelectionStart());
+ boolean isItalic = StyleConstants.isItalic(el.getAttributes());
+ SimpleAttributeSet atts = new SimpleAttributeSet();
+ StyleConstants.setItalic(atts, ! isItalic);
+ setCharacterAttributes(editor, atts, false);
+ }
+ }
+
+ /**
+ * Toggles the bold attribute for the selected text.
+ */
+ public static class BoldAction extends StyledEditorKit.StyledTextAction
+ {
+ /**
+ * Creates an instance of <code>BoldAction</code>.
+ */
+ public BoldAction()
+ {
+ super("font-bold");
+ }
+
+ /**
+ * Performs the action.
+ *
+ * @param event the <code>ActionEvent</code> that describes the action
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ JEditorPane editor = getEditor(event);
+ StyledDocument doc = getStyledDocument(editor);
+ Element el = doc.getCharacterElement(editor.getSelectionStart());
+ boolean isBold = StyleConstants.isBold(el.getAttributes());
+ SimpleAttributeSet atts = new SimpleAttributeSet();
+ StyleConstants.setItalic(atts, ! isBold);
+ setCharacterAttributes(editor, atts, false);
+ }
+ }
+
+ /**
+ * Sets the alignment attribute on the selected text.
+ */
+ public static class AlignmentAction extends StyledEditorKit.StyledTextAction
+ {
+ /**
+ * The aligment to set.
+ */
+ private int a;
+
+ /**
+ * Creates a new instance of <code>AlignmentAction</code> to set the
+ * alignment to <code>a</code>.
+ *
+ * @param nm the name of the Action
+ * @param a the alignment to set
+ */
+ public AlignmentAction(String nm, int a)
+ {
+ super(nm);
+ this.a = a;
+ }
+
+ /**
+ * Performs the action.
+ *
+ * @param event the <code>ActionEvent</code> that describes the action
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ SimpleAttributeSet atts = new SimpleAttributeSet();
+ StyleConstants.setAlignment(atts, a);
+ setParagraphAttributes(getEditor(event), atts, false);
+ }
+ }
+
+ /**
+ * Sets the foreground color attribute on the selected text.
+ */
+ public static class ForegroundAction extends StyledEditorKit.StyledTextAction
+ {
+ /**
+ * The foreground color to set.
+ */
+ private Color fg;
+
+ /**
+ * Creates a new instance of <code>ForegroundAction</code> to set the
+ * foreground color to <code>fg</code>.
+ *
+ * @param nm the name of the Action
+ * @param fg the foreground color to set
+ */
+ public ForegroundAction(String nm, Color fg)
+ {
+ super(nm);
+ this.fg = fg;
+ }
+
+ /**
+ * Performs the action.
+ *
+ * @param event the <code>ActionEvent</code> that describes the action
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ SimpleAttributeSet atts = new SimpleAttributeSet();
+ StyleConstants.setForeground(atts, fg);
+ setCharacterAttributes(getEditor(event), atts, false);
+ }
+ }
+
+ /**
+ * Sets the font size attribute on the selected text.
+ */
+ public static class FontSizeAction extends StyledEditorKit.StyledTextAction
+ {
+ /**
+ * The font size to set.
+ */
+ private int size;
+
+ /**
+ * Creates a new instance of <code>FontSizeAction</code> to set the
+ * font size to <code>size</code>.
+ *
+ * @param nm the name of the Action
+ * @param size the font size to set
+ */
+ public FontSizeAction(String nm, int size)
+ {
+ super(nm);
+ this.size = size;
+ }
+
+ /**
+ * Performs the action.
+ *
+ * @param event the <code>ActionEvent</code> that describes the action
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ SimpleAttributeSet atts = new SimpleAttributeSet();
+ StyleConstants.setFontSize(atts, size);
+ setCharacterAttributes(getEditor(event), atts, false);
+ }
+ }
+
+ /**
+ * Sets the font family attribute on the selected text.
+ */
+ public static class FontFamilyAction extends StyledEditorKit.StyledTextAction
+ {
+ /**
+ * The font family to set.
+ */
+ private String family;
+
+ /**
+ * Creates a new instance of <code>FontFamilyAction</code> to set the
+ * font family to <code>family</code>.
+ *
+ * @param nm the name of the Action
+ * @param family the font family to set
+ */
+ public FontFamilyAction(String nm, String family)
+ {
+ super(nm);
+ this.family = family;
+ }
+
+ /**
+ * Performs the action.
+ *
+ * @param event the <code>ActionEvent</code> that describes the action
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ SimpleAttributeSet atts = new SimpleAttributeSet();
+ StyleConstants.setFontFamily(atts, family);
+ setCharacterAttributes(getEditor(event), atts, false);
+ }
+ }
+
+ /**
+ * The abstract superclass of all styled TextActions. This class
+ * provides some useful methods to manipulate the text attributes.
+ */
+ public abstract static class StyledTextAction extends TextAction
+ {
+ /**
+ * Creates a new instance of <code>StyledTextAction</code>.
+ *
+ * @param nm the name of the <code>StyledTextAction</code>
+ */
+ public StyledTextAction(String nm)
+ {
+ super(nm);
+ }
+
+ /**
+ * Returns the <code>JEditorPane</code> component from which the
+ * <code>ActionEvent</code> originated.
+ *
+ * @param event the <code>ActionEvent</code>
+ * @return the <code>JEditorPane</code> component from which the
+ * <code>ActionEvent</code> originated
+ */
+ protected final JEditorPane getEditor(ActionEvent event)
+ {
+ return (JEditorPane) getTextComponent(event);
+ }
+
+ /**
+ * Sets the specified character attributes on the currently selected
+ * text of <code>editor</code>. If <code>editor</code> does not have
+ * a selection, then the attributes are used as input attributes
+ * for newly inserted content.
+ *
+ * @param editor the <code>JEditorPane</code> component
+ * @param atts the text attributes to set
+ * @param replace if <code>true</code> the current attributes of the
+ * selection are replaces, otherwise they are merged
+ */
+ protected final void setCharacterAttributes(JEditorPane editor,
+ AttributeSet atts,
+ boolean replace)
+ {
+ Document doc = editor.getDocument();
+ if (doc instanceof StyledDocument)
+ {
+ StyledDocument styleDoc = (StyledDocument) editor.getDocument();
+ EditorKit kit = editor.getEditorKit();
+ if (!(kit instanceof StyledEditorKit))
+ {
+ StyledEditorKit styleKit = (StyledEditorKit) kit;
+ int start = editor.getSelectionStart();
+ int end = editor.getSelectionEnd();
+ int dot = editor.getCaret().getDot();
+ if (start == dot && end == dot)
+ {
+ // If there is no selection, then we only update the
+ // input attributes.
+ MutableAttributeSet inputAttributes =
+ styleKit.getInputAttributes();
+ inputAttributes.addAttributes(atts);
+ }
+ else
+ styleDoc.setCharacterAttributes(start, end, atts, replace);
+ }
+ else
+ throw new AssertionError("The EditorKit for StyledTextActions "
+ + "is expected to be a StyledEditorKit");
+ }
+ else
+ throw new AssertionError("The Document for StyledTextActions is "
+ + "expected to be a StyledDocument.");
+ }
+
+ /**
+ * Returns the {@link StyledDocument} that is used by <code>editor</code>.
+ *
+ * @param editor the <code>JEditorPane</code> from which to get the
+ * <code>StyledDocument</code>
+ *
+ * @return the {@link StyledDocument} that is used by <code>editor</code>
+ */
+ protected final StyledDocument getStyledDocument(JEditorPane editor)
+ {
+ Document doc = editor.getDocument();
+ if (!(doc instanceof StyledDocument))
+ throw new AssertionError("The Document for StyledEditorKits is "
+ + "expected to be a StyledDocument.");
+
+ return (StyledDocument) doc;
+ }
+
+ /**
+ * Returns the {@link StyledEditorKit} that is used by <code>editor</code>.
+ *
+ * @param editor the <code>JEditorPane</code> from which to get the
+ * <code>StyledEditorKit</code>
+ *
+ * @return the {@link StyledEditorKit} that is used by <code>editor</code>
+ */
+ protected final StyledEditorKit getStyledEditorKit(JEditorPane editor)
+ {
+ EditorKit kit = editor.getEditorKit();
+ if (!(kit instanceof StyledEditorKit))
+ throw new AssertionError("The EditorKit for StyledDocuments is "
+ + "expected to be a StyledEditorKit.");
+
+ return (StyledEditorKit) kit;
+ }
+
+ /**
+ * Sets the specified character attributes on the paragraph that
+ * contains the currently selected
+ * text of <code>editor</code>. If <code>editor</code> does not have
+ * a selection, then the attributes are set on the paragraph that
+ * contains the current caret position.
+ *
+ * @param editor the <code>JEditorPane</code> component
+ * @param atts the text attributes to set
+ * @param replace if <code>true</code> the current attributes of the
+ * selection are replaces, otherwise they are merged
+ */
+ protected final void setParagraphAttributes(JEditorPane editor,
+ AttributeSet atts,
+ boolean replace)
+ {
+ Document doc = editor.getDocument();
+ if (doc instanceof StyledDocument)
+ {
+ StyledDocument styleDoc = (StyledDocument) editor.getDocument();
+ EditorKit kit = editor.getEditorKit();
+ if (!(kit instanceof StyledEditorKit))
+ {
+ StyledEditorKit styleKit = (StyledEditorKit) kit;
+ int start = editor.getSelectionStart();
+ int end = editor.getSelectionEnd();
+ int dot = editor.getCaret().getDot();
+ if (start == dot && end == dot)
+ {
+ // If there is no selection, then we only update the
+ // input attributes.
+ MutableAttributeSet inputAttributes =
+ styleKit.getInputAttributes();
+ inputAttributes.addAttributes(atts);
+ }
+ else
+ styleDoc.setParagraphAttributes(start, end, atts, replace);
+ }
+ else
+ throw new AssertionError("The EditorKit for StyledTextActions "
+ + "is expected to be a StyledEditorKit");
+ }
+ else
+ throw new AssertionError("The Document for StyledTextActions is "
+ + "expected to be a StyledDocument.");
+ }
+ }
+
+ /**
+ * A {@link ViewFactory} that is able to create {@link View}s for
+ * the <code>Element</code>s that are supported by
+ * <code>StyledEditorKit</code>, namely the following types of Elements:
+ *
+ * <ul>
+ * <li>{@link AbstractDocument#ContentElementName}</li>
+ * <li>{@link AbstractDocument#ParagraphElementName}</li>
+ * <li>{@link AbstractDocument#SectionElementName}</li>
+ * <li>{@link StyleConstants#ComponentElementName}</li>
+ * <li>{@link StyleConstants#IconElementName}</li>
+ * </ul>
+ */
+ static class StyledViewFactory
+ implements ViewFactory
+ {
+ /**
+ * Creates a {@link View} for the specified <code>Element</code>.
+ *
+ * @param element the <code>Element</code> to create a <code>View</code>
+ * for
+ * @return the <code>View</code> for the specified <code>Element</code>
+ * or <code>null</code> if the type of <code>element</code> is
+ * not supported
+ */
+ public View create(Element element)
+ {
+ String name = element.getName();
+ View view = null;
+ if (name.equals(AbstractDocument.ContentElementName))
+ view = new LabelView(element);
+ else if (name.equals(AbstractDocument.ParagraphElementName))
+ view = new ParagraphView(element);
+ else if (name.equals(AbstractDocument.SectionElementName))
+ view = new BoxView(element, View.Y_AXIS);
+ else if (name.equals(StyleConstants.ComponentElementName))
+ view = new ComponentView(element);
+ else if (name.equals(StyleConstants.IconElementName))
+ view = new IconView(element);
+ else
+ throw new AssertionError("Unknown Element type: "
+ + element.getClass().getName() + " : "
+ + name);
+ return view;
+ }
+ }
+
+ /**
+ * Keeps track of the caret position and updates the currentRun
+ * <code>Element</code> and the <code>inputAttributes</code>.
+ */
+ class CaretTracker
+ implements CaretListener
+ {
+ /**
+ * Notifies an update of the caret position.
+ *
+ * @param ev the event for the caret update
+ */
+ public void caretUpdate(CaretEvent ev)
+ {
+ Object source = ev.getSource();
+ if (!(source instanceof JTextComponent))
+ throw new AssertionError("CaretEvents are expected to come from a"
+ + "JTextComponent.");
+
+ JTextComponent text = (JTextComponent) source;
+ Document doc = text.getDocument();
+ if (!(doc instanceof StyledDocument))
+ throw new AssertionError("The Document used by StyledEditorKits is"
+ + "expected to be a StyledDocument");
+
+ StyledDocument styleDoc = (StyledDocument) doc;
+ currentRun = styleDoc.getCharacterElement(ev.getDot());
+ createInputAttributes(currentRun, inputAttributes);
+ }
+ }
+
+ /**
+ * Stores the <code>Element</code> at the current caret position. This
+ * is updated by {@link CaretTracker}.
+ */
+ Element currentRun;
+
+ /**
+ * The current input attributes. This is updated by {@link CaretTracker}.
+ */
+ MutableAttributeSet inputAttributes;
+
+ /**
+ * The CaretTracker that keeps track of the current input attributes, and
+ * the current character run Element.
+ */
+ CaretTracker caretTracker;
+
+ /**
+ * The ViewFactory for StyledEditorKits.
+ */
+ StyledViewFactory viewFactory;
+
+ /**
+ * Creates a new instance of <code>StyledEditorKit</code>.
+ */
+ public StyledEditorKit()
+ {
+ inputAttributes = new SimpleAttributeSet();
+ }
+
+ /**
+ * Creates an exact copy of this <code>StyledEditorKit</code>.
+ *
+ * @return an exact copy of this <code>StyledEditorKit</code>
+ */
+ public Object clone()
+ {
+ StyledEditorKit clone = (StyledEditorKit) super.clone();
+ // FIXME: Investigate which fields must be copied.
+ return clone;
+ }
+
+ /**
+ * Returns the <code>Action</code>s supported by this {@link EditorKit}.
+ * This includes the {@link BoldAction}, {@link ItalicAction} and
+ * {@link UnderlineAction} as well as the <code>Action</code>s supported
+ * by {@link DefaultEditorKit}.
+ *
+ * The other <code>Action</code>s of <code>StyledEditorKit</code> are not
+ * returned here, since they require a parameter and thus custom
+ * instantiation.
+ *
+ * @return the <code>Action</code>s supported by this {@link EditorKit}
+ */
+ public Action[] getActions()
+ {
+ Action[] actions1 = super.getActions();
+ Action[] myActions = new Action[] {
+ new FontSizeAction("font-size-8", 8),
+ new FontSizeAction("font-size-10", 10),
+ new FontSizeAction("font-size-12", 12),
+ new FontSizeAction("font-size-14", 14),
+ new FontSizeAction("font-size-16", 16),
+ new FontSizeAction("font-size-18", 18),
+ new FontSizeAction("font-size-24", 24),
+ new FontSizeAction("font-size-36", 36),
+ new FontSizeAction("font-size-48", 48),
+ new FontFamilyAction("font-family-Serif", "Serif"),
+ new FontFamilyAction("font-family-Monospaced", "Monospaced"),
+ new FontFamilyAction("font-family-SansSerif", "SansSerif"),
+ new AlignmentAction("left-justify", StyleConstants.ALIGN_LEFT),
+ new AlignmentAction("center-justify", StyleConstants.ALIGN_CENTER),
+ new AlignmentAction("right-justify", StyleConstants.ALIGN_RIGHT),
+ new BoldAction(),
+ new ItalicAction(),
+ new UnderlineAction()
+ };
+ return TextAction.augmentList(actions1, myActions);
+ }
+
+ /**
+ * Returns the current input attributes. These are automatically set on
+ * any newly inserted content, if not specified otherwise.
+ *
+ * @return the current input attributes
+ */
+ public MutableAttributeSet getInputAttributes()
+ {
+ return inputAttributes;
+ }
+
+ /**
+ * Returns the {@link Element} that represents the character run at the
+ * current caret position.
+ *
+ * @return the {@link Element} that represents the character run at the
+ * current caret position
+ */
+ public Element getCharacterAttributeRun()
+ {
+ return currentRun;
+ }
+
+ /**
+ * Creates the default {@link Document} supported by this
+ * <code>EditorKit</code>. This is an instance of
+ * {@link DefaultStyledDocument} in this case but may be overridden by
+ * subclasses.
+ *
+ * @return an instance of <code>DefaultStyledDocument</code>
+ */
+ public Document createDefaultDocument()
+ {
+ return new DefaultStyledDocument();
+ }
+
+ /**
+ * Installs this <code>EditorKit</code> on the specified {@link JEditorPane}.
+ * This basically involves setting up required listeners on the
+ * <code>JEditorPane</code>.
+ *
+ * @param component the <code>JEditorPane</code> to install this
+ * <code>EditorKit</code> on
+ */
+ public void install(JEditorPane component)
+ {
+ CaretTracker tracker = new CaretTracker();
+ component.addCaretListener(tracker);
+ }
+
+ /**
+ * Deinstalls this <code>EditorKit</code> from the specified
+ * {@link JEditorPane}. This basically involves removing all listeners from
+ * <code>JEditorPane</code> that have been set up by this
+ * <code>EditorKit</code>.
+ *
+ * @param component the <code>JEditorPane</code> from which to deinstall this
+ * <code>EditorKit</code>
+ */
+ public void deinstall(JEditorPane component)
+ {
+ CaretTracker t = caretTracker;
+ if (t != null)
+ component.removeCaretListener(t);
+ caretTracker = null;
+ }
+
+ /**
+ * Returns a {@link ViewFactory} that is able to create {@link View}s
+ * for {@link Element}s that are supported by this <code>EditorKit</code>,
+ * namely the following types of <code>Element</code>s:
+ *
+ * <ul>
+ * <li>{@link AbstractDocument#ContentElementName}</li>
+ * <li>{@link AbstractDocument#ParagraphElementName}</li>
+ * <li>{@link AbstractDocument#SectionElementName}</li>
+ * <li>{@link StyleConstants#ComponentElementName}</li>
+ * <li>{@link StyleConstants#IconElementName}</li>
+ * </ul>
+ *
+ * @return a {@link ViewFactory} that is able to create {@link View}s
+ * for {@link Element}s that are supported by this <code>EditorKit</code>
+ */
+ public ViewFactory getViewFactory()
+ {
+ if (viewFactory == null)
+ viewFactory = new StyledViewFactory();
+ return viewFactory;
+ }
+
+ /**
+ * Copies the text attributes from <code>element</code> to <code>set</code>.
+ * This is called everytime when the caret position changes to keep
+ * track of the current input attributes. The attributes in <code>set</code>
+ * are cleaned before adding the attributes of <code>element</code>.
+ *
+ * This method filters out attributes for element names, <code>Icon</code>s
+ * and <code>Component</code>s.
+ *
+ * @param element the <code>Element</code> from which to copy the text
+ * attributes
+ * @param set the inputAttributes to copy the attributes to
+ */
+ protected void createInputAttributes(Element element,
+ MutableAttributeSet set)
+ {
+ // FIXME: Filter out component, icon and element name attributes.
+ set.removeAttributes(set);
+ set.addAttributes(element.getAttributes());
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabExpander.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabExpander.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabExpander.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabExpander.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,43 @@
+/* TabExpander.java --
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+public interface TabExpander
+{
+ float nextTabStop(float x, int tabOffset);
+}
\ No newline at end of file
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabSet.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabSet.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabSet.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabSet.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,208 @@
+/* TabSet.java --
+ Copyright (C) 2004, 2006, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.io.Serializable;
+
+/**
+ * A set of tab stops. Instances of this class are immutable.
+ */
+public class TabSet implements Serializable
+{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = 2367703481999080593L;
+
+ /** Storage for the tab stops. */
+ TabStop[] tabs;
+
+ /**
+ * Creates a new <code>TabSet</code> containing the specified tab stops.
+ *
+ * @param t the tab stops (<code>null</code> permitted).
+ */
+ public TabSet(TabStop[] t)
+ {
+ if (t != null)
+ tabs = (TabStop[]) t.clone();
+ else
+ tabs = new TabStop[0];
+ }
+
+ /**
+ * Returns the tab stop with the specified index.
+ *
+ * @param i the index.
+ *
+ * @return The tab stop.
+ *
+ * @throws IllegalArgumentException if <code>i</code> is not in the range
+ * <code>0</code> to <code>getTabCount() - 1</code>.
+ */
+ public TabStop getTab(int i)
+ {
+ if (i < 0 || i >= tabs.length)
+ throw new IllegalArgumentException("Index out of bounds.");
+ return tabs[i];
+ }
+
+ /**
+ * Returns the tab following the specified location.
+ *
+ * @param location the location.
+ *
+ * @return The tab following the specified location (or <code>null</code>).
+ */
+ public TabStop getTabAfter(float location)
+ {
+ int idx = getTabIndexAfter(location);
+ if (idx == -1)
+ return null;
+ else
+ return tabs[idx];
+ }
+
+ /**
+ * Returns the number of tab stops in this tab set.
+ *
+ * @return The number of tab stops in this tab set.
+ */
+ public int getTabCount()
+ {
+ return tabs.length;
+ }
+
+ /**
+ * Returns the index of the specified tab, or -1 if the tab is not found.
+ *
+ * @param tab the tab (<code>null</code> permitted).
+ *
+ * @return The index of the specified tab, or -1.
+ */
+ public int getTabIndex(TabStop tab)
+ {
+ for (int i = 0; i < tabs.length; ++i)
+ if (tabs[i] == tab)
+ return i;
+ return -1;
+ }
+
+ /**
+ * Returns the index of the tab at or after the specified location.
+ *
+ * @param location the tab location.
+ *
+ * @return The index of the tab stop, or -1.
+ */
+ public int getTabIndexAfter(float location)
+ {
+ for (int i = 0; i < tabs.length; i++)
+ {
+ if (location <= tabs[i].getPosition())
+ return i;
+ }
+ return -1;
+ }
+
+ /**
+ * Tests this <code>TabSet</code> for equality with an arbitrary object.
+ *
+ * @param obj the object (<code>null</code> permitted).
+ *
+ * @return <code>true</code> if this <code>TabSet</code> is equal to
+ * <code>obj</code>, and <code>false</code> otherwise.
+ *
+ * @since 1.5
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == this)
+ return true;
+ if (!(obj instanceof TabSet))
+ return false;
+ TabSet that = (TabSet) obj;
+ int tabCount = getTabCount();
+ if (tabCount != that.getTabCount())
+ return false;
+ for (int i = 0; i < tabCount; i++)
+ {
+ if (!this.getTab(i).equals(that.getTab(i)))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns a hash code for this <code>TabSet</code>.
+ *
+ * @return A hash code.
+ *
+ * @since 1.5
+ */
+ public int hashCode()
+ {
+ // this hash code won't match Sun's, but that shouldn't matter...
+ int result = 193;
+ int tabs = getTabCount();
+ for (int i = 0; i < tabs; i++)
+ {
+ TabStop t = getTab(i);
+ if (t != null)
+ result = 37 * result + t.hashCode();
+ }
+ return result;
+ }
+
+ /**
+ * Returns a string representation of this <code>TabSet</code>.
+ *
+ * @return A string representation of this <code>TabSet</code>.
+ */
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append("[ ");
+ for (int i = 0; i < tabs.length; ++i)
+ {
+ if (i != 0)
+ sb.append(" - ");
+ sb.append(tabs[i].toString());
+ }
+ sb.append(" ]");
+ return sb.toString();
+ }
+}
Added: llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabStop.java
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabStop.java?rev=43913&view=auto
==============================================================================
--- llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabStop.java (added)
+++ llvm-gcc-4.2/trunk/libjava/classpath/javax/swing/text/TabStop.java Thu Nov 8 16:56:19 2007
@@ -0,0 +1,190 @@
+/* TabStop.java --
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.text;
+
+import java.io.Serializable;
+
+/**
+ * Represents a tab position in some text.
+ */
+public class TabStop implements Serializable
+{
+ /** The serialization UID (compatible with JDK1.5). */
+ private static final long serialVersionUID = -5381995917363605058L;
+
+ public static final int ALIGN_LEFT = 0;
+ public static final int ALIGN_RIGHT = 1;
+ public static final int ALIGN_CENTER = 2;
+ public static final int ALIGN_DECIMAL = 4;
+ public static final int ALIGN_BAR = 5;
+
+ public static final int LEAD_NONE = 0;
+ public static final int LEAD_DOTS = 1;
+ public static final int LEAD_HYPHENS = 2;
+ public static final int LEAD_UNDERLINE = 3;
+ public static final int LEAD_THICKLINE = 4;
+ public static final int LEAD_EQUALS = 5;
+
+ float pos;
+ int align;
+ int leader;
+
+ /**
+ * Creates a new <code>TabStop</code> for the specified tab position.
+ *
+ * @param pos the tab position.
+ */
+ public TabStop(float pos)
+ {
+ this(pos, ALIGN_LEFT, LEAD_NONE);
+ }
+
+ /**
+ * Creates a new <code>TabStop</code> with the specified attributes.
+ *
+ * @param pos the tab position.
+ * @param align the alignment (one of {@link #ALIGN_LEFT},
+ * {@link #ALIGN_CENTER}, {@link #ALIGN_RIGHT}, {@link #ALIGN_DECIMAL}
+ * or {@link #ALIGN_BAR}).
+ * @param leader the leader (one of {@link #LEAD_NONE}, {@link #LEAD_DOTS},
+ * {@link #LEAD_EQUALS}, {@link #LEAD_HYPHENS}, {@link #LEAD_THICKLINE}
+ * or {@link #LEAD_UNDERLINE}).
+ */
+ public TabStop(float pos, int align, int leader)
+ {
+ this.pos = pos;
+ this.align = align;
+ this.leader = leader;
+ }
+
+ /**
+ * Tests this <code>TabStop</code> for equality with an arbitrary object.
+ *
+ * @param other the other object (<code>null</code> permitted).
+ *
+ * @return <code>true</code> if this <code>TabStop</code> is equal to
+ * the specified object, and <code>false</code> otherwise.
+ */
+ public boolean equals(Object other)
+ {
+ return (other != null)
+ && (other instanceof TabStop)
+ && (((TabStop)other).getPosition() == this.getPosition())
+ && (((TabStop)other).getLeader() == this.getLeader())
+ && (((TabStop)other).getAlignment() == this.getAlignment());
+ }
+
+ /**
+ * Returns the tab alignment. This should be one of {@link #ALIGN_LEFT},
+ * {@link #ALIGN_CENTER}, {@link #ALIGN_RIGHT}, {@link #ALIGN_DECIMAL} or
+ * {@link #ALIGN_BAR}.
+ *
+ * @return The tab alignment.
+ */
+ public int getAlignment()
+ {
+ return align;
+ }
+
+ /**
+ * Returns the leader type. This should be one of {@link #LEAD_NONE},
+ * {@link #LEAD_DOTS}, {@link #LEAD_EQUALS}, {@link #LEAD_HYPHENS},
+ * {@link #LEAD_THICKLINE} or {@link #LEAD_UNDERLINE}.
+ *
+ * @return The leader type.
+ */
+ public int getLeader()
+ {
+ return leader;
+ }
+
+ /**
+ * Returns the tab position.
+ *
+ * @return The tab position.
+ */
+ public float getPosition()
+ {
+ return pos;
+ }
+
+ /**
+ * Returns a hash code for this <code>TabStop</code>.
+ *
+ * @return A hash code.
+ */
+ public int hashCode()
+ {
+ return (int) pos + (int) leader + (int) align;
+ }
+
+ /**
+ * Returns a string describing this <code>TabStop</code>.
+ *
+ * @return A string describing this <code>TabStop</code>.
+ */
+ public String toString()
+ {
+ String prefix = "";
+ switch (align)
+ {
+ case ALIGN_RIGHT:
+ prefix = "right ";
+ break;
+
+ case ALIGN_CENTER:
+ prefix = "center ";
+ break;
+
+ case ALIGN_DECIMAL:
+ prefix = "decimal ";
+ break;
+
+ case ALIGN_BAR:
+ prefix = "bar ";
+ break;
+
+ default:
+ break;
+ }
+
+ return prefix + "tab @" + pos
+ + ((leader == LEAD_NONE) ? "" : " (w/leaders)");
+ }
+
+}
More information about the llvm-commits
mailing list