001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.db.explorer.dlg;
043:
044: import java.awt.*;
045: import java.awt.event.*;
046: import java.io.InputStream;
047: import java.util.*;
048: import java.text.MessageFormat;
049: import java.util.logging.Logger;
050: import javax.swing.*;
051: import javax.swing.border.*;
052: import javax.swing.table.*;
053: import org.openide.DialogDescriptor;
054: import org.openide.DialogDisplayer;
055: import org.openide.NotifyDescriptor;
056: import org.openide.util.NbBundle;
057: import org.openide.util.RequestProcessor;
058: import org.netbeans.lib.ddl.impl.Specification;
059: import org.netbeans.lib.ddl.impl.CreateTable;
060: import org.netbeans.lib.ddl.util.CommandBuffer;
061: import org.netbeans.lib.ddl.impl.CreateIndex;
062: import org.netbeans.lib.ddl.util.PListReader;
063: import org.netbeans.modules.db.explorer.infos.DatabaseNodeInfo;
064: import org.netbeans.modules.db.util.TextFieldValidator;
065: import org.netbeans.modules.db.util.ValidableTextField;
066: import org.openide.awt.Mnemonics;
067: import org.openide.util.Utilities;
068:
069: public class CreateTableDialog {
070: boolean result = false;
071: Dialog dialog = null;
072: JTextField dbnamefield, dbownerfield;
073: JTable table;
074: JComboBox ownercombo;
075: JButton addbtn, delbtn;
076: Specification spec;
077: private Vector ttab;
078:
079: private static Map dlgtab = null;
080: private static final String filename = "org/netbeans/modules/db/resources/CreateTableDialog.plist"; // NOI18N
081: private ResourceBundle bundle = NbBundle
082: .getBundle("org.netbeans.modules.db.resources.Bundle"); // NOI18N
083: private static Logger LOGGER = Logger
084: .getLogger(CreateTableDialog.class.getName());
085:
086: public static final Map getProperties() {
087: if (dlgtab == null)
088: try {
089: ClassLoader cl = CreateTableDialog.class
090: .getClassLoader();
091: InputStream stream = cl.getResourceAsStream(filename);
092: if (stream == null) {
093: String message = MessageFormat
094: .format(
095: NbBundle
096: .getBundle(
097: "org.netbeans.modules.db.resources.Bundle")
098: .getString(
099: "EXC_UnableToOpenStream"),
100: new String[] { filename }); // NOI18N
101: throw new Exception(message);
102: }
103: PListReader reader = new PListReader(stream);
104: dlgtab = reader.getData();
105: stream.close();
106: } catch (Exception e) {
107: e.printStackTrace();
108: dlgtab = null;
109: }
110:
111: return dlgtab;
112: }
113:
114: public CreateTableDialog(final Specification spe,
115: DatabaseNodeInfo nfo) throws java.sql.SQLException {
116: spec = spe;
117: try {
118: JLabel label;
119: JPanel pane = new JPanel();
120: pane.setBorder(new EmptyBorder(new Insets(5, 5, 5, 5)));
121: GridBagLayout layout = new GridBagLayout();
122: GridBagConstraints constr = new GridBagConstraints();
123: pane.setLayout(layout);
124: pane.setMinimumSize(new Dimension(200, 100));
125:
126: // Table name field
127:
128: label = new JLabel();
129: Mnemonics.setLocalizedText(label, bundle
130: .getString("CreateTableName")); // NOI18N
131: label.getAccessibleContext().setAccessibleDescription(
132: bundle.getString("ACS_CreateTableNameA11yDesc"));
133: constr.anchor = GridBagConstraints.WEST;
134: constr.weightx = 0.0;
135: constr.weighty = 0.0;
136: constr.fill = GridBagConstraints.NONE;
137: constr.insets = new java.awt.Insets(2, 2, 2, 2);
138: constr.gridx = 0;
139: constr.gridy = 0;
140: layout.setConstraints(label, constr);
141: pane.add(label);
142:
143: constr.fill = GridBagConstraints.HORIZONTAL;
144: constr.weightx = 1.0;
145: constr.weighty = 0.0;
146: constr.gridx = 1;
147: constr.gridy = 0;
148: constr.insets = new java.awt.Insets(2, 2, 2, 2);
149: dbnamefield = new JTextField(bundle
150: .getString("CreateTableUntitledName"), 10); // NOI18N
151: dbnamefield.setToolTipText(bundle
152: .getString("ACS_CreateTableNameTextFieldA11yDesc"));
153: dbnamefield
154: .getAccessibleContext()
155: .setAccessibleName(
156: bundle
157: .getString("ACS_CreateTableNameTextFieldA11yName"));
158: label.setLabelFor(dbnamefield);
159: layout.setConstraints(dbnamefield, constr);
160: pane.add(dbnamefield);
161:
162: // Table owner combo
163:
164: label = new JLabel();
165: Mnemonics.setLocalizedText(label, bundle
166: .getString("CreateTableOwner")); // NOI18N
167: label.getAccessibleContext().setAccessibleDescription(
168: bundle.getString("ACS_CreateTableOwnerA11yDesc"));
169: constr.anchor = GridBagConstraints.WEST;
170: constr.weightx = 0.0;
171: constr.weighty = 0.0;
172: constr.fill = GridBagConstraints.NONE;
173: constr.insets = new java.awt.Insets(2, 10, 2, 2);
174: constr.gridx = 2;
175: constr.gridy = 0;
176: layout.setConstraints(label, constr);
177: pane.add(label);
178:
179: Vector users = new Vector();
180: String schema = nfo.getDriverSpecification().getSchema();
181: if (schema != null && schema.length() > 0)
182: users.add(schema);
183: else
184: users.add(" "); //NOI18N
185:
186: constr.fill = GridBagConstraints.HORIZONTAL;
187: constr.weightx = 0.0;
188: constr.weighty = 0.0;
189: constr.gridx = 3;
190: constr.gridy = 0;
191: constr.insets = new java.awt.Insets(2, 2, 2, 2);
192: ownercombo = new JComboBox(users);
193: ownercombo.setSelectedIndex(0);
194: ownercombo.setRenderer(new ListCellRendererImpl());
195: ownercombo.setToolTipText(bundle
196: .getString("ACS_CreateTableOwnerComboBoxA11yDesc"));
197: ownercombo
198: .getAccessibleContext()
199: .setAccessibleName(
200: bundle
201: .getString("ACS_CreateTableOwnerComboBoxA11yName"));
202: label.setLabelFor(ownercombo);
203: layout.setConstraints(ownercombo, constr);
204: pane.add(ownercombo);
205:
206: // Table columns in scrollpane
207:
208: constr.fill = GridBagConstraints.BOTH;
209: constr.weightx = 1.0;
210: constr.weighty = 1.0;
211: constr.gridx = 0;
212: constr.gridy = 1;
213: constr.gridwidth = 4;
214: constr.gridheight = 3;
215: constr.insets = new java.awt.Insets(2, 2, 2, 2);
216: table = new DataTable(new DataModel());
217: table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
218: table.setToolTipText(bundle
219: .getString("ACS_CreateTableColumnTableA11yDesc"));
220: table
221: .getAccessibleContext()
222: .setAccessibleName(
223: bundle
224: .getString("ACS_CreateTableColumnTableA11yName"));
225: table
226: .getAccessibleContext()
227: .setAccessibleDescription(
228: bundle
229: .getString("ACS_CreateTableColumnTableA11yDesc"));
230: JScrollPane scrollpane = new JScrollPane(table);
231: scrollpane.setBorder(new BevelBorder(BevelBorder.LOWERED));
232: layout.setConstraints(scrollpane, constr);
233: pane.add(scrollpane);
234:
235: // Setup cell editors for table
236:
237: Map tmap = spec.getTypeMap();
238: ttab = new Vector(tmap.size());
239: Iterator iter = tmap.keySet().iterator();
240: while (iter.hasNext()) {
241: String iterkey = (String) iter.next();
242: String iterval = (String) tmap.get(iterkey);
243: ttab.add(new TypeElement(iterkey, iterval));
244: }
245:
246: final JComboBox combo = new JComboBox(ttab);
247: combo.setSelectedIndex(0);
248: table.setDefaultEditor(String.class, new DataCellEditor(
249: new JTextField()));
250: table.getColumn("type").setCellEditor(
251: new ComboBoxEditor(combo)); // NOI18N
252: table.getColumn("size").setCellEditor(
253: new DataCellEditor(new ValidableTextField(
254: new TextFieldValidator.integer()))); // NOI18N
255: table.getColumn("scale").setCellEditor(
256: new DataCellEditor(new ValidableTextField(
257: new TextFieldValidator.integer()))); // NOI18N
258: table.setRowHeight(combo.getPreferredSize().height);
259:
260: // Button pane
261:
262: constr.fill = GridBagConstraints.HORIZONTAL;
263: constr.anchor = GridBagConstraints.NORTH;
264: constr.weightx = 0.0;
265: constr.weighty = 0.0;
266: constr.gridx = 4;
267: constr.gridy = 1;
268: constr.insets = new java.awt.Insets(2, 8, 2, 2);
269: JPanel btnpane = new JPanel();
270: GridLayout btnlay = new GridLayout(2, 1, 0, 5);
271: btnpane.setLayout(btnlay);
272: layout.setConstraints(btnpane, constr);
273: pane.add(btnpane);
274:
275: // Button add column
276:
277: addbtn = new JButton();
278: Mnemonics.setLocalizedText(addbtn, bundle
279: .getString("CreateTableAddButtonTitle")); // NOI18N
280: addbtn
281: .setToolTipText(bundle
282: .getString("ACS_CreateTableAddButtonTitleA11yDesc"));
283: btnpane.add(addbtn);
284: addbtn.addActionListener(new ActionListener() {
285: public void actionPerformed(ActionEvent event) {
286: if (table.getCellEditor() != null) {
287: table.getCellEditor().stopCellEditing();
288: }
289: DataModel model = (DataModel) table.getModel();
290: ColumnItem item = new ColumnItem();
291: item
292: .setProperty(ColumnItem.TYPE, ttab
293: .elementAt(0));
294: model.addRow(item);
295: }
296: });
297:
298: // Button delete column
299:
300: delbtn = new JButton();
301: Mnemonics.setLocalizedText(delbtn, bundle
302: .getString("CreateTableRemoveButtonTitle")); // NOI18N
303: delbtn
304: .setToolTipText(bundle
305: .getString("ACS_CreateTableRemoveButtonTitleA11yDesc"));
306: btnpane.add(delbtn);
307: delbtn.addActionListener(new ActionListener() {
308: public void actionPerformed(ActionEvent event) {
309: if (table.getCellEditor() != null) {
310: table.getCellEditor().stopCellEditing();
311: }
312: int idx = table.getSelectedRow();
313: if (idx != -1)
314: ((DataModel) table.getModel()).removeRow(idx);
315: }
316: });
317:
318: ActionListener listener = new ActionListener() {
319: public void actionPerformed(ActionEvent event) {
320: final ActionEvent evt = event;
321: if (table.getCellEditor() != null) {
322: table.getCellEditor().stopCellEditing();
323: }
324: RequestProcessor.getDefault().post(new Runnable() {
325: public void run() {
326: if (evt.getSource() == DialogDescriptor.OK_OPTION) {
327: result = validate();
328:
329: CommandBuffer cbuff = new CommandBuffer();
330: Vector idxCommands = new Vector();
331:
332: if (!result) {
333: String msg = bundle
334: .getString("EXC_InsufficientCreateTableInfo");
335: DialogDisplayer
336: .getDefault()
337: .notify(
338: new NotifyDescriptor.Message(
339: msg,
340: NotifyDescriptor.ERROR_MESSAGE));
341: }
342: try {
343: String tablename = getTableName();
344: DataModel dataModel = (DataModel) table
345: .getModel();
346: Vector data = dataModel.getData();
347: String owner = ((String) ownercombo
348: .getSelectedItem()).trim();
349:
350: CreateTableDDL ddl = new CreateTableDDL(
351: spec, owner, tablename);
352:
353: boolean wasException = ddl
354: .execute(
355: data,
356: dataModel
357: .getTablePrimaryKeys());
358:
359: //bugfix for #31064
360: combo.setSelectedItem(combo
361: .getSelectedItem());
362:
363: // was execution of commands with or without exception?
364: if (!wasException) {
365: // dialog is closed after successfully create table
366: dialog.setVisible(false);
367: dialog.dispose();
368: }
369: //dialog is not closed after unsuccessfully create table
370:
371: } catch (Exception e) {
372: e.printStackTrace();
373:
374: }
375: } else {
376: }
377: }
378: }, 0);
379: }
380: };
381:
382: pane.getAccessibleContext().setAccessibleDescription(
383: bundle.getString("ACS_CreateTableDialogA11yDesc"));
384:
385: addbtn.doClick();
386: DialogDescriptor descriptor = new DialogDescriptor(pane,
387: bundle.getString("CreateTableDialogTitle"), true,
388: listener); // NOI18N
389: // inbuilt close of the dialog is only after CANCEL button click
390: // after OK button is dialog closed by hand
391: Object[] closingOptions = { DialogDescriptor.CANCEL_OPTION };
392: descriptor.setClosingOptions(closingOptions);
393: dialog = DialogDisplayer.getDefault().createDialog(
394: descriptor);
395: dialog.setResizable(true);
396: } catch (MissingResourceException ex) {
397: ex.printStackTrace();
398: }
399: }
400:
401: public boolean run() {
402: if (dialog != null)
403: dialog.setVisible(true);
404: return result;
405: }
406:
407: public String getTableName() {
408: return dbnamefield.getText();
409: }
410:
411: private boolean validate() {
412: String tname = getTableName();
413: if (tname == null || tname.length() < 1)
414: return false;
415:
416: Vector cols = ((DataModel) table.getModel()).getData();
417: Enumeration colse = cols.elements();
418: while (colse.hasMoreElements())
419: if (!((ColumnItem) colse.nextElement()).validate())
420: return false;
421:
422: return true;
423: }
424:
425: class DataTable extends JTable {
426: static final long serialVersionUID = 1222037401669064863L;
427:
428: public DataTable(TableModel model) {
429: super (model);
430: setSurrendersFocusOnKeystroke(true);
431: TableColumnModel cmodel = getColumnModel();
432: int i;
433: int ccount = model.getColumnCount();
434: int columnWidth;
435: int preferredWidth;
436: String columnName;
437: int width = 0;
438: for (i = 0; i < ccount; i++) {
439: TableColumn col = cmodel.getColumn(i);
440: Map cmap = ColumnItem.getColumnProperty(i);
441: col.setIdentifier(cmap.get("name")); //NOI18N
442: columnName = bundle.getString("CreateTable_" + i); //NOI18N
443: columnWidth = (new Double(getFontMetrics(getFont())
444: .getStringBounds(columnName, getGraphics())
445: .getWidth())).intValue() + 20;
446: if (cmap.containsKey("width")) { // NOI18N
447: if (((Integer) cmap.get("width")).intValue() < columnWidth)
448: col.setPreferredWidth(columnWidth);
449: else
450: col.setPreferredWidth(((Integer) cmap
451: .get("width")).intValue()); // NOI18N
452: preferredWidth = col.getPreferredWidth();
453: }
454: if (cmap.containsKey("minwidth")) // NOI18N
455: if (((Integer) cmap.get("minwidth")).intValue() < columnWidth)
456: col.setMinWidth(columnWidth);
457: else
458: col
459: .setMinWidth(((Integer) cmap
460: .get("minwidth")).intValue()); // NOI18N
461: // if (cmap.containsKey("alignment")) {}
462: // if (cmap.containsKey("tip")) ((JComponent)col.getCellRenderer()).setToolTipText((String)cmap.get("tip"));
463: if (i < 7) { // the first 7 columns should be visible
464: width += col.getPreferredWidth();
465: }
466: }
467: width = Math.min(Math.max(width, 380), Toolkit
468: .getDefaultToolkit().getScreenSize().width - 100);
469: setPreferredScrollableViewportSize(new Dimension(width, 150));
470: }
471: }
472:
473: class FocusInvoker implements Runnable {
474: private JTextField xxx;
475:
476: public FocusInvoker(JTextField fld) {
477: xxx = fld;
478: }
479:
480: public void run() {
481: xxx.selectAll();
482: }
483: }
484:
485: class DataCellEditor extends DefaultCellEditor {
486: static final long serialVersionUID = 3855371868128838794L;
487:
488: public DataCellEditor(final JTextField x) {
489: super (x);
490: setClickCountToStart(1);
491: }
492: }
493:
494: class PopupInvoker implements Runnable {
495: private JComboBox jComboBox;
496:
497: public PopupInvoker(JComboBox aJComboBox) {
498: jComboBox = aJComboBox;
499: }
500:
501: public void run() {
502: try {
503: jComboBox.showPopup();
504: } catch (IllegalComponentStateException icse) {
505: // This is a valid exception that occurs
506: // if the jComboBox is somehow hide. Do nothing.
507: }
508: }
509:
510: }
511:
512: class ComboBoxEditor extends DefaultCellEditor {
513: public ComboBoxEditor(final JComboBox jComboBox) {
514: super (jComboBox);
515: jComboBox.addFocusListener(new FocusListener() {
516: public void focusGained(FocusEvent e) {
517: SwingUtilities.invokeLater(new PopupInvoker(
518: jComboBox));
519: }
520:
521: public void focusLost(FocusEvent e) {
522: }
523: });
524: }
525: }
526:
527: private static final class ListCellRendererImpl extends
528: DefaultListCellRenderer {
529:
530: public Dimension getPreferredSize() {
531: Dimension size = super .getPreferredSize();
532: // hack to fix issue 65759
533: if (Utilities.isWindows()) {
534: size.width += 4;
535: }
536: return size;
537: }
538: }
539: }
|