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 }