001: package org.osbl.client.wings.form;
002:
003: import org.conform.BeanMeta;
004: import org.osbl.agent.gui.DesignContext;
005: import org.osbl.agent.gui.ObjectDesignContext;
006: import org.osbl.client.action.ObjectActionEvent;
007: import org.osbl.client.action.ObjectAction;
008: import org.osbl.client.wings.*;
009: import org.osbl.client.wings.shell.AbstractTool;
010: import org.osbl.client.wings.shell.Environment;
011: import org.wings.*;
012: import org.wings.border.SLineBorder;
013: import org.wings.table.*;
014: import org.wingx.XTable;
015: import org.wingx.XScrollPane;
016: import org.wingx.table.XTableClickListener;
017:
018: import javax.swing.*;
019: import javax.swing.event.ListSelectionListener;
020: import java.util.*;
021: import java.util.List;
022: import java.awt.event.ActionEvent;
023: import java.awt.*;
024:
025: /**
026: * A generic base class, that implements basic ObjectList functionality. It uses
027: * an XTable width a column model constructed from con:conform bean metas and an
028: * ObjectTableModel. Furthermore it implements TitleProvider, ButtonsProvider
029: * and ToolsProvider.
030: */
031: public abstract class GenericObjectList extends XTable implements
032: ObjectList, ObjectContextAware {
033:
034: protected DelegateEnvironment environment = new DelegateEnvironment();
035:
036: protected BeanMeta beanMeta;
037:
038: protected ObjectTableModel model;
039:
040: private Map<ObjectAction, DelegateObjectAction> actionDelegates = new HashMap<ObjectAction, DelegateObjectAction>();
041:
042: private XScrollPane component;
043: protected ObjectContext context;
044: protected Map<String, Object> filters = new HashMap<String, Object>();
045:
046: protected GenericObjectList() {
047: super (null);
048: beanMeta = createBeanMeta();
049: model = createModel(beanMeta);
050:
051: setName(beanMeta.getType().getSimpleName());
052: setModel(model);
053: setColumnModel(model.getColumnModel());
054: setSelectionMode(SListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
055: setRowSelectionRenderer(new SDefaultTableRowSelectionRenderer() {
056: public SComponent getTableCellRendererComponent(
057: STable table, Object value, boolean selected,
058: int row, int col) {
059: SComponent component = super
060: .getTableCellRendererComponent(table, value,
061: selected, row, col);
062: if (row == getCurrentIndex())
063: setIcon(XIcons.ROW_CURRENT);
064: else if (selected)
065: setIcon(getSelectionMode() != SListSelectionModel.SINGLE_SELECTION ? XIcons.ROW_CHECKED
066: : XIcons.ROW_SELECTED);
067: else
068: setIcon(XIcons.ROW_PLAIN);
069:
070: return component;
071: }
072: });
073: }
074:
075: public ObjectContext getContext() {
076: if (context == null) {
077: System.out.println("new context: " + context);
078: context = new ObjectContext();
079: }
080: return context;
081: }
082:
083: public void setContext(ObjectContext context) {
084: this .context = context;
085: }
086:
087: public Environment getEnvironment() {
088: getComponent();
089: return environment;
090: }
091:
092: /**
093: * Create the bean meta, that shall be used for the column model and
094: * probably the model, too.
095: *
096: * @return the bean meta
097: */
098: protected abstract BeanMeta createBeanMeta();
099:
100: /**
101: * Create the table model.
102: *
103: * @param beanMeta
104: * the bean meta
105: * @return the table model
106: */
107: protected abstract ObjectTableModel createModel(BeanMeta beanMeta);
108:
109: /**
110: * Refresh the model. This can be an expensive operation. Call it only, if
111: * you expect, that the data has changed.
112: */
113: public void refresh() {
114: model.refresh();
115: }
116:
117: Object current;
118: int currentIndex = -1;
119:
120: public Object getCurrent() {
121: return current;
122: }
123:
124: public void setCurrent(Object current) {
125: if (this .current != current) {
126: this .current = current;
127: currentIndex = -1;
128: reload();
129: }
130: }
131:
132: protected int getCurrentIndex() {
133: if (currentIndex == -1 && current != null) {
134: Object id = idOf(current);
135: if (id != null) {
136: int rowCount = model.getRowCount();
137: for (int i = 0; i < rowCount; i++) {
138: if (id.equals(idOf(getRow(i)))) {
139: currentIndex = i;
140: break;
141: }
142: }
143: }
144: }
145: return currentIndex;
146: }
147:
148: public boolean hasNext() {
149: int index = getCurrentIndex();
150: return index != -1 && index < getRowCount() - 1;
151: }
152:
153: public void next() {
154: int index = getCurrentIndex();
155: if (index < getRowCount() - 1) {
156: index++;
157: setCurrent(getRow(index));
158: currentIndex = index;
159: }
160: }
161:
162: public boolean hasPrevious() {
163: return getCurrentIndex() > 0;
164: }
165:
166: public void previous() {
167: int index = getCurrentIndex();
168: if (index > 0) {
169: index--;
170: setCurrent(getRow(index));
171: currentIndex = index;
172: }
173: }
174:
175: public Object getSelectedObject() {
176: int selectedRow = getSelectedRow();
177: return selectedRow > -1 ? getRow(selectedRow) : null;
178: }
179:
180: // TODO: inefficient
181: public void setSelectedObjects(List objects) {
182: clearSelection();
183:
184: for (Object object : objects) {
185: Object id = idOf(object);
186: if (id == null) {
187: setSelectedRow(-1);
188: continue;
189: }
190:
191: int rowCount = model.getRowCount();
192: for (int i = 0; i < rowCount; i++) {
193: if (id.equals(idOf(getRow(i)))) {
194: getSelectionModel().addSelectionInterval(i, i);
195: continue;
196: }
197: }
198: }
199: }
200:
201: protected Object idOf(Object object) {
202: try {
203: return object.getClass().getMethod("getId").invoke(object);
204: } catch (Exception e) {
205: throw new RuntimeException(e);
206: }
207: }
208:
209: public List getSelectedObjects() {
210: int[] selectedRows = getSelectedRows();
211: List selectedObjects = new ArrayList(selectedRows.length);
212: for (int selectedRow : selectedRows) {
213: selectedObjects.add(getRow(selectedRow));
214: }
215: return selectedObjects;
216: }
217:
218: /**
219: * Obtain the rowId from the ObjectTableModel and load the respective
220: * object.
221: *
222: * @param index
223: * the row index
224: * @return the object in row <code>index</code>
225: */
226: public abstract Object getRow(int index); // was protected
227:
228: public ListSelectionListener[] getSelectionListeners() {
229: return (ListSelectionListener[]) getListeners(ListSelectionListener.class);
230: }
231:
232: public void setSelectedObject(Object object) {
233: if (object == null) {
234: clearSelection();
235: return;
236: }
237:
238: Object id = idOf(object);
239: if (id == null) {
240: setSelectedRow(-1);
241: return;
242: }
243:
244: int rowCount = model.getRowCount();
245: for (int i = 0; i < rowCount; i++) {
246: if (id.equals(idOf(getRow(i)))) {
247: setSelectedRow(i);
248: return;
249: }
250: }
251: }
252:
253: public void setLinkAction(String name, final ObjectAction linkAction) {
254: for (int i = 0; i < columnModel.getColumnCount(); i++) {
255: STableColumn column = columnModel.getColumn(i);
256: if (name.equals(column.getIdentifier())) {
257: addClickListener(i, new XTableClickListener() {
258: public void clickOccured(int row, int column) {
259: Object object = getRow(row);
260: ObjectActionEvent event = new ObjectActionEvent(
261: GenericObjectList.this , object);
262: linkAction.actionPerformed(event);
263: }
264: });
265: break;
266: }
267: }
268: }
269:
270: public SComponent getComponent() {
271: if (component == null) {
272: component = new XScrollPane(this );
273: component.setBorder(new SLineBorder(
274: new Color(153, 153, 153), 1));
275: environment.setContentPane(component);
276:
277: initializeList();
278: environment.setTitle(beanMeta.getType().getName()
279: + ".editor.title");
280: }
281: return component;
282: }
283:
284: public Class getType() {
285: return beanMeta.getType();
286: }
287:
288: protected void initializeList() {
289: }
290:
291: public void addObjectAction(ObjectAction objectAction) {
292: DelegateObjectAction action = new DelegateObjectAction(
293: objectAction);
294: actionDelegates.put(objectAction, action);
295: environment.addControl(new XButton(action));
296: }
297:
298: public void removeObjectAction(ObjectAction objectAction) {
299: throw new UnsupportedOperationException(
300: "Remove is not implemented.");
301: }
302:
303: public ObjectAction[] getObjectActions() {
304: Set<ObjectAction> objectActions = actionDelegates.keySet();
305: return objectActions.toArray(new ObjectAction[objectActions
306: .size()]);
307: }
308:
309: public void setFilter(String property, Object value) {
310: filters.put(property, value);
311: }
312:
313: public Object getFilter(String property) {
314: return filters.get(property);
315: }
316:
317: public void clearFilters() {
318: filters.clear();
319: }
320:
321: public static class DelegateObjectAction extends AbstractAction {
322: ObjectAction objectAction;
323: private ObjectList list;
324:
325: public DelegateObjectAction(ObjectAction objectAction) {
326: this .objectAction = objectAction;
327: }
328:
329: public void setList(ObjectList list) {
330: this .list = list;
331: }
332:
333: public void actionPerformed(ActionEvent event) {
334: ObjectActionEvent objectEvent = new ObjectActionEvent(list,
335: list.getSelectedObjects().toArray());
336: objectAction.actionPerformed(objectEvent);
337: }
338:
339: public Object getValue(String key) {
340: return objectAction.getValue(key);
341: }
342:
343: public void putValue(String key, Object value) {
344: objectAction.putValue(key, value);
345: }
346:
347: public void setEnabled(boolean b) {
348: objectAction.setEnabled(b);
349: }
350:
351: public boolean isEnabled() {
352: return objectAction.isEnabled();
353: }
354: }
355: }
|