001: /* ====================================================================
002: * The QueryForm License, Version 1.1
003: *
004: * Copyright (c) 1998 - 2003 David F. Glasser. All rights
005: * reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The end-user documentation included with the redistribution,
020: * if any, must include the following acknowledgment:
021: * "This product includes software developed by
022: * David F. Glasser."
023: * Alternately, this acknowledgment may appear in the software itself,
024: * if and wherever such third-party acknowledgments normally appear.
025: *
026: * 4. The names "QueryForm" and "David F. Glasser" must
027: * not be used to endorse or promote products derived from this
028: * software without prior written permission. For written
029: * permission, please contact dglasser@pobox.com.
030: *
031: * 5. Products derived from this software may not be called "QueryForm",
032: * nor may "QueryForm" appear in their name, without prior written
033: * permission of David F. Glasser.
034: *
035: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL DAVID F. GLASSER, THE APACHE SOFTWARE
039: * FOUNDATION OR ITS CONTRIBUTORS, OR ANY AUTHORS OR DISTRIBUTORS
040: * OF THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
041: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
042: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
043: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
044: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
045: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
046: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
047: * SUCH DAMAGE.
048: * ====================================================================
049: *
050: * This product includes software developed by the
051: * Apache Software Foundation (http://www.apache.org/).
052: *
053: * ====================================================================
054: *
055: * $Source: /cvsroot/qform/qform/src/org/glasser/swing/LocalDataSourceConfigDialog.java,v $
056: * $Revision: 1.11 $
057: * $Author: dglasser $
058: * $Date: 2003/12/22 03:45:49 $
059: *
060: * --------------------------------------------------------------------
061: */
062: package org.glasser.swing;
063:
064: import java.awt.*;
065: import java.awt.event.*;
066: import java.util.*;
067: import javax.swing.*;
068: import javax.swing.border.*;
069: import javax.swing.event.*;
070:
071: import org.glasser.sql.*;
072: import org.glasser.util.*;
073:
074: public class LocalDataSourceConfigDialog extends JDialog implements
075: ActionListener, ListSelectionListener {
076:
077: public static boolean debug = System
078: .getProperty("LocalDataSourceConfigDialog.debug") != null;
079:
080: LocalDataSourceConfigPanel configPanel = new LocalDataSourceConfigPanel();
081:
082: KeySelectableJList listbox = new KeySelectableJList();
083:
084: JButton btnNew = new JButton("New");
085:
086: JButton btnEdit = new JButton("Edit");
087:
088: JButton btnDelete = new JButton("Delete");
089:
090: JButton btnSave = new JButton("Save");
091:
092: JButton btnCancel = new JButton("Cancel");
093:
094: JButton btnClose = new JButton("Close");
095:
096: JButton btnConnect = new JButton("Connect");
097:
098: Vector configVector = new Vector();
099:
100: Object[][] buttonConfig = {
101: { btnNew, "N", "OPEN_NEW", "Configure a new data source." },
102: { btnEdit, "E", "EDIT_EXISTING",
103: "Edit the selected data source." },
104: { btnDelete, "D", "DELETE_EXISTING",
105: "Delete the selected data source configuration." },
106: { btnSave, "S", "SAVE", "Save changes." },
107: { btnCancel, "C", "CANCEL", "Discard changes." },
108: { btnClose, "L", "CLOSE", "Close dialog." },
109: { btnConnect, "T", "CONNECT",
110: "Connect to selected data source." } };
111:
112: public final static int NOTHING_SELECTED = 0;
113:
114: public final static int ITEM_SELECTED = 1;
115:
116: public final static int EDIT_NEW = 2;
117:
118: public final static int EDIT_EXISTING = 3;
119:
120: private int screenState = NOTHING_SELECTED;
121:
122: private final static boolean[][] buttonStates = {
123: { true, false, false, false, false, true, false } // 0 NOTHING_SELECTED
124: , { true, true, true, false, false, true, true } // 1 ITEM_SELECTED
125: , { false, false, false, true, true, false, false } // 2 EDIT_NEW
126: , { false, false, false, true, true, false, false } // 3 EDIT_EXISTING
127:
128: };
129:
130: private boolean listStates[] = { true, true, false, false };
131:
132: private boolean configPanelStates[] = { false, false, true, true };
133:
134: private boolean disableSelectionEvents = false;
135:
136: public void setScreenState(int newState) {
137:
138: int index = listbox.getSelectedIndex();
139:
140: for (int j = 0; j < buttonConfig.length; j++) {
141: JButton button = (JButton) buttonConfig[j][0];
142: button.setEnabled(buttonStates[newState][j]);
143: }
144:
145: switch (newState) {
146: case EDIT_NEW:
147:
148: LocalDataSourceConfig config = new LocalDataSourceConfig();
149: configPanel.displayObject(config);
150: selectedConfig = null;
151:
152: if (index > -1) {
153: // this flag is set to keep this method from being called
154: // from the valueChanged(ListSelectionEvent) method that will
155: // get fired as a result of removing the selection.
156: disableSelectionEvents = true;
157: listbox.removeSelectionInterval(index, index);
158: }
159: break;
160: case EDIT_EXISTING:
161: selectedConfig = (LocalDataSourceConfig) configVector
162: .get(index);
163: break;
164: case NOTHING_SELECTED:
165: configPanel.clearFields();
166: break;
167: case ITEM_SELECTED:
168: LocalDataSourceConfig ld = (LocalDataSourceConfig) configVector
169: .get(index);
170: this .configPanel.displayObject(ld);
171: break;
172:
173: }
174:
175: this .listbox.setEnabled(listStates[newState]);
176: this .configPanel.setEditable(configPanelStates[newState]);
177:
178: screenState = newState;
179:
180: }
181:
182: LocalDataSourceConfig selectedConfig = null;
183:
184: public void actionPerformed(ActionEvent e) {
185:
186: String command = e.getActionCommand();
187:
188: if (command == null)
189: command = "";
190:
191: if (command.equals("OPEN_NEW")) {
192: setScreenState(EDIT_NEW);
193: } else if (command.equals("EDIT_EXISTING")) {
194: setScreenState(EDIT_EXISTING);
195: } else if (command.equals("DELETE_EXISTING")) {
196:
197: int reply = JOptionPane.showConfirmDialog(this ,
198: "Do you want to delete the selected data source configuration?"
199: + "\n(This operation cannot be undone.)",
200: "Confirm Delete", JOptionPane.YES_NO_OPTION);
201: if (reply == JOptionPane.NO_OPTION)
202: return;
203:
204: int index = listbox.getSelectedIndex();
205: if (index > -1)
206: configVector.remove(index);
207: listbox.setListData(configVector);
208: configPanel.clearFields();
209: setScreenState(NOTHING_SELECTED);
210:
211: } else if (command.equals("SAVE")) {
212:
213: // make sure a display name was entered.
214: String displayName = configPanel.txtDisplayName.getText();
215: if (Util.isNothing(displayName)) {
216: GUIHelper
217: .errMsg(
218: this ,
219: "Please enter a display name for this data source.",
220: null);
221: configPanel.txtDisplayName.requestFocus();
222: return;
223: }
224:
225: if (selectedConfig != null) {
226: configPanel.updateObject(selectedConfig);
227: } else {
228: selectedConfig = new LocalDataSourceConfig();
229: configPanel.updateObject(selectedConfig);
230: configVector.add(selectedConfig);
231: }
232:
233: Collections.sort(configVector,
234: LocalDataSourceConfig.DISPLAY_NAME_COMPARATOR);
235: listbox.setListData(configVector);
236: listbox.setSelectedValue(selectedConfig, true);
237:
238: selectedConfig = null;
239:
240: setScreenState(ITEM_SELECTED);
241:
242: } else if (command.equals("CANCEL")) {
243: disableAndRefreshFields();
244: } else if (command.equals("CLOSE")) {
245: selectedItem = null;
246: super .setVisible(false);
247: } else if (command.equals("CONNECT")) {
248: selectedItem = (LocalDataSourceConfig) listbox
249: .getSelectedValue();
250: super .setVisible(false);
251: }
252: }
253:
254: private LocalDataSourceConfig selectedItem = null;
255:
256: public LocalDataSourceConfig getSelectedItem() {
257: return selectedItem;
258: }
259:
260: public void setVisible(boolean b) {
261:
262: // clear any previous selections when the dialog is opened.
263: if (b) {
264: selectedItem = null;
265: disableAndRefreshFields();
266: }
267: super .setVisible(b);
268: }
269:
270: /**
271: * Called whenever the value of the selection changes.
272: * @param e the event that characterizes the change.
273: */
274: public void valueChanged(ListSelectionEvent e) {
275: if (disableSelectionEvents) {
276: // when the selection is changed programatically, this flag can be
277: // set to false to keep the event listener (this method) from
278: // doing anything. The flag is reset automatically everytime it's
279: // read to be true.
280: disableSelectionEvents = false;
281: return;
282: }
283: disableAndRefreshFields();
284: }
285:
286: /**
287: * If nothing is selected in the listbox, this will make sure that the fields
288: * are cleared, and set the screen state to NOTHING_SELECTED. If something is
289: * selected, this will populate the fields from the selected object and set
290: * the screen state to ITEM_SELECTED.
291: */
292: private void disableAndRefreshFields() {
293: int index = listbox.getSelectedIndex();
294: if (index > -1) {
295: setScreenState(ITEM_SELECTED);
296: } else {
297: setScreenState(NOTHING_SELECTED);
298: }
299: }
300:
301: public void setList(Vector configs) {
302:
303: Collections.sort(configs,
304: LocalDataSourceConfig.DISPLAY_NAME_COMPARATOR);
305: configVector = configs;
306: listbox.setListData(configs);
307:
308: }
309:
310: public Vector getList() {
311: return configVector;
312: }
313:
314: public LocalDataSourceConfigDialog(Frame parent) {
315: super (parent);
316:
317: JPanel cp = new JPanel();
318: cp.setBorder(new EmptyBorder(10, 10, 10, 10));
319: cp.setLayout(new BorderLayout());
320:
321: JPanel p = new JPanel();
322: p.setLayout(new BorderLayout());
323: JLabel label = new JLabel("Data Sources");
324: label.setForeground(Color.black);
325: p.add(label, BorderLayout.NORTH);
326: listbox.setVisibleRowCount(10);
327: // listbox.setPreferredSize(new Dimension(200, 120));
328: // listbox.setBorder(new ThinBevelBorder(ThinBevelBorder.LOWERED));
329: listbox.getSelectionModel().setSelectionMode(
330: ListSelectionModel.SINGLE_SELECTION);
331: listbox.getSelectionModel().addListSelectionListener(this );
332: p.setBorder(new EmptyBorder(0, 0, 10, 0));
333: p.add(new JScrollPane(listbox), BorderLayout.CENTER);
334:
335: cp.add(p, BorderLayout.CENTER);
336:
337: p = new JPanel();
338: p.setLayout(new BorderLayout());
339: p.add(configPanel, BorderLayout.CENTER);
340:
341: JPanel buttonPanel = new JPanel();
342: buttonPanel.setLayout(new FlowLayout());
343: for (int j = 0; j < buttonConfig.length; j++) {
344: JButton button = (JButton) buttonConfig[j][0];
345: button.setMnemonic(((String) buttonConfig[j][1]).charAt(0));
346: button.setActionCommand((String) buttonConfig[j][2]);
347: button.setToolTipText((String) buttonConfig[j][3]);
348: button.addActionListener(this );
349: buttonPanel.add(button);
350: }
351: p.add(buttonPanel, BorderLayout.SOUTH);
352:
353: // create an Action that clicks the cancel button
354: ButtonClicker cancelClicker = new ButtonClicker(btnCancel);
355:
356: // give the cancelClicker a nested action that clicks the close button,
357: // so if the cancel button is disabled, the close button will be clicked.
358: cancelClicker.setNestedAction(new ButtonClicker(btnClose));
359:
360: // now bind the action to the ESCAPE key.
361: KeyStroke esc = KeyStroke.getKeyStroke("ESCAPE");
362: cp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
363: .put(esc, "_ESCAPE_");
364: cp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(esc,
365: "_ESCAPE_");
366: cp.getActionMap().put("_ESCAPE_", cancelClicker);
367:
368: cp.add(p, BorderLayout.SOUTH);
369:
370: setContentPane(cp);
371:
372: setScreenState(NOTHING_SELECTED);
373:
374: setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
375:
376: listbox.addMouseListener(new MouseAdapter() {
377: public void mouseClicked(MouseEvent e) {
378: if (e.getClickCount() == 2) {
379: Point p = e.getPoint();
380: if (debug)
381: System.out.println("clickpoint = " + p);
382: int clickedIndex = listbox.locationToIndex(p);
383:
384: if (debug)
385: System.out.println("clickedindex = "
386: + clickedIndex);
387: if (clickedIndex > -1 && btnConnect.isEnabled()) {
388: btnConnect.doClick(0);
389: }
390: }
391: }
392: });
393:
394: setModal(true);
395: pack();
396:
397: }
398:
399: public LocalDataSourceConfigDialog() {
400: this(null);
401: }
402:
403: }
|