001: package net.xoetrope.awt;
002:
003: import java.awt.Container;
004: import java.awt.Dimension;
005: import java.awt.Graphics;
006: import java.awt.ItemSelectable;
007: import java.awt.event.ItemListener;
008:
009: import net.xoetrope.xui.XAttributedComponent;
010: import net.xoetrope.xui.XModelHolder;
011: import net.xoetrope.xui.XPage;
012: import net.xoetrope.xui.data.XModel;
013: import net.xoetrope.xui.style.XStyleComponent;
014: import java.awt.BorderLayout;
015: import net.xoetrope.xui.XHashCode;
016: import java.awt.event.MouseListener;
017: import net.xoetrope.xui.data.XRowSelector;
018:
019: /**
020: * <p>Provides a simple read-only tables/grid component.</p>
021: * <p>Copyright (c) Xoetrope Ltd., 1998-2004<br>
022: * License: see license.txt
023: * $Revision: 1.21 $
024: */
025: public class XTable extends XScrollPane implements
026: XAttributedComponent, XModelHolder, ItemSelectable,
027: XStyleComponent, XHashCode, XRowSelector {
028: private XTableRenderer content;
029: private XModel model;
030: private XPanel componentPanel;
031: private int numRows;
032:
033: public XTable() {
034: super ();
035: numRows = -1;
036:
037: componentPanel = new XPanel();
038: componentPanel.setLayout(new BorderLayout());
039: add(componentPanel, BorderLayout.CENTER);
040:
041: content = new XTableRenderer(this );
042: componentPanel.add(content);
043: }
044:
045: public Container getComponentPanel() {
046: return componentPanel;
047: }
048:
049: /**
050: * Set the XModel which we will be generating the table from
051: * @param xmodel The XModel of data
052: */
053: public void setModel(XModel xmodel) {
054: model = xmodel;
055: if (model != null)
056: model.get();
057: content.setContent(xmodel);
058:
059: checkSize();
060: }
061:
062: /**
063: * Get the underlying model.
064: * @return the model
065: */
066: public XModel getModel() {
067: return model;
068: }
069:
070: /**
071: * Recalculate and check the size of the content
072: */
073: public void checkSize() {
074: content.removeCurrentComponent();
075: Dimension d = content.calcSize();
076: componentPanel.setSize(d);
077: invalidate();
078: validate();
079:
080: repaint();
081: }
082:
083: /**
084: * Set the type of component for a column
085: * @param col the field index
086: * @param className the class name
087: */
088: public void setComponentAt(int col, String className) {
089: content.setComponentAt(col, className);
090: }
091:
092: /**
093: * Set the model's name
094: * @return the name
095: */
096: public String getContent() {
097: return model.getId();
098: }
099:
100: /**
101: * Creates the scroll pane's peer and sizes the child element.
102: */
103: public void addNotify() {
104: super .addNotify();
105: setContentSize();
106: }
107:
108: private void setContentSize() {
109: if (content != null) {
110: int rows = content.getNumRows();
111: if ((rows != numRows) || !content.hasRendered()) {
112: numRows = rows;
113: Dimension d = content.calcSize();
114: componentPanel
115: .setBounds(0, 0, Math.max(
116: (this .getSize().width - 20), d.width),
117: d.height);
118: // content.setBounds( componentPanel.getBounds() );
119: invalidate();
120: validate();
121: }
122: }
123: }
124:
125: /**
126: * Set the general style of the XTable
127: * @param style XStyle
128: */
129: public void setStyle(String style) {
130: content.setStyle(style);
131: }
132:
133: /**
134: * Set the style of the header data
135: * @param style XStyle
136: */
137: public void setHeaderStyle(String style) {
138: content.setHeaderStyle(style);
139: }
140:
141: /**
142: * Set the style of the selected row
143: * @param style XStyle
144: */
145: public void setSelectedStyle(String style) {
146: content.setSelectedStyle(style);
147: }
148:
149: /**
150: * Set the style of the border
151: * @param style XStyle
152: */
153: public void setBorderStyle(String style) {
154: content.setBorderStyle(style);
155: }
156:
157: /**
158: * Check the if the table is interactive
159: * @return true if the table supports user interaction
160: */
161: public boolean isInteractiveTable() {
162: return content.isInteractiveTable();
163: }
164:
165: /**
166: * Set the user interaction state
167: * @param state true for an user interactive table.
168: */
169: public void setInteractiveTable(boolean state) {
170: content.setInteractiveTable(state);
171: }
172:
173: /**
174: * Sets the indexof the selected row
175: * @param idx the new selected row
176: */
177: public void setSelectedRow(int idx) {
178: content.setSelectedRow(idx);
179: }
180:
181: /**
182: * Get the index of the selected row
183: * @return the index of the selected row
184: */
185: public int getSelectedRow() {
186: return content.getSelectedRow();
187: }
188:
189: /**
190: * Move to the first row
191: */
192: public void first() {
193: content.setSelectedRow(0);
194: }
195:
196: /**
197: * Move to the previous row
198: */
199: public void prev() {
200: content.setSelectedRow(content.getSelectedRow() - 1);
201: }
202:
203: /**
204: * Move to the next row
205: */
206: public void next() {
207: content.setSelectedRow(content.getSelectedRow() + 1);
208: }
209:
210: /**
211: * Move to the last row
212: */
213: public void last() {
214: content.setSelectedRow(model.getNumChildren() - 1);
215: }
216:
217: /**
218: * Tie the model selection to this table's selection
219: * @param doUpdate true to tie the selections together, false to ignore
220: */
221: public void setUpdateModelSelection(boolean doUpdate) {
222: content.setUpdateModelSelection(doUpdate);
223: }
224:
225: /**
226: * Sets the bounds for this component
227: * @param x
228: * @param y
229: * @param w
230: * @param h
231: */
232: public void setBounds(int x, int y, int w, int h) {
233: Dimension d = content.calcSize();
234: componentPanel.setBounds(0, 0, (int) d.getSize().width, (int) d
235: .getSize().height);
236: // content.setBounds( componentPanel.getBounds() );
237: super .setBounds(x, y, w, h);
238: invalidate();
239: validate();
240: }
241:
242: /**
243: * recalculates the size of the scroll area for dynamic table;
244: */
245: public void setBounds() {
246: Dimension d = content.calcSize();
247: componentPanel.setBounds(0, 0, (int) d.getSize().width, (int) d
248: .getSize().height);
249: // content.setBounds( componentPanel.getBounds() );
250: invalidate();
251: validate();
252: }
253:
254: /**
255: * recalculates the size of the scroll area for dynamic table;
256: */
257: public void scrollToBottom() {
258: setScrollPosition(0, (int) getSize().height);
259: }
260:
261: /**
262: * Set the table column width;
263: * @param fieldIdx the field index
264: * @param w the new column width
265: */
266: public void setColWidth(int fieldIdx, int w) {
267: content.setColWidth(fieldIdx, w);
268: }
269:
270: /**
271: * Set one or more attributes of the component. Currently this handles the
272: * attributes
273: * <OL>
274: * <LI>headingStyle, value=the table header style</LI>
275: * <LI>selectionStyle, value=the selected row style</LI>
276: * <LI>interactive, value=true|false</LI>
277: * <LI>updateModel, value=true|false update the underlying model selection (the selected row)</LI>
278: * </OL>
279: * @param attribName the attribute name
280: * @param attribValue the attribute value
281: */
282: public void setAttribute(String attribName, String attribValue) {
283: if (attribName.compareTo("headingStyle") == 0)
284: setHeaderStyle(attribValue);
285: else if (attribName.compareTo("selectionStyle") == 0)
286: setSelectedStyle(attribValue);
287: else if (attribName.compareTo("borderStyle") == 0)
288: setBorderStyle(attribValue);
289: else if (attribName.compareTo("interactive") == 0)
290: setInteractiveTable(attribValue.compareTo("true") == 0);
291: else if (attribName.compareTo("updateModel") == 0)
292: setUpdateModelSelection(attribValue.compareTo("true") == 0);
293:
294: super .setAttribute(attribName, attribValue);
295: }
296:
297: /**
298: * Gets a field value object from the currently selected row
299: * @param fieldIdx the field offset
300: * @return the value
301: */
302: public Object getValue(int fieldIdx) {
303: int row = content.getCurrentRow();
304: return getValue(row, fieldIdx);
305: }
306:
307: /**
308: * Gets a field value object from the specified row
309: * @param rowIdx the row offset
310: * @param fieldIdx the field offset
311: * @return the value
312: */
313: public Object getValue(int rowIdx, int fieldIdx) {
314: XModel rowModel = model.get(rowIdx + content.getFirstRow());
315: Object fieldModel = rowModel.get(fieldIdx);
316: if (fieldModel instanceof XModel)
317: return ((XModel) fieldModel).get();
318: return fieldModel;
319: }
320:
321: /**
322: * Gets a field value as a string from the currently selected row
323: * @param fieldIdx the field offset
324: * @return the value
325: */
326: public String getFieldValue(int fieldIdx) {
327: return (String) getValue(fieldIdx);
328:
329: }
330:
331: /**
332: * Gets a field value as a string from the specified row
333: * @param rowIdx the row offset
334: * @param fieldIdx the field offset
335: * @return the value
336: */
337: public String getFieldValue(int rowIdx, int fieldIdx) {
338: return (String) getValue(rowIdx, fieldIdx);
339: }
340:
341: /**
342: * Adds the specified item listener to receive item events from
343: * this list. Item events are sent in response to user input, but not
344: * in response to calls to <code>select</code> or <code>deselect</code>.
345: * If listener <code>l</code> is <code>null</code>,
346: * no exception is thrown and no action is performed.
347: *
348: * @param l the item listener
349: * @see #removeItemListener( ItemListener )
350: * @see java.awt.event.ItemEvent
351: * @see java.awt.event.ItemListener
352: * @since JDK1.1
353: */
354: public synchronized void addItemListener(ItemListener l) {
355: content.addItemListener(l);
356: }
357:
358: /**
359: * Removes the specified item listener so that it no longer
360: * receives item events from this list.
361: * If listener <code>l</code> is <code>null</code>,
362: * no exception is thrown and no action is performed.
363: *
364: * @param l the item listener
365: * @see #addItemListener
366: * @see java.awt.event.ItemEvent
367: * @see java.awt.event.ItemListener
368: * @since JDK1.1
369: */
370: public synchronized void removeItemListener(ItemListener l) {
371: content.removeItemListener(l);
372: }
373:
374: /**
375: * Returns the selected items on the list in an array of objects.
376: * @see ItemSelectable
377: */
378: public Object[] getSelectedObjects() {
379: return content.getSelectedObjects();
380: }
381:
382: public void repaint() {
383: setContentSize();
384: content.repaint();
385: }
386:
387: public void paint(Graphics g) {
388: setContentSize();
389: content.repaint();
390: }
391:
392: /**
393: * Add a mouse listener
394: * @param l the new mouse listener
395: */
396: public void addMouseListener(MouseListener l) {
397: content.addMouseListener(l);
398: }
399:
400: /**
401: * Get the hash code to be used by the event handler for this component
402: * @return the hash code
403: */
404: public long getComponentHashCode() {
405: return content.hashCode();
406: }
407: }
|