001 /* 002 * Licensed under the Apache License, Version 2.0 (the "License"); 003 * you may not use this file except in compliance with the License. 004 * You may obtain a copy of the License at 005 * 006 * http://www.apache.org/licenses/LICENSE-2.0 007 * 008 * Unless required by applicable law or agreed to in writing, software 009 * distributed under the License is distributed on an "AS IS" BASIS, 010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 011 * See the License for the specific language governing permissions and 012 * limitations under the License. 013 */ 014 /* 015 * This file has been modified by Chris Pheby in accordance with Section 4.2 016 * of the Apache Software License 017 */ 018 package org.jadira.dependencynavigator.gui; 019 020 /**********************************************************************you may not use this file except in compliance with the License. You may obtain a copy of the License at 021 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software 022 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 023 * either express or implied. See the License for the specific language governing permissions and limitations under the 024 * License. Contributors: 025 **********************************************************************/ 026 import java.awt.Cursor; 027 import java.awt.Dimension; 028 import java.awt.FlowLayout; 029 import java.awt.event.ActionEvent; 030 import java.awt.event.ActionListener; 031 import java.awt.event.MouseAdapter; 032 import java.awt.event.MouseEvent; 033 import java.io.IOException; 034 import java.io.InputStream; 035 import java.util.Properties; 036 037 import javax.swing.BoxLayout; 038 import javax.swing.JButton; 039 import javax.swing.JCheckBox; 040 import javax.swing.JFrame; 041 import javax.swing.JLabel; 042 import javax.swing.JPanel; 043 import javax.swing.JScrollPane; 044 import javax.swing.JSplitPane; 045 import javax.swing.JTable; 046 import javax.swing.JTree; 047 import javax.swing.ListSelectionModel; 048 import javax.swing.SwingUtilities; 049 import javax.swing.table.JTableHeader; 050 051 import org.jadira.dependencynavigator.controller.ArtifactResolver; 052 import org.jadira.dependencynavigator.controller.Controller; 053 import org.jadira.dependencynavigator.controller.model.DuplicatesListManager; 054 import org.jadira.dependencynavigator.implementations.WorkspaceLoader; 055 import org.jadira.dependencynavigator.model.ArtifactInitialisationException; 056 import org.jadira.repositorysnapshot.RepositorySnapshotFactory; 057 058 public class DependencyBrowserGui { 059 060 public static final String ROLE = "org.jadira.dependencynavigator.gui.DependencyBrowserGui"; 061 062 private static final String PROPERTIES = "/META-INF/maven/org.jadira/maven-dependency-browser-swing-gui/pom.properties"; 063 064 private JTree tree; 065 private Controller controller; 066 private JFrame frame; 067 private JTable versions; 068 private JTable duplicates; 069 private WorkspaceLoader workspaceLoader; 070 private ArtifactResolver resolver; 071 private DuplicatesListManager duplicatesListManager; 072 private ProgressMeter progressMeter; 073 private RepositorySnapshotFactory repositorySnapshotFactory; 074 075 public void open() { 076 frame.setTitle("Maven Dependency Navigator" + loadVersion()); 077 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 078 frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.PAGE_AXIS)); 079 080 JPanel topPanel = new JPanel(); 081 topPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); 082 083 topPanel.add(createLoadButton()); 084 topPanel.add(createCheckBox("compile", controller.getCheckShowCompile())); 085 topPanel.add(createCheckBox("test", controller.getCheckShowTest())); 086 topPanel.add(createCheckBox("runtime", controller.getCheckShowRuntime())); 087 topPanel.add(createCheckBox("provided", controller.getCheckShowProvided())); 088 topPanel.add(createCheckBox("exclusions", controller.getResolveExclusions())); 089 topPanel.add(createSnapshotButton()); 090 091 JPanel bottomPanel = new JPanel(); 092 bottomPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); 093 JLabel progressLabel = new JLabel(); 094 bottomPanel.add(progressLabel); 095 progressMeter = new ProgressMeter(progressLabel); 096 progressMeter.ready(); 097 098 tree = new JTree(new DependencyTreeModel(workspaceLoader.getRoot())); 099 tree.setCellRenderer(new DependencyTreeRenderer()); 100 versions = new JTable(new VersionsTableModel(duplicatesListManager)); 101 versions.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 102 versions.setDefaultRenderer(String.class, new SelectableTableModelRenderer()); 103 versions.addMouseListener(new MouseAdapter() { 104 105 @Override 106 public void mouseClicked(MouseEvent e) { 107 JTable table = (JTable) e.getComponent(); 108 duplicatesListManager.deselect(); 109 duplicatesListManager.getVersionsListManager().select(table.getSelectedRow()); 110 tree.repaint(); 111 versions.repaint(); 112 duplicates.repaint(); 113 } 114 115 }); 116 versions.getTableHeader().addMouseListener(new MouseAdapter() { 117 118 @Override 119 public void mouseClicked(MouseEvent e) { 120 JTableHeader h = (JTableHeader) e.getSource(); 121 int vColIndex = h.getColumnModel().getColumnIndexAtX(e.getX()); 122 int mColIndex = h.getTable().convertColumnIndexToModel(vColIndex); 123 duplicatesListManager.getVersionsListManager().setArtifactInstanceMapComparator(mColIndex); 124 versions.repaint(); 125 } 126 127 }); 128 duplicates = new JTable(new DuplicatesTableModel(duplicatesListManager)); 129 duplicates.setDefaultRenderer(String.class, new SelectableTableModelRenderer()); 130 duplicates.addMouseListener(new MouseAdapter() { 131 132 @Override 133 public void mouseClicked(MouseEvent e) { 134 JTable table = (JTable) e.getComponent(); 135 duplicatesListManager.select(table.getSelectedRow()); 136 tree.repaint(); 137 versions.repaint(); 138 duplicates.repaint(); 139 } 140 141 }); 142 duplicates.getTableHeader().addMouseListener(new MouseAdapter() { 143 @Override 144 public void mouseClicked(MouseEvent e) { 145 duplicatesListManager.setOrderByIdentifier(); 146 duplicates.repaint(); 147 } 148 }); 149 150 JSplitPane versionsSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new JScrollPane(versions), new JScrollPane(duplicates)); 151 JPanel versionsPanel = new JPanel(); 152 versionsPanel.setLayout(new BoxLayout(versionsPanel, BoxLayout.PAGE_AXIS)); 153 versionsPanel.add(versionsSplit); 154 155 JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(tree), versionsPanel); 156 157 JPanel mainPanel = new JPanel(); 158 mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.LINE_AXIS)); 159 mainPanel.add(mainSplitPane); 160 161 mainPanel.setPreferredSize(new Dimension(800, 600)); 162 163 frame.getContentPane().add(topPanel); 164 frame.getContentPane().add(mainPanel); 165 frame.getContentPane().add(bottomPanel); 166 frame.pack(); 167 frame.setVisible(true); 168 169 mainSplitPane.setDividerLocation(0.5); 170 mainSplitPane.setResizeWeight(0.5); 171 versionsSplit.setDividerLocation(0.7); 172 versionsSplit.setResizeWeight(0.7); 173 } 174 175 private JButton createLoadButton() { 176 JButton loadButton = new JButton("Load"); 177 loadButton.addActionListener(new ActionListener() { 178 179 public void actionPerformed(ActionEvent e) { 180 frame.setCursor(new Cursor(Cursor.WAIT_CURSOR)); 181 PomLoaderThread pomLoader = new PomLoaderThread(workspaceLoader, "pom loader") { 182 183 public void run() { 184 try { 185 186 duplicatesListManager.reset(); 187 duplicates.repaint(); 188 versions.repaint(); 189 190 workspaceLoader.loadPom(); 191 if (workspaceLoader.getRoot() != null) { 192 workspaceLoader.getRoot().resolveDependencies(resolver, progressMeter); 193 } 194 progressMeter.ready(); 195 } catch (ArtifactInitialisationException e) { 196 progressMeter.error(e); 197 e.printStackTrace(); 198 } catch (RuntimeException e) { 199 progressMeter.error(e); 200 e.printStackTrace(); 201 } 202 updateModel(); 203 } 204 }; 205 pomLoader.start(); 206 } 207 208 }); 209 210 return loadButton; 211 } 212 213 private JCheckBox createCheckBox(String label, final Controller.BooleanController bcontroller) { 214 JCheckBox checkBox = new JCheckBox(label, bcontroller.getValue()); 215 checkBox.addActionListener(new ActionListener() { 216 217 public void actionPerformed(ActionEvent e) { 218 frame.setCursor(new Cursor(Cursor.WAIT_CURSOR)); 219 bcontroller.toggle(); 220 PomLoaderThread pomLoader = new PomLoaderThread(workspaceLoader, "pom loader") { 221 222 public void run() { 223 try { 224 duplicatesListManager.reset(); 225 workspaceLoader.reloadPom(); 226 workspaceLoader.getRoot().resolveDependencies(resolver, progressMeter); 227 progressMeter.ready(); 228 } catch (ArtifactInitialisationException e) { 229 progressMeter.error(e); 230 } catch (RuntimeException e) { 231 progressMeter.error(e); 232 } 233 updateModel(); 234 } 235 }; 236 pomLoader.start(); 237 } 238 }); 239 return checkBox; 240 } 241 242 private abstract class PomLoaderThread implements Runnable { 243 244 protected WorkspaceLoader workspaceLoader; 245 private String name; 246 247 public PomLoaderThread(WorkspaceLoader workspaceLoader, String name) { 248 this.workspaceLoader = workspaceLoader; 249 this.name = name; 250 } 251 252 public void start() { 253 Thread thread = new Thread(this); 254 thread.setName(name); 255 thread.setDaemon(true); 256 thread.start(); 257 } 258 } 259 260 /** 261 * called by background thread to queue a gui model reload 262 */ 263 public void updateModel() { 264 Runnable modelUpdate = new Runnable() { 265 266 public void run() { 267 tree.setModel(new DependencyTreeModel(workspaceLoader.getRoot())); 268 versions.setModel(new VersionsTableModel(duplicatesListManager)); 269 duplicates.setModel(new DuplicatesTableModel(duplicatesListManager)); 270 frame.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); 271 } 272 }; 273 SwingUtilities.invokeLater(modelUpdate); 274 } 275 276 /** 277 * extract the version number from the maven pom.properties file. fail silently if we can't find it as this 278 * functionality is optional. 279 */ 280 private String loadVersion() { 281 InputStream resourceStream = DependencyBrowserGui.class.getResourceAsStream(PROPERTIES); 282 if (resourceStream == null) { 283 return ""; 284 } 285 Properties properties = new Properties(); 286 try { 287 properties.load(resourceStream); 288 } catch (IOException e) { 289 return ""; 290 } 291 String version = properties.getProperty("version"); 292 if (version == null || version.trim().length() == 0) { 293 return ""; 294 } 295 return " " + version; 296 } 297 298 private JButton createSnapshotButton() { 299 JButton snapshotButton = new JButton("Snapshot"); 300 snapshotButton.setEnabled(repositorySnapshotFactory.isSnapshotEnabled()); 301 snapshotButton.addActionListener(new ActionListener() { 302 303 public void actionPerformed(ActionEvent e) { 304 repositorySnapshotFactory.createSnapshot(progressMeter); 305 } 306 }); 307 return snapshotButton; 308 } 309 }