Removed depcrecated Bebop Table component
parent
0e3ae4e99f
commit
abe48a650d
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2017 LibreCCM Foundation.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
package com.arsdigita.bebop;
|
||||
|
||||
import com.arsdigita.globalization.GlobalizedMessage;
|
||||
|
||||
// Renders strings as labels
|
||||
|
||||
public class GlobalizedLabelCellRenderer extends StringLabelCellRenderer {
|
||||
|
||||
public GlobalizedLabelCellRenderer(final String weight) {
|
||||
super(weight);
|
||||
}
|
||||
|
||||
public GlobalizedLabelCellRenderer(final boolean outputEscape) {
|
||||
super(outputEscape);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Label getLabel(final Object value) {
|
||||
return new Label((GlobalizedMessage) value);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
package com.arsdigita.bebop;
|
||||
|
||||
|
||||
import com.arsdigita.bebop.list.ListModel;
|
||||
import com.arsdigita.bebop.list.ListModelBuilder;
|
||||
import com.arsdigita.bebop.table.DefaultTableCellRenderer;
|
||||
import com.arsdigita.bebop.table.DefaultTableColumnModel;
|
||||
import com.arsdigita.bebop.table.TableColumn;
|
||||
import com.arsdigita.bebop.table.TableColumnModel;
|
||||
import com.arsdigita.bebop.table.TableModel;
|
||||
import com.arsdigita.bebop.table.TableModelBuilder;
|
||||
import com.arsdigita.util.LockableImpl;
|
||||
|
||||
|
||||
/**
|
||||
* Displays a {@link ListModel} as a grid (that is, a {@link Table})
|
||||
* of given width.
|
||||
*
|
||||
* @version $Id: Grid.java 287 2005-02-22 00:29:02Z sskracic $
|
||||
*/
|
||||
public class Grid extends Table {
|
||||
|
||||
private int m_cols;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>Grid</code>.
|
||||
* <p>
|
||||
*
|
||||
* @param builder the {@link ListModelBuilder} that provides
|
||||
* the grid with data
|
||||
*
|
||||
* @param numCols the number of columns in the grid
|
||||
*/
|
||||
public Grid(ListModelBuilder builder, int numCols) {
|
||||
super(new GridModelBuilder(builder, numCols), new DefaultTableColumnModel());
|
||||
m_cols = numCols;
|
||||
|
||||
setHeader(null);
|
||||
|
||||
TableColumnModel cols = getColumnModel();
|
||||
for(int i=0; i<numCols; i++) {
|
||||
cols.add(new TableColumn(i));
|
||||
}
|
||||
|
||||
setClassAttr("grid");
|
||||
setWidth("100%");
|
||||
// Ignore null values
|
||||
setDefaultCellRenderer(new DefaultTableCellRenderer(true) {
|
||||
@Override
|
||||
public Component getComponent(Table table, PageState state, Object value,
|
||||
boolean isSelected, Object key,
|
||||
int row, int column) {
|
||||
if(value == null)
|
||||
return new Label(" ", false);
|
||||
else
|
||||
return super.getComponent(table, state, value, isSelected, key, row, column);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param builder the {@link ListModelBuilder} that provides
|
||||
* the grid with data
|
||||
*/
|
||||
public void setModelBuilder(ListModelBuilder builder) {
|
||||
super.setModelBuilder(new GridModelBuilder(builder, getColumnCount()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of columns in the grid.
|
||||
*/
|
||||
public int getColumnCount() {
|
||||
return m_cols;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a ListModel to a TableModel
|
||||
*/
|
||||
private static class GridModelBuilder extends LockableImpl
|
||||
implements TableModelBuilder {
|
||||
|
||||
private ListModelBuilder m_builder;
|
||||
private int m_cols;
|
||||
|
||||
public GridModelBuilder(ListModelBuilder builder, int cols) {
|
||||
super();
|
||||
m_builder = builder;
|
||||
m_cols = cols;
|
||||
}
|
||||
|
||||
public TableModel makeModel(Table t, PageState s) {
|
||||
//XXX FIXME: The creation of a new List() below is a
|
||||
//Hack to compile all...remove and fix.
|
||||
//This is because makeModel requires a List arg.
|
||||
//Should add a List setter function to Grid class, and
|
||||
//initialize to null, then pass in null below if necessary...
|
||||
//Christian: I will let your review team ponder this
|
||||
//proposed change, and if approved, please assign the
|
||||
//ticket to me! -jbp
|
||||
List l = new List();
|
||||
ListModel m = m_builder.makeModel(l,s);
|
||||
return new GridTableModel(m, m_cols);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lock() {
|
||||
m_builder.lock();
|
||||
super.lock();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
package com.arsdigita.bebop;
|
||||
|
||||
import com.arsdigita.bebop.table.TableModel;
|
||||
import com.arsdigita.bebop.list.ListModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Converts a linear ListModel to a grid of items.
|
||||
* For example, <code>A B C D E F G</code> becomes:
|
||||
*
|
||||
* <code><pre>
|
||||
* A D G
|
||||
* B E .
|
||||
* C F .
|
||||
* </pre></code>
|
||||
*
|
||||
* The extraneous cells in the table are filled
|
||||
* with <code>GridTableModel.PLACEHOLDER</code>.
|
||||
*
|
||||
* @version $Id: GridTableModel.java 287 2005-02-22 00:29:02Z sskracic $
|
||||
*/
|
||||
|
||||
public class GridTableModel implements TableModel {
|
||||
|
||||
private ListModel m_items;
|
||||
private int m_colHeight, m_cols, m_size, m_index;
|
||||
private Object[] m_elements;
|
||||
private Object[] m_keys;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>GridTableModel</code>.
|
||||
* @param items a {@link ListModel} that represents the
|
||||
* items
|
||||
* @param cols the number of columns in the grid
|
||||
*/
|
||||
public GridTableModel(ListModel items, int cols) {
|
||||
m_items = items;
|
||||
m_cols = cols;
|
||||
|
||||
// Load the items into memory
|
||||
ArrayList elements = new ArrayList(), keys = new ArrayList();
|
||||
for(m_size=0; m_items.next(); m_size++) {
|
||||
elements.add(m_items.getElement());
|
||||
keys.add(m_items.getKey());
|
||||
}
|
||||
|
||||
m_elements = elements.toArray();
|
||||
m_keys = keys.toArray();
|
||||
|
||||
// Round up
|
||||
m_colHeight = m_size / m_cols;
|
||||
if(m_colHeight * m_cols < m_size) ++m_colHeight;
|
||||
|
||||
m_index = -1;
|
||||
}
|
||||
|
||||
public int getColumnCount() {
|
||||
return m_cols;
|
||||
}
|
||||
|
||||
public boolean nextRow() {
|
||||
if(m_index >= m_colHeight - 1)
|
||||
return false;
|
||||
|
||||
++m_index;
|
||||
return true;
|
||||
}
|
||||
|
||||
private Object safeGet(Object[] a, int columnIndex) {
|
||||
int i = m_index + m_colHeight*columnIndex;
|
||||
|
||||
if(i >= a.length)
|
||||
return null;
|
||||
else
|
||||
return a[i];
|
||||
}
|
||||
|
||||
public Object getElementAt(int columnIndex) {
|
||||
return safeGet(m_elements, columnIndex);
|
||||
}
|
||||
|
||||
public Object getKeyAt(int columnIndex) {
|
||||
return safeGet(m_keys, columnIndex);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
package com.arsdigita.bebop;
|
||||
|
||||
import com.arsdigita.bebop.table.TableCellRenderer;
|
||||
import com.arsdigita.bebop.table.TableModel;
|
||||
import com.arsdigita.bebop.table.TableModelBuilder;
|
||||
import com.arsdigita.bebop.util.GlobalizationUtil;
|
||||
import com.arsdigita.globalization.GlobalizedMessage;
|
||||
import com.arsdigita.util.LockableImpl;
|
||||
|
||||
/**
|
||||
* Displays a list of label-value pairs that represent the properties of some
|
||||
* object. For example, a typical <code>PropertySheet</code> may look like this:
|
||||
* <p>
|
||||
* <table cellpadding=4 cellspacing=0 border=0>
|
||||
* <tr><th>First Name:</th><td>Stanislav</td></tr>
|
||||
* <tr><th>Last Name:</th><td>Freidin</td></tr>
|
||||
* <tr><th>Mission:</th><td>Sleep</td></tr>
|
||||
* </table>
|
||||
* <p>
|
||||
* This class relies on the {@link PropertySheetModelBuilder} to supply it with
|
||||
* the right {@link PropertySheetModel} during each request. It is up to the
|
||||
* user to provide the right builder.
|
||||
* <p>
|
||||
*
|
||||
* @author Stanislav Freidin
|
||||
*
|
||||
*/
|
||||
public class PropertySheet extends Table {
|
||||
|
||||
/**
|
||||
* Constructs a new <code>PropertySheet</code>.
|
||||
*
|
||||
* @param modelBuilder the property sheet model builder that is responsible
|
||||
* for building the property sheet model
|
||||
*
|
||||
*/
|
||||
public PropertySheet(final PropertySheetModelBuilder modelBuilder) {
|
||||
|
||||
this(modelBuilder, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>PropertySheet</code> and sets the output escape
|
||||
* value.
|
||||
*
|
||||
* @param modelBuilder the property sheet model builder that is
|
||||
* responsible for building the property sheet
|
||||
* model
|
||||
* @param valueOutputEscape the value of the label-value pair's
|
||||
* output-escaping
|
||||
*
|
||||
*/
|
||||
public PropertySheet(final PropertySheetModelBuilder modelBuilder,
|
||||
final boolean valueOutputEscape) {
|
||||
|
||||
super(new PSTMBAdapter(modelBuilder), new Object[]{"Label", "Value"});
|
||||
super.setHeader(null);
|
||||
|
||||
super
|
||||
.getColumn(0)
|
||||
.setCellRenderer(new GlobalizedLabelCellRenderer(Label.BOLD));
|
||||
super.getColumn(1).setCellRenderer(new StringLabelCellRenderer(
|
||||
valueOutputEscape));
|
||||
}
|
||||
|
||||
// Convert a PropertySheetModelBuilder to a TableModelBuilder
|
||||
private static class PSTMBAdapter
|
||||
extends LockableImpl implements TableModelBuilder {
|
||||
|
||||
private PropertySheetModelBuilder modelBuilder;
|
||||
|
||||
public PSTMBAdapter(final PropertySheetModelBuilder modelBuilder) {
|
||||
this.modelBuilder = modelBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableModel makeModel(final Table table, final PageState state) {
|
||||
return new TableModelAdapter(
|
||||
modelBuilder.makeModel((PropertySheet) table, state)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lock() {
|
||||
modelBuilder.lock();
|
||||
super.lock();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Wraps a PropertySheetModel
|
||||
private static class TableModelAdapter implements TableModel {
|
||||
|
||||
private final PropertySheetModel propertySheetModel;
|
||||
private int currentRow;
|
||||
|
||||
public TableModelAdapter(final PropertySheetModel propertySheetModel) {
|
||||
this.propertySheetModel = propertySheetModel;
|
||||
currentRow = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean nextRow() {
|
||||
currentRow++;
|
||||
return propertySheetModel.nextRow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElementAt(final int columnIndex) {
|
||||
if (columnIndex == 0) {
|
||||
return propertySheetModel.getGlobalizedLabel();
|
||||
} else {
|
||||
return propertySheetModel.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getKeyAt(final int columnIndex) {
|
||||
return currentRow;
|
||||
}
|
||||
|
||||
public PropertySheetModel getPSModel() {
|
||||
return propertySheetModel;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
package com.arsdigita.bebop;
|
||||
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.util.Lockable;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link PropertySheetModel} for the {@link PropertySheet}.
|
||||
* The model will be used to get a list of properties at runtime.
|
||||
*
|
||||
* @author Stanislav Freidin
|
||||
* @version $Id: PropertySheetModelBuilder.java 287 2005-02-22 00:29:02Z sskracic $
|
||||
* @see PropertySheetModel
|
||||
*/
|
||||
|
||||
public interface PropertySheetModelBuilder extends Lockable {
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new {@link PropertySheetModel}.
|
||||
*
|
||||
* @param sheet the {@link PropertySheet}
|
||||
* @param state the page state
|
||||
* @return a {@link PropertySheetModel}.
|
||||
*/
|
||||
PropertySheetModel makeModel(PropertySheet sheet, PageState state);
|
||||
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2017 LibreCCM Foundation.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
package com.arsdigita.bebop;
|
||||
|
||||
import com.arsdigita.bebop.table.TableCellRenderer;
|
||||
|
||||
// Renders strings as labels
|
||||
|
||||
public class StringLabelCellRenderer implements TableCellRenderer {
|
||||
|
||||
private String weight;
|
||||
private boolean outputEscape = false;
|
||||
|
||||
public StringLabelCellRenderer(final String weight) {
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
public StringLabelCellRenderer(boolean outputEscape) {
|
||||
this.outputEscape = outputEscape;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getComponent(final Table table,
|
||||
final PageState state, Object value,
|
||||
final boolean isSelected,
|
||||
final Object key,
|
||||
final int row,
|
||||
final int column) {
|
||||
final Label target = getLabel(value);
|
||||
target.setOutputEscaping(outputEscape);
|
||||
if (weight != null) {
|
||||
target.setFontWeight(weight);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
protected Label getLabel(Object value) {
|
||||
return new Label((String) value);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,896 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
package com.arsdigita.bebop;
|
||||
|
||||
import static com.arsdigita.bebop.Component.*;
|
||||
|
||||
import com.arsdigita.bebop.event.EventListenerList;
|
||||
import com.arsdigita.bebop.event.TableActionAdapter;
|
||||
import com.arsdigita.bebop.event.TableActionEvent;
|
||||
import com.arsdigita.bebop.event.TableActionListener;
|
||||
import com.arsdigita.bebop.parameters.ParameterModel;
|
||||
import com.arsdigita.bebop.parameters.StringParameter;
|
||||
import com.arsdigita.bebop.table.AbstractTableModelBuilder;
|
||||
import com.arsdigita.bebop.table.DefaultTableCellRenderer;
|
||||
import com.arsdigita.bebop.table.DefaultTableColumnModel;
|
||||
import com.arsdigita.bebop.table.TableCellRenderer;
|
||||
import com.arsdigita.bebop.table.TableColumn;
|
||||
import com.arsdigita.bebop.table.TableColumnModel;
|
||||
import com.arsdigita.bebop.table.TableHeader;
|
||||
import com.arsdigita.bebop.table.TableModel;
|
||||
import com.arsdigita.bebop.table.TableModelBuilder;
|
||||
|
||||
import static com.arsdigita.bebop.util.BebopConstants.*;
|
||||
|
||||
import com.arsdigita.util.Assert;
|
||||
import com.arsdigita.xml.Element;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
/**
|
||||
* Displays statically or dynamically generated data in tabular form.
|
||||
* The data is retrieved from a <code>TableModel</code>.
|
||||
*
|
||||
* <p>
|
||||
* This class is similar to the {@link List} class, but it has two dimensions.
|
||||
* The table consists of a {@link TableModelBuilder}, a {@link TableColumnModel},
|
||||
* a {@link TableHeader} and a {@link TableCellRenderer} for each column.
|
||||
* <p>
|
||||
*
|
||||
* A table that represents a static matrix can be created fairly quickly:
|
||||
* <blockquote><pre><code> String[][] data = {
|
||||
* {"Stas", "Freidin"},
|
||||
* {"David", "Lutterkort"}
|
||||
* };
|
||||
*
|
||||
* String[] headers = {"First Name", "Last Name"};
|
||||
*
|
||||
* Table myTable = new Table(data, headers);</code></pre></blockquote>
|
||||
* <p>
|
||||
*
|
||||
* However, tables are most often used to represent database queries, not static
|
||||
* data. For these tables, the {@link TableModelBuilder} class should be used
|
||||
* to supply the <code>Table</code> class with data.
|
||||
* The {@link TableModelBuilder} class will execute the database query and
|
||||
* return a {@link TableModel}, which wraps the query.
|
||||
* <p>
|
||||
*
|
||||
* The content in the cells is rendered by the {@link TableCellRenderer} that
|
||||
* is set for the {@link TableColumn} to which the cell belongs.
|
||||
*
|
||||
* If the <code>TableCellRenderer</code> has not been set, the
|
||||
* <code>TableCellRenderer</code> for the <code>Table</code> is used.
|
||||
* By default, the <code>Table</code> class uses an inactive instance of the
|
||||
* {@link DefaultTableCellRenderer} (cell content is displayed as {@link Label}s).
|
||||
* However, if an active <code>DefaultTableCellRenderer</code> is used, the
|
||||
* cells in the table appear as links. When the user clicks a link, the
|
||||
* <code>Table</code>'s action listeners will be fired.
|
||||
*
|
||||
* <P>
|
||||
* The currently selected cell is represented by two {@link SingleSelectionModel}s -
|
||||
* one model for the row and one model for the column. Typically, the selected
|
||||
* row is identified by a string key and the selected column is identified by
|
||||
* an integer.
|
||||
*
|
||||
* @see TableModel
|
||||
* @see TableColumnModel
|
||||
*
|
||||
* @author David Lutterkort
|
||||
*/
|
||||
public class Table extends SimpleComponent {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(Table.class);
|
||||
|
||||
// Names for HTML Attributes
|
||||
private static final String WIDTH = "width";
|
||||
private static final String CELL_SPACING = "cellspacing";
|
||||
private static final String CELL_PADDING = "cellpadding";
|
||||
private static final String BORDER = "border";
|
||||
private static final String SELECTED_ROW = "row";
|
||||
/**
|
||||
* The control event when the user selects one table cell.
|
||||
* This control event will only be used when
|
||||
*/
|
||||
protected static final String CELL_EVENT = "cell";
|
||||
protected static final char SEP = ' ';
|
||||
private TableModelBuilder m_modelBuilder;
|
||||
private TableColumnModel m_columnModel;
|
||||
private TableHeader m_header;
|
||||
private RequestLocal m_tableModel;
|
||||
private SingleSelectionModel m_rowSelectionModel;
|
||||
/**
|
||||
* A listener to forward headSelected events originating from the
|
||||
* TableHeader. This will be null until somebody actually registers a
|
||||
* TableActionListener from the outside.
|
||||
*/
|
||||
private TableActionListener m_headerForward;
|
||||
private EventListenerList m_listeners;
|
||||
private TableCellRenderer m_defaultCellRenderer;
|
||||
private Component m_emptyView;
|
||||
private boolean m_striped = false;
|
||||
|
||||
/**
|
||||
* Constructs a new, empty table.
|
||||
*/
|
||||
public Table() {
|
||||
this(new Object[0][0], new Object[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a static table with the specified column headers,
|
||||
* and pre-fills it with data.
|
||||
*
|
||||
* @param data a matrix of objects that will serve as static data
|
||||
* for the table cells
|
||||
*
|
||||
* @param headers an array of string labels for the table headers
|
||||
*/
|
||||
public Table(Object[][] data, Object[] headers) {
|
||||
this(new MatrixTableModelBuilder(data), headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a table using a {@link TableModelBuilder}. The table
|
||||
* data will be generated dynamically during each request.
|
||||
*
|
||||
* @param b the {@link TableModelBuilder} that is responsible for
|
||||
* instantiating a {@link TableModel} during each request
|
||||
*
|
||||
* @param headers an array of string labels for the table headers
|
||||
*/
|
||||
public Table(TableModelBuilder b, Object[] headers) {
|
||||
this(b, new DefaultTableColumnModel(headers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a table using a {@link TableModelBuilder}. The table
|
||||
* data will be generated dynamically during each request. The
|
||||
* table's columns and headers will be provided by a
|
||||
* {@link TableColumnModel}.
|
||||
*
|
||||
* @param b the {@link TableModelBuilder} that is responsible for
|
||||
* instantiating a {@link TableModel} during each request
|
||||
*
|
||||
* @param c the {@link TableColumnModel} that will maintain the
|
||||
* columns and headers for this table
|
||||
*/
|
||||
public Table(TableModelBuilder b, TableColumnModel c) {
|
||||
super();
|
||||
m_modelBuilder = b;
|
||||
m_columnModel = c;
|
||||
setHeader(new TableHeader(m_columnModel));
|
||||
m_rowSelectionModel =
|
||||
new ParameterSingleSelectionModel(new StringParameter(SELECTED_ROW));
|
||||
m_listeners = new EventListenerList();
|
||||
m_defaultCellRenderer = new DefaultTableCellRenderer();
|
||||
initTableModel();
|
||||
}
|
||||
|
||||
// Events and listeners
|
||||
|
||||
/**
|
||||
* Adds a {@link TableActionListener} to the table. The listener is
|
||||
* fired whenever a table cell is clicked.
|
||||
*
|
||||
* @param l the {@link TableActionListener} to be added
|
||||
*/
|
||||
public void addTableActionListener(TableActionListener l) {
|
||||
Assert.isUnlocked(this);
|
||||
if (m_headerForward == null) {
|
||||
m_headerForward = createTableActionListener();
|
||||
if (m_header != null) {
|
||||
m_header.addTableActionListener(m_headerForward);
|
||||
}
|
||||
}
|
||||
m_listeners.add(TableActionListener.class, l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a {@link TableActionListener} from the table.
|
||||
*
|
||||
* @param l the {@link TableActionListener} to be removed
|
||||
*/
|
||||
public void removeTableActionListener(TableActionListener l) {
|
||||
Assert.isUnlocked(this);
|
||||
m_listeners.remove(TableActionListener.class, l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires event listeners to indicate that a new cell has been
|
||||
* selected in the table.
|
||||
*
|
||||
* @param state the page state
|
||||
* @param rowKey the key that identifies the selected row
|
||||
* @param column the integer index of the selected column
|
||||
*/
|
||||
protected void fireCellSelected(PageState state,
|
||||
Object rowKey, Integer column) throws FormProcessException {
|
||||
Iterator i = m_listeners.getListenerIterator(TableActionListener.class);
|
||||
TableActionEvent e = null;
|
||||
|
||||
while (i.hasNext()) {
|
||||
if (e == null) {
|
||||
e = new TableActionEvent(this, state, rowKey, column);
|
||||
}
|
||||
((TableActionListener) i.next()).cellSelected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires event listeners to indicate that a new header cell has been
|
||||
* selected in the table.
|
||||
*
|
||||
* @param state the page state
|
||||
* @param rowKey the key that identifies the selected row
|
||||
* @param column the integer index of the selected column
|
||||
*/
|
||||
protected void fireHeadSelected(PageState state,
|
||||
Object rowKey, Integer column) {
|
||||
Iterator i = m_listeners.getListenerIterator(TableActionListener.class);
|
||||
TableActionEvent e = null;
|
||||
|
||||
while (i.hasNext()) {
|
||||
if (e == null) {
|
||||
e = new TableActionEvent(this, state, rowKey, column);
|
||||
}
|
||||
((TableActionListener) i.next()).headSelected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new {@link TableActionListener} for this table.
|
||||
*
|
||||
* @return a new {@link TableActionListener} that should be used
|
||||
* only for this table.
|
||||
*
|
||||
*/
|
||||
protected TableActionListener createTableActionListener() {
|
||||
return new TableActionAdapter() {
|
||||
@Override
|
||||
public void headSelected(TableActionEvent e) {
|
||||
fireHeadSelected(e.getPageState(), e.getRowKey(), e.getColumn());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link TableColumnModel} for this table.
|
||||
*/
|
||||
public final TableColumnModel getColumnModel() {
|
||||
return m_columnModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new {@link TableColumnModel} for the table.
|
||||
*
|
||||
* @param v the new {@link TableColumnModel}
|
||||
*/
|
||||
public void setColumnModel(TableColumnModel v) {
|
||||
Assert.isUnlocked(this);
|
||||
m_columnModel = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link TableModelBuilder} for this table.
|
||||
*/
|
||||
public final TableModelBuilder getModelBuilder() {
|
||||
return m_modelBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new {@link TableModelBuilder} for the table.
|
||||
*
|
||||
* @param v the new {@link TableModelBuilder}
|
||||
*/
|
||||
public void setModelBuilder(TableModelBuilder v) {
|
||||
Assert.isUnlocked(this);
|
||||
m_modelBuilder = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link TableHeader} for this table. Could return null
|
||||
* if the header is hidden.
|
||||
*/
|
||||
public final TableHeader getHeader() {
|
||||
return m_header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new header for this table.
|
||||
*
|
||||
* @param v the new header for this table. If null, the header will be
|
||||
* hidden.
|
||||
*/
|
||||
public void setHeader(TableHeader v) {
|
||||
Assert.isUnlocked(this);
|
||||
if (m_headerForward != null) {
|
||||
if (m_header != null) {
|
||||
m_header.removeTableActionListener(m_headerForward);
|
||||
}
|
||||
if (v != null) {
|
||||
v.addTableActionListener(m_headerForward);
|
||||
}
|
||||
}
|
||||
m_header = v;
|
||||
if (m_header != null) {
|
||||
m_header.setTable(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i the numerical index of the column
|
||||
* @return the {@link TableColumn} whose index is i.
|
||||
*/
|
||||
public TableColumn getColumn(int i) {
|
||||
return getColumnModel().get(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the colulumn at a new numerical index. This method
|
||||
* is normally used to rearrange the order of the columns in the
|
||||
* table.
|
||||
*
|
||||
* @param i the numerical index of the column
|
||||
* @param v the column that is to be mapped at i
|
||||
*/
|
||||
public void setColumn(int i, TableColumn v) {
|
||||
getColumnModel().set(i, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link SingleSelectionModel} that is responsible
|
||||
* for selecting the current row.
|
||||
*/
|
||||
public final SingleSelectionModel getRowSelectionModel() {
|
||||
return m_rowSelectionModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the {@link SingleSelectionModel} that will be responsible
|
||||
* for selecting the current row.
|
||||
*
|
||||
* @param v a {@link SingleSelectionModel}
|
||||
*/
|
||||
public void setRowSelectionModel(SingleSelectionModel v) {
|
||||
Assert.isUnlocked(this);
|
||||
m_rowSelectionModel = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link SingleSelectionModel} that is responsible
|
||||
* for selecting the current column.
|
||||
*/
|
||||
public SingleSelectionModel getColumnSelectionModel() {
|
||||
return (getColumnModel() == null) ? null : getColumnModel().
|
||||
getSelectionModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the {@link SingleSelectionModel} that will be responsible
|
||||
* for selecting the current column.
|
||||
*
|
||||
* @param v a {@link SingleSelectionModel}
|
||||
*/
|
||||
public void setColumnSelectionModel(SingleSelectionModel v) {
|
||||
Assert.isUnlocked(this);
|
||||
// TODO: make sure table gets notified of changes
|
||||
getColumnModel().setSelectionModel(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the row and column selection models that the table holds.
|
||||
*
|
||||
* @param s represents the state of the current request
|
||||
* @post ! getRowSelectionModel().isSelected(s)
|
||||
* @post ! getColumnSelectionModel().isSelected(s)
|
||||
*/
|
||||
public void clearSelection(PageState s) {
|
||||
getRowSelectionModel().clearSelection(s);
|
||||
getColumnSelectionModel().clearSelection(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the default {@link TableCellRenderer}.
|
||||
*/
|
||||
public final TableCellRenderer getDefaultCellRenderer() {
|
||||
return m_defaultCellRenderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the default cell renderer. This renderer will
|
||||
* be used to render columns that do not specify their own
|
||||
* {@link TableCellRenderer}.
|
||||
*
|
||||
* @param v the default {@link TableCellRenderer}
|
||||
*/
|
||||
public final void setDefaultCellRenderer(TableCellRenderer v) {
|
||||
m_defaultCellRenderer = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the component that will be shown if the table is
|
||||
* empty.
|
||||
*/
|
||||
public final Component getEmptyView() {
|
||||
return m_emptyView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the empty view. The empty view is the component that
|
||||
* is shown if the table is empty. Usually, the component
|
||||
* will be a simple label, such as <code>new Label("The table is empty")</code>.
|
||||
*
|
||||
* @param v a Bebop component
|
||||
*/
|
||||
public final void setEmptyView(Component v) {
|
||||
m_emptyView = v;
|
||||
}
|
||||
|
||||
// Set HTML table attributes
|
||||
/**
|
||||
*
|
||||
* @return the HTML width of the table.
|
||||
*/
|
||||
public String getWidth() {
|
||||
return getAttribute(WIDTH);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param v the HTML width of the table
|
||||
*/
|
||||
public void setWidth(String v) {
|
||||
setAttribute(WIDTH, v);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the HTML border of the table.
|
||||
*/
|
||||
public String getBorder() {
|
||||
return getAttribute(BORDER);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param v the HTML border of the table
|
||||
*/
|
||||
public void setBorder(String v) {
|
||||
setAttribute(BORDER, v);
|
||||
}
|
||||
|
||||
public String getCellSpacing() {
|
||||
return getAttribute(CELL_SPACING);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param v the HTML width of the table
|
||||
*/
|
||||
public void setCellSpacing(String v) {
|
||||
setAttribute(CELL_SPACING, v);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the HTML cell spacing of the table.
|
||||
*/
|
||||
public String getCellPadding() {
|
||||
return getAttribute(CELL_PADDING);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param v the HTML cell padding of the table
|
||||
*/
|
||||
public void setCellPadding(String v) {
|
||||
setAttribute(CELL_PADDING, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the events for this table. This method will automatically
|
||||
* handle all user input to the table.
|
||||
*
|
||||
* @param s the page state
|
||||
* @throws javax.servlet.ServletException
|
||||
*/
|
||||
@Override
|
||||
public void respond(PageState s) throws ServletException {
|
||||
String event = s.getControlEventName();
|
||||
String rowKey = null;
|
||||
Integer column = null;
|
||||
|
||||
if (CELL_EVENT.equals(event)) {
|
||||
String value = s.getControlEventValue();
|
||||
SingleSelectionModel rowSel = getRowSelectionModel();
|
||||
SingleSelectionModel colSel = getColumnSelectionModel();
|
||||
int split = value.indexOf(SEP);
|
||||
rowKey = value.substring(0, split);
|
||||
column = new Integer(value.substring(split + 1));
|
||||
colSel.setSelectedKey(s, column);
|
||||
rowSel.setSelectedKey(s, rowKey);
|
||||
fireCellSelected(s, rowKey, column);
|
||||
} else {
|
||||
throw new ServletException("Unknown event '" + event + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the table with the containing page. The table will add the
|
||||
* state parameters of the row and column selection models, if they use
|
||||
* them, thus making the selection persist between requests.
|
||||
*
|
||||
* @param p the page that contains this table
|
||||
*/
|
||||
@Override
|
||||
public void register(Page p) {
|
||||
ParameterModel m = getRowSelectionModel() == null ? null
|
||||
: getRowSelectionModel().getStateParameter();
|
||||
if (m != null) {
|
||||
p.addComponentStateParam(this, m);
|
||||
}
|
||||
m = getColumnSelectionModel() == null ? null : getColumnSelectionModel().
|
||||
getStateParameter();
|
||||
if (m != null) {
|
||||
p.addComponentStateParam(this, m);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over the header and all the columns. If the table
|
||||
* has no header, the iterator lists only the columns.
|
||||
*
|
||||
* @return an iterator over Bebop components.
|
||||
*/
|
||||
@Override
|
||||
public Iterator children() {
|
||||
return new Iterator() {
|
||||
|
||||
int pos = (getHeader() == null) ? -1 : -2;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return pos < getColumnModel().size() - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object next() {
|
||||
pos += 1;
|
||||
if (pos == -1) {
|
||||
return getHeader();
|
||||
} else {
|
||||
return getColumn(pos);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("Read-only iterator.");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a row is seleted.
|
||||
*
|
||||
* @param s the page state
|
||||
* @param rowKey the key that identifies the row
|
||||
* @return <code>true</code> if the row is currently selected;
|
||||
* <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean isSelectedRow(PageState s, Object rowKey) {
|
||||
if (rowKey == null || getRowSelectionModel() == null) {
|
||||
return false;
|
||||
}
|
||||
return getRowSelectionModel().isSelected(s)
|
||||
&& rowKey.toString().equals(
|
||||
getRowSelectionModel().getSelectedKey(s).toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a column is selected.
|
||||
*
|
||||
* @param s the page state
|
||||
* @param column a key that identifes the column. Should be consistent
|
||||
* with the type used by the column selection model.
|
||||
* @return <code>true</code> if the column is selected;
|
||||
* <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean isSelectedColumn(PageState s, Object column) {
|
||||
if (column == null || getColumnSelectionModel() == null) {
|
||||
return false;
|
||||
}
|
||||
return getColumnSelectionModel().isSelected(s)
|
||||
&& column.toString().equals(
|
||||
getColumnSelectionModel().getSelectedKey(s).toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the cell addressed by the specified row key and
|
||||
* column number is selected in the request represented by the page
|
||||
* state.
|
||||
*
|
||||
* @param s represents the state of the page in the current request
|
||||
* @param rowKey the row key of the cell. The concrete type should agree
|
||||
* with the type used by the row selection model.
|
||||
* @param column the column of the cell. The concrete type should agree
|
||||
* with the type used by the column selection model.
|
||||
* @return <code>true</code> if the cell is selected;
|
||||
* <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean isSelectedCell(PageState s, Object rowKey, Object column) {
|
||||
return isSelectedRow(s, rowKey) && isSelectedColumn(s, column);
|
||||
}
|
||||
|
||||
public void setStriped(boolean striped) {
|
||||
m_striped = striped;
|
||||
}
|
||||
|
||||
public boolean getStriped() {
|
||||
return m_striped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds type-specific XML attributes to the XML element representing
|
||||
* this link. Subclasses should override this method if they introduce
|
||||
* more attributes than the ones {@link #generateXML generateXML}
|
||||
* produces by default.
|
||||
*
|
||||
* @param state represents the current request
|
||||
* @param element the XML element representing this table
|
||||
*/
|
||||
protected void generateExtraXMLAttributes(PageState state,
|
||||
Element element) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the XML representing the table. Gets a new {@link TableModel}
|
||||
* from the {@link TableModelBuilder} and iterates over the model's
|
||||
* rows. The value in each table cell is rendered with the help of the
|
||||
* column's table cell renderer.
|
||||
*
|
||||
* <p> Generates an XML fragment:
|
||||
* <pre>
|
||||
* <bebop:table>
|
||||
* <bebop:thead>
|
||||
* <bebpp:cell>...</cell> ...
|
||||
* </bebop:thead>
|
||||
* <bebop:tbody>
|
||||
* <bebop:trow>
|
||||
* <bebpp:cell>...</cell> ...
|
||||
* </bebop:trow>
|
||||
* ...
|
||||
* </bebop:tbody>
|
||||
* </bebop:table>
|
||||
*
|
||||
* @param s the page state
|
||||
* @param p the parent {@link Element}
|
||||
*/
|
||||
@Override
|
||||
public void generateXML(PageState s, Element p) {
|
||||
TableModel model = getTableModel(s);
|
||||
|
||||
|
||||
final boolean tableIsRegisteredWithPage =
|
||||
s.getPage().stateContains(getControler());
|
||||
|
||||
if (model.nextRow()) {
|
||||
Element table = p.newChildElement(BEBOP_TABLE, BEBOP_XML_NS);
|
||||
exportAttributes(table);
|
||||
generateExtraXMLAttributes(s, table);
|
||||
if (getHeader() != null) {
|
||||
getHeader().generateXML(s, table);
|
||||
}
|
||||
Element tbody = table.newChildElement(BEBOP_TABLEBODY, BEBOP_XML_NS);
|
||||
if (m_striped) {
|
||||
tbody.addAttribute("striped", "true");
|
||||
}
|
||||
|
||||
final int modelSize = getColumnModel().size();
|
||||
int row = 0;
|
||||
|
||||
LOGGER.debug("Creating table rows...");
|
||||
long start = System.currentTimeMillis();
|
||||
do {
|
||||
long rowStart = System.currentTimeMillis();
|
||||
Element trow = tbody.newChildElement(BEBOP_TABLEROW,
|
||||
BEBOP_XML_NS);
|
||||
|
||||
for (int i = 0; i < modelSize; i++) {
|
||||
|
||||
TableColumn tc = getColumn(i);
|
||||
if (tc.isVisible(s)) {
|
||||
TableCellRenderer r = tc.getCellRenderer();
|
||||
if (r == null) {
|
||||
r = m_defaultCellRenderer;
|
||||
}
|
||||
final int modelIndex = tc.getModelIndex();
|
||||
Object key = model.getKeyAt(modelIndex);
|
||||
Object value = model.getElementAt(modelIndex);
|
||||
boolean selected =
|
||||
isSelectedCell(s, key, new Integer(i));
|
||||
if (tableIsRegisteredWithPage) {
|
||||
/*StringBuffer coords = new StringBuffer(40);
|
||||
coords.append(model.getKeyAt(modelIndex)).append(SEP).
|
||||
append(i);
|
||||
s.setControlEvent(getControler(), CELL_EVENT,
|
||||
coords.toString());*/
|
||||
|
||||
s.setControlEvent(getControler(),
|
||||
CELL_EVENT,
|
||||
String.format("%s%s%d",
|
||||
model.getKeyAt(
|
||||
modelIndex),
|
||||
SEP,
|
||||
i));
|
||||
}
|
||||
|
||||
Element cell = trow.newChildElement(BEBOP_CELL,
|
||||
BEBOP_XML_NS);
|
||||
|
||||
tc.exportCellAttributes(cell);
|
||||
long begin = System.currentTimeMillis();
|
||||
r.getComponent(this, s, value, selected, key, row, i).
|
||||
generateXML(s, cell);
|
||||
LOGGER.debug(String.format("until here i needed %d ms",
|
||||
System.currentTimeMillis()
|
||||
- begin));
|
||||
}
|
||||
}
|
||||
row += 1;
|
||||
LOGGER.debug(
|
||||
String.format("Created row in %d ms",
|
||||
System.currentTimeMillis() - rowStart));
|
||||
} while (model.nextRow());
|
||||
LOGGER.debug(String.format("Build table rows in %d ms",
|
||||
System.currentTimeMillis() - start));
|
||||
} else if (m_emptyView != null) {
|
||||
m_emptyView.generateXML(s, p);
|
||||
}
|
||||
if (tableIsRegisteredWithPage) {
|
||||
s.clearControlEvent();
|
||||
}
|
||||
}
|
||||
|
||||
protected Component getControler() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the table model in effect for the request represented by the
|
||||
* page state.
|
||||
*
|
||||
* @param s represents the state of the page in the current request
|
||||
* @return the table model used for outputting the table.
|
||||
*/
|
||||
public TableModel getTableModel(PageState s) {
|
||||
return (TableModel) m_tableModel.get(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the request local <code>m_tableModel</code> field so that
|
||||
* it is initialized with whatever model the table model builder returns
|
||||
* for the request.
|
||||
*/
|
||||
private void initTableModel() {
|
||||
m_tableModel = new RequestLocal() {
|
||||
|
||||
@Override
|
||||
protected Object initialValue(PageState s) {
|
||||
return m_modelBuilder.makeModel(Table.this, s);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks the table against further modifications. This also locks all
|
||||
* the associated objects: the model builder, the column model, and the
|
||||
* header components.
|
||||
* @see com.arsdigita.util.Lockable#lock
|
||||
*/
|
||||
@Override
|
||||
public void lock() {
|
||||
getModelBuilder().lock();
|
||||
getColumnModel().lock();
|
||||
if (getHeader() != null) {
|
||||
getHeader().lock();
|
||||
}
|
||||
super.lock();
|
||||
}
|
||||
|
||||
/**
|
||||
* An internal class that creates a table model around a set of data given
|
||||
* as a <code>Object[][]</code>. The table models produced by this builder
|
||||
* use row numbers, converted to strings, as the key for each column of a
|
||||
* row.
|
||||
*/
|
||||
public static class MatrixTableModelBuilder
|
||||
extends AbstractTableModelBuilder {
|
||||
|
||||
private final Object[][] m_data;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
public MatrixTableModelBuilder(Object[][] data) {
|
||||
m_data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableModel makeModel(Table t, PageState s) {
|
||||
return new TableModel() {
|
||||
|
||||
private int row = -1;
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return m_data[0].length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean nextRow() {
|
||||
return (++row < m_data.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElementAt(int j) {
|
||||
return m_data[row][j];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getKeyAt(int j) {
|
||||
return String.valueOf(row);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link TableModel} that has no rows.
|
||||
*/
|
||||
public static final TableModel EMPTY_MODEL = new TableModel() {
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean nextRow() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getKeyAt(int column) {
|
||||
throw new IllegalStateException("TableModel is empty");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElementAt(int column) {
|
||||
throw new IllegalStateException("TableModel is empty");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
package com.arsdigita.bebop.table;
|
||||
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.bebop.Table;
|
||||
import com.arsdigita.util.LockableImpl;
|
||||
|
||||
/**
|
||||
* A convenience for implementing <code>TableModelBuilder</code>s. This
|
||||
* class provides a default implementation of the methods demanded by
|
||||
* <code>Lockable</code>, so that implementors of
|
||||
* <code>TableModelBuilder</code> only need to override the
|
||||
* <code>makeModel</code> method.
|
||||
*
|
||||
* @author David Lutterkort
|
||||
* @see TableModelBuilder
|
||||
* @see com.arsdigita.util.Lockable
|
||||
*
|
||||
* @version $Id$
|
||||
*/
|
||||
public abstract class AbstractTableModelBuilder extends LockableImpl
|
||||
implements TableModelBuilder {
|
||||
|
||||
/**
|
||||
* Return a table model for the request represented by
|
||||
* <code>s</code>. The table model contains all the data that is to be
|
||||
* displayed in a table. The returned table model is used only during
|
||||
* the duration of that request.
|
||||
*
|
||||
* @param t the table which will use this table model
|
||||
* @param s represents the current request
|
||||
* @return the data to be displayed in the table
|
||||
*/
|
||||
public abstract TableModel makeModel(Table t, PageState s);
|
||||
|
||||
}
|
||||
|
|
@ -1,159 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
package com.arsdigita.bebop.table;
|
||||
|
||||
|
||||
import com.arsdigita.bebop.util.GlobalizationUtil ;
|
||||
|
||||
import com.arsdigita.bebop.Component;
|
||||
import com.arsdigita.bebop.ControlLink;
|
||||
import com.arsdigita.bebop.Label;
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.bebop.Table;
|
||||
import com.arsdigita.globalization.GlobalizedMessage;
|
||||
|
||||
import com.arsdigita.util.Assert;
|
||||
import com.arsdigita.util.LockableImpl;
|
||||
|
||||
/**
|
||||
* The default renderer for table cells. This renderer is used by the
|
||||
* {@link com.arsdigita.bebop.Table} component for rendering the table
|
||||
* headers and cells if no other renderer is specified.
|
||||
*
|
||||
* <p> This renderer can operate in two different modes: <em>active</em>
|
||||
* and <em>inactive</em> mode. In inactive mode, all objects are rendered
|
||||
* by converting them to a string and enclosing that string in a {@link
|
||||
* com.arsdigita.bebop.Label}. If the renderer is in active mode, this
|
||||
* label is further enclosed in a control link. When the user clicks on
|
||||
* this link, the table will fire an <code>TableActionEvent</code> whose
|
||||
* <code>getKey()</code> and <code>getColumn()</code> method return the
|
||||
* values of the <code>key</code> and <code>column</code> parameters that
|
||||
* were passed into {@link #getComponent getComponent}.
|
||||
*
|
||||
* <p> In a nutshell, an active renderer will let the user click a link
|
||||
* that causes a <code>TableActionEvent</code> for the corresponding cell,
|
||||
* while an inactive renderer will display the values just as strings, thus
|
||||
* making it impossible for the user to cause such an event.
|
||||
*
|
||||
* @author David Lutterkort
|
||||
* @see com.arsdigita.bebop.Table
|
||||
* @see com.arsdigita.bebop.event.TableActionEvent
|
||||
*
|
||||
* @version $Id$ */
|
||||
public class DefaultTableCellRenderer extends LockableImpl
|
||||
implements TableCellRenderer {
|
||||
|
||||
private boolean m_active;
|
||||
private ThreadLocal m_label;
|
||||
private ThreadLocal m_controlLink;
|
||||
|
||||
/**
|
||||
* Creates a new table cell renderer. The table cell renderer is in
|
||||
* inactive mode.
|
||||
*/
|
||||
public DefaultTableCellRenderer() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new table cell renderer. The <code>active</code> argument
|
||||
* specifies whether the renderer should be active or not.
|
||||
*
|
||||
* @param active <code>true</code> if the renderer should generate links
|
||||
* instead of just static labels.
|
||||
*/
|
||||
public DefaultTableCellRenderer(boolean active) {
|
||||
m_active = active;
|
||||
m_label = new ThreadLocal() {
|
||||
protected Object initialValue() {
|
||||
return new Label("");
|
||||
}
|
||||
};
|
||||
m_controlLink = new ThreadLocal() {
|
||||
protected Object initialValue() {
|
||||
return new ControlLink((Label) m_label.get());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Return <code>true</code> if the renderer is in active mode. A
|
||||
* rendererin active mode will enclose the objects it renders in links
|
||||
* that, when clicked, will cause the containing table to fire a
|
||||
* <code>TableActionEvent</code>.
|
||||
*
|
||||
* @return <code>true</code> if the renderer is in active mode.
|
||||
*/
|
||||
public final boolean isActive() {
|
||||
return m_active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the renderer to active or inactive mode.
|
||||
*
|
||||
* @param v <code>true</code> if the renderer should operate in active
|
||||
* mode.
|
||||
* @pre ! isLocked()
|
||||
*/
|
||||
public void setActive(boolean v) {
|
||||
Assert.isUnlocked(this);
|
||||
m_active = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the component that should be used to render the given
|
||||
* <code>value</code>. Returns a {@link com.arsdigita.bebop.Label} if the
|
||||
* renderer is active, and a {@link com.arsdigita.bebop.ControlLink} if
|
||||
* the renderer is inactive.
|
||||
*
|
||||
* @pre table == null || table != null
|
||||
*/
|
||||
public Component getComponent(Table table, PageState state, Object value,
|
||||
boolean isSelected, Object key,
|
||||
int row, int column)
|
||||
{
|
||||
if ( ! isLocked() && table != null && table.isLocked() ) {
|
||||
lock();
|
||||
}
|
||||
|
||||
Label l;
|
||||
if ( value instanceof com.arsdigita.bebop.Component ) {
|
||||
return (com.arsdigita.bebop.Component) value;
|
||||
} else if(value instanceof GlobalizedMessage) {
|
||||
l = (Label) m_label.get();
|
||||
l.setLabel((GlobalizedMessage) value);
|
||||
} else {
|
||||
l = (Label) m_label.get();
|
||||
|
||||
if ( value == null ) {
|
||||
l.setLabel( (String) GlobalizationUtil.globalize("bebop.table.").localize());
|
||||
l.setOutputEscaping(false);
|
||||
} else {
|
||||
l.setLabel(value.toString());
|
||||
l.setOutputEscaping(true);
|
||||
}
|
||||
}
|
||||
l.setFontWeight( (isSelected && m_active) ? Label.BOLD : null );
|
||||
if (m_active && ! isSelected) {
|
||||
return (ControlLink) m_controlLink.get();
|
||||
} else {
|
||||
return l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
package com.arsdigita.bebop.table;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.arsdigita.bebop.SingleSelectionModel;
|
||||
import com.arsdigita.bebop.ParameterSingleSelectionModel;
|
||||
import com.arsdigita.bebop.parameters.IntegerParameter;
|
||||
import com.arsdigita.util.Assert;
|
||||
|
||||
/**
|
||||
* Describe interface <code>TableColumnModel</code> here.
|
||||
*
|
||||
* @author David Lutterkort
|
||||
* @version $Id$
|
||||
*/
|
||||
public class DefaultTableColumnModel implements TableColumnModel {
|
||||
|
||||
private static final String SELECTED_COLUMN="col";
|
||||
|
||||
private boolean m_locked;
|
||||
|
||||
private ArrayList m_columns;
|
||||
|
||||
private SingleSelectionModel m_selection;
|
||||
|
||||
public DefaultTableColumnModel() {
|
||||
this(new Object[0]);
|
||||
}
|
||||
|
||||
public DefaultTableColumnModel(SingleSelectionModel sel) {
|
||||
this(new Object[0], sel);
|
||||
}
|
||||
|
||||
public DefaultTableColumnModel(Object[] headers) {
|
||||
this(headers,
|
||||
new ParameterSingleSelectionModel(new IntegerParameter(SELECTED_COLUMN)) );
|
||||
}
|
||||
|
||||
public DefaultTableColumnModel(Object[] headers, SingleSelectionModel sel) {
|
||||
m_columns = new ArrayList();
|
||||
m_selection = sel;
|
||||
|
||||
for (int i=0; i < headers.length; i++) {
|
||||
add(new TableColumn(i, headers[i], new Integer(i)));
|
||||
}
|
||||
}
|
||||
|
||||
public void add(TableColumn column) {
|
||||
Assert.isUnlocked(this);
|
||||
m_columns.add(column);
|
||||
}
|
||||
|
||||
public void add(int columnIndex, TableColumn column) {
|
||||
Assert.isUnlocked(this);
|
||||
m_columns.add(columnIndex, column);
|
||||
}
|
||||
|
||||
public TableColumn get(int columnIndex) {
|
||||
return (TableColumn) m_columns.get(columnIndex);
|
||||
}
|
||||
|
||||
public void set(int columnIndex, TableColumn v) {
|
||||
m_columns.set(columnIndex, v);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return m_columns.size();
|
||||
}
|
||||
|
||||
public int getIndex(Object key) {
|
||||
if ( key == null ) {
|
||||
return -1;
|
||||
}
|
||||
for (int i=0; i<size(); i++) {
|
||||
TableColumn t = get(i);
|
||||
if ( key.equals(t.getHeaderKey()) ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public Iterator columns() {
|
||||
return m_columns.iterator();
|
||||
}
|
||||
|
||||
public void remove(TableColumn column) {
|
||||
Assert.isUnlocked(this);
|
||||
m_columns.remove(column);
|
||||
}
|
||||
|
||||
public final SingleSelectionModel getSelectionModel() {
|
||||
return m_selection;
|
||||
}
|
||||
|
||||
public void setSelectionModel(SingleSelectionModel model) {
|
||||
Assert.isUnlocked(this);
|
||||
m_selection = model;
|
||||
}
|
||||
|
||||
public final void lock() {
|
||||
m_locked = true;
|
||||
}
|
||||
|
||||
public final boolean isLocked() {
|
||||
return m_locked;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2016 LibreCCM Foundation.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
package com.arsdigita.bebop.table;
|
||||
|
||||
import org.libreccm.cdi.utils.CdiUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class is used as an bridge between a CDI based Controller class and
|
||||
* a Bebop {@link TableModel}. The Controller provides a (transactional) method
|
||||
* for retrieving the data to show in the table. The table model simply retrieves
|
||||
* the Controller bean using the {@link CdiUtil} and uses the returned list of
|
||||
* objects of this class for creating the table rows.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
* @param <K> Type of the row key.
|
||||
*/
|
||||
public class RowData<K> {
|
||||
|
||||
private K rowKey;
|
||||
|
||||
private final String[] cols;
|
||||
|
||||
public RowData(final int numCols) {
|
||||
cols = new String[numCols];
|
||||
}
|
||||
|
||||
public K getRowKey() {
|
||||
return rowKey;
|
||||
}
|
||||
|
||||
public void setRowKey(final K rowKey) {
|
||||
this.rowKey = rowKey;
|
||||
}
|
||||
|
||||
public String getColData(final int colIndex) {
|
||||
return cols[colIndex];
|
||||
}
|
||||
|
||||
public void setColData(final int colIndex, final String data) {
|
||||
cols[colIndex] = data;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,126 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
package com.arsdigita.bebop.table;
|
||||
|
||||
|
||||
import com.arsdigita.bebop.util.GlobalizationUtil ;
|
||||
|
||||
import com.arsdigita.bebop.Component;
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.bebop.Table;
|
||||
|
||||
/**
|
||||
* Render one cell in a table. The renderer returns a component whose
|
||||
* {@link com.arsdigita.bebop.Component#generateXML generateXML} method
|
||||
* will be called by the table to include the data for the cell in the
|
||||
* table's output.
|
||||
*
|
||||
* <p> The table uses the returned component only until it calls the cell
|
||||
* renderer again, so that cell renderers may reuse the same object in
|
||||
* subsequent calls to {@link #getComponent getComponent}.
|
||||
*
|
||||
* <p> As an example, consider the following implementation of a table cell
|
||||
* renderer, which simply converts the passed in <code>value</code> to a
|
||||
* string and encloses it in a label. The cell renderer converts the passed
|
||||
* in value to a string and uses that to set the text to display for a
|
||||
* label. If the value is selected, the label is bolded. As an added twist,
|
||||
* the table cell renderer uses only one label for each thread from which
|
||||
* it is accessed (rather than creating a new <code>Label</code> for each
|
||||
* call) by storing the label in a <code>ThreadLocal</code> variable.
|
||||
*
|
||||
* <pre>
|
||||
* public class MyTableCellRenderer implements TableCellRenderer {
|
||||
*
|
||||
* private ThreadLocal m_label;
|
||||
*
|
||||
* public MyTableCellRenderer() {
|
||||
* m_label = new ThreadLocal() {
|
||||
* protected Object initialValue() {
|
||||
* return new Label("");
|
||||
* }
|
||||
* };
|
||||
* }
|
||||
*
|
||||
* public Component getComponent(Table table, PageState state, Object value,
|
||||
* boolean isSelected, Object key,
|
||||
* int row, int column) {
|
||||
* Label l = (Label) m_label.get();
|
||||
* l.setLabel(value.toString());
|
||||
* l.setFontWeight( isSelected ? Label.BOLD : null );
|
||||
* return l;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author David Lutterkort
|
||||
* @see com.arsdigita.bebop.Table Table
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface TableCellRenderer {
|
||||
|
||||
/**
|
||||
* Return a component with the visual representation for the passed in
|
||||
* <code>key</code> and <code>value</code>.
|
||||
*
|
||||
* <p> The table sets the control event prior to calling this method, so
|
||||
* that any control link returned as the component will, when clicked,
|
||||
* cause the table to fire a <code>TableActionEvent</code> whose
|
||||
* <code>getRowKey()</code> and <code>getColumn()</code> return the
|
||||
* values of <code>key</code> and <code>column</code>. A simple cell
|
||||
* renderer that achieves this would implement this method in the
|
||||
* following way:
|
||||
* <pre>
|
||||
* public Component getComponent(Table table, PageState state, Object value,
|
||||
* boolean isSelected, Object key,
|
||||
* int row, int column) {
|
||||
* return new ControlLink(value.toString());
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p> The <code>column</code> refers to a column in the table's {@link
|
||||
* TableColumnModel}, i.e. the visual column on the screen, and not the
|
||||
* table's representation of the underlying data in the {@link
|
||||
* TableModel}.
|
||||
*
|
||||
* @param table the table requesting the rendering.
|
||||
* @param state represents the state of the current request.
|
||||
* @param value the data element to render as returned by the table
|
||||
* model's {@link TableModel#getElementAt getElementAt(column)}.
|
||||
* @param isSelected true if this item is selected.
|
||||
* @param key the key identifying this row (and possibly column) as
|
||||
* returned by the table model's {@link TableModel#getKeyAt
|
||||
* getKeyAt(column)}
|
||||
* @param row the number of the row in the table, the first row has
|
||||
* number <code>0</code>.
|
||||
* @param column the number of the table column.
|
||||
* @return the component that should be used to render the
|
||||
* <code>value</code>.
|
||||
* @pre table != null
|
||||
* @pre state != null
|
||||
* @pre value != null
|
||||
* @pre key != null
|
||||
* @pre row >= 0
|
||||
* @pre column >= 0 && column < table.getColumnModel().size()
|
||||
* @post return != null
|
||||
* @see TableColumnModel
|
||||
*/
|
||||
Component getComponent(Table table, PageState state, Object value,
|
||||
boolean isSelected, Object key,
|
||||
int row, int column);
|
||||
}
|
||||
|
|
@ -1,458 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
package com.arsdigita.bebop.table;
|
||||
|
||||
import static com.arsdigita.bebop.Component.*;
|
||||
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.bebop.SimpleComponent;
|
||||
|
||||
import com.arsdigita.util.Assert;
|
||||
import com.arsdigita.bebop.util.Attributes;
|
||||
import com.arsdigita.util.Lockable;
|
||||
import com.arsdigita.xml.Element;
|
||||
|
||||
/**
|
||||
* One column in a table. The <code>TableColumn</code> stores important
|
||||
* display-related information about a table column, such as the column
|
||||
* header, the renderers for the column header and ordinary cells in this
|
||||
* column and from which column in the table model values should be taken
|
||||
* when rendering table cells. The set of table columns for a table is
|
||||
* maintained by a {@link TableColumnModel}.
|
||||
*
|
||||
* <p> <code>TableColumn</code> allows the column ordering to be different
|
||||
* between the underlying {@link TableModel} and the view presented by the
|
||||
* <code>Table</code>: each column contains a <code>modelIndex</code>
|
||||
* property. This is the column that is retrieved from the
|
||||
* <code>TableModel</code> when the values are displayed, regardless of the
|
||||
* position of the <code>TableColumn</code> in the
|
||||
* <code>TableColumnModel</code>. This makes it possible to display the
|
||||
* same table model in several tables with reordered or omitted columns.
|
||||
*
|
||||
* <p> The <code>TableColumn</code> stores also the value and key used for
|
||||
* the header of the column. These objects are passed to the header cell
|
||||
* renderer when the header of the table is rendered. The value is usually
|
||||
* used to generate the visible information for the table header, and is
|
||||
* often a string. The key is usually used to identify the underlying
|
||||
* object, or to just identify the column, and can be any object whose
|
||||
* <code>toString()</code> method returns a representation that can be
|
||||
* included in a URL. In the simplest case, this may just be an
|
||||
* <code>Integer</code> containing the index of the column in the column
|
||||
* model.
|
||||
*
|
||||
* @author David Lutterkort
|
||||
* @see com.arsdigita.bebop.Table
|
||||
* @see TableColumnModel
|
||||
*
|
||||
* @version $Id$ */
|
||||
public class TableColumn extends SimpleComponent
|
||||
implements Lockable {
|
||||
|
||||
|
||||
/**
|
||||
* The name of the width attribute used in the XML.
|
||||
*/
|
||||
private static final String WIDTH_ATTR = "width";
|
||||
|
||||
/**
|
||||
* The name of the align attribute used in the XML.
|
||||
*/
|
||||
private static final String ALIGN_ATTR = "align";
|
||||
|
||||
/**
|
||||
* The name of the valign attribute used in the XML.
|
||||
*/
|
||||
private static final String VALIGN_ATTR = "valign";
|
||||
|
||||
/**
|
||||
* The number of the column in the table model from which to get values.
|
||||
*/
|
||||
private int m_modelIndex;
|
||||
|
||||
/**
|
||||
* The renderer used for ordinary cells in this column. Null by default,
|
||||
* which instructs the <code>Table</code> to use its default renderer.
|
||||
*/
|
||||
private TableCellRenderer m_cellRenderer;
|
||||
|
||||
/**
|
||||
* The renderer used for the header of the column. Null by default, which
|
||||
* instructs the <code>TableHeader</code> to use its default renderer.
|
||||
*/
|
||||
private TableCellRenderer m_headerRenderer;
|
||||
|
||||
/**
|
||||
* The key for identifying the header. Will be passed to the header cell
|
||||
* renderer.
|
||||
*/
|
||||
private Object m_headerKey;
|
||||
|
||||
/**
|
||||
* The display value for identifying the header. Will be passed to the
|
||||
* header cell renderer.
|
||||
* Usually this will be a {@link Label} passed in by a pattern like
|
||||
* {@code new Label(GlobalizedMessage)}. But it could be any object,
|
||||
* e.g.an image as well. The use of a string is possible but strongly
|
||||
* discouraged because it results in non-localizable UI.
|
||||
*/
|
||||
private Object m_headerValue;
|
||||
|
||||
/**
|
||||
* The display attributes for each cell in this column
|
||||
*/
|
||||
private Attributes m_cellAttrs;
|
||||
|
||||
/**
|
||||
* Creates a new table column with <code>modelIndex</code> 0 and header
|
||||
* value and key equal to <code>null</code>.
|
||||
*/
|
||||
public TableColumn() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new table column with the given <code>modelIndex</code> and
|
||||
* header value and key equal to <code>null</code>.
|
||||
*
|
||||
* @param modelIndex the index of the column in the table model from
|
||||
* which to retrieve values
|
||||
* @pre modelIndex >= 0
|
||||
*/
|
||||
public TableColumn(int modelIndex) {
|
||||
this(modelIndex, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new table column with the given <code>modelIndex</code> and
|
||||
* header value. The header key is equal to <code>null</code>.
|
||||
*
|
||||
* @param modelIndex the index of the column in the table model from
|
||||
* which to retrieve values.
|
||||
* @param value the value for the column header.
|
||||
* @pre modelIndex >= 0
|
||||
*/
|
||||
public TableColumn(int modelIndex, Object value) {
|
||||
this(modelIndex, value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new table column with the given <code>modelIndex</code> and
|
||||
* header value and key.
|
||||
*
|
||||
* @param modelIndex the index of the column in the table model from
|
||||
* which to retrieve values.
|
||||
* @param value the value for the column header.
|
||||
* @param key the key for the column header.
|
||||
* @pre modelIndex >= 0
|
||||
*/
|
||||
public TableColumn(int modelIndex, Object value, Object key) {
|
||||
super();
|
||||
m_modelIndex = modelIndex;
|
||||
m_headerValue = value;
|
||||
m_headerKey = key;
|
||||
|
||||
m_cellAttrs = new Attributes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the renderer used for the column header. This is
|
||||
* <code>null</code> by default, in which case the default renderer for
|
||||
* the {@link TableHeader} of the table to which this column belongs is
|
||||
* used.
|
||||
*
|
||||
* @return the renderer used for the column header.
|
||||
*/
|
||||
public final TableCellRenderer getHeaderRenderer() {
|
||||
return m_headerRenderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the renderer used for the column header. The header key and value
|
||||
* objects are passed to the renderer when the column header will be
|
||||
* rendererd.
|
||||
*
|
||||
* @param v the new renderer for the column header.
|
||||
* @see #getHeaderRenderer
|
||||
* @see #getCellRenderer
|
||||
*/
|
||||
public void setHeaderRenderer(TableCellRenderer v) {
|
||||
Assert.isUnlocked(this);
|
||||
m_headerRenderer = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the renderer used for the cells in this column. This is
|
||||
* <code>null</code> by default, in which case the default renderer of
|
||||
* the {@link com.arsdigita.bebop.Table#getDefaultCellRenderer() table} to which this column
|
||||
* belongs is used.
|
||||
*
|
||||
* @return the renderer used for the cells in this column.
|
||||
*/
|
||||
public final TableCellRenderer getCellRenderer() {
|
||||
return m_cellRenderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the renderer used for cells in this column.
|
||||
*
|
||||
* @param v the new renderer for the cells in this column.
|
||||
* @see #getCellRenderer
|
||||
* @see #getHeaderRenderer
|
||||
*/
|
||||
public void setCellRenderer(TableCellRenderer v) {
|
||||
Assert.isUnlocked(this);
|
||||
m_cellRenderer = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the display value used for the header. This is the object that is
|
||||
* passed to the renderer. Usually this will be a {@link Label} previously
|
||||
* passed in by a pattern like {@code new Label(GlobalizedMessage)}.
|
||||
* The use of a string is possible but strongly discouraged.
|
||||
*
|
||||
* @return the display value for the header.
|
||||
*/
|
||||
public final Object getHeaderValue() {
|
||||
return m_headerValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the display value for the header. This object is passed through to
|
||||
* the header renderer without any modifications.
|
||||
* Usually this will be a {@link Label} passed in by a pattern like
|
||||
* {@code new Label(GlobalizedMessage)}. The use of a string is possible
|
||||
* but strongly discouraged because it results in non-localizable UI.
|
||||
*
|
||||
* @param value the new display value for the header.
|
||||
* @see #getHeaderValue
|
||||
*/
|
||||
public void setHeaderValue(Object value) {
|
||||
Assert.isUnlocked(this);
|
||||
m_headerValue = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key used to identify the header of this column. In the
|
||||
* simplest case, this is an <code>Integer</code> containing the index of
|
||||
* the column.
|
||||
*
|
||||
* @return the key used to identify the header of this column.
|
||||
*/
|
||||
public final Object getHeaderKey() {
|
||||
return m_headerKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the key used to identify the header of this column.
|
||||
*
|
||||
* @param key the new key for identifying the header of this column.
|
||||
* @see #getHeaderKey
|
||||
*/
|
||||
public void setHeaderKey(Object key) {
|
||||
Assert.isUnlocked(this);
|
||||
m_headerKey = key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of the column from which values are taken in the {@link
|
||||
* TableModel}.
|
||||
*
|
||||
* @return the index of the column in the table model from which values
|
||||
* are taken.
|
||||
* @see #setModelIndex setModelIndex
|
||||
*/
|
||||
public final int getModelIndex() {
|
||||
return m_modelIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the index of the column in the {@link TableModel} from which the
|
||||
* values are taken when this column is rendered.
|
||||
*
|
||||
* @param v the new index of the column in the table model from which to
|
||||
* take values.
|
||||
*/
|
||||
public void setModelIndex(int v) {
|
||||
Assert.isUnlocked(this);
|
||||
m_modelIndex = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the width for this column.
|
||||
*
|
||||
* @return the width of this column.
|
||||
* @see #setWidth setWidth
|
||||
*/
|
||||
public String getWidth() {
|
||||
return getAttribute(WIDTH_ATTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the width of this column. The string <code>v</code> is added as an
|
||||
* attribute to the XML element for this column in the table header.
|
||||
*
|
||||
* @param v the width of this column
|
||||
*/
|
||||
public void setWidth(String v) {
|
||||
Assert.isUnlocked(this);
|
||||
setAttribute(WIDTH_ATTR, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the horizontal alignment this column. The string <code>v</code>
|
||||
* is added as an attribute to the XML element for each cell in this column
|
||||
*
|
||||
* @param v the width of this column
|
||||
*/
|
||||
public void setAlign(String v) {
|
||||
Assert.isUnlocked(this);
|
||||
m_cellAttrs.setAttribute(ALIGN_ATTR, v);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the horizontal alignment this column's header. The string
|
||||
* <code>v</code> is added as an attribute to the XML element for
|
||||
* the column's header cell.
|
||||
*
|
||||
* @param v the width of this column */
|
||||
public void setHeadAlign(String v) {
|
||||
Assert.isUnlocked(this);
|
||||
setAttribute(ALIGN_ATTR, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the vertical alignment this column. The string <code>v</code>
|
||||
* is added as an attribute to the XML element for each cell in this column
|
||||
*
|
||||
* @param v the width of this column
|
||||
*/
|
||||
public void setVAlign(String v) {
|
||||
Assert.isUnlocked(this);
|
||||
m_cellAttrs.setAttribute(VALIGN_ATTR, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the vertical alignment this column's header. The string
|
||||
* <code>v</code> is added as an attribute to the XML element for
|
||||
* this column's header cell.
|
||||
*
|
||||
* @param v the width of this column */
|
||||
public void setHeadVAlign(String v) {
|
||||
Assert.isUnlocked(this);
|
||||
setAttribute(VALIGN_ATTR, v);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the style attribute for the column's
|
||||
* cells. <code>style</code> should be a valid CSS style, since
|
||||
* its value will be copied verbatim to the output and appear as a
|
||||
* <tt>style</tt> attribute in the top level XML or HTML output
|
||||
* element.
|
||||
*
|
||||
* @param style a valid CSS style description for use in the
|
||||
* <tt>style</tt> attribute of an HTML tag
|
||||
* @see <a href="#standard">Standard Attributes</a> */
|
||||
public void setStyleAttr(String style) {
|
||||
Assert.isUnlocked(this);
|
||||
m_cellAttrs.setAttribute(STYLE, style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the style attribute for the column's header
|
||||
* cell. <code>style</code> should be a valid CSS style, since its
|
||||
* value will be copied verbatim to the output and appear as a
|
||||
* <tt>style</tt> attribute in the top level XML or HTML output
|
||||
* element.
|
||||
*
|
||||
* @param style a valid CSS style description for use in the
|
||||
* <tt>style</tt> attribute of an HTML tag
|
||||
* @see <a href="#standard">Standard Attributes</a> */
|
||||
public void setHeadStyleAttr(String style) {
|
||||
Assert.isUnlocked(this);
|
||||
setAttribute(STYLE, style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the class attribute for the column's
|
||||
* cells. <code>style</code> should be the name of a defined CSS
|
||||
* class, since its value will be copied verbatim to the output
|
||||
* and appear as a <tt>class</tt> attribute in the top level XML
|
||||
* or HTML output element.
|
||||
*
|
||||
* @param style a valid CSS style description for use in the
|
||||
* <tt>style</tt> attribute of an HTML tag
|
||||
* @see <a href="#standard">Standard Attributes</a> */
|
||||
public void setClassAttr(String c) {
|
||||
Assert.isUnlocked(this);
|
||||
m_cellAttrs.setAttribute(CLASS, c);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the class attribute for the column's header
|
||||
* cell. <code>style</code> should be the name of a defined CSS
|
||||
* class, since its value will be copied verbatim to the output
|
||||
* and appear as a <tt>class</tt> attribute in the top level XML
|
||||
* or HTML output element.
|
||||
*
|
||||
* @param style a valid CSS style description for use in the
|
||||
* <tt>style</tt> attribute of an HTML tag
|
||||
* @see <a href="#standard">Standard Attributes</a> */
|
||||
public void setHeadClassAttr(String c) {
|
||||
Assert.isUnlocked(this);
|
||||
setAttribute(CLASS, c);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add all the XML attributes for this column.
|
||||
*
|
||||
* @param e the XML element to which attributes will be added.
|
||||
*/
|
||||
public void exportCellAttributes(Element e) {
|
||||
m_cellAttrs.exportAttributes(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all the XML attributes for this column to this
|
||||
* element. Package-friendly since it is only used by {@link
|
||||
* TableHeader}.
|
||||
*
|
||||
* @param e the XML element to which attributes will be added.
|
||||
*/
|
||||
final void exportHeadAttributes(Element e) {
|
||||
super.exportAttributes(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an <code>UnsupportedOperationException</code>. This method can
|
||||
* only be called if the table column is not properly contained in a
|
||||
* table.
|
||||
*
|
||||
* @param s represents the current request
|
||||
* @param e the parent element
|
||||
*/
|
||||
public void generateXML(PageState s, Element e) {
|
||||
throw new UnsupportedOperationException("TableColumn used outside of a Table");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
package com.arsdigita.bebop.table;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.arsdigita.bebop.SingleSelectionModel;
|
||||
import com.arsdigita.util.Lockable;
|
||||
|
||||
/**
|
||||
* Describe interface <code>TableColumnModel</code> here.
|
||||
*
|
||||
* @author David Lutterkort
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface TableColumnModel extends Lockable {
|
||||
|
||||
|
||||
void add(TableColumn column);
|
||||
|
||||
TableColumn get(int columnIndex);
|
||||
|
||||
/**
|
||||
* Insert a column at the given index. The columns from
|
||||
* <code>columnIndex</code> on are shifted one up.
|
||||
*
|
||||
* @param columnIndex the index for the new column.
|
||||
* @param column the table column to add to the model.
|
||||
* @pre 0 <= columnIndex && columnIndex <= size()
|
||||
*/
|
||||
void add(int columnIndex, TableColumn column);
|
||||
|
||||
void set(int columnIndex, TableColumn v);
|
||||
|
||||
int size();
|
||||
|
||||
int getIndex(Object columnIdentifier);
|
||||
|
||||
Iterator columns();
|
||||
|
||||
void remove(TableColumn column);
|
||||
|
||||
SingleSelectionModel getSelectionModel();
|
||||
|
||||
void setSelectionModel(SingleSelectionModel model);
|
||||
}
|
||||
|
|
@ -1,298 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
package com.arsdigita.bebop.table;
|
||||
|
||||
import static com.arsdigita.bebop.Component.*;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import com.arsdigita.bebop.Component;
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.bebop.SimpleComponent;
|
||||
import com.arsdigita.bebop.Table;
|
||||
import com.arsdigita.bebop.event.EventListenerList;
|
||||
import com.arsdigita.bebop.event.TableActionEvent;
|
||||
import com.arsdigita.bebop.event.TableActionListener;
|
||||
|
||||
import com.arsdigita.util.Assert;
|
||||
import com.arsdigita.xml.Element;
|
||||
|
||||
/**
|
||||
* This class is used by {@link Table} in order to maintain its headers.
|
||||
*
|
||||
* <code>TableHeader</code> is responsible for setting the control event
|
||||
* in order to notify the {@link Table} when one of the column headers
|
||||
* is clicked.
|
||||
*
|
||||
* @author David Lutterkort
|
||||
* @version $Id$
|
||||
*/
|
||||
public class TableHeader extends SimpleComponent {
|
||||
|
||||
|
||||
/**
|
||||
* The control event when the user clicks on a column header.
|
||||
*/
|
||||
public static final String HEAD_EVENT = "head";
|
||||
|
||||
private TableCellRenderer m_defaultRenderer;
|
||||
|
||||
private TableColumnModel m_columnModel;
|
||||
|
||||
private Table m_table;
|
||||
|
||||
private EventListenerList m_listeners;
|
||||
|
||||
/**
|
||||
* Create a new <code>TableHeader</code>
|
||||
*/
|
||||
public TableHeader() {
|
||||
this(new DefaultTableColumnModel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new <code>TableHeader</code>
|
||||
*
|
||||
* @param model the {@link TableColumnModel} that the header
|
||||
* will use in order to generate and maintain the
|
||||
* column headers.
|
||||
*/
|
||||
public TableHeader(TableColumnModel model) {
|
||||
m_columnModel = model;
|
||||
m_defaultRenderer = new DefaultTableCellRenderer();
|
||||
m_listeners = new EventListenerList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an {@link TableActionListener} to the header.
|
||||
* The listener will be fired whenever this header is
|
||||
* selected by the user.
|
||||
*
|
||||
* @param l the {@link TableActionListener} to add
|
||||
*/
|
||||
public void addTableActionListener(TableActionListener l) {
|
||||
Assert.isUnlocked(this);
|
||||
m_listeners.add(TableActionListener.class, l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a {@link TableActionListener} from the header
|
||||
*
|
||||
*@param l the {@link TableActionListener} to remove
|
||||
*/
|
||||
public void removeTableActionListener(TableActionListener l) {
|
||||
Assert.isUnlocked(this);
|
||||
m_listeners.remove(TableActionListener.class, l);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Notify all listeners that the header was selected
|
||||
*
|
||||
* @param state the page state
|
||||
* @param rowKey the key of the selected row, as returned by
|
||||
* <code>Table.getRowSelectionModel().getSelectedKey(state)</code>.
|
||||
* this key may be null.
|
||||
* @param column The index of the selected column
|
||||
*
|
||||
*/
|
||||
protected void fireHeadSelected(PageState state,
|
||||
Object rowKey, Integer column) {
|
||||
Iterator
|
||||
i=m_listeners.getListenerIterator(TableActionListener.class);
|
||||
TableActionEvent e = null;
|
||||
|
||||
while (i.hasNext()) {
|
||||
if ( e == null ) {
|
||||
e = new TableActionEvent(this, state, rowKey, column);
|
||||
}
|
||||
((TableActionListener) i.next()).headSelected(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Respond to the current event by selecting the current
|
||||
* column
|
||||
*
|
||||
* @param s the page state
|
||||
*/
|
||||
public void respond(PageState s) throws ServletException {
|
||||
String event = s.getControlEventName();
|
||||
if ( HEAD_EVENT.equals(event) ) {
|
||||
String value = s.getControlEventValue();
|
||||
// FIXME: ParameterData allows its value to be set to anything, even
|
||||
// if it isn't compatible with the ParameterModel
|
||||
// We need to change ParameterModel/Data to fail earlier on bad data
|
||||
Integer col = new Integer(value);
|
||||
getColumnModel().getSelectionModel().setSelectedKey(s, col);
|
||||
fireHeadSelected(s, null, col);
|
||||
} else {
|
||||
throw new ServletException("Unknown event '" + event + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the parent {@link Table}
|
||||
*/
|
||||
public final Table getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the parent {@link Table}
|
||||
*
|
||||
* @param v the parent table
|
||||
*/
|
||||
public void setTable(Table v) {
|
||||
Assert.isUnlocked(this);
|
||||
m_table = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link TableColumnModel} which maintains the headers
|
||||
*/
|
||||
public final TableColumnModel getColumnModel() {
|
||||
return m_columnModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link TableColumnModel} which will maintain the headers
|
||||
*
|
||||
* @param v the new {@link TableColumnModel}
|
||||
*/
|
||||
public void setColumnModel(TableColumnModel v) {
|
||||
Assert.isUnlocked(this);
|
||||
m_columnModel = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the default {@link TableCellRenderer} for this header
|
||||
*/
|
||||
public final TableCellRenderer getDefaultRenderer() {
|
||||
return m_defaultRenderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default {@link TableCellRenderer} for this header.
|
||||
* Header cells will be rendered with this renderer unless
|
||||
* the column model specifies an alternative renderer.
|
||||
*
|
||||
* @param v the new default renderer
|
||||
*/
|
||||
public void setDefaultRenderer(TableCellRenderer v) {
|
||||
Assert.isUnlocked(this);
|
||||
m_defaultRenderer = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the XML for this header. The XML will be of the form
|
||||
* <blockquote><pre><code>
|
||||
* <bebop:thead>
|
||||
* <bebop:cell>...</bebop:cell>
|
||||
* ...
|
||||
* </bebop:thead>
|
||||
* </code><pre></blockquote>
|
||||
*
|
||||
* @param s the page state
|
||||
* @param p the parent element
|
||||
*/
|
||||
public void generateXML(PageState s, Element p) {
|
||||
if ( isVisible(s) ) {
|
||||
Element thead = p.newChildElement("bebop:thead", BEBOP_XML_NS);
|
||||
exportAttributes(thead);
|
||||
|
||||
for (int i=0; i < m_columnModel.size(); i++) {
|
||||
TableColumn t = m_columnModel.get(i);
|
||||
|
||||
if ( t.isVisible(s) ) {
|
||||
TableCellRenderer r = t.getHeaderRenderer();
|
||||
|
||||
if ( r == null ) {
|
||||
r = getDefaultRenderer();
|
||||
}
|
||||
|
||||
boolean isSel = isSelected(s, t.getHeaderKey(), i);
|
||||
|
||||
Component c = r.getComponent(getTable(), s, t.getHeaderValue(), isSel,
|
||||
t.getHeaderKey(), -1, i);
|
||||
|
||||
if (c != null) {
|
||||
// supports having a table header disappear
|
||||
// completely, mainly useful for the odd special case
|
||||
// where a second-row element is being displayed.
|
||||
|
||||
Element cell = thead.newChildElement("bebop:cell", BEBOP_XML_NS);
|
||||
t.exportHeadAttributes(cell);
|
||||
|
||||
// Mark the cell as selected if it is selected
|
||||
if(isSel) {
|
||||
cell.addAttribute("selected", "1");
|
||||
}
|
||||
|
||||
// I added this check so that a table which is not
|
||||
// added to the Page can still be used to render
|
||||
// table XML.
|
||||
|
||||
boolean tableIsRegisteredWithPage =
|
||||
s.getPage().stateContains(getControler());
|
||||
|
||||
if (tableIsRegisteredWithPage) {
|
||||
s.setControlEvent(getControler(), HEAD_EVENT,
|
||||
String.valueOf(i));
|
||||
}
|
||||
|
||||
c.generateXML(s, cell);
|
||||
|
||||
if (tableIsRegisteredWithPage) {
|
||||
s.clearControlEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Component getControler() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given column is selected. This information
|
||||
* will be passed to the {@link TableCellRenderer} for this header.
|
||||
*
|
||||
* @param s the page state
|
||||
* @param key the header key for the column as returned by
|
||||
* <code>TableColumn.getHeaderKey()</code>
|
||||
* @param column the index of the column to test
|
||||
*/
|
||||
protected boolean isSelected(PageState s, Object key, int column) {
|
||||
if (getTable().getColumnSelectionModel() == null) {
|
||||
return false;
|
||||
}
|
||||
Object sel = getTable()
|
||||
.getColumnSelectionModel().getSelectedKey(s);
|
||||
if(sel == null) {
|
||||
return false;
|
||||
}
|
||||
return (column == ((Integer)sel).intValue());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
package com.arsdigita.bebop.table;
|
||||
|
||||
/**
|
||||
* The <code>TableModel</code> is the abstraction a {@link
|
||||
* com.arsdigita.bebop.Table Table} uses to access the data it
|
||||
* displays. The table will ask its {@link TableModelBuilder} to
|
||||
* instantiate a new table model once for each request it processes.
|
||||
*
|
||||
* <p> The table will request each element in the model at most once per
|
||||
* request, moving through the rows with successive calls to {@link
|
||||
* #nextRow}. For each row, the table retrieves the values and keys in each
|
||||
* column with calls to {@link #getElementAt} and {@link #getKeyAt}.
|
||||
*
|
||||
* <p> The table data is accessed by the table by moving through the rows
|
||||
* of the table model with calls to {@link #nextRow}. The data for each
|
||||
* column in a row is represented by two objects: the data element which
|
||||
* usually contains display information for that column and can be as
|
||||
* simple as a string, and the key, which is used to identify the
|
||||
* column. The key is usually a suitable representation of the primary key
|
||||
* of the underlying object in the database. The key needs to be unique
|
||||
* amongst all <em>rows</em> in the table model, but doesn't need to
|
||||
* uniquely identify the row <em>and</em> column for that data item -
|
||||
* all calls to {@link #getKeyAt} can return the same value for one row in
|
||||
* the table model.
|
||||
*
|
||||
* @see com.arsdigita.bebop.Table Table
|
||||
* @see TableModelBuilder
|
||||
*
|
||||
* @author David Lutterkort
|
||||
* @version $Id$ */
|
||||
public interface TableModel {
|
||||
|
||||
|
||||
/**
|
||||
* Return the number of columns this table model has.
|
||||
*
|
||||
* @return the number of columns in the table model
|
||||
* @post return >= 0
|
||||
*/
|
||||
int getColumnCount();
|
||||
|
||||
/**
|
||||
* Move to the next row and return true if the model is now positioned on
|
||||
* a valid row. Initially, the table model is positioned before the first
|
||||
* row. The table will call this method before it retrieves the data for
|
||||
* the row with calls to {@link #getElementAt getElementAt} and {@link
|
||||
* #getKeyAt getKeyAt}.
|
||||
*
|
||||
* <p> If this method returns <code>true</code>, subsequent calls to
|
||||
* {@link #getElementAt getElementAt} and {@link #getKeyAt getKeyAt} have
|
||||
* to succeed and return non-null objects. If this method returns
|
||||
* <code>false</code>, the table assumes that it has traversed all the
|
||||
* data contained in this model.
|
||||
*
|
||||
* @return <code>true</code> if the model is positioned on a valid row
|
||||
*/
|
||||
boolean nextRow();
|
||||
|
||||
/**
|
||||
* Return the data element for the given column and the current row. The
|
||||
* returned object will be passed to the table cell renderer as the
|
||||
* <code>value</code> argument without modifications.
|
||||
*
|
||||
* @param columnIndex the number of the column for which to get data
|
||||
* @return the object to pass to the table cell renderer for display
|
||||
* @pre columnIndex >= 0 && columnIndex < getColumnCount()
|
||||
* @post return != null
|
||||
* @see TableCellRenderer
|
||||
*/
|
||||
Object getElementAt(int columnIndex);
|
||||
|
||||
/**
|
||||
* Return the key for the given column and the current row. The key has
|
||||
* to be unique for each <em>row</em> in the table model, but does not
|
||||
* need to be unique for each row <em>and</em> column, though it may.
|
||||
* The key is passed to the table cell renderer as the <code>key</code>
|
||||
* argument.
|
||||
*
|
||||
* @param columnIndex the number of the column for which to get data
|
||||
* @return the key for the given column and the current row.
|
||||
* @pre columnIndex >= 0 && columnIndex < getColumnCount()
|
||||
* @post return != null
|
||||
* @see TableCellRenderer
|
||||
*/
|
||||
Object getKeyAt(int columnIndex);
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
package com.arsdigita.bebop.table;
|
||||
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.bebop.Table;
|
||||
import com.arsdigita.util.Lockable;
|
||||
|
||||
/**
|
||||
* Builds the request-specific table models. A table retrieves the data it
|
||||
* displays by asking the table model builder for a table model. This is
|
||||
* done for each request; the table does not cahce table models across
|
||||
* requests. If such caching is desired, it has to be performed by the
|
||||
* table model builder.
|
||||
*
|
||||
* <p> Typically, the table model builder will run a database query based
|
||||
* on the information contained in the page state and return the result of
|
||||
* the database query by wrapping it in a table model. The table will then
|
||||
* traverse the table model during rendering.
|
||||
*
|
||||
* <p> The table model builder is automatically locked by the table to
|
||||
* which it was added either through one of the {@link
|
||||
* com.arsdigita.bebop.Table Table} constructors or with a call to {@link
|
||||
* com.arsdigita.bebop.Table#setModelBuilder}.
|
||||
*
|
||||
* @see com.arsdigita.bebop.Table Table
|
||||
* @see TableModel
|
||||
*
|
||||
* @author David Lutterkort
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface TableModelBuilder extends Lockable {
|
||||
|
||||
|
||||
/**
|
||||
* Return a table model for the request represented by
|
||||
* <code>s</code>. The table model contains all the data that is to be
|
||||
* displayed in a table. The returned table model is used only during
|
||||
* the duration of that request.
|
||||
*
|
||||
* @param t the table which will use this table model
|
||||
* @param s represents the current request
|
||||
* @return the data to be displayed in the table
|
||||
* @pre t != null
|
||||
* @pre s != null
|
||||
* @post return != null
|
||||
*/
|
||||
TableModel makeModel(Table t, PageState s);
|
||||
}
|
||||
Loading…
Reference in New Issue