View Javadoc

1   /**
2    * Copyright (C) 2008 Atlassian
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.atlassian.theplugin.idea.config.serverconfig;
18  
19  import com.atlassian.theplugin.commons.ServerType;
20  import com.atlassian.theplugin.commons.cfg.BambooServerCfg;
21  import com.atlassian.theplugin.commons.cfg.CrucibleServerCfg;
22  import com.atlassian.theplugin.commons.cfg.JiraServerCfg;
23  import com.atlassian.theplugin.commons.cfg.ServerCfg;
24  import com.atlassian.theplugin.commons.cfg.ServerId;
25  import com.atlassian.theplugin.idea.Constants;
26  import com.atlassian.theplugin.idea.config.serverconfig.model.RootNode;
27  import com.atlassian.theplugin.idea.config.serverconfig.model.ServerNode;
28  import com.atlassian.theplugin.idea.config.serverconfig.model.ServerNodeFactory;
29  import com.atlassian.theplugin.idea.config.serverconfig.model.ServerTreeModel;
30  import com.atlassian.theplugin.idea.config.serverconfig.model.ServerTypeNode;
31  import com.atlassian.theplugin.idea.config.serverconfig.util.ServerNameUtil;
32  import com.intellij.openapi.actionSystem.ActionGroup;
33  import com.intellij.openapi.actionSystem.ActionManager;
34  import com.intellij.openapi.actionSystem.DataProvider;
35  import com.intellij.openapi.ui.Messages;
36  import org.jetbrains.annotations.NonNls;
37  import org.jetbrains.annotations.Nullable;
38  
39  import javax.swing.*;
40  import javax.swing.event.TreeSelectionEvent;
41  import javax.swing.event.TreeSelectionListener;
42  import javax.swing.tree.DefaultMutableTreeNode;
43  import javax.swing.tree.TreeNode;
44  import javax.swing.tree.TreePath;
45  import javax.swing.tree.TreeSelectionModel;
46  import java.awt.*;
47  import java.awt.event.MouseAdapter;
48  import java.awt.event.MouseEvent;
49  import java.util.Collection;
50  
51  public final class ServerTreePanel extends JPanel implements TreeSelectionListener, DataProvider {
52  
53  	private JTree serverTree = null;
54  	private ServerTreeModel model;
55  	private DefaultMutableTreeNode selectedNode = null;
56  	private boolean forceExpand = true;
57  
58  	private static final int WIDTH = 150;
59  	private static final int HEIGHT = 250;
60  	private static final int VISIBLE_ROW_COUNT = 7;
61      private Collection<ServerCfg> servers;
62  
63      /**
64  	 * serverConfigPanel needs to be initialized outside of the constructor to avoid cyclic dependency.
65  	 * @param serverConfigPanel panel to invoke storeServer() and showEmptyPanel() on.
66  	 */
67  	public void setServerConfigPanel(ServerConfigPanel serverConfigPanel) {
68  		this.serverConfigPanel = serverConfigPanel;
69  	}
70  
71  	private ServerConfigPanel serverConfigPanel;
72  
73  	public ServerTreePanel() {
74  		initLayout();
75  	}
76  
77  	private void initLayout() {
78  		setLayout(new BorderLayout());
79  		setMinimumSize(new Dimension(WIDTH, HEIGHT));
80  		add(new JScrollPane(getServerTree()), BorderLayout.CENTER);
81  	}
82  
83  	private void expandAllPaths() {
84  		for (int i = 0; i < serverTree.getRowCount(); ++i) {
85                   serverTree.expandRow(i);
86          }
87      }
88  
89  	private JTree getServerTree() {
90  		if (serverTree == null) {
91  			serverTree = new JTree();
92  
93              serverTree.setName("Server tree");
94  
95              model = new ServerTreeModel(new RootNode());
96  			serverTree.setModel(model);
97  
98  			serverTree.setRootVisible(false);
99  			serverTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
100 			serverTree.setVisibleRowCount(VISIBLE_ROW_COUNT);
101 			serverTree.setShowsRootHandles(true);
102 
103 			serverTree.addTreeSelectionListener(this);
104 			serverTree.addMouseListener(new MouseAdapter() {
105 				public static final String TOOLBAR_NAME = "ThePlugin.AddRemoveServerPopup";
106 
107 				@Override
108 				public void mousePressed(MouseEvent e) {
109 					processPopup(e);
110 				}
111 
112 				@Override
113 				public void mouseReleased(MouseEvent e) {
114 					processPopup(e);
115 				}
116 
117 				public void processPopup(MouseEvent e) {
118 					if (e.isPopupTrigger() == false) {
119 						return;
120 					}
121 
122 					final JTree theTree = (JTree) e.getComponent();
123 
124 					TreePath path = theTree.getPathForLocation(e.getX(), e.getY());
125 					if (path != null) {
126 						theTree.setSelectionPath(path);
127 					}
128 //					Object o = path.getLastPathComponent();
129 //					if (o instanceof ServerNode) {
130 						ActionGroup menu = (ActionGroup) ActionManager.getInstance().getAction(TOOLBAR_NAME);
131 						if (menu == null) {
132 							return;
133 						}
134 						ActionManager.getInstance().createActionPopupMenu(toString(), menu)
135 								.getComponent().show(e.getComponent(), e.getX(), e.getY());
136 //					}
137 				}
138 			});
139 			
140 
141 			serverTree.setCellRenderer(new ServerTreeRenderer());
142 		}
143 		return serverTree;
144 	}
145 
146 	@Override
147     public void setEnabled(boolean b) {
148 		super.setEnabled(b);
149 		getServerTree().setEnabled(b);
150 	}
151 
152 	public String addServer(ServerType serverType) {
153 
154 
155         String name = ServerNameUtil.suggestNewName(servers);
156         ServerCfg newServer = createNewServer(serverType, name);
157 
158         servers.add(newServer);
159 
160         ServerNode child = ServerNodeFactory.getServerNode(newServer);
161 		ServerTypeNode serverTypeNode = model.getServerTypeNode(serverType, true);
162 		model.insertNodeInto(child, serverTypeNode, serverTypeNode.getChildCount());
163 
164 		TreePath path = new TreePath(child.getPath());
165 		serverTree.scrollPathToVisible(path);
166 		serverTree.setSelectionPath(path);
167 		serverTree.expandPath(path);
168 
169 		return newServer.getName();
170 	}
171 
172     private ServerCfg createNewServer(final ServerType serverType, final String name) {
173         ServerId id = new ServerId();
174 			// CHECKSTYLE:OFF
175 		switch (serverType) {
176 			// CHECKSTYLE:ON
177             case BAMBOO_SERVER:
178                 return new BambooServerCfg(true, name, id);
179             case CRUCIBLE_SERVER:
180                 return new CrucibleServerCfg(name, id);
181             case JIRA_SERVER:
182                 return new JiraServerCfg(name, id);
183         }
184         throw new RuntimeException("Unhandled server type [" + serverType + "]");
185     }
186 
187 
188     public void copyServer() {
189 /*
190 		ServerBean newServer = new ServerBean();
191 		newServer.setName(suggestCopyName(ConfigurationFactory.getConfiguration()
192 				.getBambooConfiguration().transientGetServers()));
193 		ConfigurationFactory.getConfiguration().getBambooConfiguration().addServer(newServer);
194 		serverTree.updateUI();
195 		return newServer.getName();
196 */
197 	}
198 
199 	public void removeServer() {
200 		if (selectedNode != null) {
201 			if (selectedNode instanceof ServerNode) {
202 				final ServerNode selectedServerNode = (ServerNode) this.selectedNode;
203 				int response = Messages.showYesNoDialog(
204 						"Are you sure you want to delete the selected server?",
205 						"Confirm server delete",
206 						Messages.getQuestionIcon()						
207 						);
208 
209 				if (response != 0) {
210 					return;
211 				}
212 
213                 servers.remove(selectedServerNode.getServer());
214 				TreeNode parent = selectedServerNode.getParent();
215 				selectedServerNode.removeFromParent();
216 				model.nodeStructureChanged(parent);
217 			}
218 		}
219 	}
220 
221 	public void setData(Collection<ServerCfg> newServers) {
222         servers = newServers;
223         // jgorycki: I assume this method will only be called at the beginning of the dialog's lifecycle.
224 		// I want to expand all paths in the tree and not select any nodes - hence showing an empty panel
225 		updateTreeConfiguration();
226 		if (forceExpand) {
227 			// do this only during first operation
228 			expandAllPaths();
229 //			forceExpand = false;
230 		}
231 	}
232 
233 	private ServerNode updateServerTree() {
234         ServerNode firstServerNode = null;
235 
236         model = new ServerTreeModel(new RootNode());
237         serverTree.setModel(model);
238 
239 
240             // !servers.isEmpty() because:
241 			// if server list is empty, don't create server type node,
242 			// otherwise create node - it would be required
243 //			ServerTypeNode serverTypeNode = model.getServerTypeNode(serverType, !servers.isEmpty());
244 //			TreePath serverNodePath = new TreePath(serverTypeNode.getPath());
245 //			boolean doExpand = serverTree.isExpanded(serverNodePath);
246 
247             for (ServerCfg server : servers) {
248 				ServerNode child = ServerNodeFactory.getServerNode(server);
249 			    ServerTypeNode serverTypeNode = model.getServerTypeNode(server.getServerType(), true);
250 
251 				model.insertNodeInto(child, serverTypeNode, serverTypeNode.getChildCount());
252 
253                 if (firstServerNode == null) {
254 					firstServerNode = child;
255 				}
256 
257 				if (selectedNode != null && selectedNode instanceof ServerNode) {
258 					ServerNode serverNode = (ServerNode) selectedNode;
259 					if (child.getServer().getServerId().equals(serverNode.getServer().getServerId())) {
260 						firstServerNode = child;
261 					}
262 				}
263                 model.nodeStructureChanged(serverTypeNode);
264 			}
265 
266 //			if (doExpand) {
267 //				serverTree.expandPath(serverNodePath);
268 //			}
269         return firstServerNode;
270     }
271 
272 
273     private void updateTreeConfiguration() {
274         //DefaultMutableTreeNode tmpNode = selectedNode;
275         selectedNode = updateServerTree();
276 		if (selectedNode != null) {
277 			TreePath path = new TreePath(selectedNode.getPath());
278 			serverTree.scrollPathToVisible(path);
279 			serverTree.setSelectionPath(path);
280 			serverTree.expandPath(path);
281 			return;
282 		} else {
283 			serverConfigPanel.showEmptyPanel();
284 		}
285 //		if (tmpNode != null) {
286 //            TreePath path = new TreePath(tmpNode.getPath());
287 //            if (doesExistInModel(model, path)) {
288 //                selectedNode = tmpNode;
289 //                serverTree.scrollPathToVisible(path);
290 //                serverTree.setSelectionPath(path);
291 //                return;
292 //            }
293 //        }
294 
295 //
296 //        selectedNode = null;
297 //        serverConfigPanel.showEmptyPanel();
298 //        if (firstServerNode != null) {
299 //            TreePath path = new TreePath(firstServerNode.getPath());
300 //            serverTree.scrollPathToVisible(path);
301 //            serverTree.setSelectionPath(path);
302 //            serverTree.expandPath(path);
303 //        }
304     }
305 
306     public void valueChanged(TreeSelectionEvent e) {
307         TreePath oldPath = e.getOldLeadSelectionPath();
308         if (oldPath != null) {
309             DefaultMutableTreeNode oldNode = (DefaultMutableTreeNode) oldPath.getLastPathComponent();
310             if (oldNode != null && oldNode instanceof ServerNode) {
311                 serverConfigPanel.saveData(((ServerNode) oldNode).getServerType());
312             }
313             model.nodeChanged(oldNode);
314 
315         }
316 
317 		TreePath path = e.getNewLeadSelectionPath();
318 
319 		if (path != null) {
320 			selectedNode = (DefaultMutableTreeNode) path.getLastPathComponent();
321 			if (selectedNode instanceof ServerNode) {
322 				ServerCfg server = ((ServerNode) selectedNode).getServer();
323                 serverConfigPanel.editServer(server);
324 //                else {
325 //					// PL-235 show blank panel if server from tree node does not exist in configuration
326 //					// it happens if you add server, click cancel and open config window again
327 //					serverConfigPanel.showEmptyPanel();
328 //				}
329 			} else if (selectedNode instanceof ServerTypeNode) {
330 				serverConfigPanel.showEmptyPanel();
331 			}
332 		} else {
333 			serverConfigPanel.showEmptyPanel();
334 		}
335 	}
336 
337 
338 	private ServerCfg getSelectedServer() {
339 		if (selectedNode instanceof ServerNode) {
340 			return ((ServerNode) selectedNode).getServer();
341 		}
342 		return null;
343 	}
344 
345 	@Nullable
346 	public Object getData(@NonNls final String dataId) {
347 		if (dataId.equals(Constants.SERVER)) {
348 			return getSelectedServer();
349 		} else if (dataId.equals(Constants.SERVER_TYPE)) {
350 			if (selectedNode instanceof ServerTypeNode) {
351 				final ServerTypeNode serverTypeNode = (ServerTypeNode) selectedNode;
352 				return serverTypeNode.getServerType();
353 			}
354 		}
355 		return null;
356 	}
357 }