1 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 ; 50 import javax.swing.event.ListSelectionListener ; 51 import javax.swing.event.ListSelectionEvent ; 52 import javax.swing.event.AncestorListener ; 53 import javax.swing.event.AncestorEvent ; 54 import java.lang.reflect.InvocationTargetException ; 55 import java.awt.event.MouseListener ; 56 import java.awt.event.MouseEvent ; 57 import java.awt.event.ActionEvent ; 58 import java.awt.event.KeyEvent ; 59 import java.awt.Component ; 60 import java.awt.Color ; 61 import java.awt.Point ; 62 import java.util.*; 63 import java.io.File ; 64 import org.netbeans.modules.versioning.util.SystemActionBridge; 65 66 73 class SyncTable implements MouseListener , ListSelectionListener , AncestorListener { 74 75 private NodeTableModel tableModel; 76 private JTable table; 77 private JScrollPane component; 78 private SyncFileNode [] nodes = new SyncFileNode[0]; 79 80 private String [] tableColumns; 81 private TableSorter sorter; 82 83 86 private static final Map<String , String []> columnLabels = new HashMap<String , String []>(4); 87 { 88 ResourceBundle loc = NbBundle.getBundle(SyncTable.class); 89 columnLabels.put(SyncFileNode.COLUMN_NAME_BRANCH, new String [] { 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 [] { 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 [] { 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 [] { 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 o1, Object o2) { 105 Node.Property p1 = (Node.Property) o1; 106 Node.Property p2 = (Node.Property) o2; 107 String sk1 = (String ) p1.getValue("sortkey"); if (sk1 != null) { 109 String sk2 = (String ) p2.getValue("sortkey"); return sk1.compareToIgnoreCase(sk2); 111 } else { 112 try { 113 String s1 = (String ) p1.getValue(); 114 String s2 = (String ) p2.getValue(); 115 return s1.compareToIgnoreCase(s2); 116 } catch (Exception 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 borderColor = UIManager.getColor("scrollpane_border"); if (borderColor == null) borderColor = UIManager.getColor("controlShadow"); 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")); table.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(SyncTable.class, "ACSD_VersioningTable")); setColumns(new String [] { 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 e) { 151 showPopup(org.netbeans.modules.versioning.util.Utils.getPositionForPopup(table)); 152 } 153 }); 154 } 155 156 void setDefaultColumnSizes() { 157 SwingUtilities.invokeLater(new Runnable () { 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 event) { 182 setDefaultColumnSizes(); 183 } 184 185 public void ancestorMoved(AncestorEvent event) { 186 } 187 188 public void ancestorRemoved(AncestorEvent 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 209 final void setColumns(String [] 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 [] columns) { 225 Node.Property [] properties = new Node.Property[columns.length]; 226 for (int i = 0; i < columns.length; i++) { 227 String column = columns[i]; 228 String [] labels = (String []) columnLabels.get(column); 229 properties[i] = new ColumnDescriptor(column, String .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 name, Class type, String displayName, String shortDescription) { 246 super(name, type, displayName, shortDescription); 247 } 248 249 public Object getValue() throws IllegalAccessException , InvocationTargetException { 250 return null; 251 } 252 } 253 254 private void showPopup(final MouseEvent 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 () { 271 public void run() { 272 JPopupMenu menu = getPopup(); 274 menu.show(table, e.getX(), e.getY()); 275 } 276 }); 277 } 278 279 private void showPopup(Point p) { 280 JPopupMenu menu = getPopup(); 281 menu.show(table, p.x, p.y); 282 } 283 284 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"))); Mnemonics.setLocalizedText(item, item.getText()); 313 item = menu.add(new SystemActionBridge(SystemAction.get(UpdateAction.class), actionString("CTL_PopupMenuItem_Update"))); Mnemonics.setLocalizedText(item, item.getText()); 315 item = menu.add(new SystemActionBridge(SystemAction.get(CommitAction.class), actionString("CTL_PopupMenuItem_Commit"))); 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"))); 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") : actionString("CTL_PopupMenuItem_Blame"))); Mnemonics.setLocalizedText(item, item.getText()); 328 329 item = menu.add(new SystemActionBridge(SystemAction.get(SearchHistoryAction.class), actionString("CTL_PopupMenuItem_SearchHistory"))); Mnemonics.setLocalizedText(item, item.getText()); 331 332 menu.add(new JSeparator()); 333 String 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"); } else { 338 label = org.openide.util.NbBundle.getMessage(SyncTable.class, "CTL_PopupMenuItem_ExcludeFromCommit"); } 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 [] files = SvnUtils.getCurrentContext(null).getFiles(); 348 349 for (int i = 0; i < files.length; i++) { 350 File 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")); } else if (allLocallyDeleted) { 363 revertAction = new SystemActionBridge(SystemAction.get(RevertModificationsAction.class), actionString("CTL_PopupMenuItem_RevertDelete")); } else { 365 revertAction = new SystemActionBridge(SystemAction.get(RevertModificationsAction.class), actionString("CTL_PopupMenuItem_GetClean")); } 367 item = menu.add(revertAction); 368 Mnemonics.setLocalizedText(item, item.getText()); 369 370 373 Action ignoreAction = new SystemActionBridge(SystemAction.get(IgnoreAction.class), 374 ((IgnoreAction)SystemAction.get(IgnoreAction.class)).getActionStatus(files) == IgnoreAction.UNIGNORING ? 375 actionString("CTL_PopupMenuItem_Unignore") : actionString("CTL_PopupMenuItem_Ignore")); item = menu.add(ignoreAction); 378 Mnemonics.setLocalizedText(item, item.getText()); 379 380 return menu; 381 } 382 383 387 private String actionString(String key) { 388 ResourceBundle actionsLoc = NbBundle.getBundle(Annotator.class); 389 return actionsLoc.getString(key); 390 } 391 392 public void mouseEntered(MouseEvent e) { 393 } 394 395 public void mouseExited(MouseEvent e) { 396 } 397 398 public void mousePressed(MouseEvent e) { 399 if (e.isPopupTrigger()) { 400 showPopup(e); 401 } 402 } 403 404 public void mouseReleased(MouseEvent e) { 405 if (e.isPopupTrigger()) { 406 showPopup(e); 407 } 408 } 409 410 public void mouseClicked(MouseEvent 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 (this, 0, "")); } 420 } 421 } 422 423 public void valueChanged(ListSelectionEvent 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; 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 final Node [] nodes = selectedNodes.toArray(new Node[selectedNodes.size()]); 441 if (SwingUtilities.isEventDispatchThread()) { 442 tc.setActivatedNodes(nodes); 443 } else { 444 SwingUtilities.invokeLater(new Runnable () { 445 public void run() { 446 tc.setActivatedNodes(nodes); 447 } 448 }); 449 } 450 } 451 452 private class SyncTableCellRenderer extends DefaultTableCellRenderer { 453 454 private FilePathCellRenderer pathRenderer = new FilePathCellRenderer(); 455 456 public Component getTableCellRendererComponent(JTable table, Object 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(); } 464 if (SvnModuleConfig.getDefault().isExcludedFromCommit(node.getFile().getAbsolutePath())) { 465 String nodeName = node.getDisplayName(); 466 if (isSelected) { 467 value = "<html><s>" + nodeName + "</s></html>"; } else { 469 value = "<html><s>" + Subversion.getInstance().getAnnotator().annotateNameHtml(nodeName, node.getFileInformation(), null) + "</s>"; } 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 path = nodes[sorter.modelIndex(row)].getFile().getAbsolutePath(); 480 ((JComponent) renderer).setToolTipText(path); 481 } 482 return renderer; 483 } 484 } 485 } 486 | Popular Tags |