| package com.intellij.remoteServer.impl.runtime.ui; |
| |
| import com.intellij.ide.DataManager; |
| import com.intellij.ide.actions.ContextHelpAction; |
| import com.intellij.ide.util.treeView.AbstractTreeNode; |
| import com.intellij.ide.util.treeView.NodeDescriptor; |
| import com.intellij.ide.util.treeView.NodeRenderer; |
| import com.intellij.ide.util.treeView.TreeVisitor; |
| import com.intellij.openapi.application.ModalityState; |
| import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure; |
| import com.intellij.openapi.Disposable; |
| import com.intellij.openapi.actionSystem.*; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.ui.Splitter; |
| import com.intellij.openapi.util.Comparing; |
| import com.intellij.openapi.util.Disposer; |
| import com.intellij.remoteServer.configuration.RemoteServer; |
| import com.intellij.remoteServer.impl.runtime.log.LoggingHandlerImpl; |
| import com.intellij.remoteServer.impl.runtime.ui.tree.DeploymentNode; |
| import com.intellij.remoteServer.impl.runtime.ui.tree.ServerNode; |
| import com.intellij.remoteServer.impl.runtime.ui.tree.TreeBuilderBase; |
| import com.intellij.remoteServer.runtime.ConnectionStatus; |
| import com.intellij.remoteServer.runtime.ServerConnection; |
| import com.intellij.remoteServer.runtime.ServerConnectionListener; |
| import com.intellij.remoteServer.runtime.ServerConnectionManager; |
| import com.intellij.ui.DoubleClickListener; |
| import com.intellij.ui.ScrollPaneFactory; |
| import com.intellij.ui.SideBorder; |
| import com.intellij.ui.components.panels.Wrapper; |
| import com.intellij.ui.treeStructure.Tree; |
| import com.intellij.util.Alarm; |
| import com.intellij.util.ui.UIUtil; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| |
| import javax.swing.*; |
| import javax.swing.event.TreeSelectionEvent; |
| import javax.swing.event.TreeSelectionListener; |
| import javax.swing.tree.DefaultMutableTreeNode; |
| import javax.swing.tree.DefaultTreeModel; |
| import java.awt.*; |
| import java.awt.event.MouseEvent; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.Set; |
| |
| /** |
| * @author michael.golubev |
| */ |
| public class ServersToolWindowContent extends JPanel implements Disposable { |
| public static final DataKey<ServersToolWindowContent> KEY = DataKey.create("serversToolWindowContent"); |
| @NonNls private static final String PLACE_TOOLBAR = "ServersToolWindowContent#Toolbar"; |
| @NonNls private static final String SERVERS_TOOL_WINDOW_TOOLBAR = "RemoteServersViewToolbar"; |
| |
| @NonNls |
| private static final String HELP_ID = "Application_Servers_tool_window"; |
| private static final String MESSAGE_CARD = "message"; |
| private static final String EMPTY_SELECTION_MESSAGE = "Select a server or deployment in the tree to view details"; |
| |
| private static final int POLL_DEPLOYMENTS_DELAY = 2000; |
| |
| private final Tree myTree; |
| private final CardLayout myPropertiesPanelLayout; |
| private final JPanel myPropertiesPanel; |
| private final JLabel myMessageLabel; |
| private final Map<String, JComponent> myLogComponents = new HashMap<String, JComponent>(); |
| |
| private final DefaultTreeModel myTreeModel; |
| private TreeBuilderBase myBuilder; |
| private AbstractTreeNode<?> myLastSelection; |
| |
| private final Project myProject; |
| |
| public ServersToolWindowContent(@NotNull Project project) { |
| super(new BorderLayout()); |
| myProject = project; |
| |
| myTreeModel = new DefaultTreeModel(new DefaultMutableTreeNode()); |
| myTree = new Tree(myTreeModel); |
| myTree.setRootVisible(false); |
| |
| myTree.setShowsRootHandles(true); |
| myTree.setCellRenderer(new NodeRenderer()); |
| myTree.setLineStyleAngled(); |
| |
| getMainPanel().add(createToolbar(), BorderLayout.WEST); |
| Splitter splitter = new Splitter(false, 0.3f); |
| splitter.setFirstComponent(ScrollPaneFactory.createScrollPane(myTree, SideBorder.LEFT)); |
| myPropertiesPanelLayout = new CardLayout(); |
| myPropertiesPanel = new JPanel(myPropertiesPanelLayout); |
| myMessageLabel = new JLabel(EMPTY_SELECTION_MESSAGE, SwingConstants.CENTER); |
| myPropertiesPanel.add(MESSAGE_CARD, new Wrapper(myMessageLabel)); |
| splitter.setSecondComponent(myPropertiesPanel); |
| getMainPanel().add(splitter, BorderLayout.CENTER); |
| |
| setupBuilder(project); |
| |
| for (RemoteServersViewContributor contributor : RemoteServersViewContributor.EP_NAME.getExtensions()) { |
| contributor.setupTree(myProject, myTree, myBuilder); |
| } |
| |
| myTree.addTreeSelectionListener(new TreeSelectionListener() { |
| @Override |
| public void valueChanged(TreeSelectionEvent e) { |
| onSelectionChanged(); |
| } |
| }); |
| new DoubleClickListener() { |
| @Override |
| protected boolean onDoubleClick(MouseEvent event) { |
| Set<ServersTreeStructure.RemoteServerNode> nodes = getSelectedRemoteServerNodes(); |
| if (nodes.size() == 1) { |
| RemoteServer<?> server = nodes.iterator().next().getValue(); |
| ServerConnectionManager.getInstance().getOrCreateConnection(server); |
| return true; |
| } |
| return false; |
| } |
| }.installOn(myTree); |
| } |
| |
| private void onSelectionChanged() { |
| Set<AbstractTreeNode> nodes = myBuilder.getSelectedElements(AbstractTreeNode.class); |
| if (nodes.size() != 1) { |
| showMessageLabel(EMPTY_SELECTION_MESSAGE); |
| myLastSelection = null; |
| return; |
| } |
| |
| AbstractTreeNode<?> node = nodes.iterator().next(); |
| if (Comparing.equal(node, myLastSelection)) { |
| return; |
| } |
| |
| myLastSelection = node; |
| if (node instanceof ServersTreeStructure.LogProvidingNode) { |
| ServersTreeStructure.LogProvidingNode logNode = (ServersTreeStructure.LogProvidingNode)node; |
| LoggingHandlerImpl loggingHandler = logNode.getLoggingHandler(); |
| if (loggingHandler != null) { |
| String cardName = logNode.getLogId(); |
| JComponent oldComponent = myLogComponents.get(cardName); |
| JComponent logComponent = loggingHandler.getConsole().getComponent(); |
| if (!logComponent.equals(oldComponent)) { |
| myLogComponents.put(cardName, logComponent); |
| if (oldComponent != null) { |
| myPropertiesPanel.remove(oldComponent); |
| } |
| myPropertiesPanel.add(cardName, logComponent); |
| } |
| myPropertiesPanelLayout.show(myPropertiesPanel, cardName); |
| } |
| else { |
| showMessageLabel(""); |
| } |
| } |
| else if (node instanceof ServersTreeStructure.RemoteServerNode) { |
| updateServerDetails((ServersTreeStructure.RemoteServerNode)node); |
| } |
| else { |
| showMessageLabel(""); |
| } |
| } |
| |
| private void updateServerDetails(ServersTreeStructure.RemoteServerNode node) { |
| RemoteServer<?> server = ((ServersTreeStructure.RemoteServerNode)node).getValue(); |
| ServerConnection connection = ServerConnectionManager.getInstance().getConnection(server); |
| if (connection == null || connection.getStatus() == ConnectionStatus.DISCONNECTED) { |
| showMessageLabel("Double-click on the server node to connect"); |
| } |
| else { |
| showMessageLabel(connection.getStatusText()); |
| } |
| } |
| |
| private void showMessageLabel(final String text) { |
| myMessageLabel.setText(UIUtil.toHtml(text)); |
| myPropertiesPanelLayout.show(myPropertiesPanel, MESSAGE_CARD); |
| } |
| |
| private void setupBuilder(final @NotNull Project project) { |
| ServersTreeStructure structure = new ServersTreeStructure(project); |
| myBuilder = new TreeBuilderBase(myTree, structure, myTreeModel) { |
| @Override |
| protected boolean isAutoExpandNode(NodeDescriptor nodeDescriptor) { |
| return nodeDescriptor instanceof ServersTreeStructure.RemoteServerNode || nodeDescriptor instanceof ServersTreeStructure.DeploymentNodeImpl; |
| } |
| }; |
| Disposer.register(this, myBuilder); |
| |
| project.getMessageBus().connect().subscribe(ServerConnectionListener.TOPIC, new ServerConnectionListener() { |
| @Override |
| public void onConnectionCreated(@NotNull ServerConnection<?> connection) { |
| getBuilder().queueUpdate(); |
| pollDeployments(connection); |
| } |
| |
| @Override |
| public void onConnectionStatusChanged(@NotNull ServerConnection<?> connection) { |
| getBuilder().queueUpdate(); |
| updateSelectedServerDetails(); |
| } |
| |
| @Override |
| public void onDeploymentsChanged(@NotNull ServerConnection<?> connection) { |
| getBuilder().queueUpdate(); |
| updateSelectedServerDetails(); |
| } |
| }); |
| } |
| |
| private void updateSelectedServerDetails() { |
| if (myLastSelection instanceof ServersTreeStructure.RemoteServerNode) { |
| updateServerDetails((ServersTreeStructure.RemoteServerNode)myLastSelection); |
| } |
| } |
| |
| private static void pollDeployments(final ServerConnection connection) { |
| connection.computeDeployments(new Runnable() { |
| |
| @Override |
| public void run() { |
| new Alarm().addRequest(new Runnable() { |
| |
| @Override |
| public void run() { |
| if (connection == ServerConnectionManager.getInstance().getConnection(connection.getServer())) { |
| pollDeployments(connection); |
| } |
| } |
| }, POLL_DEPLOYMENTS_DELAY, ModalityState.any()); |
| } |
| }); |
| } |
| |
| private JComponent createToolbar() { |
| DefaultActionGroup group = new DefaultActionGroup(); |
| group.add(ActionManager.getInstance().getAction(SERVERS_TOOL_WINDOW_TOOLBAR)); |
| group.add(new Separator()); |
| group.add(new ContextHelpAction(HELP_ID)); |
| |
| ActionToolbar actionToolBar = ActionManager.getInstance().createActionToolbar(PLACE_TOOLBAR, group, false); |
| |
| |
| myTree.putClientProperty(DataManager.CLIENT_PROPERTY_DATA_PROVIDER, new DataProvider() { |
| |
| @Override |
| public Object getData(@NonNls String dataId) { |
| if (KEY.getName().equals(dataId)) { |
| return ServersToolWindowContent.this; |
| } |
| for (RemoteServersViewContributor contributor : RemoteServersViewContributor.EP_NAME.getExtensions()) { |
| Object data = contributor.getData(dataId, ServersToolWindowContent.this); |
| if (data != null) { |
| return data; |
| } |
| } |
| return null; |
| } |
| }); |
| actionToolBar.setTargetComponent(myTree); |
| return actionToolBar.getComponent(); |
| } |
| |
| public JPanel getMainPanel() { |
| return this; |
| } |
| |
| public Set<ServerNode> getSelectedServerNodes() { |
| return myBuilder.getSelectedElements(ServerNode.class); |
| } |
| |
| public Set<DeploymentNode> getSelectedDeploymentNodes() { |
| return myBuilder.getSelectedElements(DeploymentNode.class); |
| } |
| |
| public Set<ServersTreeStructure.RemoteServerNode> getSelectedRemoteServerNodes() { |
| return myBuilder.getSelectedElements(ServersTreeStructure.RemoteServerNode.class); |
| } |
| |
| @Override |
| public void dispose() { |
| } |
| |
| public TreeBuilderBase getBuilder() { |
| return myBuilder; |
| } |
| |
| @NotNull |
| public Project getProject() { |
| return myProject; |
| } |
| |
| public void select(@NotNull final ServerConnection<?> connection) { |
| myBuilder.select(ServersTreeStructure.RemoteServerNode.class, new TreeVisitor<ServersTreeStructure.RemoteServerNode>() { |
| @Override |
| public boolean visit(@NotNull ServersTreeStructure.RemoteServerNode node) { |
| return node.getValue().equals(connection.getServer()); |
| } |
| }, null, false); |
| } |
| |
| public void select(@NotNull final ServerConnection<?> connection, @NotNull final String deploymentName) { |
| myBuilder.getUi().queueUpdate(connection).doWhenDone(new Runnable() { |
| @Override |
| public void run() { |
| myBuilder.select(ServersTreeStructure.DeploymentNodeImpl.class, new TreeVisitor<ServersTreeStructure.DeploymentNodeImpl>() { |
| @Override |
| public boolean visit(@NotNull ServersTreeStructure.DeploymentNodeImpl node) { |
| AbstractTreeNode parent = node.getParent(); |
| return parent instanceof ServersTreeStructure.RemoteServerNode && |
| ((ServersTreeStructure.RemoteServerNode)parent).getValue().equals(connection.getServer()) |
| && node.getValue().getName().equals(deploymentName); |
| } |
| }, null, false); |
| } |
| }); |
| } |
| } |