001: /*
002: * Beryl - A web platform based on XML, XSLT and Java
003: * This file is part of the Beryl XML GUI
004: *
005: * Copyright (C) 2004 Wenzel Jakob <wazlaf@tigris.org>
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011:
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-3107 USA
020: */
021:
022: package org.beryl.gui.widgets;
023:
024: import java.awt.Component;
025: import java.awt.Dimension;
026: import java.awt.event.ActionEvent;
027: import java.awt.event.ActionListener;
028:
029: import javax.swing.ComboBoxModel;
030: import javax.swing.JComboBox;
031:
032: import org.beryl.gui.GUIException;
033: import org.beryl.gui.Widget;
034: import org.beryl.gui.WidgetInfo;
035: import org.beryl.gui.model.ListDataModel;
036: import org.beryl.gui.model.MapChangeEvent;
037: import org.beryl.gui.model.MapDataModel;
038: import org.beryl.gui.model.ModelChangeEvent;
039:
040: public class ComboBox extends Widget {
041: protected static WidgetInfo comboBoxInfo = null;
042: private JComboBox comboBox = null;
043: private ListDataModel listDataModel = null;
044: private String indexKey = null, valueKey = null;
045: private boolean sendEvents = true;
046: private boolean processEvents = true;
047:
048: static {
049: comboBoxInfo = new WidgetInfo(ComboBox.class, widgetInfo);
050: comboBoxInfo.addProperty("valuekey", "string", "");
051: comboBoxInfo.addProperty("indexkey", "string", "");
052: };
053:
054: public static class ComboBoxDataModelAdapter extends
055: List.ListDataModelAdapter implements ComboBoxModel {
056: private Object selectedItem = null;
057:
058: public ComboBoxDataModelAdapter(ListDataModel model) {
059: super (model);
060: }
061:
062: public void setSelectedItem(Object anItem) {
063: selectedItem = anItem;
064: }
065:
066: public Object getSelectedItem() {
067: return selectedItem;
068: }
069: };
070:
071: public ComboBox(Widget parent, String name) throws GUIException {
072: super (parent, name);
073: comboBox = new JComboBox();
074: comboBox.setPreferredSize(new Dimension(MAX_WIDTH,
075: DEFAULT_HEIGHT));
076: comboBox.addActionListener(new ActionListener() {
077: public void actionPerformed(ActionEvent e) {
078: try {
079: MapDataModel model = getDataModel();
080: if (sendEvents && model != null) {
081: try {
082: sendEvents = false;
083: processEvents = false;
084: if (indexKey != null)
085: model.setValue(ComboBox.this , indexKey,
086: new Integer(comboBox
087: .getSelectedIndex()));
088: if (valueKey != null)
089: model.setValue(ComboBox.this , valueKey,
090: comboBox.getSelectedItem());
091: } finally {
092: sendEvents = true;
093: processEvents = true;
094: }
095: }
096: } catch (GUIException ex) {
097: throw new RuntimeException(ex);
098: }
099: }
100: });
101: }
102:
103: public void addChild(Widget widget, Object constraint)
104: throws GUIException {
105: if (widget instanceof Item) {
106: try {
107: if (listDataModel == null) {
108: listDataModel = new ListDataModel();
109: sendEvents = false;
110: comboBox.setModel(new ComboBoxDataModelAdapter(
111: listDataModel));
112: }
113: listDataModel.addValue(this , widget);
114: addChild(widget);
115: } finally {
116: sendEvents = true;
117: }
118: } else {
119: throw new GUIException(
120: "Only Item children are allowed inside a ComboBox");
121: }
122: }
123:
124: public void removeChildWidget(Widget widget) throws GUIException {
125: if (listDataModel != null) {
126: listDataModel.removeValue(this , widget);
127: super .removeChildWidget(widget);
128: } else {
129: throw new GUIException(
130: "There are no static items to remove");
131: }
132: }
133:
134: public void setProperty(String name, Object value)
135: throws GUIException {
136: if ("indexkey".equals(name)) {
137: indexKey = (String) value;
138: } else if ("valuekey".equals(name)) {
139: valueKey = (String) value;
140: } else {
141: super .setProperty(name, value);
142: }
143: }
144:
145: public void setListDataModel(ListDataModel listDataModel)
146: throws GUIException {
147: ModelChangeEvent event = new ModelChangeEvent(this ,
148: listDataModel);
149: this .listDataModel = listDataModel;
150: sendEvents = false;
151: try {
152: comboBox.setModel(new ComboBoxDataModelAdapter(
153: listDataModel));
154: } finally {
155: sendEvents = true;
156: }
157: /* Reload data model information */
158: modelChanged(event);
159: }
160:
161: public ListDataModel getListDataModel() {
162: return this .listDataModel;
163: }
164:
165: private void reload() throws GUIException {
166: MapDataModel model = getDataModel();
167: if (model != null) {
168: try {
169: processEvents = false;
170:
171: Integer index = indexKey == null ? null
172: : (Integer) model.getValue(indexKey);
173: Object value = valueKey == null ? null : model
174: .getValue(valueKey);
175:
176: if (index != null) {
177: comboBox.setSelectedIndex(index.intValue());
178: comboBox.repaint();
179: } else if (value != null) {
180: comboBox.setSelectedItem(value);
181: comboBox.repaint();
182: }
183:
184: if (((value != null && index == null) || (value == null && index == null))
185: && indexKey != null) {
186: model.setValue(ComboBox.this , indexKey,
187: new Integer(comboBox.getSelectedIndex()));
188: }
189:
190: if (((index != null && value == null) || (value == null && index == null))
191: && valueKey != null) {
192: model.setValue(ComboBox.this , valueKey, comboBox
193: .getSelectedItem());
194: }
195: } finally {
196: processEvents = true;
197: }
198: } else {
199: }
200: }
201:
202: public void modelChanged(ModelChangeEvent e) throws GUIException {
203: if (processEvents) {
204: try {
205: sendEvents = false;
206: if (e.getSource() == this ) {
207: try {
208: reload();
209: } catch (IllegalArgumentException ex) {
210: /* Ignore, list data model is not yet set */
211: } catch (ArrayIndexOutOfBoundsException ex) {
212: /* Ignore, list data model is not yet set */
213: }
214: } else if (e instanceof MapChangeEvent) {
215: MapChangeEvent event = (MapChangeEvent) e;
216: if (event.getKey() == null) {
217: reload();
218: } else if (event.getKey().equals(indexKey)) {
219: try {
220: comboBox.setSelectedIndex(((Integer) event
221: .getNewValue()).intValue());
222: comboBox.repaint();
223: try {
224: processEvents = false;
225: if (valueKey != null)
226: ((MapDataModel) event.getModel())
227: .setValue(
228: ComboBox.this ,
229: valueKey,
230: comboBox
231: .getSelectedItem());
232: } finally {
233: processEvents = true;
234: }
235: } catch (IllegalArgumentException ex) {
236: throw new GUIException(
237: "Changed data model has a bad selection index",
238: ex);
239: }
240: } else if (event.getKey().equals(valueKey)) {
241: try {
242: comboBox.setSelectedItem(event
243: .getNewValue());
244: comboBox.repaint();
245: try {
246: processEvents = false;
247: if (indexKey != null)
248: ((MapDataModel) event.getModel())
249: .setValue(
250: ComboBox.this ,
251: indexKey,
252: new Integer(
253: comboBox
254: .getSelectedIndex()));
255: } finally {
256: processEvents = true;
257: }
258: } catch (IllegalArgumentException ex) {
259: throw new GUIException(
260: "Changed data model has a bad selection value",
261: ex);
262: }
263: }
264: }
265: } finally {
266: sendEvents = true;
267: }
268: }
269: }
270:
271: public JComboBox getComboBox() {
272: return comboBox;
273: }
274:
275: public Component getWidget() {
276: return comboBox;
277: }
278:
279: public WidgetInfo getWidgetInfo() {
280: return comboBoxInfo;
281: }
282: }
|