1
2
3
4
5
6
7
8
9
10
11
12
13 package org.abstracthorizon.aequo.file;
14
15 import java.awt.BorderLayout;
16 import java.awt.Color;
17 import java.awt.Component;
18 import java.awt.Dimension;
19 import java.awt.Rectangle;
20 import java.awt.event.ActionEvent;
21 import java.awt.event.ActionListener;
22 import java.awt.event.ComponentEvent;
23 import java.awt.event.ComponentListener;
24 import java.awt.event.FocusEvent;
25 import java.awt.event.FocusListener;
26 import java.awt.event.MouseEvent;
27 import java.awt.event.MouseListener;
28 import java.io.File;
29 import java.io.IOException;
30 import java.text.Format;
31 import java.text.SimpleDateFormat;
32 import java.util.ArrayList;
33 import java.util.List;
34
35 import javax.swing.Action;
36 import javax.swing.BorderFactory;
37 import javax.swing.Icon;
38 import javax.swing.JComponent;
39 import javax.swing.JLabel;
40 import javax.swing.JMenu;
41 import javax.swing.JMenuBar;
42 import javax.swing.JMenuItem;
43 import javax.swing.JPanel;
44 import javax.swing.JPopupMenu;
45 import javax.swing.JSeparator;
46 import javax.swing.JSplitPane;
47 import javax.swing.JTable;
48 import javax.swing.JToolBar;
49 import javax.swing.ListSelectionModel;
50 import javax.swing.UIManager;
51 import javax.swing.border.BevelBorder;
52 import javax.swing.event.ListSelectionEvent;
53 import javax.swing.event.ListSelectionListener;
54 import javax.swing.table.DefaultTableCellRenderer;
55 import javax.swing.table.TableColumn;
56 import javax.swing.table.TableColumnModel;
57
58 import org.abstracthorizon.aequo.CompareEntry;
59 import org.abstracthorizon.aequo.GlobalContext;
60 import org.abstracthorizon.aequo.action.AboutAction;
61 import org.abstracthorizon.aequo.action.CloseWindowAction;
62 import org.abstracthorizon.aequo.file.action.FileBaseAction;
63 import org.abstracthorizon.aequo.file.action.NewSessionAction;
64 import org.abstracthorizon.aequo.file.action.RefreshSubtreeAction;
65 import org.abstracthorizon.aequo.gui.AbstractComparePanel;
66 import org.abstracthorizon.aequo.gui.DropDownBoxComponent;
67 import org.abstracthorizon.aequo.gui.RowFocusBorder;
68 import org.abstracthorizon.aequo.text.TextCompareEntry;
69 import org.abstracthorizon.aequo.text.action.ShowComparisonAction;
70 import org.abstracthorizon.aequo.util.Preferences;
71 import org.abstracthorizon.aequo.util.StringUtils;
72 import org.abstracthorizon.aequo.util.filters.Filter;
73 import org.abstracthorizon.aequo.util.prefs.RecentFileEntry;
74 import org.abstracthorizon.aequo.util.prefs.RecentFilters;
75
76
77
78
79
80
81 public class TableFileComparePanel extends AbstractComparePanel<File, FileCompareEntry> {
82
83
84 protected JSplitPane splitPane;
85
86
87 protected JPanel leftBottomBar;
88
89
90 protected JPanel rightBottomBar;
91
92
93 protected JLabel leftStatus;
94
95
96 protected JLabel rightStatus;
97
98
99 protected JLabel bottomStatus;
100
101
102 protected Icon fileIcon;
103
104
105 protected Icon directoryIcon;
106
107
108 protected FilesModel compareModel;
109
110
111 public static final Format dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
112
113
114
115
116
117
118 public TableFileComparePanel(GlobalContext context, FilesModel compareModel) {
119 super(context, compareModel);
120 this.compareModel = compareModel;
121 this.context = context;
122
123 directoryIcon = UIManager.getIcon("FileView.directoryIcon");
124 fileIcon = UIManager.getIcon("FileView.fileIcon");
125 }
126
127
128
129
130 public void initialise() {
131 splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
132
133 super.initialise();
134
135 leftBottomBar = new JPanel(new BorderLayout());
136 rightBottomBar = new JPanel(new BorderLayout());
137
138 leftStatus = new JLabel(" ");
139 rightStatus = new JLabel(" ");
140
141 leftStatus.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
142 rightStatus.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
143
144 leftStatus.setPreferredSize(new Dimension(50, leftStatus.getPreferredSize().height));
145 rightStatus.setPreferredSize(new Dimension(50, rightStatus.getPreferredSize().height));
146
147 leftBottomBar.add(leftStatus, BorderLayout.CENTER);
148 rightBottomBar.add(rightStatus, BorderLayout.CENTER);
149
150 bottomLeftPanel.add(leftBottomBar, BorderLayout.CENTER);
151 bottomRightPanel.add(rightBottomBar, BorderLayout.CENTER);
152
153 bottomStatus = new JLabel(" ");
154 bottomStatus.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
155 add(bottomStatus, BorderLayout.SOUTH);
156
157 splitPane.setLeftComponent(leftPanel);
158 splitPane.setRightComponent(rightPanel);
159 splitPane.setResizeWeight(0.5d);
160 add(splitPane, BorderLayout.CENTER);
161 splitPane.setDividerLocation(0.5d);
162
163 compareModel.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
164
165 public void valueChanged(ListSelectionEvent e) {
166 if (!e.getValueIsAdjusting()) {
167 ListSelectionModel selModel = compareModel.getSelectionModel();
168 if (selModel.isSelectionEmpty()) {
169
170 leftStatus.setText("");
171 rightStatus.setText("");
172 } else {
173 int leftDir = 0;
174 int rightDir = 0;
175 int leftFiles = 0;
176 int rightFiles = 0;
177 long leftSize = 0;
178 long rightSize = 0;
179
180 int min = selModel.getMinSelectionIndex();
181 int max = selModel.getMaxSelectionIndex();
182 for (int i = min; i <= max; i++) {
183 if (selModel.isSelectedIndex(i)) {
184 FileCompareEntry entry = compareModel.get(i);
185 if (entry.hasChildren()) {
186 if (entry.getData(0).exists()) {
187 leftDir++;
188 leftSize = leftSize + entry.getSize(0);
189 }
190 if (entry.getData(1).exists()) {
191 rightDir++;
192 rightSize = rightSize + entry.getSize(1);
193 }
194 } else {
195 if (entry.getData(0).exists()) {
196 leftFiles++;
197 leftSize = leftSize + entry.getSize(0);
198 }
199 if (entry.getData(1).exists()) {
200 rightFiles++;
201 rightSize = rightSize + entry.getSize(1);
202 }
203 }
204 }
205 }
206
207 leftStatus.setText(leftDir + " dirs " + leftFiles + " files in total of " + StringUtils.normaliseSize(leftSize));
208 rightStatus.setText(rightDir + " dirs " + rightFiles + " files in total of " + StringUtils.normaliseSize(rightSize));
209
210 }
211 }
212 }
213 });
214
215 }
216
217
218
219
220 protected void createActions() {
221 createCachedAction("ShowComparisonAction");
222 createCachedAction("RefreshSubtreeAction");
223 createCachedAction("BinaryComparisonAction");
224 createCachedAction("NewSessionAction");
225
226 createCachedColumnActions("CopyToAction");
227 createCachedColumnActions("MoveToAction");
228 createCachedColumnActions("TouchAction");
229
230 createCachedColumnActions("RemoveFromViewAction");
231 createCachedColumnActions("DeleteAction");
232
233 createCachedAction("CollapseAction");
234 createCachedAction("ExpandAction");
235 createCachedAction("ExpandAllAction");
236
237 createCachedAction("SelectAllAction");
238 createCachedAction("SelectFilesAction");
239 }
240
241
242
243
244 protected void setUpColors() {
245 foreGrounds.put(CompareEntry.EMPTY, Color.BLACK);
246 backGrounds.put(CompareEntry.EMPTY, new Color(232, 232, 232));
247
248 foreGrounds.put(CompareEntry.EQUAL, Color.BLACK);
249 backGrounds.put(CompareEntry.EQUAL, Color.WHITE);
250
251 foreGrounds.put(CompareEntry.LESS, Color.BLACK);
252 backGrounds.put(CompareEntry.LESS, new Color(255, 208, 208));
253
254 foreGrounds.put(CompareEntry.GREATER, Color.BLACK);
255 backGrounds.put(CompareEntry.GREATER, new Color(208, 208, 255));
256
257 foreGrounds.put(CompareEntry.DIFFERENT, Color.BLACK);
258 backGrounds.put(CompareEntry.DIFFERENT, new Color(255, 128, 128));
259
260 foreGrounds.put(TextCompareEntry.SIMILAR, Color.BLACK);
261 backGrounds.put(TextCompareEntry.SIMILAR, new Color(255, 224, 224));
262
263 foreGrounds.put(TextCompareEntry.CHANGED, Color.BLACK);
264 backGrounds.put(TextCompareEntry.CHANGED, new Color(255, 255, 180));
265 }
266
267
268
269
270
271 protected JComponent createLeftComponent() {
272 JTable table = new JTable((FilesModel)compareModel);
273
274 setUpTable(table);
275 FileCellRenderer renderer = new FileCellRenderer(0);
276 table.setDefaultRenderer(FileCompareEntry.class, renderer);
277
278 return table;
279 }
280
281
282
283
284
285 protected JComponent createRightComponent() {
286 JTable table = new JTable((FilesModel)compareModel);
287
288 setUpTable(table);
289 FileCellRenderer renderer = new FileCellRenderer(1);
290 table.setDefaultRenderer(FileCompareEntry.class, renderer);
291
292 return table;
293 }
294
295
296
297
298
299 protected void setUpTable(JTable table) {
300 table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
301 table.setSelectionModel(compareModel.getSelectionModel());
302 table.addFocusListener(tableRowFocusListener);
303 table.setShowGrid(false);
304 table.setShowVerticalLines(false);
305 table.setShowHorizontalLines(false);
306 table.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
307
308 TableColumnModel columnModel = table.getColumnModel();
309 columnModel.setColumnSelectionAllowed(false);
310
311 TableColumn col0 = columnModel.getColumn(0);
312 col0.setPreferredWidth(-1);
313 col0.setModelIndex(0);
314
315 TableColumn col1 = columnModel.getColumn(1);
316 int col1Width = table.getFontMetrics(table.getFont()).stringWidth("0000000") + 2;
317 col1.setPreferredWidth(col1Width);
318 col1.setModelIndex(1);
319
320 TableColumn col2 = columnModel.getColumn(2);
321 int col2Width = table.getFontMetrics(table.getFont()).stringWidth("00/00/0000 00:00:00") + 2;
322 col2.setPreferredWidth(col2Width);
323 col2.setModelIndex(2);
324
325 table.addComponentListener(new ComponentListener() {
326
327 boolean first = true;
328
329 public void componentHidden(ComponentEvent e) { }
330
331 public void componentMoved(ComponentEvent e) { }
332
333 public void componentResized(ComponentEvent e) {
334 if (first) {
335 JTable table = (JTable)e.getComponent();
336
337 TableColumnModel columnModel = table.getColumnModel();
338 columnModel.setColumnSelectionAllowed(false);
339
340 int width = table.getWidth() - table.getInsets().left - table.getInsets().right;
341
342 TableColumn col1 = columnModel.getColumn(1);
343 int col1Width = table.getFontMetrics(table.getFont()).stringWidth("00000MB") + 2;
344 col1.setPreferredWidth(col1Width);
345 col1.setModelIndex(1);
346
347 TableColumn col2 = columnModel.getColumn(2);
348 int col2Width = table.getFontMetrics(table.getFont()).stringWidth("00/00/0000 00:00:00") + 2;
349 col2.setPreferredWidth(col2Width);
350 col2.setModelIndex(2);
351
352 TableColumn col0 = columnModel.getColumn(0);
353 col0.setPreferredWidth(width - col1Width - col2Width - 10);
354 col0.setModelIndex(0);
355
356 first = false;
357 }
358 }
359
360 public void componentShown(ComponentEvent e) { }
361
362 });
363 }
364
365
366
367
368 protected void createLists() {
369 super.createLists();
370
371 DoubleClickMouseInputListener doubleClickListener = new DoubleClickMouseInputListener();
372 leftList.addMouseListener(doubleClickListener);
373 rightList.addMouseListener(doubleClickListener);
374
375
376
377
378
379
380 }
381
382
383
384
385
386
387 protected JPopupMenu createActionMenu(int column) {
388 JPopupMenu menu = super.createActionMenu(column);
389
390 menu.add(new DefaultActionMenuItem());
391
392 menu.add(new JSeparator());
393 menu.add(actionsCache.get("RefreshSubtreeAction"));
394 menu.add(actionsCache.get("BinaryComparisonAction"));
395 menu.add(actionsCache.get("NewSessionAction"));
396 menu.add(new JSeparator());
397
398 menu.add(actionsCache.get("CopyToAction"));
399 menu.add(actionsCache.get("MoveToAction"));
400 menu.add(actionsCache.get("TouchAction"));
401 menu.add(new JSeparator());
402
403
404
405
406
407
408 menu.add(actionsCache.get("RemoveFromViewAction"));
409 menu.add(new JSeparator());
410 menu.add(actionsCache.get("DeleteAction"));
411
412 updateCachedActionsColumn(column);
413
414 return menu;
415 }
416
417
418
419
420
421 public void createMenu(JMenuBar menuBar) {
422 super.createMenu(menuBar);
423
424 JMenu fileMenu = obtainMenu("File", menuBar);
425 CloseWindowAction closeAction = new CloseWindowAction();
426 closeAction.setWindow(getEnclosingFrame());
427 JMenuItem closeWindowAction = new JMenuItem(closeAction);
428 fileMenu.add(closeWindowAction, 3);
429
430 JMenu editMenu = obtainMenu("Edit", menuBar);
431 editMenu.add(actionsCache.get("CopyToAction"));
432 editMenu.add(actionsCache.get("MoveToAction"));
433 editMenu.add(actionsCache.get("TouchAction"));
434 editMenu.addSeparator();
435 editMenu.add(actionsCache.get("SelectAllAction"));
436 editMenu.add(actionsCache.get("SelectFilesAction"));
437 editMenu.addSeparator();
438 editMenu.add(actionsCache.get("RemoveFromViewAction"));
439 editMenu.addSeparator();
440 editMenu.add(actionsCache.get("DeleteAction"));
441 editMenu.addChangeListener(new MenuChangeListener());
442
443 JMenu viewMenu = obtainMenu("View", menuBar);
444 menuBar.add(viewMenu);
445 viewMenu.add(createAction("RefreshAllAction"));
446 RefreshSubtreeAction refreshSubtreeAction = (RefreshSubtreeAction)createAction("RefreshSubtreeAction");
447 refreshSubtreeAction.setName("Refresh Subtree");
448 viewMenu.add(refreshSubtreeAction);
449 viewMenu.addChangeListener(new MenuChangeListener());
450
451 JMenu actionMenu = obtainMenu("Action", menuBar);
452 menuBar.add(actionMenu);
453
454 actionMenu.add(new DefaultActionMenuItem());
455 actionMenu.add(actionsCache.get("ExpandAllAction"));
456 actionMenu.addSeparator();
457 actionMenu.add(actionsCache.get("BinaryComparisonAction"));
458 NewSessionAction newSessionAction = (NewSessionAction)createAction("NewSessionAction");
459 newSessionAction.setName("New Session from Element");
460 actionMenu.add(newSessionAction);
461 actionMenu.addChangeListener(new MenuChangeListener());
462
463
464
465
466
467 }
468
469
470
471
472 protected void createPanels() {
473 super.createPanels();
474
475 Preferences prefs = getGlobalContext().getPreferences();
476
477 JToolBar topToolBar = new JToolBar();
478
479 topToolBar.add(createAction("org.abstracthorizon.aequo.action.NewSessionAction"));
480 topToolBar.add(createAction("RefreshAllAction"));
481 List<Filter> filters = RecentFilters.allRecentFilters(prefs);
482 List<String> strings = new ArrayList<String>(filters.size());
483 for (Filter filter : filters) {
484 strings.add(filter.getFilters());
485 }
486
487 DropDownBoxComponent filtersInput = new DropDownBoxComponent("Filters: ", compareModel.getFilter().getFilters(), strings);
488 filtersInput.addActionListener(new ActionListener() {
489 public void actionPerformed(ActionEvent e) {
490 DropDownBoxComponent filtersInput = (DropDownBoxComponent)e.getSource();
491 Filter newFilter = new Filter(filtersInput.getSelected());
492 Filter oldFilter = compareModel.getFilter();
493 if (!newFilter.equals(oldFilter)) {
494 compareModel.setFilter(newFilter);
495 if (oldFilter.hasBeenAdded(newFilter)) {
496 compareModel.filterOut();
497 } else {
498
499 compareModel.refresh();
500 }
501
502
503 Preferences prefs = getGlobalContext().getPreferences();
504 RecentFileEntry fileEntry =
505 new RecentFileEntry(
506 compareModel.getData(0).getAbsolutePath(),
507 compareModel.getData(1).getAbsolutePath(),
508 newFilter.toString());
509
510 if (RecentFilters.writeNew(prefs, newFilter) | RecentFileEntry.writeNew(prefs, fileEntry)) {
511 try {
512 prefs.save();
513 } catch (IOException ex) {
514 ex.printStackTrace();
515 }
516 }
517
518 }
519 }
520 });
521 topToolBar.addSeparator();
522 topToolBar.add(filtersInput);
523 topToolBar.addSeparator();
524 topToolBar.add(new JSeparator());
525 AboutAction aboutAction = (AboutAction)createAction("AboutAction");
526 aboutAction.setName("<=>");
527 topToolBar.add(aboutAction);
528 add(topToolBar, BorderLayout.PAGE_START);
529
530
531 JToolBar leftToolBar = new JToolBar();
532 leftPanel.add(leftToolBar, BorderLayout.NORTH);
533 leftToolBar.add(createAction("ReplaceSideAction", 0));
534 List<String> oldFiles = new ArrayList<String>();
535
536 int max = RecentFileEntry.getNumberOfRecent(prefs);
537 for (int i = 0; i <= max; i++) {
538 RecentFileEntry entry = RecentFileEntry.read(prefs, i);
539 if (!oldFiles.contains(entry.left)) {
540 oldFiles.add(entry.left);
541 }
542 if (!oldFiles.contains(entry.right)) {
543 oldFiles.add(entry.right);
544 }
545 }
546
547 DropDownBoxComponent leftFileInput = new DropDownBoxComponent(compareModel.getData(0).getAbsolutePath(), oldFiles);
548 leftFileInput.addActionListener(new FileDropdownListener(compareModel, 0));
549 leftToolBar.addSeparator();
550 leftToolBar.add(leftFileInput);
551 leftToolBar.addSeparator();
552
553 JToolBar rightToolBar = new JToolBar();
554 rightPanel.add(rightToolBar, BorderLayout.NORTH);
555 rightToolBar.add(createAction("ReplaceSideAction", 1));
556
557 DropDownBoxComponent rightFileInput = new DropDownBoxComponent(compareModel.getData(1).getAbsolutePath(), oldFiles);
558 rightFileInput.addActionListener(new FileDropdownListener(compareModel, 1));
559 rightToolBar.addSeparator();
560 rightToolBar.add(rightFileInput);
561 rightToolBar.addSeparator();
562
563 }
564
565
566
567
568
569 protected void updateAction(Action a) {
570 super.updateAction(a);
571 if (a instanceof FileBaseAction) {
572 FileBaseAction fileBaseAction = (FileBaseAction)a;
573 fileBaseAction.setFilesModel(compareModel);
574 }
575 }
576
577
578
579
580
581 protected void updateMenu(Component[] components) {
582 for (Component c : components) {
583 if (c instanceof DefaultActionMenuItem) {
584 DefaultActionMenuItem item = (DefaultActionMenuItem)c;
585 item.update();
586 }
587 }
588 super.updateMenu(components);
589 }
590
591
592
593
594 protected class FileCellRenderer extends DefaultTableCellRenderer {
595
596
597 private final RowFocusBorder focusBorder = new RowFocusBorder();
598
599
600 protected int modelColumn;
601
602
603
604
605
606 public FileCellRenderer(int modelColumn) {
607 this.modelColumn = modelColumn;
608 setBorder(focusBorder);
609 }
610
611 public Component getTableCellRendererComponent(JTable table, Object value,
612 boolean isSelected, boolean hasFocus, int row, int column) {
613
614 hasFocus = table.hasFocus() && (table.getSelectionModel().getLeadSelectionIndex() == row);
615
616 int columns = table.getColumnCount();
617
618 setFont(table.getFont());
619 setEnabled(table.isEnabled());
620
621 FileCompareEntry entry = (FileCompareEntry)value;
622
623 File file = entry.getData(modelColumn);
624
625 byte result = entry.getStatus(modelColumn);
626 boolean fileExists = file.exists();
627 long fileModifiedDate = file.lastModified();
628 long fileSize = entry.getSize(modelColumn);
629 String name = file.getName();
630
631 if (!fileExists) {
632 result = CompareEntry.EMPTY;
633 }
634
635 if (column == 0) {
636 focusBorder.setLeftMargin(entry.getLevel() * 10);
637
638 if (fileExists) {
639 StringBuffer text = new StringBuffer();
640 text.append(name);
641 setText(text.toString());
642 } else {
643 setText(null);
644 }
645
646 if (file.isDirectory()) {
647 setIcon(directoryIcon);
648 } else if (fileExists) {
649 setIcon(fileIcon);
650 } else {
651 setIcon(null);
652 }
653 setHorizontalAlignment(JLabel.LEFT);
654 } else if (column == 1) {
655 focusBorder.setLeftMargin(0);
656 if (fileExists) {
657 String normalised = StringUtils.normaliseSize(fileSize);
658 setText(normalised);
659 } else {
660 setText("");
661 }
662 setIcon(null);
663 setHorizontalAlignment(JLabel.RIGHT);
664 if (result == CompareEntry.EQUAL) {
665 long[] sizes = entry.getSizes();
666 for (int i = 0; i < sizes.length; i++) {
667 if (i != modelColumn) {
668 if (sizes[i] != fileSize) {
669 result = CompareEntry.SIMILAR;
670 }
671 }
672 }
673 }
674 } else if (column == 2) {
675 focusBorder.setLeftMargin(0);
676 if (fileExists) {
677 setText(dateFormat.format(fileModifiedDate));
678 } else {
679 setText("");
680 }
681 setIcon(null);
682 setHorizontalAlignment(JLabel.LEFT);
683
684 if (result == CompareEntry.EQUAL) {
685 File[] files = entry.getData();
686 for (int i = 0; i < files.length; i++) {
687 if (i != modelColumn) {
688 if (files[i].lastModified() != fileModifiedDate) {
689 result = CompareEntry.SIMILAR;
690 }
691 }
692 }
693 }
694 } else {
695 setText("");
696 setIcon(null);
697 }
698
699 if (columns == 1) {
700 focusBorder.setCellType(RowFocusBorder.ONLY_CELL_IN_ROW);
701 } else if (column == 0) {
702 focusBorder.setCellType(RowFocusBorder.FIRST_CELL_IN_ROW);
703 } else if (column == columns - 1) {
704 focusBorder.setCellType(RowFocusBorder.LAST_CELL_IN_ROW);
705 } else {
706 focusBorder.setCellType(RowFocusBorder.MIDDLE_CELL_IN_ROW);
707 }
708 focusBorder.setFocused(hasFocus);
709
710 Color foreGround = foreGrounds.get(result);
711 Color backGround = backGrounds.get(result);
712 if (foreGround == null) {
713 throw new IllegalStateException("result = " + result);
714 }
715 if (backGround == null) {
716 throw new IllegalStateException("result = " + result);
717 }
718
719 if (isSelected) {
720 backGround = backGround.darker();
721 }
722
723 setForeground(foreGround);
724 setBackground(backGround);
725
726 return this;
727 }
728 }
729
730
731
732
733 protected class DoubleClickMouseInputListener implements MouseListener {
734
735 public DoubleClickMouseInputListener() {
736 }
737
738 public void mouseClicked(MouseEvent e) {
739 if (e.getClickCount() == 2) {
740 int index = compareModel.getSelectionModel().getLeadSelectionIndex();
741
742 if (index >= 0) {
743 FileCompareEntry entry = (FileCompareEntry)compareModel.get(index);
744 if (entry.children != null) {
745
746 FileCompareEntry nextEntry = null;
747
748 if (index < compareModel.getSize() - 1) {
749 nextEntry = (FileCompareEntry)compareModel.get(index + 1);
750 }
751
752 boolean expand = ((nextEntry == null) || (entry.getLevel() >= nextEntry.getLevel()));
753
754 if (expand) {
755 compareModel.expand(entry);
756 } else {
757 compareModel.collapse(entry);
758 }
759 } else {
760 boolean isDir = false;
761 int i = 0;
762 File[] files = entry.getData();
763 while (!isDir && (i < files.length)) {
764 isDir = files[i].isDirectory();
765 i++;
766 }
767 if (!isDir) {
768 ShowComparisonAction showComparisonAction = new ShowComparisonAction(entry);
769 showComparisonAction.setGlobalContext(getGlobalContext());
770 showComparisonAction.perform(null);
771 }
772 }
773 }
774 }
775 }
776
777 public void mouseEntered(MouseEvent e) {
778 }
779
780 public void mouseExited(MouseEvent e) {
781 }
782
783 public void mousePressed(MouseEvent e) {
784 ListSelectionModel selModel = compareModel.getSelectionModel();
785 if (e.isPopupTrigger()) {
786
787 int index = ((JTable)e.getComponent()).rowAtPoint(e.getPoint());
788 if (index >= 0) {
789 if (e.isControlDown()) {
790 if (!selModel.isSelectedIndex(index)) {
791 selModel.addSelectionInterval(index, index);
792 }
793 } else {
794 if (!selModel.isSelectedIndex(index)) {
795 selModel.setSelectionInterval(index, index);
796 }
797 }
798 }
799
800 JPopupMenu popup = leftPopupMenu;
801 if (e.getComponent() == rightList) {
802 popup = rightPopupMenu;
803 updateCachedActionsColumn(1);
804 if (!rightList.hasFocus()) {
805 rightList.grabFocus();
806 }
807 } else {
808 updateCachedActionsColumn(0);
809 if (!leftList.hasFocus()) {
810 leftList.grabFocus();
811 }
812 }
813 updateMenu(popup.getComponents());
814 popup.show(e.getComponent(), e.getX(), e.getY());
815 }
816 }
817
818 public void mouseReleased(MouseEvent e) {
819 }
820 }
821
822
823 protected static TableRowFocusListener tableRowFocusListener = new TableRowFocusListener();
824
825
826
827
828 protected static class TableRowFocusListener implements FocusListener {
829
830 public void focusGained(FocusEvent e) {
831 repaintLeadCell((JTable)e.getComponent());
832 }
833
834 public void focusLost(FocusEvent e) {
835 repaintLeadCell((JTable)e.getComponent());
836 }
837
838 private void repaintLeadCell(JTable table) {
839
840 int row = table.getSelectionModel().getLeadSelectionIndex();
841 if (row >= 0) {
842 Rectangle firstCell = table.getCellRect(row, 0, false);
843 Rectangle lastCell = table.getCellRect(row, 2, false);
844 int height = firstCell.height;
845 if (lastCell.height > height) {
846 height = lastCell.height;
847 }
848 int width = lastCell.x - firstCell.x + lastCell.width;
849 Rectangle dirtyRect = new Rectangle(firstCell.x, firstCell.y, width, height);
850 table.repaint(dirtyRect);
851 }
852 }
853
854 }
855
856
857
858
859 protected static class FileDropdownListener implements ActionListener {
860
861 protected int column;
862
863 protected FilesModel filesModel;
864
865 public FileDropdownListener(FilesModel filesModel, int column) {
866 this.column = column;
867 this.filesModel = filesModel;
868 }
869
870 public void actionPerformed(ActionEvent event) {
871 DropDownBoxComponent component = (DropDownBoxComponent)event.getSource();
872 File file = new File(component.getSelected());
873 if (file.exists()) {
874 filesModel.setData(column, file);
875 filesModel.refresh();
876 }
877 }
878 }
879
880
881
882
883 protected class DefaultActionMenuItem extends JMenuItem {
884
885 public DefaultActionMenuItem() {
886 }
887
888 protected void update() {
889 int i = compareModel.getSelectionModel().getLeadSelectionIndex();
890 if (i >= 0) {
891 FileCompareEntry entry = compareModel.get(i);
892 if (entry.hasChildren()) {
893 FileCompareEntry child = entry.getChildren()[0];
894 if (child.getIndex() >= 0) {
895 setAction(actionsCache.get("CollapseAction"));
896 } else {
897 setAction(actionsCache.get("ExpandAction"));
898 }
899 return;
900 }
901 }
902 setAction(actionsCache.get("ShowComparisonAction"));
903 setEnabled(false);
904 }
905 }
906 }