1 19 package org.netbeans.modules.localhistory.ui.view; 20 21 import java.awt.BorderLayout ; 22 import java.awt.GridBagLayout ; 23 import java.awt.Point ; 24 import java.beans.PropertyChangeEvent ; 25 import java.beans.PropertyChangeListener ; 26 import java.beans.PropertyVetoException ; 27 import java.io.File ; 28 import java.lang.reflect.InvocationTargetException ; 29 import java.util.ArrayList ; 30 import java.util.List ; 31 import java.util.ResourceBundle ; 32 import javax.swing.BorderFactory ; 33 import javax.swing.JPanel ; 34 import javax.swing.JTable ; 35 import javax.swing.JTree ; 36 import javax.swing.SwingUtilities ; 37 import javax.swing.tree.DefaultTreeCellRenderer ; 38 import javax.swing.tree.TreePath ; 39 import javax.swing.tree.TreeSelectionModel ; 40 import org.netbeans.modules.localhistory.LocalHistory; 41 import org.netbeans.modules.localhistory.store.LocalHistoryStore; 42 import org.netbeans.modules.localhistory.store.StoreEntry; 43 import org.openide.explorer.ExplorerManager; 44 import org.openide.explorer.view.TreeTableView; 45 import org.openide.nodes.Node; 46 import org.openide.nodes.PropertySupport; 47 import org.openide.util.NbBundle; 48 import org.openide.util.RequestProcessor; 49 50 54 public class LocalHistoryFileView implements PropertyChangeListener { 55 56 private FileTablePanel tablePanel; 57 private File [] files; 58 59 private RequestProcessor.Task refreshTask; 60 private RefreshTable refreshTable; 61 62 public LocalHistoryFileView(File [] files) { 63 this(files, -1); 64 } 65 66 public LocalHistoryFileView(File [] files, long toSelect) { 67 tablePanel = new FileTablePanel(); 68 LocalHistory.getInstance().getLocalHistoryStore().addPropertyChangeListener(this); this.files = files; 70 refreshTablePanel(toSelect); 71 } 72 73 public void propertyChange(PropertyChangeEvent evt) { 74 if(LocalHistoryStore.PROPERTY_CHANGED.equals(evt.getPropertyName())) { 75 storeChanged(evt); 76 } 77 } 78 79 public ExplorerManager getExplorerManager() { 80 return tablePanel.getExplorerManager(); 81 } 82 83 public StoreEntry[] getSelectedEntries() { 84 Node[] nodes = tablePanel.getExplorerManager().getSelectedNodes(); 85 if(nodes != null && nodes.length > 0) { 86 List <StoreEntry> entries = new ArrayList <StoreEntry>(); 87 for(Node node : nodes) { 88 entries.add(node.getLookup().lookup(StoreEntry.class)); 89 } 90 return entries.toArray(new StoreEntry[entries.size()]); 91 } 92 return new StoreEntry[0]; 93 } 94 95 public JPanel getPanel() { 96 return tablePanel; 97 } 98 99 public void close() { 100 LocalHistory.getInstance().getLocalHistoryStore().removePropertyChangeListener(this); 101 } 102 103 private Node getNode(long ts) { 104 if(ts == -1) return null; 105 Node root = tablePanel.getExplorerManager().getRootContext(); 106 Node[] dayNodes = root.getChildren().getNodes(); 107 if(dayNodes != null && dayNodes.length > 0) { 108 for(Node dayNode : dayNodes) { 109 Node[] entryNodes = dayNode.getChildren().getNodes(); 110 if(entryNodes != null && entryNodes.length > 0) { 111 for(Node entryNode : entryNodes) { 112 StoreEntry se = entryNode.getLookup().lookup(StoreEntry.class); 113 if(se != null && se.getTimestamp() == ts) { 114 return entryNode; 115 } 116 } 117 } 118 } 119 } 120 return null; 121 } 122 123 private void storeChanged(PropertyChangeEvent evt) { 124 Object newValue = evt.getNewValue(); 125 Object oldValue = evt.getOldValue(); 126 if( newValue != null && contains( (File ) newValue ) || 127 oldValue != null && contains( (File ) oldValue ) ) 128 { 129 refreshTablePanel(-1); 130 } 131 } 132 133 private boolean contains(File file) { 134 for(File f : files) { 135 if(f.equals(file)) { 136 return true; 137 } 138 } 139 return false; 140 } 141 142 private void refreshTablePanel(long toSelect) { 143 if(refreshTask == null) { 144 refreshTable = new RefreshTable(); 145 RequestProcessor rp = new RequestProcessor(); 146 refreshTask = rp.create(refreshTable); 147 } 148 refreshTable.setup(toSelect); 149 refreshTask.schedule(100); 150 } 151 152 private void selectNodes(final Node[] nodes) { 153 SwingUtilities.invokeLater(new Runnable () { 154 public void run() { 155 try { 156 tablePanel.getExplorerManager().setSelectedNodes(nodes); 157 } catch (PropertyVetoException ex) { 158 } 160 } 161 }); 162 } 163 164 168 private class RefreshTable implements Runnable { 169 private long toSelect; 170 void setup(long toSelect) { 171 this.toSelect = toSelect; 172 } 173 public void run() { 174 Node oldExploredContext = getExplorerManager().getExploredContext(); 175 Node root = LocalHistoryRootNode.createRootNode(files); 176 177 Node[] oldSelection = getExplorerManager().getSelectedNodes(); 178 tablePanel.getExplorerManager().setRootContext(root); 179 180 if(toSelect > -1) { 181 Node node = getNode(toSelect); 182 if(node != null) { 183 oldSelection = new Node[] { node }; 184 } 185 } 186 187 if (oldSelection != null && oldSelection.length > 0) { 188 Node[] newSelection = getEqualNodes(root, oldSelection); 189 if(newSelection.length > 0) { 190 selectNodes(newSelection); 191 } else { 192 if(oldExploredContext != null) { 193 Node[] newExploredContext = getEqualNodes(root, new Node[] { oldExploredContext }); 194 if(newExploredContext.length > 0) { 195 selectFirstNeighborNode(newExploredContext[0], oldSelection[0]); 196 } 197 } 198 } 199 } else { 200 selectFirstNode(root); 201 } 202 tablePanel.revalidate(); 203 tablePanel.repaint(); 204 } 205 206 private Node[] getEqualNodes(Node root, Node[] oldNodes) { 207 List <Node> ret = new ArrayList <Node>(); 208 for(Node on : oldNodes) { 209 Node node = findEqualInChildren(root, on); 210 if(node != null) { 211 ret.add(node); 212 } 213 } 214 return ret.toArray(new Node[ret.size()]); 215 } 216 217 private Node findEqualInChildren(Node node, Node toFind) { 218 Node[] children = node.getChildren().getNodes(); 219 for(Node child : children) { 220 if(toFind.getName().equals(child.getName())) { 221 return child; 222 } 223 Node n = findEqualInChildren(child, toFind); 224 if(n != null) { 225 return n; 226 } 227 } 228 return null; 229 } 230 231 private void selectFirstNode(final Node root) { 232 Node[] dateFolders = root.getChildren().getNodes(); 233 if (dateFolders != null && dateFolders.length > 0) { 234 final Node[] nodes = dateFolders[0].getChildren().getNodes(); 235 if (nodes != null && nodes.length > 0) { 236 selectNodes(new Node[]{ nodes[0] }); 237 } 238 } 239 } 240 241 private void selectFirstNeighborNode(Node context, Node oldSelection) { 242 tablePanel.getExplorerManager().setExploredContext(context); 243 Node[] children = context.getChildren().getNodes(); 244 if(children.length > 0 && children[0] instanceof Comparable ) { 245 Node[] newSelection = new Node[] { children[0] } ; 246 for(int i = 1; i < children.length; i++) { 247 Comparable c = (Comparable ) children[i]; 248 if( c.compareTo(oldSelection) < 0 ) { 249 newSelection[0] = children[i]; 250 } 251 } 252 selectNodes(newSelection); 253 } 254 } 255 } 256 257 private class FileTablePanel extends JPanel implements ExplorerManager.Provider { 259 260 private final BrowserTreeTableView treeView; 261 private final ExplorerManager manager; 262 263 public FileTablePanel() { 264 manager = new ExplorerManager(); 265 266 setLayout(new GridBagLayout ()); 267 268 treeView = new BrowserTreeTableView(); 269 setLayout(new BorderLayout ()); 270 add(treeView, BorderLayout.CENTER); 271 } 272 273 public ExplorerManager getExplorerManager() { 274 return manager; 275 } 276 277 private class BrowserTreeTableView extends TreeTableView { 278 BrowserTreeTableView() { 279 setupColumns(); 280 281 tree.setShowsRootHandles(true); 282 tree.setRootVisible(false); 283 setDefaultActionAllowed (false); 284 setBorder(BorderFactory.createEtchedBorder()); 285 setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); 288 setPopupAllowed(true); 289 290 DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer (); 291 renderer.setLeafIcon(null); 292 tree.setCellRenderer(renderer); 293 294 } 295 296 JTree getTree() { 297 return tree; 298 } 299 300 JTable getTable() { 301 return treeTable; 302 } 303 304 public void startEditingAtPath(TreePath path) { 305 tree.startEditingAtPath(path); 306 } 307 308 public void addNotify() { 309 super.addNotify(); 310 setDefaultColumnSizes(); 311 } 312 313 private void setupColumns() { 314 ResourceBundle loc = NbBundle.getBundle(FileTablePanel.class); 315 316 Node.Property [] columns = new Node.Property[1]; 317 columns = new Node.Property[1]; 318 columns[0] = new ColumnDescriptor<String >( 319 StoreEntryNode.PROPERTY_NAME_LABEL, 320 String .class, 321 loc.getString("LBL_LocalHistory_Column_Label"), loc.getString("LBL_LocalHistory_Column_Label_Desc")); setProperties(columns); 324 } 325 326 private void setDefaultColumnSizes() { 327 SwingUtilities.invokeLater(new Runnable () { 328 public void run() { 329 int width = getWidth(); 330 treeTable.getColumnModel().getColumn(0).setPreferredWidth(width * 35 / 100); 331 treeTable.getColumnModel().getColumn(1).setPreferredWidth(width * 65 / 100); 332 } 333 }); 334 } 335 } 336 337 int rowAtPoint(Point point) { 338 return treeView.getTable().rowAtPoint(point); 339 } 340 } 341 342 private static class ColumnDescriptor<T> extends PropertySupport.ReadOnly<T> { 343 public ColumnDescriptor(String name, Class <T> type, String displayName, String shortDescription) { 344 super(name, type, displayName, shortDescription); 345 } 346 public T getValue() throws IllegalAccessException , InvocationTargetException { 347 return null; 348 } 349 } 350 } 351 | Popular Tags |