Java tutorial
/** * Copyright (c) Microsoft Corporation * * All rights reserved. * * MIT License * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH * THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package com.microsoft.azuretools.azureexplorer.views; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.MouseTrackListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.ui.IActionBars; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.ViewPart; import com.microsoft.azure.hdinsight.serverexplore.HDInsightRootModuleImpl; import com.microsoft.azuretools.authmanage.AuthMethodManager; import com.microsoft.azuretools.azurecommons.helpers.AzureCmdException; import com.microsoft.azuretools.azureexplorer.Activator; import com.microsoft.azuretools.azureexplorer.AzureModuleImpl; import com.microsoft.azuretools.core.handlers.SelectSubsriptionsCommandHandler; import com.microsoft.azuretools.core.handlers.SignInCommandHandler; import com.microsoft.azuretools.core.handlers.SignOutCommandHandler; import com.microsoft.azuretools.core.utils.PluginUtil; import com.microsoft.tooling.msservices.components.DefaultLoader; import com.microsoft.tooling.msservices.helpers.collections.ListChangeListener; import com.microsoft.tooling.msservices.helpers.collections.ListChangedEvent; import com.microsoft.tooling.msservices.helpers.collections.ObservableList; import com.microsoft.tooling.msservices.serviceexplorer.Node; import com.microsoft.tooling.msservices.serviceexplorer.NodeAction; import com.microsoft.tooling.msservices.serviceexplorer.azure.AzureModule; import com.microsoft.tooling.msservices.serviceexplorer.azure.storage.StorageModule; public class ServiceExplorerView extends ViewPart implements PropertyChangeListener { /** * The ID of the view as specified by the extension. */ public static final String ID = "com.microsoft.azuretools.azureexplorer.views.ServiceExplorerView"; private TreeViewer viewer; private Action refreshAction; private Action signInOutAction; private Action selectSubscriptionAction; private Action doubleClickAction; private AzureModule azureModule; /* * The content provider class is responsible for * providing objects to the view. It can wrap * existing objects in adapters or simply return * objects as-is. These objects may be sensitive * to the current input of the view, or ignore * it and always show the same content * (like Task List, for example). */ class ViewContentProvider implements IStructuredContentProvider, ITreeContentProvider { private TreeNode invisibleRoot; public void inputChanged(Viewer v, Object oldInput, Object newInput) { } public void dispose() { } public Object[] getElements(Object parent) { if (parent.equals(getViewSite())) { if (invisibleRoot == null) initialize(); return getChildren(invisibleRoot); } return getChildren(parent); } public Object getParent(Object child) { if (child instanceof TreeNode) { return (((TreeNode) child).node).getParent().getViewData(); } return null; } public Object[] getChildren(Object parent) { if (parent instanceof TreeNode) { return ((TreeNode) parent).getChildNodes().toArray(); } return new Object[0]; } public boolean hasChildren(Object parent) { if (parent instanceof TreeNode) return ((TreeNode) parent).getChildNodes().size() > 0; return false; } private void initialize() { azureModule = new AzureModuleImpl(); HDInsightRootModuleImpl hdInsightRootModule = new HDInsightRootModuleImpl(azureModule); azureModule.setHdInsightModule(hdInsightRootModule); invisibleRoot = new TreeNode(null); invisibleRoot.add(createTreeNode(azureModule)); azureModule.load(false); } } private class TreeNode { Node node; List<TreeNode> childNodes = new ArrayList<TreeNode>(); public TreeNode(Node node) { this.node = node; } public void add(TreeNode treeNode) { childNodes.add(treeNode); } public List<TreeNode> getChildNodes() { return childNodes; } public void remove(TreeNode treeNode) { childNodes.remove(treeNode); } @Override public String toString() { return node.getName(); } } private TreeNode createTreeNode(Node node) { TreeNode treeNode = new TreeNode(node); // associate the TreeNode with the Node via it's "viewData" // property; this allows us to quickly retrieve the DefaultMutableTreeNode // object associated with a Node node.setViewData(treeNode); // listen for property change events on the node node.addPropertyChangeListener(this); // listen for structure changes on the node, i.e. when child nodes are // added or removed node.getChildNodes().addChangeListener(new NodeListChangeListener(treeNode)); // create child tree nodes for each child node if (node.hasChildNodes()) { for (Node childNode : node.getChildNodes()) { treeNode.add(createTreeNode(childNode)); } } return treeNode; } private void removeEventHandlers(Node node) { node.removePropertyChangeListener(this); ObservableList<Node> childNodes = node.getChildNodes(); childNodes.removeAllChangeListeners(); // if (node.hasChildNodes()) { // this remove call should cause the NodeListChangeListener object // registered on it's child nodes to fire which should recursively // clean up event handlers on it's children node.removeAllChildNodes(); } } @Override public void propertyChange(final PropertyChangeEvent evt) { // this event is fired whenever a property on a node in the // model changes; we respond by triggering a node change // event in the tree's model final Node node = (Node) evt.getSource(); Display.getDefault().asyncExec(new Runnable() { @Override public void run() { viewer.refresh((TreeNode) node.getViewData()); } }); } private class NodeListChangeListener implements ListChangeListener { private TreeNode treeNode; public NodeListChangeListener(TreeNode treeNode) { this.treeNode = treeNode; } @Override public void listChanged(final ListChangedEvent e) { switch (e.getAction()) { case add: // create child tree nodes for the new nodes for (Node childNode : (Collection<Node>) e.getNewItems()) { treeNode.add(createTreeNode(childNode)); } break; case remove: // unregister all event handlers recursively and remove // child nodes from the tree for (Node childNode : (Collection<Node>) e.getOldItems()) { removeEventHandlers(childNode); // remove this node from the tree treeNode.remove((TreeNode) childNode.getViewData()); } break; } Display.getDefault().asyncExec(new Runnable() { @Override public void run() { viewer.refresh(treeNode); } }); } } class ViewLabelProvider extends LabelProvider { public String getText(Object obj) { return obj.toString(); } public Image getImage(Object obj) { if (obj instanceof TreeNode) { String iconPath = ((TreeNode) obj).node.getIconPath(); if (iconPath != null) { return Activator.getImageDescriptor("icons/" + iconPath).createImage();//Activator.getDefault().getImageRegistry().get((((Node) obj).getIconPath())); } } return super.getImage(obj); } } class NameSorter extends ViewerSorter { } /** * The constructor. */ public ServiceExplorerView() { } /** * This is a callback that will allow us * to create the viewer and initialize it. */ public void createPartControl(Composite parent) { viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); viewer.setContentProvider(new ViewContentProvider()); viewer.setLabelProvider(new ViewLabelProvider()); viewer.setSorter(new NameSorter()); viewer.setInput(getViewSite()); // Create the help context id for the viewer's control PlatformUI.getWorkbench().getHelpSystem().setHelp(viewer.getControl(), "com.microsoft.azuretools.azureexplorer.viewer"); makeActions(); hookContextMenu(); hookMouseActions(); contributeToActionBars(); } private void hookContextMenu() { MenuManager menuMgr = new MenuManager("#PopupMenu"); menuMgr.setRemoveAllWhenShown(true); menuMgr.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager manager) { if (viewer.getSelection().isEmpty()) { return; } if (viewer.getSelection() instanceof IStructuredSelection) { IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); Node node = ((TreeNode) selection.getFirstElement()).node; if (node.hasNodeActions()) { for (final NodeAction nodeAction : node.getNodeActions()) { ImageDescriptor imageDescriptor = nodeAction.getIconPath() != null ? Activator.getImageDescriptor("icons/" + nodeAction.getIconPath()) : null; Action action = new Action(nodeAction.getName(), imageDescriptor) { public void run() { nodeAction.fireNodeActionEvent(); } }; action.setEnabled(nodeAction.isEnabled()); manager.add(action); } } } } }); Menu menu = menuMgr.createContextMenu(viewer.getControl()); viewer.getControl().setMenu(menu); } private void contributeToActionBars() { IActionBars bars = getViewSite().getActionBars(); fillLocalToolBar(bars.getToolBarManager()); updateActions(); try { Runnable signInOutListener = new Runnable() { @Override public void run() { updateActions(); } }; AuthMethodManager.getInstance().addSignInEventListener(signInOutListener); AuthMethodManager.getInstance().addSignOutEventListener(signInOutListener); } catch (Exception ex) { DefaultLoader.getUIHelper().logError(ex.getMessage(), ex); } } private void updateActions() { try { boolean isSignedIn = AuthMethodManager.getInstance().isSignedIn(); selectSubscriptionAction.setEnabled(isSignedIn); signInOutAction.setImageDescriptor(Activator .getImageDescriptor(isSignedIn ? "icons/SignOutLight_16.png" : "icons/SignInLight_16.png")); signInOutAction.setToolTipText(isSignedIn ? "Sign Out" : "Sign In"); } catch (Exception ex) { // ignore } } private void fillLocalToolBar(IToolBarManager manager) { manager.add(refreshAction); manager.add(signInOutAction); manager.add(selectSubscriptionAction); manager.add(new Separator()); } private void makeActions() { refreshAction = new Action("Refresh", Activator.getImageDescriptor("icons/RefreshLight_16.png")) { public void run() { azureModule.load(true); } }; refreshAction.setToolTipText("Refresh"); signInOutAction = new Action("Sign In/Sign Out", com.microsoft.azuretools.core.Activator.getImageDescriptor("icons/SignOutLight_16.png")) { public void run() { try { AuthMethodManager authMethodManager = AuthMethodManager.getInstance(); boolean isSignedIn = authMethodManager.isSignedIn(); if (isSignedIn) { SignOutCommandHandler.doSignOut(PluginUtil.getParentShell()); } else { SignInCommandHandler.doSignIn(PluginUtil.getParentShell()); } } catch (Exception ex) { Activator.getDefault().log(ex.getMessage(), ex); } } }; selectSubscriptionAction = new Action("Select Subscriptions", com.microsoft.azuretools.core.Activator.getImageDescriptor("icons/ConnectAccountsLight_16.png")) { public void run() { try { if (AuthMethodManager.getInstance().isSignedIn()) { SelectSubsriptionsCommandHandler.onSelectSubscriptions(PluginUtil.getParentShell()); azureModule.load(false); } } catch (Exception ex) { } } }; selectSubscriptionAction.setToolTipText("Select Subscriptions"); doubleClickAction = new Action() { public void run() { ISelection selection = viewer.getSelection(); Object obj = ((IStructuredSelection) selection).getFirstElement(); if (!viewer.getExpandedState(obj)) { viewer.expandToLevel(obj, 1); } else { viewer.collapseToLevel(obj, 1); } } }; } private void hookMouseActions() { viewer.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { doubleClickAction.run(); } }); Tree tree = (Tree) viewer.getControl(); tree.addMouseListener(new MouseAdapter() { @Override public void mouseUp(MouseEvent e) { if (e.button == 1) { // left button TreeItem[] selection = ((Tree) e.widget).getSelection(); if (selection.length > 0) { TreeItem item = ((Tree) e.widget).getSelection()[0]; Node node = ((TreeNode) item.getData()).node; // if the node in question is in a "loading" state then // we do not propagate the click event to it if (!node.isLoading()) { node.getClickAction().fireNodeActionEvent(); } } } } }); } /** * Passing the focus request to the viewer's control. */ public void setFocus() { viewer.getControl().setFocus(); } }