2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
41
package org.netbeans.modules.xml.tax.beans.editor;
43
import java.awt.Component;
44
import java.awt.event.KeyAdapter;
45
import java.awt.event.MouseAdapter;
46
import java.awt.event.MouseEvent;
47
import java.awt.event.KeyEvent;
48
import java.beans.Customizer;
49
import java.beans.PropertyChangeEvent;
50
import java.beans.PropertyChangeListener;
51
import javax.swing.event.ListSelectionEvent;
52
import javax.swing.event.TableModelEvent;
53
import javax.swing.event.ListSelectionListener;
54
import javax.swing.JPanel;
55
import javax.swing.JLabel;
56
import javax.swing.UIManager;
57
import javax.swing.JTable;
58
import javax.swing.ListSelectionModel;
59
import javax.swing.DefaultCellEditor;
60
import javax.swing.JTextField;
61
import javax.swing.table.TableColumn;
62
import javax.swing.table.JTableHeader;
63
import javax.swing.table.AbstractTableModel;
64
import javax.swing.table.TableCellRenderer;
65
import javax.swing.table.TableColumnModel;
67
import org.netbeans.tax.TreeNamedObjectMap;
68
import org.netbeans.tax.TreeAttribute;
69
import org.netbeans.tax.TreeName;
70
import org.netbeans.tax.TreeException;
72
import org.netbeans.modules.xml.tax.beans.TreeObjectListProxyListener;
73
import org.netbeans.modules.xml.tax.beans.Lib;
74
import org.netbeans.modules.xml.tax.util.TAXUtil;
77
* Table oriented customizer of TreeElement attribute list.
80
* @author Vladimir Zboril
81
* @author Libor Kramolis
84
public class TreeElementAttributeListCustomizer extends JPanel implements Customizer, PropertyChangeListener {
86
/** Serial Version UID */
87
private static final long serialVersionUID = 1071471854210683733L;
89
private String headerToolTip;
91
private final int COL_NAME = 0;
92
private final int COL_VALUE = 1;
93
private final int COL_COUNT = 2;
99
/** Creates new form TreeElementAttributeListCustomizer */
101
public TreeElementAttributeListCustomizer() {
103
headerToolTip = Util.THIS.getString("PROP_headerTooltip");
106
upButton.setMnemonic(Util.THIS.getChar("MNE_element_attributelist_up")); // NOI18N
107
downButton.setMnemonic(Util.THIS.getChar("MNE_element_attributelist_down")); // NOI18N
108
removeButton.setMnemonic(Util.THIS.getChar("MNE_element_attributelist_remove")); // NOI18N
109
addButton.setMnemonic(Util.THIS.getChar("MNE_element_attributelist_add")); // NOI18N
112
// Add custom header renderer supporting sorting
113
attrTable.getTableHeader().setDefaultRenderer(new HeaderRenderer());
115
// Cells should become editable on single mouse click
116
final JTextField editorComponent = new JTextField();
117
editorComponent.getCaret().setVisible(true);
118
final DefaultCellEditor singleClickEditor = new DefaultCellEditor(editorComponent);
119
singleClickEditor.setClickCountToStart(1);
120
attrTable.setDefaultEditor(String.class, singleClickEditor);
122
// Set ListSelectionModel
123
attrTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
124
ListSelectionModel rowsm = attrTable.getSelectionModel();
125
rowsm.addListSelectionListener (new ListSelectionListener(){
126
public void valueChanged (ListSelectionEvent e) {
127
if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("\n#=- TreeElementAttributeListCustomizer::ListSelectionListener.valueChanged: event = " + e);
128
if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("#=- event.getValueIsAdjusting() = " + e.getValueIsAdjusting());
129
if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("#=- event.getFirstIndex() = " + e.getFirstIndex());
130
if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("#=- event.getLastIndex() = " + e.getLastIndex());
132
if (e.getValueIsAdjusting())
134
ListSelectionModel lsm = (ListSelectionModel)e.getSource();
136
if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("#=- event.getSource() = " + lsm);
137
if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("#=- selectionModel.isSelectionEmpty() = " + lsm.isSelectionEmpty());
138
if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("#=- attrTable.getSelectedRow() = " + attrTable.getSelectedRow());
139
if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug ("#=- attrTable.getRowCount() = " + attrTable.getRowCount());
141
if ( lsm.isSelectionEmpty() ||
142
( attrTable.getRowCount() == 0 ) ) {
143
upButton.setEnabled (false);
144
downButton.setEnabled (false);
145
removeButton.setEnabled (false);
147
upButton.setEnabled (attrTable.getSelectedRow() > 0);
148
downButton.setEnabled (attrTable.getSelectedRow() < (numRows() - 1));
149
removeButton.setEnabled (true);
154
//Click to header - sorting
155
attrTable.getTableHeader().addMouseListener(new MouseAdapter() {
156
public void mouseClicked(MouseEvent e) {
157
TableColumnModel colModel = attrTable.getColumnModel();
158
int columnIndex = colModel.getColumnIndexAtX(e.getX());
159
// No column was clicked.
160
if(columnIndex < 0) return;
161
int modelIndex = colModel.getColumn(columnIndex).getModelIndex();
162
// not detected column
163
if (modelIndex < 0) return;
165
AttlistTableModel tm = (AttlistTableModel) attrTable.getModel();
166
tm.sortByColumn(columnIndex);
174
private int numRows(){
175
return attrTable.getModel().getRowCount();
178
//Get count of columns
179
private int numCols(){
180
return attrTable.getModel().getColumnCount();
187
/** This method is called from within the constructor to
188
* initialize the form.
189
* WARNING: Do NOT modify this code. The content of this method is
190
* always regenerated by the FormEditor.
192
private void initComponents() {//GEN-BEGIN:initComponents
193
java.awt.GridBagConstraints gridBagConstraints;
195
tableScrollPane = new javax.swing.JScrollPane();
196
attrTable = new javax.swing.JTable();
197
upButton = new javax.swing.JButton();
198
downButton = new javax.swing.JButton();
199
addButton = new javax.swing.JButton();
200
removeButton = new javax.swing.JButton();
202
setLayout(new java.awt.GridBagLayout());
204
setPreferredSize(new java.awt.Dimension(350, 230));
205
attrTable.setPreferredScrollableViewportSize(new java.awt.Dimension(200, 150));
206
tableScrollPane.setViewportView(attrTable);
208
gridBagConstraints = new java.awt.GridBagConstraints();
209
gridBagConstraints.gridx = 0;
210
gridBagConstraints.gridy = 0;
211
gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER;
212
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
213
gridBagConstraints.weightx = 1.0;
214
gridBagConstraints.weighty = 1.0;
215
gridBagConstraints.insets = new java.awt.Insets(12, 12, 0, 0);
216
add(tableScrollPane, gridBagConstraints);
218
upButton.setText(Util.THIS.getString ("TEXT_element_attributelist_up"));
219
upButton.setEnabled(false);
220
upButton.addActionListener(new java.awt.event.ActionListener() {
221
public void actionPerformed(java.awt.event.ActionEvent evt) {
222
upButtonActionPerformed(evt);
226
gridBagConstraints = new java.awt.GridBagConstraints();
227
gridBagConstraints.gridx = 1;
228
gridBagConstraints.gridy = 0;
229
gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
230
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
231
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
232
gridBagConstraints.insets = new java.awt.Insets(12, 12, 0, 11);
233
add(upButton, gridBagConstraints);
235
downButton.setText(Util.THIS.getString ("TEXT_element_attributelist_down"));
236
downButton.setEnabled(false);
237
downButton.addActionListener(new java.awt.event.ActionListener() {
238
public void actionPerformed(java.awt.event.ActionEvent evt) {
239
downButtonActionPerformed(evt);
243
gridBagConstraints = new java.awt.GridBagConstraints();
244
gridBagConstraints.gridx = 1;
245
gridBagConstraints.gridy = 1;
246
gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
247
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
248
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
249
gridBagConstraints.insets = new java.awt.Insets(5, 12, 0, 11);
250
add(downButton, gridBagConstraints);
252
addButton.setText(Util.THIS.getString ("TEXT_element_attributelist_add"));
253
addButton.addActionListener(new java.awt.event.ActionListener() {
254
public void actionPerformed(java.awt.event.ActionEvent evt) {
255
addButtonActionPerformed(evt);
259
gridBagConstraints = new java.awt.GridBagConstraints();
260
gridBagConstraints.gridx = 1;
261
gridBagConstraints.gridy = 2;
262
gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
263
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
264
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
265
gridBagConstraints.insets = new java.awt.Insets(5, 12, 0, 11);
266
add(addButton, gridBagConstraints);
268
removeButton.setText(Util.THIS.getString ("TEXT_element_attributelist_remove"));
269
removeButton.setEnabled(false);
270
removeButton.addActionListener(new java.awt.event.ActionListener() {
271
public void actionPerformed(java.awt.event.ActionEvent evt) {
272
removeButtonActionPerformed(evt);
276
gridBagConstraints = new java.awt.GridBagConstraints();
277
gridBagConstraints.gridx = 1;
278
gridBagConstraints.gridy = 3;
279
gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
280
gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER;
281
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
282
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
283
gridBagConstraints.insets = new java.awt.Insets(5, 12, 0, 11);
284
add(removeButton, gridBagConstraints);
286
}//GEN-END:initComponents
289
* The button at right side was pressed
291
private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addButtonActionPerformed
293
AttlistTableModel tm = (AttlistTableModel) attrTable.getModel();
295
int actualIndex = numRows() - 1;
296
attrTable.getSelectionModel().setSelectionInterval(actualIndex, actualIndex);
297
}//GEN-LAST:event_addButtonActionPerformed
300
* The button at right side was pressed
302
private void upButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_upButtonActionPerformed
304
AttlistTableModel tm = (AttlistTableModel) attrTable.getModel();
305
int index = attrTable.getSelectedRow();
307
tm.moveRow(index, index - 1);
308
attrTable.getSelectionModel().setSelectionInterval(index - 1,index - 1);
310
}//GEN-LAST:event_upButtonActionPerformed
313
* The button at right side was pressed
315
private void removeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeButtonActionPerformed
317
AttlistTableModel tm = (AttlistTableModel) attrTable.getModel();
319
int sel = attrTable.getSelectedRow();
323
if (sel <= numRows() - 1)
324
attrTable.getSelectionModel().setSelectionInterval(sel,sel);
326
attrTable.getSelectionModel().setSelectionInterval(sel - 1, sel - 1);
327
} else removeButton.setEnabled(false);
329
}//GEN-LAST:event_removeButtonActionPerformed
332
* The button at right side was pressed
334
private void downButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downButtonActionPerformed
336
AttlistTableModel tm = (AttlistTableModel) attrTable.getModel();
337
int index = attrTable.getSelectedRow();
338
if (index > -1 && index < numRows() - 1) {
339
tm.moveRow(index, index + 1);
340
attrTable.getSelectionModel().setSelectionInterval(index + 1,index + 1);
342
}//GEN-LAST:event_downButtonActionPerformed
345
// Variables declaration - do not modify//GEN-BEGIN:variables
346
private javax.swing.JTable attrTable;
347
private javax.swing.JButton addButton;
348
private javax.swing.JScrollPane tableScrollPane;
349
private javax.swing.JButton downButton;
350
private javax.swing.JButton upButton;
351
private javax.swing.JButton removeButton;
352
// End of variables declaration//GEN-END:variables
355
private TreeNamedObjectMap peer;
356
private AttlistTableModel tableModel;
360
public void setObject (Object obj) {
361
peer = (TreeNamedObjectMap) obj;
362
tableModel = new AttlistTableModel(/*peer*/);
363
attrTable.setModel(tableModel);
364
// we do not "delete" column anymore
365
// attrTable.addKeyListener(new RowKeyListener(attrTable));
367
/** First table column is row selector. */
368
TableColumn column = null;
369
for (int i = 0; i < COL_COUNT; i++) {
370
column = attrTable.getColumnModel().getColumn (i);
371
//column.setPreferredWidth (50);
376
TreeObjectListProxyListener proxy = new TreeObjectListProxyListener(peer);
377
proxy.addPropertyChangeListener(org.openide.util.WeakListeners.propertyChange(this, proxy));
381
/** Udate state accordingly*/
382
public void propertyChange(final PropertyChangeEvent e) {
383
if (e.getSource() == null)
389
/** Update visualization accordingly. */
390
private void updateView () {
391
tableModel.fireTableDataChanged();
395
// class RowKeyListener
399
* Deletes whole row by pressing DELETE on row column.
402
private class RowKeyListener extends KeyAdapter {
405
private JTable table;
412
public RowKeyListener (JTable table) {
423
public void keyReleased (KeyEvent e) {
424
//if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug("Event: " + e); // NOI18N
425
if (e.getKeyCode() == KeyEvent.VK_DELETE) {
426
tableModel.removeRow (table.getSelectedRow());
427
// peer.remove (peer.get (table.getSelectedRow()));
428
// tableModel.fireTableDataChanged();
435
// class AttlistTableModel
441
private class AttlistTableModel extends AbstractTableModel {
443
/** Serial Version UID */
444
private static final long serialVersionUID = 1567143493464383838L;
446
boolean ascending = true;
447
int SortedColumn = -1;
454
/** Create a data node for a given data object.
455
* The provided children object will be used to hold all child nodes.
456
* @param obj object to work with
457
* @param ch children container for the node
459
public AttlistTableModel () {
463
/** Returns the number of rows in the model */
464
public int getRowCount () {
469
/** Returns the number of columns in the model */
470
public int getColumnCount () {
474
/** Returns the class for a model. */
475
public Class getColumnClass (int index) {
480
// // Get unique attribute name for added blank rows
481
// private String getUniqueName(){
482
// int index = 0, i = 0;
483
// final String prefix = "attribute-"; // NOI18N
484
// String result = prefix + Integer.toString(index);
485
// while (i<numRows()){
486
// if (result.equals(attrTable.getValueAt(i,0))) {
487
// result = prefix + Integer.toString(++index);
496
public void addRow () {
498
TreeAttribute attr = (TreeAttribute) Lib.createAttributeDialog(true);
500
boolean toSet = true;
501
TreeAttribute oldAttribute = (TreeAttribute) peer.get (attr.getTreeName());
502
if ( oldAttribute != null ) {
503
toSet = Lib.confirmAction
504
(Util.THIS.getString ("MSG_replace_attribute", attr.getQName()));
509
fireTableStructureChanged();
514
peer.add (new TreeAttribute (getUniqueName(), ""));
516
fireTableStructureChanged();
517
} catch (TreeException exc) {
518
TAXUtil.notifyTreeException (exc);
525
public void removeRow (int row) {
527
fireTableStructureChanged();
532
public void moveRow (int fromIndex, int toIndex) {
534
peer.switchObjects (fromIndex, toIndex);
537
fireTableStructureChanged();
538
} catch (TreeException exc) {
539
TAXUtil.notifyTreeException (exc);
545
public Object getValueAt (int row, int column) {
546
TreeAttribute attr = (TreeAttribute) peer.get(row);
549
return attr.getQName();
551
return attr.getValue();
559
public void setValueAt (Object val, int row, int column) {
560
TreeAttribute attr = (TreeAttribute) peer.get (row);
562
if (column == COL_NAME) {
564
String attrName = (String) val;
566
boolean toSet = true;
567
TreeAttribute oldAttribute = (TreeAttribute) peer.get (new TreeName (attrName));
568
if ( attr != oldAttribute ) {
569
if ( oldAttribute != null ) {
570
toSet = Lib.confirmAction
571
(Util.THIS.getString ("MSG_replace_attribute", attrName));
575
attr.setQName (attrName);
578
} else if (column == COL_VALUE) {
579
attr.setValue ((String) val);
581
} catch (TreeException exc) {
582
TAXUtil.notifyTreeException (exc);
588
public String getColumnName (int column) {
591
return Util.THIS.getString ("NAME_column_name");
593
return Util.THIS.getString ("NAME_column_value");
599
/** Returns true for all cells which are editable. For a
600
* a new cell is editable only name field.
602
public boolean isCellEditable (int rowIndex, int columnIndex) {
608
public void sortByColumn (int column) {
610
if (SortedColumn == column)
611
ascending = !ascending;
613
SortedColumn = column;
617
indexes = new int[getRowCount()];
618
for (int row = 0; row < getRowCount(); row++) {
624
int[] indx = new int[indexes.length];
625
for (int row = 0; row < indx.length; row++) {
626
indx[indexes[row]] = row;
631
fireTableChanged(new TableModelEvent(this));
632
} catch (TreeException exc) {
633
TAXUtil.notifyTreeException (exc);
639
private void n2sort (int col) {
640
for (int i = 0; i < getRowCount(); i++) {
641
for (int j = i + 1; j < getRowCount(); j++) {
642
if (compare(indexes[i], indexes[j], col) == -1) {
644
int tmp = indexes[i];
645
indexes[i] = indexes[j];
654
private int compare (int row1, int row2, int col) {
655
int result = compareRowsByColumn(row1, row2, col);
657
return ascending ? -result : result;
664
private int compareRowsByColumn (int row1, int row2, int column) {
666
Class type = getColumnClass(column);
668
Object o1 = getValueAt(row1, column);
669
Object o2 = getValueAt(row2, column);
672
// If both values are null, return 0.
674
if (o1 == null && o2 == null) {
676
} else if (o1 == null) {
678
} else if (o2 == null) {
684
if (type == String.class) {
685
String s1 = (String) getValueAt(row1, column);
686
String s2 = (String) getValueAt(row2, column);
687
int result = s1.compareTo(s2);
691
} else if (result > 0) {
700
} // end: class AttlistTableModel
707
private class HeaderRenderer extends JLabel implements TableCellRenderer {
709
/** Serial Version UID */
710
private static final long serialVersionUID =-3658206203140258583L;
712
public HeaderRenderer() {
714
setHorizontalAlignment(JLabel.LEFT);
715
setBorder(UIManager.getBorder("TableHeader.cellBorder")); // NOI18N
716
setToolTipText(headerToolTip);
719
public Component getTableCellRendererComponent (JTable table, Object value,
720
boolean isSelected, boolean hasFocus,int row, int column) {
723
JTableHeader header = table.getTableHeader();
724
if (header != null) {
725
setForeground(header.getForeground());
726
setBackground(header.getBackground());
727
setFont(header.getFont());
731
AttlistTableModel tm = (AttlistTableModel)table.getModel();
732
if (column == tm.SortedColumn)
733
setIcon(tm.ascending ? new javax.swing.ImageIcon(getClass().getResource("down.gif")): // NOI18N
734
new javax.swing.ImageIcon(getClass().getResource("up.gif"))); // NOI18N
735
else setIcon(new javax.swing.ImageIcon(getClass().getResource("no.gif"))); // NOI18N
737
setText((value == null) ? "" : value.toString()); // NOI18N
740
} // end: class HeaderRenderer
742
/** Initialize accesibility
744
public void initAccessibility(){
746
this.getAccessibleContext().setAccessibleDescription(Util.THIS.getString("ACSD_TreeElementAttributeListCustomizer"));
748
addButton.getAccessibleContext().setAccessibleDescription(Util.THIS.getString("ACSD_addButton"));
749
removeButton.getAccessibleContext().setAccessibleDescription(Util.THIS.getString("ACSD_removeButton"));
750
upButton.getAccessibleContext().setAccessibleDescription(Util.THIS.getString("ACSD_upButton"));
751
downButton.getAccessibleContext().setAccessibleDescription(Util.THIS.getString("ACSD_downButton"));
753
attrTable.getAccessibleContext().setAccessibleDescription(Util.THIS.getString("ACSD_attrTable"));
754
attrTable.getAccessibleContext().setAccessibleName(Util.THIS.getString("ACSN_attrTable"));