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.subversion.ui.commit;
043:
044: import org.netbeans.modules.versioning.util.FilePathCellRenderer;
045: import org.netbeans.modules.versioning.util.TableSorter;
046: import org.netbeans.modules.subversion.util.SvnUtils;
047: import org.netbeans.modules.subversion.SvnFileNode;
048: import org.netbeans.modules.subversion.FileInformation;
049: import org.netbeans.modules.subversion.Subversion;
050: import org.openide.util.NbBundle;
051:
052: import javax.swing.*;
053: import javax.swing.event.AncestorEvent;
054: import javax.swing.event.AncestorListener;
055: import javax.swing.event.TableModelListener;
056: import javax.swing.event.TableModelEvent;
057: import javax.swing.table.DefaultTableCellRenderer;
058: import javax.swing.table.TableModel;
059: import javax.swing.table.TableColumnModel;
060: import java.awt.Component;
061: import java.lang.String;
062: import java.util.*;
063:
064: /**
065: * {@link #getComponent Table} that displays nodes in the commit dialog.
066: *
067: * @author Maros Sandor
068: */
069: public class CommitTable implements AncestorListener,
070: TableModelListener {
071:
072: public static String[] COMMIT_COLUMNS = new String[] {
073: CommitTableModel.COLUMN_NAME_NAME,
074: CommitTableModel.COLUMN_NAME_STATUS,
075: CommitTableModel.COLUMN_NAME_ACTION,
076: CommitTableModel.COLUMN_NAME_PATH };
077:
078: public static String[] IMPORT_COLUMNS = new String[] {
079: CommitTableModel.COLUMN_NAME_NAME,
080: CommitTableModel.COLUMN_NAME_ACTION,
081: CommitTableModel.COLUMN_NAME_PATH };
082:
083: private CommitTableModel tableModel;
084: private JTable table;
085: private JComponent component;
086:
087: private TableSorter sorter;
088: private String[] columns;
089: private String[] sortByColumns;
090:
091: public CommitTable(JLabel label, String[] columns,
092: String[] sortByColumns) {
093: init(label, columns, null);
094: this .sortByColumns = sortByColumns;
095: setSortingStatus();
096: }
097:
098: public CommitTable(JLabel label, String[] columns,
099: TableSorter sorter) {
100: init(label, columns, sorter);
101: }
102:
103: private void init(JLabel label, String[] columns, TableSorter sorter) {
104: tableModel = new CommitTableModel(columns);
105: tableModel.addTableModelListener(this );
106: if (sorter == null) {
107: sorter = new TableSorter(tableModel);
108: }
109: this .sorter = sorter;
110: table = new JTable(this .sorter);
111: table.getTableHeader().setReorderingAllowed(false);
112: table.setDefaultRenderer(String.class,
113: new CommitStringsCellRenderer());
114: table.setDefaultEditor(CommitOptions.class,
115: new CommitOptionsCellEditor());
116: table.getTableHeader().setReorderingAllowed(true);
117: this .sorter.setTableHeader(table.getTableHeader());
118: table.setRowHeight(table.getRowHeight() * 6 / 5);
119: table.addAncestorListener(this );
120: component = new JScrollPane(table,
121: JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
122: JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
123: label.setLabelFor(table);
124: table.getAccessibleContext().setAccessibleDescription(
125: NbBundle.getMessage(CommitTable.class,
126: "ACSD_CommitTable")); // NOI18N
127: setColumns(columns);
128: }
129:
130: public void ancestorAdded(AncestorEvent event) {
131: setDefaultColumnSizes();
132: }
133:
134: /**
135: * Sets sizes of Commit table columns, kind of hardcoded.
136: */
137: private void setDefaultColumnSizes() {
138: int width = table.getWidth();
139: TableColumnModel columnModel = table.getColumnModel();
140: if (columns == null || columnModel == null)
141: return; // unsure when this methed will be called (component realization)
142: if (columnModel.getColumnCount() != columns.length)
143: return;
144: if (columns.length == 3) {
145: for (int i = 0; i < columns.length; i++) {
146: String col = columns[i];
147: sorter.setColumnComparator(i, null);
148: if (col.equals(CommitTableModel.COLUMN_NAME_NAME)) {
149: sorter.setColumnComparator(i,
150: new FileNameComparator());
151: columnModel.getColumn(i).setPreferredWidth(
152: width * 30 / 100);
153: } else if (col
154: .equals(CommitTableModel.COLUMN_NAME_ACTION)) {
155: columnModel.getColumn(i).setPreferredWidth(
156: width * 15 / 100);
157: } else {
158: columnModel.getColumn(i).setPreferredWidth(
159: width * 40 / 100);
160: }
161: }
162: } else if (columns.length == 4) {
163: for (int i = 0; i < columns.length; i++) {
164: String col = columns[i];
165: sorter.setColumnComparator(i, null);
166: if (col.equals(CommitTableModel.COLUMN_NAME_NAME)) {
167: sorter.setColumnComparator(i,
168: new FileNameComparator());
169: columnModel.getColumn(i).setPreferredWidth(
170: width * 30 / 100);
171: } else if (col
172: .equals(CommitTableModel.COLUMN_NAME_STATUS)) {
173: sorter.setColumnComparator(i,
174: new StatusComparator());
175: columnModel.getColumn(i).setPreferredWidth(
176: width * 15 / 100);
177: } else if (col
178: .equals(CommitTableModel.COLUMN_NAME_ACTION)) {
179: columnModel.getColumn(i).setPreferredWidth(
180: width * 15 / 100);
181: } else {
182: columnModel.getColumn(i).setPreferredWidth(
183: width * 40 / 100);
184: }
185: }
186: } else if (columns.length == 5) {
187: for (int i = 0; i < columns.length; i++) {
188: String col = columns[i];
189: sorter.setColumnComparator(i, null);
190: if (col.equals(CommitTableModel.COLUMN_NAME_NAME)) {
191: sorter.setColumnComparator(i,
192: new FileNameComparator());
193: columnModel.getColumn(i).setPreferredWidth(
194: width * 25 / 100);
195: } else if (col
196: .equals(CommitTableModel.COLUMN_NAME_STATUS)) {
197: sorter.setColumnComparator(i,
198: new StatusComparator());
199: sorter.setSortingStatus(i, TableSorter.ASCENDING);
200: columnModel.getColumn(i).setPreferredWidth(
201: width * 15 / 100);
202: } else if (col
203: .equals(CommitTableModel.COLUMN_NAME_ACTION)) {
204: columnModel.getColumn(i).setPreferredWidth(
205: width * 15 / 100);
206: } else {
207: columnModel.getColumn(i).setPreferredWidth(
208: width * 30 / 100);
209: }
210: }
211: }
212: }
213:
214: private void setSortingStatus() {
215: for (int i = 0; i < sortByColumns.length; i++) {
216: String sortByColumn = sortByColumns[i];
217: for (int j = 0; j < columns.length; j++) {
218: String column = columns[j];
219: if (column.equals(sortByColumn)) {
220: sorter
221: .setSortingStatus(
222: j,
223: column.equals(sortByColumn) ? TableSorter.ASCENDING
224: : TableSorter.NOT_SORTED);
225: break;
226: }
227: }
228: }
229: }
230:
231: public TableSorter getSorter() {
232: return sorter;
233: }
234:
235: public void ancestorMoved(AncestorEvent event) {
236: }
237:
238: public void ancestorRemoved(AncestorEvent event) {
239: }
240:
241: void setColumns(String[] cols) {
242: if (Arrays.equals(columns, cols))
243: return;
244: columns = cols;
245: tableModel.setColumns(cols);
246: setDefaultColumnSizes();
247: }
248:
249: public void setNodes(SvnFileNode[] nodes) {
250: tableModel.setNodes(nodes);
251: }
252:
253: /**
254: * @return Map<SvnFileNode, CommitOptions>
255: */
256: public Map<SvnFileNode, CommitOptions> getCommitFiles() {
257: return tableModel.getCommitFiles();
258: }
259:
260: /**
261: * @return table in a scrollpane
262: */
263: public JComponent getComponent() {
264: return component;
265: }
266:
267: void dataChanged() {
268: int idx = table.getSelectedRow();
269: tableModel.fireTableDataChanged();
270: if (idx != -1)
271: table.getSelectionModel().addSelectionInterval(idx, idx);
272: }
273:
274: TableModel getTableModel() {
275: return tableModel;
276: }
277:
278: public void tableChanged(TableModelEvent e) {
279: // change in commit options may alter name rendering (strikethrough)
280: table.repaint();
281: }
282:
283: public void setRootFile(String repositoryPath, String rootLocalPath) {
284: tableModel.setRootFile(repositoryPath, rootLocalPath);
285: }
286:
287: private class CommitOptionsCellEditor extends DefaultCellEditor {
288:
289: private final Object[] dirAddOptions = new Object[] {
290: CommitOptions.ADD_DIRECTORY, CommitOptions.EXCLUDE };
291:
292: private final Object[] addOptions = new Object[] {
293: CommitOptions.ADD_TEXT, CommitOptions.ADD_BINARY,
294: CommitOptions.EXCLUDE };
295: private final Object[] commitOptions = new Object[] {
296: CommitOptions.COMMIT, CommitOptions.EXCLUDE };
297:
298: private final Object[] removeOptions = new Object[] {
299: CommitOptions.COMMIT_REMOVE, CommitOptions.EXCLUDE };
300:
301: public CommitOptionsCellEditor() {
302: super (new JComboBox());
303: }
304:
305: public Component getTableCellEditorComponent(JTable table,
306: Object value, boolean isSelected, int row, int column) {
307: FileInformation info = tableModel.getNode(
308: sorter.modelIndex(row)).getInformation();
309: int fileStatus = info.getStatus();
310: JComboBox combo = (JComboBox) editorComponent;
311: if (fileStatus == FileInformation.STATUS_VERSIONED_DELETEDLOCALLY
312: || fileStatus == FileInformation.STATUS_VERSIONED_REMOVEDLOCALLY) {
313: combo.setModel(new DefaultComboBoxModel(removeOptions));
314: } else if ((fileStatus & FileInformation.STATUS_IN_REPOSITORY) == 0) {
315: if (info.isDirectory()) {
316: combo.setModel(new DefaultComboBoxModel(
317: dirAddOptions));
318: } else {
319: combo
320: .setModel(new DefaultComboBoxModel(
321: addOptions));
322: }
323: } else {
324: combo.setModel(new DefaultComboBoxModel(commitOptions));
325: }
326: return super .getTableCellEditorComponent(table, value,
327: isSelected, row, column);
328: }
329: }
330:
331: private class CommitStringsCellRenderer extends
332: DefaultTableCellRenderer {
333:
334: private FilePathCellRenderer pathRenderer = new FilePathCellRenderer();
335:
336: public Component getTableCellRendererComponent(JTable table,
337: Object value, boolean isSelected, boolean hasFocus,
338: int row, int column) {
339: int col = table.convertColumnIndexToModel(column);
340: if (columns[col] == CommitTableModel.COLUMN_NAME_NAME) {
341: TableSorter sorter = (TableSorter) table.getModel();
342: CommitTableModel model = (CommitTableModel) sorter
343: .getTableModel();
344: SvnFileNode node = model
345: .getNode(sorter.modelIndex(row));
346: CommitOptions options = model.getOptions(sorter
347: .modelIndex(row));
348: if (!isSelected) {
349: value = "<html>"
350: + Subversion
351: .getInstance()
352: .getAnnotator()
353: .annotateNameHtml(
354: // NOI18N
355: node.getFile().getName(),
356: node.getInformation(), null);
357: }
358: if (options == CommitOptions.EXCLUDE) {
359: value = "<html><s>" + value + "</s></html>"; // NOI18N
360: }
361: return super .getTableCellRendererComponent(table,
362: value, isSelected, hasFocus, row, column);
363: } else if (columns[col] == CommitTableModel.COLUMN_NAME_PATH) {
364: return pathRenderer
365: .getTableCellRendererComponent(table, value,
366: isSelected, hasFocus, row, column);
367: } else {
368: return super .getTableCellRendererComponent(table,
369: value, isSelected, hasFocus, row, column);
370: }
371: }
372: }
373:
374: private class StatusComparator extends
375: SvnUtils.ByImportanceComparator {
376: public int compare(Object o1, Object o2) {
377: Integer row1 = (Integer) o1;
378: Integer row2 = (Integer) o2;
379: return super .compare(tableModel.getNode(row1.intValue())
380: .getInformation(), tableModel.getNode(
381: row2.intValue()).getInformation());
382: }
383: }
384:
385: private class FileNameComparator implements Comparator {
386: public int compare(Object o1, Object o2) {
387: Integer row1 = (Integer) o1;
388: Integer row2 = (Integer) o2;
389: return tableModel.getNode(row1.intValue()).getName()
390: .compareToIgnoreCase(
391: tableModel.getNode(row2.intValue())
392: .getName());
393: }
394: }
395:
396: }
|