0001: package org.gui4j.component;
0002:
0003: import java.awt.Color;
0004: import java.awt.Component;
0005: import java.awt.Dimension;
0006: import java.awt.Font;
0007: import java.awt.Point;
0008: import java.awt.Rectangle;
0009: import java.awt.event.MouseEvent;
0010: import java.io.Serializable;
0011: import java.util.ArrayList;
0012: import java.util.Collection;
0013: import java.util.HashMap;
0014: import java.util.Iterator;
0015: import java.util.List;
0016: import java.util.Map;
0017:
0018: import javax.swing.JComponent;
0019: import javax.swing.JLabel;
0020: import javax.swing.JTable;
0021: import javax.swing.ListSelectionModel;
0022: import javax.swing.table.DefaultTableCellRenderer;
0023: import javax.swing.table.JTableHeader;
0024: import javax.swing.table.TableCellEditor;
0025: import javax.swing.table.TableCellRenderer;
0026: import javax.swing.table.TableColumn;
0027:
0028: import org.apache.commons.logging.Log;
0029: import org.apache.commons.logging.LogFactory;
0030:
0031: import org.gui4j.Gui4jCallBase;
0032: import org.gui4j.Gui4jGetValue;
0033: import org.gui4j.component.util.StringUtil;
0034: import org.gui4j.core.Gui4jCall;
0035: import org.gui4j.core.Gui4jComponentContainer;
0036: import org.gui4j.core.Gui4jComponentInstance;
0037: import org.gui4j.core.Gui4jQualifiedComponent;
0038: import org.gui4j.core.Gui4jSwingContainer;
0039: import org.gui4j.core.Gui4jTextAttribute;
0040: import org.gui4j.core.Gui4jThreadManager;
0041: import org.gui4j.core.Gui4jTypeManager;
0042: import org.gui4j.core.listener.Gui4jMouseListenerMatrix;
0043: import org.gui4j.core.swing.BooleanTableCellRenderer;
0044: import org.gui4j.core.swing.ComboBoxCellEdit;
0045: import org.gui4j.core.swing.Gui4jCellEditor;
0046: import org.gui4j.core.swing.Gui4jJTable;
0047: import org.gui4j.core.swing.Gui4jJTableHeader;
0048: import org.gui4j.core.swing.Gui4jRefreshTable;
0049: import org.gui4j.core.swing.Gui4jTableListener;
0050: import org.gui4j.core.swing.MultiLineLabelUI;
0051: import org.gui4j.core.swing.RowHeaderAbstractTableModel;
0052: import org.gui4j.core.swing.RowHeaderTable;
0053: import org.gui4j.core.util.ComboBoxNullItem;
0054: import org.gui4j.core.util.SparseMatrix;
0055: import org.gui4j.event.Gui4jEventListener;
0056: import org.gui4j.util.Pair;
0057:
0058: /**
0059: * Table supporting dynamic count of columns and rows
0060: */
0061: public class Gui4jMatrix extends Gui4jJComponent {
0062: protected static final Log mLogger = LogFactory
0063: .getLog(Gui4jMatrix.class);
0064:
0065: public static final String PARAM_COL = "col";
0066: public static final String PARAM_ROW = "row";
0067: public static final String PARAM_VALUE = "value";
0068: public static final String PARAM_COLVALUE = "colValue";
0069: public static final String PARAM_ROWVALUE = "rowValue";
0070: public static final String PARAM_LIST = "list";
0071: public static final String PARAM_LIST_ITEM = "listItem";
0072:
0073: private static final String SELECTION_LISTENER_ID = "selectionListener";
0074:
0075: protected final Gui4jTypeManager mColManager;
0076: protected final Gui4jTypeManager mRowManager;
0077: protected final SparseMatrix mCellManager;
0078: protected final boolean mUseCacheDflt;
0079:
0080: protected final int mVisibleRows;
0081: protected final int mHeaderLines;
0082: protected final boolean mUseRowHeaders;
0083: protected final boolean mUseColumnHeaders;
0084: protected final boolean mAutomaticRefresh;
0085: protected final Gui4jThreadManager mGui4jThreadManager;
0086:
0087: protected int mRowSelectionMode = ListSelectionModel.SINGLE_SELECTION;
0088: protected int mColSelectionMode = ListSelectionModel.SINGLE_SELECTION;
0089: protected boolean mReorderingAllowed = true;
0090: protected boolean mRowSelectionAllowed = true;
0091:
0092: protected Gui4jCall[] mRefresh;
0093: protected Gui4jCall mOnSetValue;
0094: private Gui4jCall mHeaderBackground;
0095:
0096: protected final int mResizeMode;
0097:
0098: /**
0099: * Constructor Gui4jMatrix.
0100: *
0101: * @param gui4jComponentContainer
0102: * @param id
0103: * @param visibleRows
0104: * @param headerLines
0105: * @param useCache
0106: * @param useRowHeaders
0107: * @param useColumnHeaders
0108: * @param automaticRefresh
0109: * @param resizeMode
0110: */
0111: public Gui4jMatrix(Gui4jComponentContainer gui4jComponentContainer,
0112: String id, int visibleRows, int headerLines,
0113: boolean useCache, boolean useRowHeaders,
0114: boolean useColumnHeaders, boolean automaticRefresh,
0115: int resizeMode) {
0116: super (gui4jComponentContainer,
0117: useRowHeaders ? RowHeaderTable.class
0118: : Gui4jJTable.class, id);
0119: mUseCacheDflt = useCache;
0120: mUseRowHeaders = useRowHeaders;
0121: mUseColumnHeaders = useColumnHeaders;
0122: mAutomaticRefresh = automaticRefresh;
0123: mGui4jThreadManager = getGui4j().getGui4jThreadManager();
0124: mVisibleRows = visibleRows;
0125: mHeaderLines = headerLines;
0126: mResizeMode = resizeMode;
0127:
0128: mColManager = new Gui4jTypeManager();
0129: mRowManager = new Gui4jTypeManager();
0130: mCellManager = new SparseMatrix();
0131:
0132: }
0133:
0134: public void addGui4jCol(Class type, Gui4jCol gui4jCol) {
0135: mColManager.add(type, gui4jCol);
0136: }
0137:
0138: public void addGui4jRow(Class type, Gui4jRow gui4jRow) {
0139: mRowManager.add(type, gui4jRow);
0140: }
0141:
0142: public void addGui4jCell(Gui4jCell gui4jCell) {
0143: // mLogger.debug("setting row="+gui4jCell.getGui4jRow().mClassType+",
0144: // col="+gui4jCell.getGui4jCol().mClassType+", cell="+gui4jCell.mValue);
0145: mCellManager.set(gui4jCell.getGui4jRow(), gui4jCell
0146: .getGui4jCol(), gui4jCell);
0147: }
0148:
0149: public void setColumns(
0150: Gui4jComponentInstance gui4jComponentInstance,
0151: final Collection columns) {
0152: Gui4jJTable jTable = (Gui4jJTable) gui4jComponentInstance
0153: .getSwingComponent();
0154: jTable.endCellEditing();
0155: final Gui4jTableModel tm = (Gui4jTableModel) jTable.getModel();
0156:
0157: Gui4jThreadManager
0158: .executeInSwingThreadAndContinue(new Runnable() {
0159: public void run() {
0160: tm.setColumns(columns);
0161: }
0162: });
0163: }
0164:
0165: public void setRows(Gui4jComponentInstance gui4jComponentInstance,
0166: final Collection rows) {
0167: Gui4jJTable jTable = (Gui4jJTable) gui4jComponentInstance
0168: .getSwingComponent();
0169: jTable.endCellEditing();
0170: final Gui4jTableModel model = (Gui4jTableModel) jTable
0171: .getModel();
0172: Gui4jThreadManager
0173: .executeInSwingThreadAndContinue(new Runnable() {
0174: public void run() {
0175: model.setRows(rows);
0176: }
0177: });
0178:
0179: }
0180:
0181: public void setContent(
0182: Gui4jComponentInstance gui4jComponentInstance, Pair content) {
0183: Gui4jJTable jTable = (Gui4jJTable) gui4jComponentInstance
0184: .getSwingComponent();
0185: jTable.endCellEditing();
0186: final Gui4jTableModel model = (Gui4jTableModel) jTable
0187: .getModel();
0188: final Object first = content.getFirst();
0189: final Object second = content.getSecond();
0190: if (!(first instanceof Collection)) {
0191: mLogger.error(
0192: "First part of pair must be instanceof Collection: "
0193: + first, new Throwable());
0194: return;
0195: }
0196: if (!(second instanceof Collection)) {
0197: mLogger.error(
0198: "Second part of pair must be instanceof Collection: "
0199: + second, new Throwable());
0200: return;
0201: }
0202:
0203: Gui4jThreadManager
0204: .executeInSwingThreadAndContinue(new Runnable() {
0205: public void run() {
0206: model.setContent((Collection) first,
0207: (Collection) second);
0208: }
0209: });
0210:
0211: }
0212:
0213: public void setRefresh(Gui4jCall[] refresh) {
0214: mRefresh = refresh;
0215: }
0216:
0217: public boolean setCellSelectionPair(
0218: Gui4jComponentInstance componentInstance, Pair pair) {
0219: JTable table = (JTable) componentInstance.getSwingComponent();
0220: if (pair != null) {
0221: Gui4jTableModel model = (Gui4jTableModel) table.getModel();
0222: Gui4jMouseListenerMatrix selectionListener = (Gui4jMouseListenerMatrix) componentInstance
0223: .getStorage(SELECTION_LISTENER_ID);
0224:
0225: int row = model.getRowIndex(pair.getFirst());
0226: int col = model.getColumnIndex(pair.getSecond());
0227:
0228: if (row >= 0 && row < table.getRowCount() && col >= 0
0229: && col < table.getColumnCount()) {
0230: if (table.getCellEditor() != null && table.isEditing()) {
0231: table.getCellEditor().stopCellEditing();
0232: }
0233: if (selectionListener != null) {
0234: selectionListener.setValueChangeActive(false);
0235: }
0236: table.setRowSelectionInterval(row, row);
0237: table.setColumnSelectionInterval(col, col);
0238: if (selectionListener != null) {
0239: selectionListener.setValueChangeActive(true);
0240: selectionListener.valueChanged(null); // fire only one
0241: // event for the
0242: // combined row and
0243: // column change
0244: }
0245: Rectangle rect = table.getCellRect(row, col, true);
0246: table.scrollRectToVisible(rect);
0247: return true;
0248: }
0249: }
0250: return false;
0251: }
0252:
0253: /**
0254: * Sets the onSetValue.
0255: *
0256: * @param onSetValue
0257: * The onSetValue to set
0258: */
0259: public void setOnSetValue(Gui4jCall onSetValue) {
0260: mOnSetValue = onSetValue;
0261: }
0262:
0263: /**
0264: * Sets the headerBackground.
0265: *
0266: * @param headerBackground
0267: */
0268: public void setHeaderBackground(Gui4jCall headerBackground) {
0269: mHeaderBackground = headerBackground;
0270: }
0271:
0272: /**
0273: * @see org.gui4j.core.Gui4jAbstractComponent#setProperties(Gui4jComponentInstance)
0274: */
0275: protected void setProperties(
0276: Gui4jComponentInstance gui4jComponentInstance) {
0277: super .setProperties(gui4jComponentInstance);
0278: Gui4jJTable table = (Gui4jJTable) gui4jComponentInstance
0279: .getSwingComponent();
0280: table.setAutoResizeMode(mResizeMode);
0281: Font font = table.getFont();
0282: table.setDefaultEditor(Object.class, Gui4jCellEditor
0283: .createTextEditor(font, true));
0284:
0285: Color headerBackground = null;
0286: if (mHeaderBackground != null) {
0287: headerBackground = (Color) mHeaderBackground
0288: .getValueNoParams(gui4jComponentInstance
0289: .getGui4jCallBase(), null);
0290: }
0291:
0292: if (mUseColumnHeaders) {
0293: JTableHeader tableHeader = new Gui4jJTableHeader(table
0294: .getColumnModel(), font, mHeaderLines);
0295: if (headerBackground != null) {
0296: tableHeader.setBackground(headerBackground);
0297: }
0298: table.setTableHeader(tableHeader);
0299: }
0300:
0301: JTableHeader tableHeader = table.getTableHeader();
0302: if (tableHeader != null) {
0303: tableHeader.setReorderingAllowed(mReorderingAllowed);
0304: tableHeader.setFont(font);
0305: TableCellRenderer renderer = tableHeader
0306: .getDefaultRenderer();
0307: Component c = renderer.getTableCellRendererComponent(table,
0308: "", false, false, 0, 0);
0309: if (mHeaderLines == 1 && c instanceof JLabel) {
0310: ((JLabel) c).setUI(MultiLineLabelUI.getInstance());
0311: }
0312: }
0313:
0314: {
0315: JLabel l = new JLabel("X");
0316: l.setFont(font);
0317: table.setRowHeight(l.getPreferredSize().height + 4);
0318: }
0319:
0320: if (mVisibleRows != -1) {
0321: Dimension d = new Dimension(table.getPreferredSize());
0322: d.setSize(d.getWidth(), table.getRowHeight() * mVisibleRows
0323: + 3);
0324: table.setPreferredScrollableViewportSize(d);
0325: }
0326:
0327: final Gui4jTableModel tableModel = (Gui4jTableModel) table
0328: .getModel();
0329: if (mUseRowHeaders) {
0330: JLabel label = new JLabel();
0331: label.setFont(font);
0332: RowHeaderTable ctable = (RowHeaderTable) table;
0333: ctable.setRowHeaderFont(font);
0334: ctable.setRowHeaderHeight(table.getRowHeight());
0335: tableModel.refreshRows();
0336: if (headerBackground != null) {
0337: ((RowHeaderTable.RowHeaderRenderer) ctable
0338: .getRowHeader().getCellRenderer())
0339: .setBackground(headerBackground);
0340: }
0341: }
0342: tableModel.setInitialized();
0343: tableModel.refreshColumns(tableModel);
0344:
0345: final Flag hasOnCellSelect = new Flag();
0346: final Flag hasOnCellClick = new Flag();
0347: final Flag hasOnCellDblClick = new Flag();
0348: mCellManager.traverse(new SparseMatrix.Traverser() {
0349: public void work(Object row, Object col, Object value) {
0350: Gui4jCell gui4jCell = (Gui4jCell) value;
0351: hasOnCellSelect.val |= gui4jCell.mOnCellSelect != null;
0352: hasOnCellClick.val |= gui4jCell.mOnCellClick != null;
0353: hasOnCellDblClick.val |= gui4jCell.mOnCellDblClick != null;
0354: }
0355: });
0356:
0357: if (hasOnCellSelect.val) {
0358: Gui4jMouseListenerMatrix.CellListener cellListener = new Gui4jMouseListenerMatrix.CellListener() {
0359: public void handle(int[] rows, int[] cols,
0360: Gui4jCallBase gui4jController,
0361: Gui4jThreadManager gui4jThreadManager) {
0362: if (rows.length == 1 && cols.length == 1) {
0363: tableModel.handleOnCellSelect(rows[0], cols[0],
0364: gui4jController, gui4jThreadManager);
0365: }
0366: }
0367: };
0368: Gui4jMouseListenerMatrix selectionListener = new Gui4jMouseListenerMatrix(
0369: gui4jComponentInstance, 1, cellListener);
0370: table.getSelectionModel().addListSelectionListener(
0371: selectionListener);
0372: table.getColumnModel().getSelectionModel()
0373: .addListSelectionListener(selectionListener);
0374: gui4jComponentInstance.setStorage(SELECTION_LISTENER_ID,
0375: selectionListener);
0376: }
0377:
0378: if (hasOnCellClick.val) {
0379: Gui4jMouseListenerMatrix.CellListener cellListener = new Gui4jMouseListenerMatrix.CellListener() {
0380: public void handle(int[] rows, int[] cols,
0381: Gui4jCallBase gui4jController,
0382: Gui4jThreadManager gui4jThreadManager) {
0383: if (rows.length == 1 && cols.length == 1) {
0384: tableModel.handleOnCellClick(rows[0], cols[0],
0385: gui4jController, gui4jThreadManager);
0386: }
0387: }
0388: };
0389: Gui4jMouseListenerMatrix mouseListener = new Gui4jMouseListenerMatrix(
0390: gui4jComponentInstance, 1, cellListener);
0391: table.addMouseListener(mouseListener);
0392: }
0393:
0394: if (hasOnCellDblClick.val) {
0395: Gui4jMouseListenerMatrix.CellListener cellListener = new Gui4jMouseListenerMatrix.CellListener() {
0396: public void handle(int[] rows, int[] cols,
0397: Gui4jCallBase gui4jController,
0398: Gui4jThreadManager gui4jThreadManager) {
0399: if (rows.length == 1 && cols.length == 1) {
0400: tableModel.handleOnCellDblClick(rows[0],
0401: cols[0], gui4jController,
0402: gui4jThreadManager);
0403: }
0404: }
0405: };
0406: Gui4jMouseListenerMatrix mouseListener = new Gui4jMouseListenerMatrix(
0407: gui4jComponentInstance, 2, cellListener);
0408: table.addMouseListener(mouseListener);
0409: }
0410: }
0411:
0412: /*
0413: * (non-Javadoc)
0414: *
0415: * @see org.gui4j.core.Gui4jAbstractComponent#createComponentInstance(org.gui4j.core.Gui4jSwingContainer,
0416: * org.gui4j.Gui4jCallBase, org.gui4j.core.Gui4jQualifiedComponent)
0417: */
0418: protected Gui4jComponentInstance createComponentInstance(
0419: Gui4jSwingContainer gui4jSwingContainer,
0420: Gui4jCallBase gui4jCallBase,
0421: Gui4jQualifiedComponent gui4jComponentInPath) {
0422: Gui4jTableModel tm = new Gui4jTableModel(gui4jSwingContainer,
0423: gui4jCallBase);
0424:
0425: registerEvents(gui4jSwingContainer, gui4jCallBase, mRefresh, tm);
0426:
0427: Gui4jJTable table;
0428: if (mUseRowHeaders) {
0429: table = new RowHeaderTable(tm, tm);
0430: } else {
0431: table = new Gui4jJTable(tm, tm);
0432: }
0433: if (!mUseColumnHeaders) {
0434: table.setTableHeader(null);
0435: }
0436: table.getSelectionModel().setSelectionMode(mRowSelectionMode);
0437: table.getColumnModel().getSelectionModel().setSelectionMode(
0438: mColSelectionMode);
0439: table.setRowSelectionAllowed(mRowSelectionAllowed);
0440: Gui4jComponentInstance gui4jComponentInstance = new Gui4jComponentInstance(
0441: gui4jSwingContainer, table, gui4jComponentInPath);
0442: tm.setGui4jComponentInstance(gui4jComponentInstance);
0443:
0444: return gui4jComponentInstance;
0445: }
0446:
0447: /**
0448: * Sets the reorderingAllowed.
0449: *
0450: * @param reorderingAllowed
0451: * The reorderingAllowed to set
0452: */
0453: public void setReorderingAllowed(boolean reorderingAllowed) {
0454: mReorderingAllowed = reorderingAllowed;
0455: }
0456:
0457: /**
0458: * Sets the colSelectionMode.
0459: *
0460: * @param colSelectionMode
0461: * The colSelectionMode to set
0462: */
0463: public void setColSelectionMode(int colSelectionMode) {
0464: mColSelectionMode = colSelectionMode;
0465: }
0466:
0467: /**
0468: * Sets the rowSelectionMode.
0469: *
0470: * @param rowSelectionMode
0471: * The rowSelectionMode to set
0472: */
0473: public void setRowSelectionMode(int rowSelectionMode) {
0474: mRowSelectionMode = rowSelectionMode;
0475: }
0476:
0477: /**
0478: * Sets the rowSelectionAllowed.
0479: *
0480: * @param rowSelectionAllowed
0481: * The rowSelectionAllowed to set
0482: */
0483: public void setRowSelectionAllowed(boolean rowSelectionAllowed) {
0484: mRowSelectionAllowed = rowSelectionAllowed;
0485: }
0486:
0487: protected Point getPopupLocation(
0488: Gui4jComponentInstance gui4jComponentInstance,
0489: MouseEvent mouseEvent, Object context) {
0490: if (mouseEvent != null) {
0491: return mouseEvent.getPoint();
0492: }
0493:
0494: JTable table = (JTable) gui4jComponentInstance.getComponent();
0495: Rectangle selection = table.getCellRect(table.getSelectedRow(),
0496: table.getSelectedColumn(), true);
0497: return new Point(selection.x + selection.width / 2, selection.y
0498: + selection.height / 2);
0499: }
0500:
0501: protected Object getPopupContext(
0502: Gui4jComponentInstance gui4jComponentInstance,
0503: MouseEvent mouseEvent) {
0504: JTable table = (JTable) gui4jComponentInstance.getComponent();
0505: Gui4jTableModel model = (Gui4jTableModel) table.getModel();
0506: int row = table.getSelectedRow();
0507: int col = table.getSelectedColumn();
0508: mLogger.debug("Computing popup context for row " + row
0509: + ", col " + col);
0510: Gui4jCell cell = model.getGui4jCell(row, col);
0511: if (cell != null && cell.mPopupContext != null) {
0512: Map paramMap = cell.getParamMap(gui4jComponentInstance
0513: .getGui4jCallBase(), row, col, true, model);
0514: return cell.mPopupContext.getValue(gui4jComponentInstance
0515: .getGui4jCallBase(), paramMap, null);
0516: }
0517: return null;
0518: }
0519:
0520: /**
0521: * @see org.gui4j.core.Gui4jComponent#dispose(Gui4jComponentInstance)
0522: */
0523: public void dispose(Gui4jComponentInstance gui4jComponentInstance) {
0524: super .dispose(gui4jComponentInstance);
0525: Gui4jJTable jTable = (Gui4jJTable) gui4jComponentInstance
0526: .getSwingComponent();
0527: Gui4jTableModel model = (Gui4jTableModel) jTable.getModel();
0528: model.dispose();
0529: }
0530:
0531: // *************************************************************************************
0532: // ROW
0533: // *************************************************************************************
0534: public final class Gui4jRow implements Serializable {
0535: private final Gui4jCall mRowName;
0536: private final Gui4jTextAttribute mGui4jTextAttribute;
0537: protected final Class mClassType;
0538:
0539: public Gui4jRow(Class classType, Gui4jCall rowName,
0540: Gui4jTextAttribute gui4jTextAttribute) {
0541: mRowName = rowName;
0542: mGui4jTextAttribute = gui4jTextAttribute;
0543: mClassType = classType;
0544: }
0545:
0546: public Gui4jRow copy(Class newClassType) {
0547: return new Gui4jRow(newClassType, mRowName,
0548: mGui4jTextAttribute);
0549: }
0550:
0551: public Gui4jTextAttribute getGui4jTextAttribute() {
0552: return mGui4jTextAttribute;
0553: }
0554:
0555: protected String getName(Gui4jCallBase gui4jController,
0556: int row, Gui4jTableModel model) {
0557: if (mRowName != null) {
0558: Map paramMap = new HashMap();
0559: paramMap.put(PARAM_ROW, new Integer(row));
0560: paramMap.put(PARAM_ROWVALUE, model.mRows.get(row));
0561: return (String) mRowName.getValue(gui4jController,
0562: paramMap, null);
0563: } else {
0564: return null;
0565: }
0566: }
0567: }
0568:
0569: // *************************************************************************************
0570: // COL
0571: // *************************************************************************************
0572:
0573: public final class Gui4jCol implements Serializable {
0574: protected final Class mClassType;
0575: private final Gui4jCall mColName;
0576: private final Gui4jCall mCharacters;
0577: private final Gui4jCall mMaxCharacters;
0578: private final Gui4jTextAttribute mGui4jTextAttribute;
0579: private double mWeight = 1.0;
0580:
0581: public Gui4jCol(Class classType, Gui4jCall colName,
0582: Gui4jTextAttribute gui4jTextAttribute,
0583: Gui4jCall characters, Gui4jCall maxCharacters) {
0584: mColName = colName;
0585: mGui4jTextAttribute = gui4jTextAttribute;
0586: mCharacters = characters;
0587: mMaxCharacters = maxCharacters;
0588: mClassType = classType;
0589: }
0590:
0591: public Gui4jCol copy(Class newClassType) {
0592: Gui4jCol c = new Gui4jCol(newClassType, mColName,
0593: mGui4jTextAttribute, mCharacters, mMaxCharacters);
0594: c.setWeight(mWeight);
0595: return c;
0596: }
0597:
0598: public void setWeight(double weight) {
0599: mWeight = weight;
0600: }
0601:
0602: public double getWeight() {
0603: return mWeight;
0604: }
0605:
0606: public Gui4jTextAttribute getGui4jTextAttribute() {
0607: return mGui4jTextAttribute;
0608: }
0609:
0610: public String getName(Gui4jCallBase gui4jController, int col,
0611: Gui4jTableModel model) {
0612: if (mColName != null) {
0613: Map paramMap = new HashMap();
0614: paramMap.put(PARAM_COL, new Integer(col));
0615: paramMap.put(PARAM_COLVALUE, model.mColumns.get(col));
0616: return (String) mColName.getValue(gui4jController,
0617: paramMap, null);
0618: } else {
0619: return null;
0620: }
0621: }
0622:
0623: public boolean charactersDefined() {
0624: return mCharacters != null;
0625: }
0626:
0627: public boolean maxCharactersDefined() {
0628: return mMaxCharacters != null;
0629: }
0630:
0631: public int getCharacters(Gui4jCallBase gui4jController) {
0632: assert mCharacters != null;
0633: Integer i = (Integer) mCharacters.getValueNoParams(
0634: gui4jController, null);
0635: return i.intValue();
0636: }
0637:
0638: public int getMaxCharacters(Gui4jCallBase gui4jController) {
0639: assert mMaxCharacters != null;
0640: Integer i = (Integer) mMaxCharacters.getValueNoParams(
0641: gui4jController, null);
0642: return i.intValue();
0643: }
0644: }
0645:
0646: // *************************************************************************************
0647: // CELL
0648: // *************************************************************************************
0649: public final class Gui4jCell implements Serializable {
0650: private final Gui4jRow mGui4jRow;
0651: private final Gui4jCol mGui4jCol;
0652: private final Gui4jTextAttribute mGui4jTextAttribute;
0653:
0654: protected Gui4jCall mValue;
0655: private final Gui4jCall mSetValue;
0656: private final Gui4jCall mEnabled;
0657: private final Gui4jCall mList;
0658: private final Gui4jCall mListItem;
0659: private final Gui4jCall mListNullItem;
0660: private final Gui4jCall mListEditable;
0661: private final Gui4jCall mStringConvert;
0662: protected final Gui4jCall mOnCellSelect;
0663: protected final Gui4jCall mOnCellClick;
0664: protected final Gui4jCall mOnCellDblClick;
0665: protected final Gui4jCall mTooltip;
0666: protected final Gui4jCall mNotifyTempValue;
0667: protected final Gui4jCall mPopupContext;
0668:
0669: public Gui4jCell(Class rowType, Class columnType,
0670: Gui4jTextAttribute gui4jTextAttribute, Gui4jCall value,
0671: Gui4jCall setValue, Gui4jCall enabled, Gui4jCall list,
0672: Gui4jCall listItem, Gui4jCall listNullItem,
0673: Gui4jCall listEditable, Gui4jCall stringConvert,
0674: Gui4jCall onCellSelect, Gui4jCall onCellClick,
0675: Gui4jCall onCellDblClick, Gui4jCall tooltip,
0676: Gui4jCall notifyTempValue, Gui4jCall popupContext) {
0677: assert rowType != null;
0678: assert columnType != null;
0679: {
0680: Gui4jRow row = (Gui4jRow) mRowManager.get(rowType);
0681: /*
0682: * if (row != null) { mLogger.debug("RowType =
0683: * "+rowType.getName()+" gui4jRow="+row.mClassType.getName()); }
0684: */
0685: if (row == null) {
0686: mLogger.info(getId() + ": row for type "
0687: + rowType.getName() + " not defined");
0688: mGui4jRow = new Gui4jRow(rowType, null, null);
0689: mRowManager.add(rowType, mGui4jRow);
0690: } else {
0691: //
0692: if (row.mClassType != rowType) {
0693: mLogger
0694: .debug("Creating new Gui4jRow instance for type "
0695: + rowType.getName()
0696: + " as copy from "
0697: + row.mClassType.getName());
0698: row = row.copy(rowType);
0699: mRowManager.add(rowType, row);
0700: }
0701: // */
0702: mGui4jRow = row;
0703: }
0704: }
0705: {
0706: Gui4jCol col = (Gui4jCol) mColManager.get(columnType);
0707: if (col == null) {
0708: mLogger.info(getId() + ": column for type "
0709: + columnType.getName() + " not defined");
0710: mGui4jCol = new Gui4jCol(columnType, null, null,
0711: null, null);
0712: mColManager.add(columnType, mGui4jCol);
0713: } else {
0714: //
0715: if (col.mClassType != columnType) {
0716: mLogger
0717: .debug("Creating new Gui4jCol instance for type "
0718: + columnType.getName()
0719: + " as copy from "
0720: + col.mClassType.getName());
0721: col = col.copy(columnType);
0722: mColManager.add(columnType, col);
0723: }
0724: // */
0725: mGui4jCol = col;
0726: }
0727: }
0728: mGui4jTextAttribute = gui4jTextAttribute;
0729: mValue = value;
0730: mSetValue = setValue;
0731: mEnabled = enabled;
0732: mList = list;
0733: mListItem = listItem;
0734: mListNullItem = listNullItem;
0735: mListEditable = listEditable;
0736: mStringConvert = stringConvert;
0737: mOnCellSelect = onCellSelect;
0738: mOnCellClick = onCellClick;
0739: mOnCellDblClick = onCellDblClick;
0740: mTooltip = tooltip;
0741: mNotifyTempValue = notifyTempValue;
0742: mPopupContext = popupContext;
0743: }
0744:
0745: public String getTooltip(Gui4jCallBase gui4jController,
0746: int row, int col, Gui4jTableModel model) {
0747: if (mTooltip != null) {
0748: Map m = getParamMap(gui4jController, row, col, true,
0749: model);
0750: String value = (String) mTooltip.getValue(
0751: gui4jController, m, null);
0752: return value;
0753: } else {
0754: return null;
0755: }
0756: }
0757:
0758: public Object getValue(Gui4jCallBase gui4jController, int row,
0759: int col, Gui4jTableModel model) {
0760: if (mValue != null) {
0761: Map m = getParamMap(gui4jController, row, col, true,
0762: model);
0763: Object value = mValue
0764: .getValue(gui4jController, m, null);
0765: // mLogger.debug(getId()+": getValue("+row+", "+col+") =
0766: // "+value);
0767: return value;
0768: } else {
0769: return null;
0770: }
0771: }
0772:
0773: public void invalidateCall() {
0774: mValue = null;
0775: }
0776:
0777: public void setValue(Gui4jCallBase gui4jController, int row,
0778: int col, Object value, Gui4jTableModel model) {
0779: if (mSetValue != null) {
0780: Map paramMap = getParamMap(gui4jController, row, col,
0781: false, model);
0782:
0783: if (value instanceof ComboBoxNullItem) {
0784: value = null;
0785: }
0786:
0787: paramMap.put(PARAM_VALUE, value);
0788:
0789: Gui4jGetValue[] work;
0790: if (mOnSetValue != null) {
0791: work = new Gui4jGetValue[] { mSetValue,
0792: new Gui4jRefreshTable(model, row, col),
0793: model.getAutomaticRefresh(), mOnSetValue };
0794: } else {
0795: work = new Gui4jGetValue[] { mSetValue,
0796: new Gui4jRefreshTable(model, row, col),
0797: model.getAutomaticRefresh() };
0798: }
0799:
0800: // XXX mGui4jThreadManager.performWork(gui4jController, work,
0801: // paramMap, mNotifyTempValue != null);
0802: mGui4jThreadManager.performWork(gui4jController, work,
0803: paramMap, false);
0804: }
0805: }
0806:
0807: public void handleOnCellSelect(int row, int col,
0808: Gui4jCallBase gui4jController,
0809: Gui4jThreadManager gui4jThreadManager,
0810: Gui4jTableModel model) {
0811: if (mOnCellSelect != null) {
0812: gui4jThreadManager.performWork(gui4jController,
0813: mOnCellSelect, getParamMap(gui4jController,
0814: row, col, false, model));
0815: }
0816: }
0817:
0818: public void handleOnCellClick(int row, int col,
0819: Gui4jCallBase gui4jController,
0820: Gui4jThreadManager gui4jThreadManager,
0821: Gui4jTableModel model) {
0822: if (mOnCellClick != null) {
0823: gui4jThreadManager.performWork(gui4jController,
0824: mOnCellClick, getParamMap(gui4jController, row,
0825: col, false, model));
0826: }
0827: }
0828:
0829: public void handleOnCellDblClick(int row, int col,
0830: Gui4jCallBase gui4jController,
0831: Gui4jThreadManager gui4jThreadManager,
0832: Gui4jTableModel model) {
0833: if (mOnCellDblClick != null) {
0834: gui4jThreadManager.performWork(gui4jController,
0835: mOnCellDblClick, getParamMap(gui4jController,
0836: row, col, false, model));
0837: }
0838: }
0839:
0840: public boolean isEnabled(Gui4jCallBase gui4jController,
0841: int row, int col, Gui4jTableModel model) {
0842: if (mEnabled != null) {
0843: Map m = getParamMap(gui4jController, row, col, true,
0844: model);
0845:
0846: Boolean enabled = (Boolean) mEnabled.getValue(
0847: gui4jController, m, Boolean.TRUE);
0848: if (enabled != null) {
0849: return enabled.booleanValue();
0850: } else {
0851: return false;
0852: }
0853: } else {
0854: return true;
0855: }
0856: }
0857:
0858: public boolean isEditable(Gui4jCallBase gui4jController,
0859: int row, int col, Gui4jTableModel model) {
0860: return mSetValue != null
0861: && isEnabled(gui4jController, row, col, model);
0862: }
0863:
0864: public void prepareEditor(Gui4jCallBase gui4jController,
0865: TableCellEditor editor, int row, int column,
0866: Gui4jTableModel model) {
0867: if (mList != null) {
0868: ComboBoxCellEdit edit = (ComboBoxCellEdit) editor;
0869: Map m = getParamMap(gui4jController, row, column, true,
0870: model);
0871: edit.setParamMap(m);
0872: Collection content = (Collection) m.get(PARAM_LIST);
0873: String nullItemText = null;
0874: if (mListNullItem != null) {
0875: nullItemText = (String) mListNullItem
0876: .getValueNoParams(gui4jController,
0877: "(undefined)");
0878: if (nullItemText == null
0879: || nullItemText.length() == 0) {
0880: nullItemText = " ";
0881: // combobox can't deal correctly with null elements and
0882: // empty strings
0883: }
0884: }
0885: edit.setContent(content, nullItemText);
0886: Object selectedItem = m.get(PARAM_LIST_ITEM);
0887: edit.setSelectedItem(selectedItem);
0888: // System.out.println(
0889: // "contentContainsSel = " + content.contains(selectedItem) + ",
0890: // sel=" + selectedItem);
0891: } else if (editor instanceof Gui4jCellEditor) {
0892: Gui4jCellEditor edit = (Gui4jCellEditor) editor;
0893: if (mNotifyTempValue != null) {
0894: Map m = getParamMap(gui4jController, row, column,
0895: false, model);
0896: edit.setNotificationCallback(gui4jController,
0897: mNotifyTempValue, m, PARAM_VALUE);
0898: } else {
0899: edit
0900: .setNotificationCallback(null, null, null,
0901: null);
0902: }
0903: }
0904: }
0905:
0906: protected final Map getParamMap(Gui4jCallBase gui4jController,
0907: int row, int col, boolean includeListItem,
0908: Gui4jTableModel model) {
0909: Map m = new HashMap();
0910: m.put(PARAM_COL, new Integer(col));
0911: m.put(PARAM_ROW, new Integer(row));
0912: m.put(PARAM_COLVALUE, model.mColumns.get(col));
0913: m.put(PARAM_ROWVALUE, model.mRows.get(row));
0914:
0915: if (mList != null) {
0916: Collection collection = (Collection) mList.getValue(
0917: gui4jController, m, null);
0918: m.put(PARAM_LIST, collection);
0919: if (includeListItem && mListItem != null) {
0920: Object listItem = mListItem.getValue(
0921: gui4jController, m, null);
0922: m.put(PARAM_LIST_ITEM, listItem);
0923: }
0924: }
0925:
0926: return m;
0927: }
0928:
0929: public TableCellEditor getCellEditor(
0930: Gui4jCallBase gui4jController, Font font,
0931: TableCellEditor editor, int row, int column,
0932: Gui4jTableModel model) {
0933: if (mList != null) {
0934: if (mGui4jTextAttribute != null
0935: && mGui4jTextAttribute.getFont() != null) {
0936: font = (Font) mGui4jTextAttribute.getFont()
0937: .getValueNoParams(gui4jController, font);
0938: }
0939: ComboBoxCellEdit edit = ComboBoxCellEdit.getInstance(
0940: gui4jController, mValue, mStringConvert,
0941: PARAM_LIST_ITEM, font);
0942: edit.setParamMap(getParamMap(gui4jController, row,
0943: column, true, model));
0944: if (mListEditable != null) {
0945: Boolean editable = (Boolean) mListEditable
0946: .getValueNoParams(gui4jController, null);
0947: edit.setEditable(Boolean.TRUE.equals(editable));
0948: }
0949:
0950: return edit;
0951: } else {
0952: return editor;
0953: }
0954: }
0955:
0956: public Gui4jCol getGui4jCol() {
0957: return mGui4jCol;
0958: }
0959:
0960: public Gui4jRow getGui4jRow() {
0961: return mGui4jRow;
0962: }
0963:
0964: public Gui4jTextAttribute getTextAttribute() {
0965: return mGui4jTextAttribute;
0966: }
0967:
0968: public TableCellRenderer getCellRenderer(
0969: Gui4jComponentInstance gui4jComponentInstance,
0970: Font font, TableCellRenderer renderer) {
0971: renderer = (TableCellRenderer) gui4jComponentInstance
0972: .getStorage(this );
0973: if (renderer == null) {
0974: Gui4jJTable table = (Gui4jJTable) gui4jComponentInstance
0975: .getSwingComponent();
0976: renderer = new CellRenderer(gui4jComponentInstance,
0977: table, this );
0978: gui4jComponentInstance.setStorage(this , renderer);
0979: }
0980: return renderer;
0981: }
0982:
0983: }
0984:
0985: // *************************************************************************************
0986: // CellRenderer
0987: // *************************************************************************************
0988: public interface Enabled {
0989: boolean isEnabled(int row, int column);
0990: }
0991:
0992: public final class CellRenderer extends DefaultTableCellRenderer {
0993: private final Color mDefaultForeground;
0994: private final Color mDefaultBackground;
0995: private final Font mDefaultFont;
0996: private final int mAlignment;
0997:
0998: private final Color mBackground;
0999: private final Gui4jCall mBackgroundCall;
1000:
1001: private final Color mForeground;
1002: private final Gui4jCall mForegroundCall;
1003: private final Color mEvenBackground;
1004: private final Font mFont;
1005: private final TableCellRenderer booleanCellRenderer;
1006:
1007: private final Gui4jCell mGui4jCell;
1008: private final Gui4jCallBase mGui4jController;
1009: private final Gui4jTableModel mTableModel;
1010:
1011: public CellRenderer(
1012: Gui4jComponentInstance gui4jComponentInstance,
1013: Gui4jJTable table, Gui4jCell gui4jCell) {
1014: mGui4jCell = gui4jCell;
1015: mGui4jController = gui4jComponentInstance
1016: .getGui4jCallBase();
1017: mTableModel = (Gui4jTableModel) table.getModel();
1018:
1019: mDefaultBackground = getBackground();
1020: mDefaultForeground = getForeground();
1021: mDefaultFont = getFont();
1022:
1023: booleanCellRenderer = new BooleanTableCellRenderer(
1024: noFocusBorder);
1025:
1026: // use local variables to simplify calls
1027: Gui4jTextAttribute cellAttribute = mGui4jCell
1028: .getTextAttribute();
1029: Gui4jTextAttribute colAttribute = mGui4jCell.getGui4jCol()
1030: .getGui4jTextAttribute();
1031: Gui4jTextAttribute rowAttribute = mGui4jCell.getGui4jRow()
1032: .getGui4jTextAttribute();
1033:
1034: {
1035: // background may be evaluated dynamically
1036: Color color = null;
1037: mBackgroundCall = Gui4jTextAttribute.getCall(
1038: cellAttribute, colAttribute, rowAttribute,
1039: new Gui4jTextAttribute.Gui4jCallProvider() {
1040: public Gui4jCall retrieveGui4jCall(
1041: Gui4jTextAttribute textAttribute) {
1042: return textAttribute.getBackground();
1043: }
1044: });
1045: if (mBackgroundCall != null
1046: && mBackgroundCall.getUsedParams().isEmpty()) {
1047: color = Gui4jTextAttribute.getColor(
1048: mGui4jController, mBackgroundCall);
1049: }
1050: mBackground = color;
1051: }
1052: {
1053: // foreground may be evaluated dynamically
1054: Color color = null;
1055: mForegroundCall = Gui4jTextAttribute.getCall(
1056: cellAttribute, colAttribute, rowAttribute,
1057: new Gui4jTextAttribute.Gui4jCallProvider() {
1058: public Gui4jCall retrieveGui4jCall(
1059: Gui4jTextAttribute textAttribute) {
1060: return textAttribute.getForeground();
1061: }
1062: });
1063: if (mForegroundCall != null
1064: && mForegroundCall.getUsedParams().isEmpty()) {
1065: color = Gui4jTextAttribute.getColor(
1066: mGui4jController, mForegroundCall);
1067: }
1068: mForeground = color;
1069: }
1070:
1071: {
1072: // even background, font and alignment are evaluated statically
1073: mEvenBackground = Gui4jTextAttribute.getEvenBackground(
1074: mGui4jController, cellAttribute, colAttribute,
1075: rowAttribute);
1076: mFont = Gui4jTextAttribute.getFont(mGui4jController,
1077: cellAttribute, colAttribute, rowAttribute);
1078: mAlignment = Gui4jTextAttribute.getAlignment(
1079: cellAttribute, colAttribute, rowAttribute);
1080: }
1081: }
1082:
1083: /**
1084: * @see javax.swing.table.TableCellRenderer#getTableCellRendererComponent(JTable,
1085: * Object, boolean, boolean, int, int)
1086: */
1087: public Component getTableCellRendererComponent(JTable table,
1088: Object value, boolean isSelected, boolean hasFocus,
1089: int row, int column) {
1090: setForeground(mDefaultForeground);
1091: setBackground(mDefaultBackground);
1092: setFont(mDefaultFont);
1093: setEnabled(mGui4jCell.isEnabled(mGui4jController, row,
1094: column, mTableModel));
1095:
1096: // get the renderer component for this cell
1097: JComponent c;
1098: if (value != null && value.getClass() == Boolean.class) {
1099: // special checkbox renderer for booleans
1100: BooleanTableCellRenderer renderer = (BooleanTableCellRenderer) booleanCellRenderer
1101: .getTableCellRendererComponent(table, value,
1102: isSelected, hasFocus, row, column);
1103: // renderer.setUnselectedBackground(background);
1104: c = renderer;
1105: } else {
1106: c = (JComponent) super
1107: .getTableCellRendererComponent(table, value,
1108: isSelected, hasFocus, row, column);
1109: }
1110:
1111: if (!isSelected) {
1112: if (mForeground != null) {
1113: c.setForeground(mForeground);
1114: } else if (mForegroundCall != null) {
1115: Map paramMap = mGui4jCell.getParamMap(
1116: mGui4jController, row, column, false,
1117: mTableModel);
1118: paramMap.put(PARAM_VALUE, value);
1119: c.setForeground((Color) mForegroundCall.getValue(
1120: mGui4jController, paramMap, null));
1121: }
1122: if (!mTableModel.ignoreBackground()) {
1123: if (row % 2 == 0 && mEvenBackground != null) {
1124: c.setBackground(mEvenBackground);
1125: } else {
1126: if (mBackground != null) {
1127: c.setBackground(mBackground);
1128: } else if (mBackgroundCall != null) {
1129: Map paramMap = mGui4jCell.getParamMap(
1130: mGui4jController, row, column,
1131: false, mTableModel);
1132: paramMap.put(PARAM_VALUE, value);
1133: c.setBackground((Color) mBackgroundCall
1134: .getValue(mGui4jController,
1135: paramMap, null));
1136: }
1137: }
1138:
1139: }
1140: }
1141: if (mFont != null) {
1142: c.setFont(mFont);
1143: }
1144: if (c instanceof JLabel) {
1145: JLabel l = (JLabel) c;
1146: l.setHorizontalAlignment(mAlignment);
1147: String tooltip = mGui4jCell.getTooltip(
1148: mGui4jController, row, column, mTableModel);
1149: if ("".equals(tooltip)) {
1150: tooltip = null;
1151: }
1152: l.setToolTipText(tooltip);
1153: }
1154: return c;
1155: }
1156:
1157: }
1158:
1159: // *************************************************************************************
1160: // TABLE MODEL
1161: // *************************************************************************************
1162:
1163: public final class Gui4jTableModel extends
1164: RowHeaderAbstractTableModel implements Gui4jTableListener,
1165: Enabled, Gui4jEventListener {
1166: protected List mColumns = new ArrayList();
1167: protected List mRows = new ArrayList();
1168: private boolean mUseCache;
1169: private Object[][] mCache;
1170:
1171: private Gui4jSwingContainer mGui4jSwingContainer;
1172: private Gui4jCallBase mGui4jController;
1173: private Gui4jComponentInstance mGui4jComponentInstance;
1174: private Gui4jJTable mTable;
1175:
1176: private Gui4jRow[] mGui4jRows;
1177: private Gui4jCol[] mGui4jCols;
1178: private Gui4jCell[][] mGui4jCells;
1179:
1180: private boolean arraysAreValid = false;
1181: private boolean initialized = false;
1182: private int mPageNo = -1; // für Drucken
1183: private boolean ignoreBackground = false; // für Drucken ohne
1184:
1185: // Hintergrund (=true)
1186:
1187: protected Gui4jTableModel(
1188: Gui4jSwingContainer gui4jSwingContainer,
1189: Gui4jCallBase gui4jCallBase) {
1190: mGui4jSwingContainer = gui4jSwingContainer;
1191: mGui4jController = gui4jCallBase;
1192: mUseCache = mUseCacheDflt;
1193: clearCache();
1194: }
1195:
1196: public Gui4jGetValue getAutomaticRefresh() {
1197: if (mAutomaticRefresh && mTable != null) {
1198: return mTable.getAutomaticRefreshAction();
1199: } else {
1200: return null;
1201: }
1202: }
1203:
1204: public void setIgnoreBackground(boolean flag) {
1205: if (flag != ignoreBackground) {
1206: ignoreBackground = flag;
1207: if (mTable != null) {
1208: mTable.repaint();
1209: if (mTable instanceof RowHeaderTable) {
1210: RowHeaderTable rowHeaderTable = (RowHeaderTable) mTable;
1211: rowHeaderTable.repaint();
1212: }
1213: }
1214: }
1215:
1216: }
1217:
1218: public boolean ignoreBackground() {
1219: return ignoreBackground;
1220: }
1221:
1222: public void setInitialized() {
1223: initialized = true;
1224: }
1225:
1226: public void setRows(Collection rows) {
1227: if (rows != null) {
1228: mRows = new ArrayList(rows);
1229: } else {
1230: mRows = new ArrayList();
1231: }
1232: clearCache();
1233: refreshRows();
1234: }
1235:
1236: public void setContent(Collection rows, Collection colummns) {
1237: setColumns(colummns);
1238: setRows(rows);
1239: }
1240:
1241: public void setColumns(Collection columns) {
1242: mColumns = new ArrayList(columns);
1243: clearCache();
1244: refreshColumns(this );
1245: }
1246:
1247: public void clearCache() {
1248: if (mUseCache) {
1249: mCache = new Object[mRows.size()][mColumns.size()];
1250: } else {
1251: mCache = null;
1252: }
1253: }
1254:
1255: /**
1256: * @see org.gui4j.core.swing.RowHeaderTableModel#getRowName(int)
1257: */
1258: public String getRowName(int row) {
1259: Gui4jRow gui4jRow = getGui4jRow(row);
1260: return gui4jRow == null ? "" : gui4jRow.getName(
1261: mGui4jController, row, this );
1262: }
1263:
1264: /**
1265: * @see javax.swing.table.TableModel#getColumnName(int)
1266: */
1267: public String getColumnName(int col) {
1268: Gui4jCol gui4jCol = getGui4jCol(col);
1269: if (gui4jCol != null) {
1270: String name = gui4jCol.getName(mGui4jController, col,
1271: this );
1272: if (name == null || name.equals("")) {
1273: return name;
1274: }
1275: if (name.startsWith("\n")) {
1276: return " " + name;
1277: }
1278: return name;
1279: } else {
1280: return " ";
1281: }
1282: }
1283:
1284: /**
1285: * @see org.gui4j.core.swing.RowHeaderAbstractTableModel#setRowName(int,
1286: * String)
1287: */
1288: public void setRowName(int rowNumber, String newName) {
1289: // nothing todo
1290: }
1291:
1292: /**
1293: * @see org.gui4j.core.swing.RowHeaderTableModel#setRowName(int, Object)
1294: */
1295: public void setRowName(int rowNumber, Object newName) {
1296: // nothing todo
1297: }
1298:
1299: /**
1300: * @see javax.swing.table.TableModel#getColumnCount()
1301: */
1302: public int getColumnCount() {
1303: return mColumns.size();
1304: }
1305:
1306: /**
1307: * @see javax.swing.table.TableModel#getRowCount()
1308: */
1309: public int getRowCount() {
1310: return mRows.size();
1311: }
1312:
1313: private Gui4jCell findByInheritance(Gui4jRow row, Gui4jCol col) {
1314: final EncapsulateGui4jCell container = new EncapsulateGui4jCell();
1315: container.mGui4jCell = null;
1316: final Class rowClass = row.mClassType;
1317: final Class colClass = col.mClassType;
1318: /*
1319: * mLogger.debug( "Searching for rowClass = " + rowClass.getName() + ",
1320: * colClass = " + colClass.getName());
1321: */
1322: mCellManager.traverse(new SparseMatrix.Traverser() {
1323: public void work(Object pRow, Object pCol, Object value) {
1324: Class currentRowClass = ((Gui4jRow) pRow).mClassType;
1325: Class currentColClass = ((Gui4jCol) pCol).mClassType;
1326: Gui4jCell currentCell = (Gui4jCell) value;
1327: if (currentRowClass.isAssignableFrom(rowClass)
1328: && currentColClass
1329: .isAssignableFrom(colClass)) {
1330: if (container.mGui4jCell != null) {
1331: if (container.mGui4jCell.getGui4jRow().mClassType
1332: .isAssignableFrom(currentRowClass)
1333: && container.mGui4jCell
1334: .getGui4jCol().mClassType
1335: .isAssignableFrom(currentColClass)) {
1336: container.mGui4jCell = currentCell;
1337: /*
1338: * mLogger.debug( "Using rowClass = " +
1339: * currentRowClass.getName() + ", colClass = " +
1340: * currentColClass.getName());
1341: */
1342: }
1343: } else {
1344: container.mGui4jCell = currentCell;
1345: /*
1346: * mLogger.debug( "Using rowClass = " +
1347: * currentRowClass.getName() + ", colClass = " +
1348: * currentColClass.getName());
1349: */
1350: }
1351: }
1352: }
1353: });
1354: return container.mGui4jCell;
1355: }
1356:
1357: private void recompute() {
1358: if (!arraysAreValid && mRows != null && mColumns != null) {
1359: int rows = mRows.size();
1360: int cols = mColumns.size();
1361: int i = 0;
1362: mGui4jRows = new Gui4jRow[rows];
1363: for (Iterator it = mRows.iterator(); it.hasNext(); i++) {
1364: Object object = it.next();
1365: assert object != null;
1366: Gui4jRow gui4jRow = (Gui4jRow) mRowManager
1367: .get(object.getClass());
1368: if (gui4jRow == null) {
1369: gui4jRow = new Gui4jRow(object.getClass(),
1370: null, null);
1371: mRowManager.add(object.getClass(), gui4jRow);
1372: }
1373: mGui4jRows[i] = gui4jRow;
1374: }
1375:
1376: i = 0;
1377: mGui4jCols = new Gui4jCol[cols];
1378: for (Iterator it = mColumns.iterator(); it.hasNext(); i++) {
1379: Object object = it.next();
1380: assert object != null;
1381: Gui4jCol gui4jCol = (Gui4jCol) mColManager
1382: .get(object.getClass());
1383: if (gui4jCol == null) {
1384: gui4jCol = new Gui4jCol(object.getClass(),
1385: null, null, null, null);
1386: mColManager.add(object.getClass(), gui4jCol);
1387: }
1388: mGui4jCols[i] = gui4jCol;
1389: }
1390: mGui4jCells = new Gui4jCell[rows][cols];
1391: for (int r = 0; r < rows; r++) {
1392: for (int c = 0; c < cols; c++) {
1393: Gui4jRow gui4jRow = mGui4jRows[r];
1394: Gui4jCol gui4jCol = mGui4jCols[c];
1395: if (gui4jRow != null && gui4jCol != null) {
1396: Gui4jCell gui4jCell = (Gui4jCell) mCellManager
1397: .get(gui4jRow, gui4jCol);
1398: if (gui4jCell == null) {
1399: gui4jCell = findByInheritance(gui4jRow,
1400: gui4jCol);
1401: } else {
1402: }
1403: if (gui4jCell == null) {
1404: mLogger
1405: .debug("Creating 'on the fly' instance of Gui4jCell for ("
1406: + mRows.get(r)
1407: .getClass()
1408: .getName()
1409: + " gui4jRow="
1410: + gui4jRow.mClassType
1411: .getName()
1412: + ", "
1413: + mColumns.get(c)
1414: .getClass()
1415: .getName()
1416: + " gui4jCol="
1417: + gui4jCol.mClassType
1418: .getName()
1419: + ")");
1420: // mRows.get(r).getClass(),
1421: // mColumns.get(c).getClass(),
1422: gui4jCell = new Gui4jCell(
1423: gui4jRow.mClassType,
1424: gui4jCol.mClassType, null,
1425: null, null, null, null, null,
1426: null, null, null, null, null,
1427: null, null, null, null);
1428: mCellManager.set(gui4jRow, gui4jCol,
1429: gui4jCell);
1430: }
1431: if (mGui4jCells != null) {
1432: // XXX
1433: mGui4jCells[r][c] = gui4jCell;
1434: }
1435: }
1436: }
1437: }
1438: arraysAreValid = true;
1439: }
1440: }
1441:
1442: private Gui4jRow getGui4jRow(int row) {
1443: recompute();
1444: assert row >= 0 && row < mRows.size();
1445: return mGui4jRows == null ? null : mGui4jRows[row];
1446: }
1447:
1448: private Gui4jCol getGui4jCol(int col) {
1449: recompute();
1450: assert col >= 0 && col < mColumns.size();
1451: return mGui4jCols[col];
1452: }
1453:
1454: private Gui4jCell getGui4jCell(int row, int col) {
1455: recompute();
1456: if (row >= 0 && row < mRows.size() && col >= 0
1457: && col < mColumns.size()) {
1458: return mGui4jCells[row][col];
1459: } else {
1460: mLogger.error("Invalid row or column index: row=" + row
1461: + ", col=" + col + ", rows=" + mRows.size()
1462: + ", cols=" + mColumns.size());
1463: return null;
1464: }
1465: }
1466:
1467: public boolean isUsingCache() {
1468: return mUseCache;
1469: }
1470:
1471: public void setUseCache(boolean flag, int pageNo) {
1472: mUseCache = flag;
1473: if (!mUseCache || pageNo != mPageNo) {
1474: mPageNo = pageNo;
1475: clearCache();
1476: }
1477: }
1478:
1479: /**
1480: * @see javax.swing.table.TableModel#getValueAt(int, int)
1481: */
1482: public Object getValueAt(int row, int col) {
1483: if (mUseCache && mCache != null && row < mCache.length
1484: && col < mCache[row].length) {
1485: Object object = mCache[row][col];
1486: if (object != null) {
1487: return object;
1488: }
1489: }
1490: Gui4jCell gui4jCell = getGui4jCell(row, col);
1491: try {
1492: Object object = gui4jCell == null ? null : gui4jCell
1493: .getValue(mGui4jController, row, col, this );
1494: if (mUseCache && mCache != null && row < mCache.length
1495: && col < mCache[row].length) {
1496: mCache[row][col] = object;
1497: }
1498: return object;
1499: } catch (Throwable t) {
1500: getGui4j().handleException(mGui4jController, t, null);
1501: gui4jCell.invalidateCall();
1502: return null;
1503: }
1504: }
1505:
1506: /**
1507: * @see javax.swing.table.TableModel#setValueAt(Object, int, int)
1508: */
1509: public void setValueAt(Object value, int row, int col) {
1510: Gui4jCell gui4jCell = getGui4jCell(row, col);
1511: if (gui4jCell != null) {
1512: gui4jCell.setValue(mGui4jController, row, col, value,
1513: this );
1514: }
1515: }
1516:
1517: public int getRowIndex(Object object) {
1518: return mRows.indexOf(object);
1519: }
1520:
1521: public int getColumnIndex(Object object) {
1522: return mColumns.indexOf(object);
1523: }
1524:
1525: /**
1526: * @see javax.swing.table.TableModel#isCellEditable(int, int)
1527: */
1528: public boolean isCellEditable(int row, int col) {
1529: if (handleReadOnly()
1530: && mGui4jSwingContainer.inReadOnlyMode()) {
1531: return false;
1532: }
1533: Gui4jCell cell = getGui4jCell(row, col);
1534: if (cell != null) {
1535: return cell
1536: .isEditable(mGui4jController, row, col, this );
1537: } else {
1538: return true;
1539: }
1540: }
1541:
1542: /**
1543: * @see org.gui4j.core.swing.Gui4jTableListener#getCellEditor(TableCellEditor,
1544: * int, int)
1545: */
1546: public TableCellEditor getCellEditor(TableCellEditor editor,
1547: int row, int column) {
1548: Gui4jCell cell = getGui4jCell(row, column);
1549: return cell == null ? editor : cell.getCellEditor(
1550: mGui4jController, mGui4jComponentInstance
1551: .getSwingComponent().getFont(), editor,
1552: row, column, this );
1553: }
1554:
1555: /**
1556: * @see org.gui4j.core.swing.Gui4jTableListener#getCellRenderer(TableCellRenderer,
1557: * int, int)
1558: */
1559: public TableCellRenderer getCellRenderer(
1560: TableCellRenderer renderer, int row, int column) {
1561: Gui4jCell cell = getGui4jCell(row, column);
1562: return cell == null ? renderer : cell.getCellRenderer(
1563: mGui4jComponentInstance, mGui4jComponentInstance
1564: .getSwingComponent().getFont(), renderer);
1565: }
1566:
1567: /**
1568: * @see org.gui4j.core.swing.Gui4jTableListener#prepareEditor(TableCellEditor,
1569: * int, int)
1570: */
1571: public void prepareEditor(TableCellEditor editor, int row,
1572: int column) {
1573: Gui4jCell cell = getGui4jCell(row, column);
1574: if (cell != null) {
1575: cell.prepareEditor(mGui4jController, editor, row,
1576: column, this );
1577: }
1578: }
1579:
1580: public void handleOnCellSelect(int row, int col,
1581: Gui4jCallBase gui4jController,
1582: Gui4jThreadManager gui4jThreadManager) {
1583: Gui4jCell cell = getGui4jCell(row, col);
1584: if (cell != null) {
1585: cell.handleOnCellSelect(row, col, gui4jController,
1586: gui4jThreadManager, this );
1587: }
1588: }
1589:
1590: public void handleOnCellClick(int row, int col,
1591: Gui4jCallBase gui4jController,
1592: Gui4jThreadManager gui4jThreadManager) {
1593: Gui4jCell cell = getGui4jCell(row, col);
1594: if (cell != null) {
1595: cell.handleOnCellClick(row, col, gui4jController,
1596: gui4jThreadManager, this );
1597: }
1598: }
1599:
1600: public void handleOnCellDblClick(int row, int col,
1601: Gui4jCallBase gui4jController,
1602: Gui4jThreadManager gui4jThreadManager) {
1603: Gui4jCell cell = getGui4jCell(row, col);
1604: if (cell != null) {
1605: cell.handleOnCellDblClick(row, col, gui4jController,
1606: gui4jThreadManager, this );
1607: }
1608: }
1609:
1610: public void setGui4jComponentInstance(
1611: Gui4jComponentInstance gui4jComponentInstance) {
1612: mGui4jComponentInstance = gui4jComponentInstance;
1613: mTable = (Gui4jJTable) mGui4jComponentInstance
1614: .getSwingComponent();
1615: }
1616:
1617: protected void refreshColumns(Gui4jTableModel model) {
1618: if (mTable != null) {
1619: // Tabelle noch nicht zerstoert
1620: if (!initialized) {
1621: return;
1622: }
1623: arraysAreValid = false;
1624: // mLogger.debug("Refreshing columns of table " + getId() + "
1625: // count = " + mColumns.size());
1626: // mTable.setModel(this);
1627: mTable.createDefaultColumnsFromModel();
1628: // fireTableStructureChanged();
1629: Font font = mTable.getFont();
1630: JTableHeader tableHeader = mTable.getTableHeader();
1631:
1632: double sumWeight = 0.0;
1633: int sumWidth = 0;
1634:
1635: if (tableHeader != null) {
1636:
1637: double headerHeight = tableHeader
1638: .getPreferredSize().getHeight();
1639: for (int c = 0; c < mColumns.size(); c++) {
1640: Gui4jCol gui4jCol = getGui4jCol(c);
1641: TableColumn tableColumn = mTable
1642: .getColumnModel().getColumn(c);
1643: sumWidth += tableColumn.getPreferredWidth();
1644: sumWeight += gui4jCol.getWeight();
1645: String name = gui4jCol.getName(
1646: mGui4jController, c, this );
1647: TableCellRenderer renderer = tableHeader
1648: .getDefaultRenderer();
1649: if (renderer != null) {
1650: if (name != null && name.startsWith("\n")) {
1651: name = "XXX" + name;
1652: }
1653: JLabel label = new JLabel(name);
1654: label.setFont(font);
1655: label.setUI(MultiLineLabelUI.getInstance());
1656: double height = label.getPreferredSize()
1657: .getHeight() + 4;
1658: if (height > headerHeight) {
1659: headerHeight = height;
1660: }
1661: }
1662: }
1663: {
1664: Dimension d = new Dimension(tableHeader
1665: .getPreferredSize());
1666: d.height = (int) headerHeight;
1667:
1668: // workaround for bug in swing
1669: // resizing does not work if we have horizontal
1670: // scrollbars
1671: if (mResizeMode != JTable.AUTO_RESIZE_OFF) {
1672: tableHeader.setPreferredSize(d);
1673: }
1674: }
1675: }
1676: {
1677: for (int c = 0; c < mColumns.size(); c++) {
1678: Gui4jCol gui4jCol = getGui4jCol(c);
1679: TableColumn tableColumn = mTable
1680: .getColumnModel().getColumn(c);
1681: double weight = gui4jCol.getWeight();
1682: if (gui4jCol.maxCharactersDefined()) {
1683: int width = mTable
1684: .getFontMetrics(font)
1685: .stringWidth(
1686: StringUtil
1687: .copy(
1688: 'M',
1689: gui4jCol
1690: .getMaxCharacters(mGui4jController)));
1691: tableColumn.setMaxWidth(width);
1692: tableColumn.setPreferredWidth(width);
1693: } else if (gui4jCol.charactersDefined()) {
1694: int width = mTable
1695: .getFontMetrics(font)
1696: .stringWidth(
1697: StringUtil
1698: .copy(
1699: 'M',
1700: gui4jCol
1701: .getCharacters(mGui4jController)));
1702: tableColumn.setPreferredWidth(width);
1703: } else {
1704: tableColumn
1705: .setPreferredWidth((int) (sumWidth
1706: * weight / sumWeight));
1707: }
1708: }
1709: }
1710: }
1711: }
1712:
1713: public void dispose() {
1714: mTable = null;
1715: mGui4jRows = null;
1716: mGui4jCols = null;
1717: mGui4jCells = null;
1718: mGui4jController = null;
1719: mGui4jSwingContainer = null;
1720: mColumns.clear();
1721: mRows.clear();
1722: mGui4jComponentInstance = null;
1723: mTable = null;
1724: }
1725:
1726: protected void refreshRows() {
1727: arraysAreValid = false;
1728: // mLogger.debug("Refreshing rows of table " + getId() + " count = "
1729: // + mRows.size());
1730: Font font = mTable.getFont();
1731: if (mUseRowHeaders) {
1732: JLabel label = new JLabel();
1733: label.setFont(font);
1734: int preferredWidth = 10;
1735: for (int i = 0; i < mRows.size(); i++) {
1736: label.setText(getRowName(i));
1737: int width = label.getPreferredSize().width + 8;
1738: if (width > preferredWidth) {
1739: preferredWidth = width;
1740: }
1741: }
1742: RowHeaderTable ctable = (RowHeaderTable) mTable;
1743: if (ctable != null) {
1744: ctable.setRowHeaderWidth(preferredWidth);
1745: ctable.setRowHeaderFont(font);
1746: ctable.setRowHeaderHeight(mTable.getRowHeight());
1747: ctable.refreshRowHeaders();
1748: }
1749: }
1750:
1751: fireTableDataChanged();
1752: }
1753:
1754: /**
1755: * @see org.gui4j.component.Gui4jMatrix.Enabled#isEnabled(int, int)
1756: */
1757: public boolean isEnabled(int row, int column) {
1758: Gui4jCell gui4jCell = getGui4jCell(row, column);
1759: if (gui4jCell != null) {
1760: return gui4jCell.isEnabled(mGui4jController, row,
1761: column, this );
1762: } else {
1763: return true;
1764: }
1765: }
1766:
1767: /**
1768: * @see org.gui4j.event.Gui4jEventListener#eventOccured()
1769: */
1770: public void eventOccured() {
1771: Runnable run = new Runnable() {
1772: public void run() {
1773: clearCache();
1774: fireTableRowsUpdated(0, getRowCount() - 1);
1775: }
1776: };
1777: Gui4jThreadManager.executeInSwingThreadAndWait(run);
1778: }
1779:
1780: }
1781:
1782: private static class Flag {
1783: boolean val;
1784: }
1785:
1786: private static class EncapsulateGui4jCell {
1787: protected Gui4jCell mGui4jCell;
1788: }
1789:
1790: }
|