KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > subversion > ui > status > SyncTable


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.subversion.ui.status;
21
22 import org.netbeans.modules.subversion.*;
23 import org.netbeans.modules.subversion.ui.blame.BlameAction;
24 import org.netbeans.modules.subversion.ui.commit.*;
25 import org.netbeans.modules.subversion.ui.commit.CommitAction;
26 import org.netbeans.modules.subversion.ui.commit.ExcludeFromCommitAction;
27 import org.netbeans.modules.subversion.ui.history.SearchHistoryAction;
28 import org.netbeans.modules.subversion.ui.ignore.IgnoreAction;
29 import org.netbeans.modules.subversion.ui.update.RevertModificationsAction;
30 import org.netbeans.modules.subversion.ui.update.UpdateAction;
31 import org.netbeans.modules.subversion.ui.diff.DiffAction;
32 import org.netbeans.modules.subversion.util.*;
33 import org.openide.explorer.view.NodeTableModel;
34 import org.openide.nodes.*;
35 import org.openide.nodes.PropertySupport.ReadOnly;
36 import org.openide.windows.TopComponent;
37 import org.openide.util.NbBundle;
38 import org.openide.util.actions.SystemAction;
39 import org.openide.ErrorManager;
40 import org.openide.awt.MouseUtils;
41 import org.openide.awt.Mnemonics;
42 import org.netbeans.modules.versioning.util.FilePathCellRenderer;
43 import org.netbeans.modules.versioning.util.TableSorter;
44 import org.netbeans.modules.subversion.SvnModuleConfig;
45 import org.netbeans.modules.subversion.Subversion;
46 import org.netbeans.modules.subversion.Annotator;
47
48 import javax.swing.*;
49 import javax.swing.table.DefaultTableCellRenderer JavaDoc;
50 import javax.swing.event.ListSelectionListener JavaDoc;
51 import javax.swing.event.ListSelectionEvent JavaDoc;
52 import javax.swing.event.AncestorListener JavaDoc;
53 import javax.swing.event.AncestorEvent JavaDoc;
54 import java.lang.reflect.InvocationTargetException JavaDoc;
55 import java.awt.event.MouseListener JavaDoc;
56 import java.awt.event.MouseEvent JavaDoc;
57 import java.awt.event.ActionEvent JavaDoc;
58 import java.awt.event.KeyEvent JavaDoc;
59 import java.awt.Component JavaDoc;
60 import java.awt.Color JavaDoc;
61 import java.awt.Point JavaDoc;
62 import java.util.*;
63 import java.io.File JavaDoc;
64 import org.netbeans.modules.versioning.util.SystemActionBridge;
65
66 /**
67  * Controls the {@link #getComponent() tsble} that displays nodes
68  * in the Versioning view. The table is {@link #setTableModel populated)
69  * from VersioningPanel.
70  *
71  * @author Maros Sandor
72  */

73 class SyncTable implements MouseListener JavaDoc, ListSelectionListener JavaDoc, AncestorListener JavaDoc {
74
75     private NodeTableModel tableModel;
76     private JTable table;
77     private JScrollPane component;
78     private SyncFileNode [] nodes = new SyncFileNode[0];
79     
80     private String JavaDoc [] tableColumns;
81     private TableSorter sorter;
82
83     /**
84      * Defines labels for Versioning view table columns.
85      */

86     private static final Map<String JavaDoc, String JavaDoc[]> columnLabels = new HashMap<String JavaDoc, String JavaDoc[]>(4);
87     {
88         ResourceBundle loc = NbBundle.getBundle(SyncTable.class);
89         columnLabels.put(SyncFileNode.COLUMN_NAME_BRANCH, new String JavaDoc [] {
90                                           loc.getString("CTL_VersioningView_Column_Branch_Title"),
91                                           loc.getString("CTL_VersioningView_Column_Branch_Desc")});
92         columnLabels.put(SyncFileNode.COLUMN_NAME_NAME, new String JavaDoc [] {
93                                           loc.getString("CTL_VersioningView_Column_File_Title"),
94                                           loc.getString("CTL_VersioningView_Column_File_Desc")});
95         columnLabels.put(SyncFileNode.COLUMN_NAME_STATUS, new String JavaDoc [] {
96                                           loc.getString("CTL_VersioningView_Column_Status_Title"),
97                                           loc.getString("CTL_VersioningView_Column_Status_Desc")});
98         columnLabels.put(SyncFileNode.COLUMN_NAME_PATH, new String JavaDoc [] {
99                                           loc.getString("CTL_VersioningView_Column_Path_Title"),
100                                           loc.getString("CTL_VersioningView_Column_Path_Desc")});
101     }
102
103     private static final Comparator NodeComparator = new Comparator() {
104         public int compare(Object JavaDoc o1, Object JavaDoc o2) {
105             Node.Property p1 = (Node.Property) o1;
106             Node.Property p2 = (Node.Property) o2;
107             String JavaDoc sk1 = (String JavaDoc) p1.getValue("sortkey"); // NOI18N
108
if (sk1 != null) {
109                 String JavaDoc sk2 = (String JavaDoc) p2.getValue("sortkey"); // NOI18N
110
return sk1.compareToIgnoreCase(sk2);
111             } else {
112                 try {
113                     String JavaDoc s1 = (String JavaDoc) p1.getValue();
114                     String JavaDoc s2 = (String JavaDoc) p2.getValue();
115                     return s1.compareToIgnoreCase(s2);
116                 } catch (Exception JavaDoc e) {
117                     ErrorManager.getDefault().notify(e);
118                     return 0;
119                 }
120             }
121         }
122     };
123     
124     public SyncTable() {
125         tableModel = new NodeTableModel();
126         sorter = new TableSorter(tableModel);
127         sorter.setColumnComparator(Node.Property.class, NodeComparator);
128         table = new JTable(sorter);
129         sorter.setTableHeader(table.getTableHeader());
130         table.setRowHeight(table.getRowHeight() * 6 / 5);
131         component = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
132         component.getViewport().setBackground(table.getBackground());
133         Color JavaDoc borderColor = UIManager.getColor("scrollpane_border"); // NOI18N
134
if (borderColor == null) borderColor = UIManager.getColor("controlShadow"); // NOI18N
135
component.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, borderColor));
136         table.addMouseListener(this);
137         table.setDefaultRenderer(Node.Property.class, new SyncTableCellRenderer());
138         table.getSelectionModel().addListSelectionListener(this);
139         table.addAncestorListener(this);
140         table.getAccessibleContext().setAccessibleName(NbBundle.getMessage(SyncTable.class, "ACSN_VersioningTable")); // NOI18N
141
table.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(SyncTable.class, "ACSD_VersioningTable")); // NOI18N
142
setColumns(new String JavaDoc[] {
143             SyncFileNode.COLUMN_NAME_NAME,
144             SyncFileNode.COLUMN_NAME_STATUS,
145             SyncFileNode.COLUMN_NAME_PATH}
146         );
147         table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ).put(
148                 KeyStroke.getKeyStroke(KeyEvent.VK_F10, KeyEvent.SHIFT_DOWN_MASK ), "org.openide.actions.PopupAction");
149         table.getActionMap().put("org.openide.actions.PopupAction", new AbstractAction() {
150             public void actionPerformed(ActionEvent JavaDoc e) {
151                 showPopup(org.netbeans.modules.versioning.util.Utils.getPositionForPopup(table));
152             }
153         });
154     }
155
156     void setDefaultColumnSizes() {
157         SwingUtilities.invokeLater(new Runnable JavaDoc() {
158             public void run() {
159                 int width = table.getWidth();
160                 if (tableColumns.length == 3) {
161                     for (int i = 0; i < tableColumns.length; i++) {
162                         if (SyncFileNode.COLUMN_NAME_PATH.equals(tableColumns[i])) {
163                             table.getColumnModel().getColumn(i).setPreferredWidth(width * 60 / 100);
164                         } else {
165                             table.getColumnModel().getColumn(i).setPreferredWidth(width * 20 / 100);
166                         }
167                     }
168                 } else if (tableColumns.length == 4) {
169                     for (int i = 0; i < tableColumns.length; i++) {
170                         if (SyncFileNode.COLUMN_NAME_PATH.equals(tableColumns[i])) {
171                             table.getColumnModel().getColumn(i).setPreferredWidth(width * 55 / 100);
172                         } else {
173                             table.getColumnModel().getColumn(i).setPreferredWidth(width * 15 / 100);
174                         }
175                     }
176                 }
177             }
178         });
179     }
180
181     public void ancestorAdded(AncestorEvent JavaDoc event) {
182         setDefaultColumnSizes();
183     }
184
185     public void ancestorMoved(AncestorEvent JavaDoc event) {
186     }
187
188     public void ancestorRemoved(AncestorEvent JavaDoc event) {
189     }
190
191     public SyncFileNode [] getDisplayedNodes() {
192         int n = sorter.getRowCount();
193         SyncFileNode [] ret = new SyncFileNode[n];
194         for (int i = 0; i < n; i++) {
195             ret[i] = nodes[sorter.modelIndex(i)];
196         }
197         return ret;
198     }
199
200     public JComponent getComponent() {
201         return component;
202     }
203     
204     /**
205      * Sets visible columns in the Versioning table.
206      *
207      * @param columns array of column names, they must be one of SyncFileNode.COLUMN_NAME_XXXXX constants.
208      */

209     final void setColumns(String JavaDoc [] columns) {
210         if (Arrays.equals(columns, tableColumns)) return;
211         setModelProperties(columns);
212         tableColumns = columns;
213         for (int i = 0; i < tableColumns.length; i++) {
214             sorter.setColumnComparator(i, null);
215             sorter.setSortingStatus(i, TableSorter.NOT_SORTED);
216             if (SyncFileNode.COLUMN_NAME_STATUS.equals(tableColumns[i])) {
217                 sorter.setSortingStatus(i, TableSorter.ASCENDING);
218                 break;
219             }
220         }
221         setDefaultColumnSizes();
222     }
223         
224     private void setModelProperties(String JavaDoc [] columns) {
225         Node.Property [] properties = new Node.Property[columns.length];
226         for (int i = 0; i < columns.length; i++) {
227             String JavaDoc column = columns[i];
228             String JavaDoc [] labels = (String JavaDoc[]) columnLabels.get(column);
229             properties[i] = new ColumnDescriptor(column, String JavaDoc.class, labels[0], labels[1]);
230         }
231         tableModel.setProperties(properties);
232     }
233
234     void setTableModel(SyncFileNode [] nodes) {
235         this.nodes = nodes;
236         tableModel.setNodes(nodes);
237     }
238
239     void focus() {
240         table.requestFocus();
241     }
242
243     private static class ColumnDescriptor extends ReadOnly {
244         
245         public ColumnDescriptor(String JavaDoc name, Class JavaDoc type, String JavaDoc displayName, String JavaDoc shortDescription) {
246             super(name, type, displayName, shortDescription);
247         }
248
249         public Object JavaDoc getValue() throws IllegalAccessException JavaDoc, InvocationTargetException JavaDoc {
250             return null;
251         }
252     }
253
254     private void showPopup(final MouseEvent JavaDoc e) {
255         int row = table.rowAtPoint(e.getPoint());
256         if (row != -1) {
257             boolean makeRowSelected = true;
258             int [] selectedrows = table.getSelectedRows();
259
260             for (int i = 0; i < selectedrows.length; i++) {
261                 if (row == selectedrows[i]) {
262                     makeRowSelected = false;
263                     break;
264                 }
265             }
266             if (makeRowSelected) {
267                 table.getSelectionModel().setSelectionInterval(row, row);
268             }
269         }
270         SwingUtilities.invokeLater(new Runnable JavaDoc() {
271             public void run() {
272                 // invoke later so the selection on the table will be set first
273
JPopupMenu menu = getPopup();
274                 menu.show(table, e.getX(), e.getY());
275             }
276         });
277     }
278
279     private void showPopup(Point JavaDoc p) {
280         JPopupMenu menu = getPopup();
281         menu.show(table, p.x, p.y);
282     }
283     
284     /**
285      * Constructs contextual Menu: File Node
286         <pre>
287         Open
288         -------------------
289         Diff (default action)
290         Update
291         Commit...
292         --------------------
293         Conflict Resolved (on conflicting file)
294         --------------------
295         Blame
296         Show History...
297         --------------------
298         Revert Modifications (Revert Delete)(Delete)
299         Exclude from Commit (Include in Commit)
300         Ignore (Unignore)
301         </pre>
302      */

303     private JPopupMenu getPopup() {
304
305         JPopupMenu menu = new JPopupMenu();
306         JMenuItem item;
307         
308         item = menu.add(new OpenInEditorAction());
309         Mnemonics.setLocalizedText(item, item.getText());
310         menu.add(new JSeparator());
311         item = menu.add(new SystemActionBridge(SystemAction.get(DiffAction.class), actionString("CTL_PopupMenuItem_Diff"))); // NOI18N
312
Mnemonics.setLocalizedText(item, item.getText());
313         item = menu.add(new SystemActionBridge(SystemAction.get(UpdateAction.class), actionString("CTL_PopupMenuItem_Update"))); // NOI18N
314
Mnemonics.setLocalizedText(item, item.getText());
315         item = menu.add(new SystemActionBridge(SystemAction.get(CommitAction.class), actionString("CTL_PopupMenuItem_Commit"))); // NOI18N
316
Mnemonics.setLocalizedText(item, item.getText());
317         
318         menu.add(new JSeparator());
319         item = menu.add(new SystemActionBridge(SystemAction.get(ConflictResolvedAction.class), org.openide.util.NbBundle.getMessage(SyncTable.class, "CTL_PopupMenuItem_ConflictResolved"))); // NOI18N
320
Mnemonics.setLocalizedText(item, item.getText());
321                 
322         menu.add(new JSeparator());
323         item = menu.add(new SystemActionBridge(SystemAction.get(BlameAction.class),
324                                                ((BlameAction)SystemAction.get(BlameAction.class)).visible(null) ?
325                                                actionString("CTL_PopupMenuItem_HideBlame") : // NOI18N
326
actionString("CTL_PopupMenuItem_Blame"))); // NOI18N
327
Mnemonics.setLocalizedText(item, item.getText());
328         
329         item = menu.add(new SystemActionBridge(SystemAction.get(SearchHistoryAction.class), actionString("CTL_PopupMenuItem_SearchHistory"))); // NOI18N
330
Mnemonics.setLocalizedText(item, item.getText());
331
332         menu.add(new JSeparator());
333         String JavaDoc label;
334         ExcludeFromCommitAction exclude = (ExcludeFromCommitAction) SystemAction.get(ExcludeFromCommitAction.class);
335         if (exclude.getActionStatus(null) == exclude.INCLUDING) {
336             label = org.openide.util.NbBundle.getMessage(SyncTable.class, "CTL_PopupMenuItem_IncludeInCommit"); // NOI18N
337
} else {
338             label = org.openide.util.NbBundle.getMessage(SyncTable.class, "CTL_PopupMenuItem_ExcludeFromCommit"); // NOI18N
339
}
340         item = menu.add(new SystemActionBridge(exclude, label));
341         Mnemonics.setLocalizedText(item, item.getText());
342         
343         Action revertAction;
344         boolean allLocallyNew = true;
345         boolean allLocallyDeleted = true;
346         FileStatusCache cache = Subversion.getInstance().getStatusCache();
347         File JavaDoc [] files = SvnUtils.getCurrentContext(null).getFiles();
348         
349         for (int i = 0; i < files.length; i++) {
350             File JavaDoc file = files[i];
351             FileInformation info = cache.getStatus(file);
352             if ((info.getStatus() & DeleteLocalAction.LOCALLY_DELETABLE_MASK) == 0 ) {
353                 allLocallyNew = false;
354             }
355             if (info.getStatus() != FileInformation.STATUS_VERSIONED_DELETEDLOCALLY && info.getStatus() != FileInformation.STATUS_VERSIONED_REMOVEDLOCALLY) {
356                 allLocallyDeleted = false;
357             }
358         }
359         if (allLocallyNew) {
360             SystemAction systemAction = SystemAction.get(DeleteLocalAction.class);
361             revertAction = new SystemActionBridge(systemAction, actionString("CTL_PopupMenuItem_Delete")); // NOI18N
362
} else if (allLocallyDeleted) {
363             revertAction = new SystemActionBridge(SystemAction.get(RevertModificationsAction.class), actionString("CTL_PopupMenuItem_RevertDelete")); // NOI18N
364
} else {
365             revertAction = new SystemActionBridge(SystemAction.get(RevertModificationsAction.class), actionString("CTL_PopupMenuItem_GetClean")); // NOI18N
366
}
367         item = menu.add(revertAction);
368         Mnemonics.setLocalizedText(item, item.getText());
369
370 // item = menu.add(new SystemActionBridge(SystemAction.get(ResolveConflictsAction.class), actionString("CTL_PopupMenuItem_ResolveConflicts"))); // NOI18N
371
// Mnemonics.setLocalizedText(item, item.getText());
372

373         Action ignoreAction = new SystemActionBridge(SystemAction.get(IgnoreAction.class),
374            ((IgnoreAction)SystemAction.get(IgnoreAction.class)).getActionStatus(files) == IgnoreAction.UNIGNORING ?
375            actionString("CTL_PopupMenuItem_Unignore") : // NOI18N
376
actionString("CTL_PopupMenuItem_Ignore")); // NOI18N
377
item = menu.add(ignoreAction);
378         Mnemonics.setLocalizedText(item, item.getText());
379
380         return menu;
381     }
382
383     /**
384      * Workaround.
385      * I18N Test Wizard searches for keys in syncview package Bundle.properties
386      */

387     private String JavaDoc actionString(String JavaDoc key) {
388         ResourceBundle actionsLoc = NbBundle.getBundle(Annotator.class);
389         return actionsLoc.getString(key);
390     }
391     
392     public void mouseEntered(MouseEvent JavaDoc e) {
393     }
394
395     public void mouseExited(MouseEvent JavaDoc e) {
396     }
397
398     public void mousePressed(MouseEvent JavaDoc e) {
399         if (e.isPopupTrigger()) {
400             showPopup(e);
401         }
402     }
403
404     public void mouseReleased(MouseEvent JavaDoc e) {
405         if (e.isPopupTrigger()) {
406             showPopup(e);
407         }
408     }
409
410     public void mouseClicked(MouseEvent JavaDoc e) {
411         if (SwingUtilities.isLeftMouseButton(e) && MouseUtils.isDoubleClick(e)) {
412             int row = table.rowAtPoint(e.getPoint());
413             if (row == -1) return;
414             row = sorter.modelIndex(row);
415             Action action = nodes[row].getPreferredAction();
416             if (action == null || !action.isEnabled()) action = new OpenInEditorAction();
417             if (action.isEnabled()) {
418                 action.actionPerformed(new ActionEvent JavaDoc(this, 0, "")); // NOI18N
419
}
420         }
421     }
422
423     public void valueChanged(ListSelectionEvent JavaDoc e) {
424         List<SyncFileNode> selectedNodes = new ArrayList<SyncFileNode>();
425         ListSelectionModel selectionModel = table.getSelectionModel();
426         final TopComponent tc = (TopComponent) SwingUtilities.getAncestorOfClass(TopComponent.class, table);
427         if (tc == null) return; // table is no longer in component hierarchy
428

429         int min = selectionModel.getMinSelectionIndex();
430         if (min != -1) {
431             int max = selectionModel.getMaxSelectionIndex();
432             for (int i = min; i <= max; i++) {
433                 if (selectionModel.isSelectedIndex(i)) {
434                     int idx = sorter.modelIndex(i);
435                     selectedNodes.add(nodes[idx]);
436                 }
437             }
438         }
439         // this method may be called outside of AWT if a node fires change events from some other thread, see #79174
440
final Node [] nodes = selectedNodes.toArray(new Node[selectedNodes.size()]);
441         if (SwingUtilities.isEventDispatchThread()) {
442             tc.setActivatedNodes(nodes);
443         } else {
444             SwingUtilities.invokeLater(new Runnable JavaDoc() {
445                 public void run() {
446                     tc.setActivatedNodes(nodes);
447                 }
448             });
449         }
450     }
451     
452     private class SyncTableCellRenderer extends DefaultTableCellRenderer JavaDoc {
453         
454         private FilePathCellRenderer pathRenderer = new FilePathCellRenderer();
455         
456         public Component getTableCellRendererComponent(JTable table, Object JavaDoc value, boolean isSelected, boolean hasFocus, int row, int column) {
457             Component renderer;
458             int modelColumnIndex = table.convertColumnIndexToModel(column);
459             if (modelColumnIndex == 0) {
460                 SyncFileNode node = nodes[sorter.modelIndex(row)];
461                 if (!isSelected) {
462                     value = "<html>" + node.getHtmlDisplayName(); // NOI18N
463
}
464                 if (SvnModuleConfig.getDefault().isExcludedFromCommit(node.getFile().getAbsolutePath())) {
465                     String JavaDoc nodeName = node.getDisplayName();
466                     if (isSelected) {
467                         value = "<html><s>" + nodeName + "</s></html>"; // NOI18N
468
} else {
469                         value = "<html><s>" + Subversion.getInstance().getAnnotator().annotateNameHtml(nodeName, node.getFileInformation(), null) + "</s>"; // NOI18N
470
}
471                 }
472             }
473             if (modelColumnIndex == 2) {
474                 renderer = pathRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
475             } else {
476                 renderer = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
477             }
478             if (renderer instanceof JComponent) {
479                 String JavaDoc path = nodes[sorter.modelIndex(row)].getFile().getAbsolutePath();
480                 ((JComponent) renderer).setToolTipText(path);
481             }
482             return renderer;
483         }
484     }
485 }
486
Popular Tags