Mercurial > hg > release > thermostat-0.5
changeset 877:ec6d1e7c6fed
Move some swing classes to more appropriate packages
Move some classes in the com.thermostat.client.swing package (and
subpackages) to more appropriate locations.
Main window should not be public api:
c.r.t.c.s.MainWindow -> c.r.t.c.s.internal.MainWindow
c.r.t.c.s.MainWindowTest -> c.r.t.c.s.internal.MainWindowTest
These classes are not components; move them:
c.r.t.c.s.components.EdtHelper -> c.r.t.c.s.EdtHelper
c.r.t.c.s.components.EdtHelperTest -> c.r.t.c.s.EdtHelperTest
c.r.t.c.s.components.GraphicsUtils -> c.r.t.c.s.GraphicUtils
c.r.t.c.s.components.HtmlTextBuilder -> c.r.t.c.s.HtmlTextBuilder
Also remove public static void main(String[] args) methods from
ActionButton and StatusBar. The code from ActionButton is now a unit
test.
Reviewed-by: vanaltj
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-December/004854.html
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/EdtHelper.java Tue Dec 18 16:39:38 2012 -0500 @@ -0,0 +1,119 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.client.swing; + +import java.awt.EventQueue; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.Callable; + +import javax.swing.SwingUtilities; + +/** + * Allows operations to be performed consistently on the Swing EDT + * irrespective of whether the caller is running on the EDT or not. + * + * @see SwingUtilities#invokeAndWait(Runnable) + * @see SwingUtilities#invokeLater(Runnable) + */ +public class EdtHelper { + + @SuppressWarnings("serial") + private static class CallableException extends RuntimeException { + + private CallableException(Exception ex) { + super(ex); + } + + } + + private static class CallableWrapper<T> implements Runnable { + + private Callable<T> callable; + private T result; + + private CallableWrapper(Callable<T> c) { + callable = c; + } + + @Override + public void run() { + try { + result = callable.call(); + } catch (Exception ex) { + throw new CallableException(ex); + } + } + + private T getResult() { + return result; + } + } + + /** + * Invoke the supplied {@link Runnable} on the EDT. + * @param r encapsulates the code to run + * @throws InvocationTargetException encapsulates the actual exception + * that occurs when executing this code. + * @throws InterruptedException + */ + public void callAndWait(Runnable r) throws InvocationTargetException, InterruptedException { + if (EventQueue.isDispatchThread()) { + try { + r.run(); + } catch (Exception ex) { + throw new InvocationTargetException(ex); + } + } else { + EventQueue.invokeAndWait(r); + } + } + + /** + * Invokes the supplied {@link Callable} on the EDT, waits until it is + * finished execution and returns the result of invoking {@link Callable#call()}. + * @param c encapsulates the code to execute + * @return the result produce by c + * @throws InvocationTargetException indicates an exception occurred when executing the callable + * @throws InterruptedException + */ + public <T> T callAndWait(Callable<T> c) throws InvocationTargetException, InterruptedException { + CallableWrapper<T> w = new CallableWrapper<>(c); + callAndWait(w); + return w.getResult(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/GraphicsUtils.java Tue Dec 18 16:39:38 2012 -0500 @@ -0,0 +1,95 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.client.swing; + +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.geom.RoundRectangle2D; + +import javax.swing.JComponent; + +import sun.swing.SwingUtilities2; + +@SuppressWarnings("restriction") +public class GraphicsUtils { + + private static GraphicsUtils instance = new GraphicsUtils(); + public static GraphicsUtils getInstance() { + return instance; + } + + public Graphics2D createAAGraphics(Graphics g) { + Graphics2D graphics = (Graphics2D) g.create(); + graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + return graphics; + } + + public void drawStringWithShadow(JComponent component, Graphics2D graphics, String string, Color foreground, int x, int y) { + // paint it twice to give a subtle drop shadow effect + + graphics.setColor(new Color(0f, 0f, 0f, 0.1f)); + SwingUtilities2.drawString(component, graphics, string, x, y + 1); + + graphics.setColor(foreground); + SwingUtilities2.drawString(component, graphics, string, x, y); + } + + public void drawString(JComponent component, Graphics2D graphics, String string, Color foreground, int x, int y) { + graphics.setColor(foreground); + SwingUtilities2.drawString(component, graphics, string, x, y); + } + + public FontMetrics getFontMetrics(JComponent component, Font font) { + return SwingUtilities2.getFontMetrics(component, font); + } + + public Shape getRoundShape(int width, int height) { + return new RoundRectangle2D.Double(0, 0, width, height, 4, 4); + } + + public void setGradientPaint(Graphics2D g, int x, int height, Color start, Color stop) { + Paint paint = new GradientPaint(x, 0, start, 0, height, stop); + g.setPaint(paint); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/HtmlTextBuilder.java Tue Dec 18 16:39:38 2012 -0500 @@ -0,0 +1,118 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.client.swing; + +public class HtmlTextBuilder { + + /* + * The api provided by this class needs to be cleaned up. + */ + + private final StringBuilder text = new StringBuilder(); + + public HtmlTextBuilder() { + // do nothing + } + + public HtmlTextBuilder(String text) { + text = escape(text); + this.text.append(text); + } + + public HtmlTextBuilder bold(boolean on) { + if (on) { + this.text.append("<b>"); + } else { + this.text.append("</b>"); + } + return this; + } + + public HtmlTextBuilder bold(String toBold) { + text.append("<b>").append(toBold).append("</b>"); + return this; + } + + public HtmlTextBuilder larger(String toAppend) { + text.append("<font size='+2'>").append(escape(toAppend)).append("</font>"); + return this; + } + + public HtmlTextBuilder huge(String toAppend) { + text.append("<font size='+6'>").append(escape(toAppend)).append("</font>"); + return this; + } + + @Override + public String toString() { + // FIXME + return null; + } + + public String toHtml() { + return "<html>" + text.toString() + "</html>"; + } + + public String toPartialHtml() { + return text.toString(); + } + + private static String escape(String toEscape) { + // FIXME implement this + return toEscape; + } + + public HtmlTextBuilder append(String toAppend) { + text.append(escape(toAppend)); + return this; + } + + public HtmlTextBuilder appendRaw(String toAppend) { + text.append(toAppend); + return this; + } + + public static String boldHtml(String toBold) { + return new HtmlTextBuilder().bold(toBold).toHtml(); + } + + public HtmlTextBuilder newLine() { + text.append("<br>"); + return this; + } + +}
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/MainWindow.java Tue Dec 18 22:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,804 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.client.swing; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.awt.image.BufferedImage; -import java.io.PrintStream; -import java.lang.reflect.InvocationTargetException; -import java.nio.ByteBuffer; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutionException; - -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JFrame; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; -import javax.swing.JTree; -import javax.swing.KeyStroke; -import javax.swing.SwingUtilities; -import javax.swing.SwingWorker; -import javax.swing.ToolTipManager; -import javax.swing.event.TreeExpansionEvent; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.event.TreeWillExpandListener; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeCellRenderer; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.ExpandVetoException; -import javax.swing.tree.TreeNode; -import javax.swing.tree.TreePath; -import javax.swing.tree.TreeSelectionModel; - -import sun.misc.Signal; - -import com.redhat.thermostat.client.core.Filter; -import com.redhat.thermostat.client.core.views.BasicView; -import com.redhat.thermostat.client.core.views.SearchFieldView.SearchAction; -import com.redhat.thermostat.client.locale.LocaleResources; -import com.redhat.thermostat.client.osgi.service.DecoratorProvider; -import com.redhat.thermostat.client.osgi.service.MenuAction; -import com.redhat.thermostat.client.osgi.service.VMContextAction; -import com.redhat.thermostat.client.swing.components.EdtHelper; -import com.redhat.thermostat.client.swing.components.HtmlTextBuilder; -import com.redhat.thermostat.client.swing.components.StatusBar; -import com.redhat.thermostat.client.swing.components.ThermostatPopupMenu; -import com.redhat.thermostat.client.swing.internal.MainView; -import com.redhat.thermostat.client.swing.internal.components.DecoratedDefaultMutableTreeNode; -import com.redhat.thermostat.client.swing.views.SearchFieldSwingView; -import com.redhat.thermostat.client.ui.Decorator; -import com.redhat.thermostat.client.ui.IconDescriptor; -import com.redhat.thermostat.common.ActionEvent; -import com.redhat.thermostat.common.ActionListener; -import com.redhat.thermostat.common.ActionNotifier; -import com.redhat.thermostat.common.HostsVMsLoader; -import com.redhat.thermostat.common.dao.HostRef; -import com.redhat.thermostat.common.dao.Ref; -import com.redhat.thermostat.common.dao.VmRef; -import com.redhat.thermostat.common.locale.Translate; -import com.redhat.thermostat.common.utils.StringUtils; - -public class MainWindow extends JFrame implements MainView { - - public static final String MAIN_WINDOW_NAME = "Thermostat_mainWindo_JFrame_parent#1"; - - private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer(); - - /** - * Updates a TreeModel in the background in an Swing EDT-safe manner. - */ - private static class BackgroundTreeModelWorker extends SwingWorker<DefaultMutableTreeNode, Void> { - - private JTree tree; - - private final DefaultTreeModel treeModel; - private DefaultMutableTreeNode treeRoot; - - private List<Filter<HostRef>> hostFilters; - private List<Filter<VmRef>> vmFilters; - private List<DecoratorProvider<HostRef>> hostDecorators; - private List<DecoratorProvider<VmRef>> vmDecorators; - - private HostsVMsLoader hostsVMsLoader; - - public BackgroundTreeModelWorker(DefaultTreeModel model, DefaultMutableTreeNode root, - List<Filter<HostRef>> hostFilters, List<Filter<VmRef>> vmFilters, - List<DecoratorProvider<HostRef>> hostDecorators, - List<DecoratorProvider<VmRef>> vmDecorators, - HostsVMsLoader hostsVMsLoader, JTree tree) - { - this.hostFilters = hostFilters; - this.vmFilters = vmFilters; - - this.vmDecorators = vmDecorators; - this.hostDecorators = hostDecorators; - - this.treeModel = model; - this.treeRoot = root; - this.hostsVMsLoader = hostsVMsLoader; - this.tree = tree; - } - - @Override - protected DefaultMutableTreeNode doInBackground() throws Exception { - DefaultMutableTreeNode root = new DefaultMutableTreeNode(); - - Collection<HostRef> hostsInRemoteModel = hostsVMsLoader.getHosts(); - buildHostSubTree(root, hostsInRemoteModel); - return root; - } - - private boolean buildHostSubTree(DefaultMutableTreeNode parent, Collection<HostRef> objectsInRemoteModel) { - boolean subTreeMatches = false; - for (HostRef inRemoteModel : objectsInRemoteModel) { - DecoratedDefaultMutableTreeNode inTreeNode = - new DecoratedDefaultMutableTreeNode(inRemoteModel); - - boolean shouldInsert = false; - if (hostFilters == null) { - shouldInsert = true; - } else { - shouldInsert = true; - for (Filter<HostRef> filter : hostFilters) { - if (!filter.matches(inRemoteModel)) { - shouldInsert = false; - break; - } - } - } - - Collection<VmRef> children = hostsVMsLoader.getVMs(inRemoteModel); - boolean subtreeResult = buildVmSubTree(inTreeNode, children); - if (subtreeResult) { - shouldInsert = true; - } - - if (shouldInsert) { - for (DecoratorProvider<HostRef> decorator : hostDecorators) { - Filter<HostRef> filter = decorator.getFilter(); - if (filter != null && filter.matches(inRemoteModel)) { - inTreeNode.addDecorator(decorator.getDecorator()); - } - } - - parent.add(inTreeNode); - subTreeMatches = true; - } - } - - return subTreeMatches; - } - - private boolean buildVmSubTree(DefaultMutableTreeNode parent, Collection<VmRef> objectsInRemoteModel) { - boolean subTreeMatches = false; - for (VmRef inRemoteModel : objectsInRemoteModel) { - DecoratedDefaultMutableTreeNode inTreeNode = - new DecoratedDefaultMutableTreeNode(inRemoteModel); - - boolean shouldInsert = false; - if (vmFilters == null) { - shouldInsert = true; - } else { - shouldInsert = true; - for (Filter<VmRef> filter : vmFilters) { - if (!filter.matches(inRemoteModel)) { - shouldInsert = false; - break; - } - } - } - - if (shouldInsert) { - for (DecoratorProvider<VmRef> decorator : vmDecorators) { - Filter<VmRef> filter = decorator.getFilter(); - if (filter != null && filter.matches(inRemoteModel)) { - inTreeNode.addDecorator(decorator.getDecorator()); - } - } - - parent.add(inTreeNode); - subTreeMatches = true; - } - } - - return subTreeMatches; - } - - @Override - protected void done() { - DefaultMutableTreeNode sourceRoot; - try { - sourceRoot = get(); - syncTree(sourceRoot, treeModel, treeRoot); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } - } - - private void syncTree(DefaultMutableTreeNode sourceRoot, DefaultTreeModel targetModel, DefaultMutableTreeNode targetNode) { - - @SuppressWarnings("unchecked") // We know what we put into these trees. - List<DefaultMutableTreeNode> sourceChildren = Collections.list(sourceRoot.children()); - - @SuppressWarnings("unchecked") - List<DefaultMutableTreeNode> targetChildren = Collections.list(targetNode.children()); - for (DefaultMutableTreeNode sourceChild : sourceChildren) { - Ref sourceRef = (Ref) sourceChild.getUserObject(); - DefaultMutableTreeNode targetChild = null; - for (DefaultMutableTreeNode aChild : targetChildren) { - Ref targetRef = (Ref) aChild.getUserObject(); - if (targetRef.equals(sourceRef)) { - targetChild = aChild; - if (sourceChild instanceof DecoratedDefaultMutableTreeNode) { - DecoratedDefaultMutableTreeNode source = (DecoratedDefaultMutableTreeNode) sourceChild; - ((DecoratedDefaultMutableTreeNode) targetChild).setDecorators(source.getDecorators()); - } - break; - } - } - - if (targetChild == null) { - targetChild = new DecoratedDefaultMutableTreeNode(sourceRef); - if (sourceChild instanceof DecoratedDefaultMutableTreeNode) { - DecoratedDefaultMutableTreeNode source = (DecoratedDefaultMutableTreeNode) sourceChild; - ((DecoratedDefaultMutableTreeNode) targetChild).setDecorators(source.getDecorators()); - } - targetModel.insertNodeInto(targetChild, targetNode, targetNode.getChildCount()); - } - - syncTree(sourceChild, targetModel, targetChild); - } - - for (DefaultMutableTreeNode targetChild : targetChildren) { - Ref targetRef = (Ref) targetChild.getUserObject(); - boolean matchFound = false; - for (DefaultMutableTreeNode sourceChild : sourceChildren) { - Ref sourceRef = (Ref) sourceChild.getUserObject(); - if (targetRef.equals(sourceRef)) { - matchFound = true; - break; - } - } - - if (!matchFound) { - targetModel.removeNodeFromParent(targetChild); - } - } - ensureRootIsExpanded(targetModel); - } - - private void ensureRootIsExpanded(final DefaultTreeModel model) { - DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot(); - tree.expandPath(new TreePath(root.getPath())); - } - - } - - private static final long serialVersionUID = 5608972421496808177L; - - private final JMenuBar mainMenuBar = new JMenuBar(); - private final MenuHelper mainMenuHelper = new MenuHelper(mainMenuBar); - private JPanel contentArea = null; - - private SearchFieldSwingView searchField = new SearchFieldSwingView(); - private JTree agentVmTree = null; - - private final ShutdownClient shutdownAction; - - private ActionNotifier<Action> actionNotifier = new ActionNotifier<>(this); - - private ThermostatPopupMenu vmContextMenu; - private StatusBar statusBar; - - private final DefaultMutableTreeNode publishedRoot = - new DefaultMutableTreeNode(translator.localize(LocaleResources.MAIN_WINDOW_TREE_ROOT_NAME)); - private final DefaultTreeModel publishedTreeModel = new DefaultTreeModel(publishedRoot); - - @SuppressWarnings("restriction") - public MainWindow() { - super(); - - setName(MAIN_WINDOW_NAME); - - shutdownAction = new ShutdownClient(); - - searchField.addActionListener(new ActionListener<SearchAction>() { - @Override - public void actionPerformed(ActionEvent<SearchAction> actionEvent) { - switch (actionEvent.getActionId()) { - case TEXT_CHANGED: - fireViewAction(Action.HOST_VM_TREE_FILTER); - break; - } - } - }); - agentVmTree = new JTree(publishedTreeModel); - agentVmTree.setName("agentVmTree"); - agentVmTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); - agentVmTree.setCellRenderer(new AgentVmTreeCellRenderer()); - agentVmTree.addTreeWillExpandListener(new TreeWillExpandListener() { - @Override - public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException { - /* Yup, tree will expand */ - } - - @Override - public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException { - if (new TreePath(publishedRoot.getPath()).equals(event.getPath())) { - throw new ExpandVetoException(event, "root cant be collapsed"); - } - } - }); - ToolTipManager.sharedInstance().registerComponent(agentVmTree); - contentArea = new JPanel(new BorderLayout()); - - setupMenus(); - setupPanels(); - - this.setPreferredSize(new Dimension(800, 600)); - - agentVmTree.setSelectionPath(new TreePath(((DefaultMutableTreeNode) publishedTreeModel.getRoot()).getPath())); - - //agentVmTree.setLargeModel(true); - agentVmTree.setRowHeight(25); - - statusBar = new StatusBar(); - getContentPane().add(statusBar, BorderLayout.SOUTH); - - setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); - addWindowListener(shutdownAction); - - // Handle SIGTERM/SIGINT properly - Signal.handle(new Signal("TERM"), shutdownAction); - Signal.handle(new Signal("INT"), shutdownAction); - - addComponentListener(new ComponentAdapter() { - - @Override - public void componentShown(ComponentEvent e) { - fireViewAction(Action.VISIBLE); - } - - @Override - public void componentHidden(ComponentEvent e) { - fireViewAction(Action.HIDDEN); - } - }); - - } - - private void setupMenus() { - - JMenu fileMenu = new JMenu(translator.localize(LocaleResources.MENU_FILE)); - fileMenu.getPopupMenu().setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1)); - mainMenuBar.add(fileMenu); - - JMenuItem fileExitMenu = new JMenuItem(translator.localize(LocaleResources.MENU_FILE_EXIT)); - fileExitMenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_DOWN_MASK)); - fileExitMenu.addActionListener(shutdownAction); - fileMenu.add(fileExitMenu); - - JMenu editMenu = new JMenu(translator.localize(LocaleResources.MENU_EDIT)); - mainMenuBar.add(editMenu); - - JMenuItem configureClientMenuItem = new JMenuItem(translator.localize(LocaleResources.MENU_EDIT_CONFIGURE_CLIENT)); - configureClientMenuItem.setName("showClientConfig"); - configureClientMenuItem.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent e) { - fireViewAction(Action.SHOW_CLIENT_CONFIG); - } - }); - editMenu.add(configureClientMenuItem); - - editMenu.addSeparator(); - JMenuItem historyModeMenuItem = new JCheckBoxMenuItem(translator.localize(LocaleResources.MENU_EDIT_ENABLE_HISTORY_MODE)); - historyModeMenuItem.setName("historyModeSwitch"); - historyModeMenuItem.setSelected(false); - historyModeMenuItem.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent e) { - fireViewAction(Action.SWITCH_HISTORY_MODE); - } - }); - editMenu.add(historyModeMenuItem); - - JMenu viewMenu = new JMenu(translator.localize(LocaleResources.MENU_VIEW)); - mainMenuBar.add(viewMenu); - JMenuItem configureAgentMenuItem = new JMenuItem(translator.localize(LocaleResources.MENU_VIEW_AGENTS)); - configureAgentMenuItem.setName("showAgentConfig"); - configureAgentMenuItem.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent e) { - fireViewAction(Action.SHOW_AGENT_CONFIG); - } - }); - viewMenu.add(configureAgentMenuItem); - - JMenu helpMenu = new JMenu(translator.localize(LocaleResources.MENU_HELP)); - helpMenu.getPopupMenu().setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1)); - mainMenuBar.add(helpMenu); - - JMenuItem helpAboutMenu = new JMenuItem(translator.localize(LocaleResources.MENU_HELP_ABOUT)); - helpAboutMenu.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent e) { - fireViewAction(Action.SHOW_ABOUT_DIALOG); - } - }); - helpMenu.add(helpAboutMenu); - setJMenuBar(mainMenuBar); - } - - private void setupPanels() { - JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); - splitPane.setOneTouchExpandable(true); - - JPanel navigationPanel = new JPanel(new BorderLayout()); - - navigationPanel.add(searchField, BorderLayout.PAGE_START); - - agentVmTree.addTreeSelectionListener(new TreeSelectionListener() { - @Override - public void valueChanged(TreeSelectionEvent e) { - if (e.isAddedPath()) { - fireViewAction(Action.HOST_VM_SELECTION_CHANGED); - } - } - }); - registerContextActionListener(agentVmTree); - - JScrollPane treeScrollPane = new JScrollPane(agentVmTree); - - navigationPanel.add(treeScrollPane); - - JPanel detailsPanel = createDetailsPanel(); - - navigationPanel.setMinimumSize(new Dimension(200,500)); - detailsPanel.setMinimumSize(new Dimension(500, 500)); - - splitPane.add(navigationPanel); - splitPane.add(detailsPanel); - - getContentPane().add(splitPane); - } - - private void registerContextActionListener(JTree agentVmTree2) { - vmContextMenu = new ThermostatPopupMenu(); - agentVmTree2.addMouseListener(new MouseAdapter() { - @Override - public void mousePressed(MouseEvent e) { - if (e.isPopupTrigger()) { - Ref ref = getSelectedHostOrVm(); - if (ref instanceof VmRef) { - fireViewAction(Action.SHOW_VM_CONTEXT_MENU, e); - } - } - } - }); - } - - @Override - public void showVMContextActions(final List<VMContextAction> actions, final MouseEvent e) { - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - vmContextMenu.removeAll(); - - for (final VMContextAction action: actions) { - JMenuItem contextAction = new JMenuItem(); - contextAction.setText(action.getName()); - contextAction.setToolTipText(action.getDescription()); - - contextAction.addActionListener(new java.awt.event.ActionListener() { - @Override - public void actionPerformed(java.awt.event.ActionEvent e) { - fireViewAction(Action.VM_CONTEXT_ACTION, action); - } - }); - vmContextMenu.add(contextAction); - } - - vmContextMenu.show((Component)e.getSource(), e.getX(), e.getY()); - } - - }); - } - - private JPanel createDetailsPanel() { - JPanel result = new JPanel(new BorderLayout()); - result.add(contentArea, BorderLayout.CENTER); - return result; - } - - @SuppressWarnings("restriction") - public class ShutdownClient extends WindowAdapter implements java.awt.event.ActionListener, sun.misc.SignalHandler { - - @Override - public void windowClosing(WindowEvent e) { - shutdown(); - } - - @Override - public void actionPerformed(java.awt.event.ActionEvent e) { - shutdown(); - } - - @Override - public void handle(Signal arg0) { - shutdown(); - } - - private void shutdown() { - dispose(); - fireViewAction(Action.SHUTDOWN); - } - - } - - private static class AgentVmTreeCellRenderer extends DefaultTreeCellRenderer { - private static final long serialVersionUID = 4444642511815252481L; - - @Override - public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { - - Object node = ((DefaultMutableTreeNode) value).getUserObject(); - setToolTipText(createToolTipText(node)); - - Component component = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); - if (value instanceof DecoratedDefaultMutableTreeNode) { - DecoratedDefaultMutableTreeNode treeNode = (DecoratedDefaultMutableTreeNode) value; - setAnnotation(treeNode, node, component); - } - - return component; - } - - // TODO: we can cache more, for example the full icon, not just the decoration - private Map<Decorator, ImageIcon> decoratorsCache = new HashMap<>(); - private void setAnnotation(DecoratedDefaultMutableTreeNode treeNode, Object value, Component component) { - - List<Decorator> decorators = treeNode.getDecorators(); - for (Decorator dec : decorators) { - String newText = dec.getLabel(getText()); - setText(newText); - setLabelFor(component); - - ImageIcon icon = decoratorsCache.get(dec); - if (icon == null) { - //System.err.println("cache miss: " + dec); - IconDescriptor iconDescriptor = dec.getIconDescriptor(); - if (iconDescriptor != null) { - ByteBuffer data = iconDescriptor.getData(); - icon = new ImageIcon(data.array()); - decoratorsCache.put(dec, icon); - } - } - - if (icon == null) { - return; - } - - Icon currentIcon = getIcon(); - switch (dec.getQuadrant()) { - case BOTTOM_LEFT: - int y = currentIcon.getIconHeight() - icon.getIconHeight(); - paintCustomIcon(currentIcon, icon, y); - break; - - case TOP_LEFT: - paintCustomIcon(currentIcon, icon, 0); - break; - - case MAIN: - default: - setIcon(icon); - break; - } - } - } - - private void paintCustomIcon(Icon currentIcon, ImageIcon icon, int y) { - BufferedImage image = new BufferedImage(currentIcon.getIconWidth(), - currentIcon.getIconHeight(), - BufferedImage.TYPE_INT_ARGB); - Graphics2D graphics = (Graphics2D) image.getGraphics(); - - currentIcon.paintIcon(null, graphics, 0, 0); - graphics.drawImage(icon.getImage(), 0, y, null); - - setIcon(new ImageIcon(image)); - } - - private String createToolTipText(Object value) { - if (value instanceof HostRef) { - HostRef hostRef = (HostRef) value; - String hostNameHtml = new HtmlTextBuilder().bold(hostRef.getHostName()).toPartialHtml(); - String agentIdHtml = new HtmlTextBuilder().bold(hostRef.getAgentId()).toPartialHtml(); - HtmlTextBuilder builder = new HtmlTextBuilder() - .appendRaw(translator.localize(LocaleResources.TREE_HOST_TOOLTIP_HOST_NAME, hostNameHtml)) - .newLine() - .appendRaw(translator.localize(LocaleResources.TREE_HOST_TOOLTIP_AGENT_ID, agentIdHtml)); - return builder.toHtml(); - } else if (value instanceof VmRef) { - VmRef vmRef = (VmRef) value; - String vmNameHtml= new HtmlTextBuilder().bold(vmRef.getName()).toPartialHtml(); - String vmIdHtml = new HtmlTextBuilder().bold(vmRef.getIdString()).toPartialHtml(); - HtmlTextBuilder builder = new HtmlTextBuilder() - .appendRaw(translator.localize(LocaleResources.TREE_HOST_TOOLTIP_VM_NAME, vmNameHtml)) - .newLine() - .appendRaw(translator.localize(LocaleResources.TREE_HOST_TOOLTIP_VM_ID, vmIdHtml)); - return builder.toHtml(); - } else { - return null; - } - } - } - - @Override - public JFrame getTopFrame() { - return this; - } - - @Override - public void addActionListener(ActionListener<Action> l) { - actionNotifier.addActionListener(l); - } - - public void removeViewActionListener(ActionListener<Action> l) { - actionNotifier.removeActionListener(l); - } - - private void fireViewAction(Action action) { - actionNotifier.fireAction(action); - } - - private void fireViewAction(Action action, Object payload) { - actionNotifier.fireAction(action, payload); - } - - @Override - public void updateTree(List<Filter<HostRef>> hostFilters, List<Filter<VmRef>> vmFilters, - List<DecoratorProvider<HostRef>> hostDecorators, - List<DecoratorProvider<VmRef>> vmDecorators, - HostsVMsLoader hostsVMsLoader) - { - BackgroundTreeModelWorker worker = - new BackgroundTreeModelWorker(publishedTreeModel, publishedRoot, - hostFilters, vmFilters, hostDecorators, vmDecorators, hostsVMsLoader, agentVmTree); - worker.execute(); - } - - @SuppressWarnings("unused") // Used for debugging but not in production code. - private static void printTree(PrintStream out, TreeNode node, int depth) { - out.println(StringUtils.repeat(" ", depth) + node.toString()); - @SuppressWarnings("unchecked") - List<TreeNode> children = Collections.list(node.children()); - for (TreeNode child : children) { - printTree(out, child, depth + 1); - } - } - - @Override - public void setWindowTitle(String title) { - setTitle(title); - } - - @Override - public void showMainWindow() { - try { - new EdtHelper().callAndWait(new Runnable() { - - @Override - public void run() { - pack(); - setVisible(true); - } - }); - } catch (InvocationTargetException e) { - throw new RuntimeException(e); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - - @Override - public void hideMainWindow() { - setVisible(false); - dispose(); - } - - @Override - public void setStatusBarPrimaryStatus(final String primaryStatus) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - statusBar.setPrimaryStatus(primaryStatus); - } - }); - } - - @Override - public void setSubView(final BasicView view) { - if (view instanceof SwingComponent) { - final SwingComponent swingComp = (SwingComponent)view; - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - contentArea.removeAll(); - Component toAdd = swingComp.getUiComponent(); - contentArea.add(toAdd); - contentArea.revalidate(); - } - }); - } - } - - @Override - public void addMenu(MenuAction action) { - mainMenuHelper.addMenuAction(action); - } - - @Override - public void removeMenu(MenuAction action) { - mainMenuHelper.removeMenuAction(action); - } - - /** - * Returns null to indicate no Ref is selected - */ - @Override - public Ref getSelectedHostOrVm() { - TreePath path = agentVmTree.getSelectionPath(); - if (path == null || path.getPathCount() == 1) { - return null; - } - return (Ref) ((DefaultMutableTreeNode) path.getLastPathComponent()).getUserObject(); - } - - @Override - public String getHostVmTreeFilterText() { - return searchField.getSearchText(); - } -}
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/MenuHelper.java Tue Dec 18 22:02:42 2012 +0100 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/MenuHelper.java Tue Dec 18 16:39:38 2012 -0500 @@ -50,7 +50,6 @@ import javax.swing.MenuElement; import com.redhat.thermostat.client.osgi.service.MenuAction; -import com.redhat.thermostat.client.swing.components.EdtHelper; import com.redhat.thermostat.common.utils.LoggingUtils; import com.redhat.thermostat.common.utils.StringUtils;
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ActionButton.java Tue Dec 18 22:02:42 2012 +0100 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ActionButton.java Tue Dec 18 16:39:38 2012 -0500 @@ -99,45 +99,5 @@ } } - public static void main(String[] args) throws InvocationTargetException, InterruptedException { - SwingUtilities.invokeAndWait(new Runnable() { - - @Override - public void run() { - JFrame frame = new JFrame(); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - HeaderPanel header = new HeaderPanel(); - header.setHeader("Test"); - - Icon icon = new Icon() { - - @Override - public void paintIcon(Component c, Graphics g, int x, int y) { - g.setColor(Color.CYAN); - g.fillRect(x, y, 16, 16); - } - - @Override - public int getIconWidth() { - // TODO Auto-generated method stub - return 16; - } - - @Override - public int getIconHeight() { - // TODO Auto-generated method stub - return 16; - } - }; - - header.addToolBarButton(new ActionButton(icon, "Fluff")); - - frame.getContentPane().add(header); - frame.setSize(500, 500); - frame.setVisible(true); - } - }); - } }
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ActionButtonUI.java Tue Dec 18 22:02:42 2012 +0100 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ActionButtonUI.java Tue Dec 18 16:39:38 2012 -0500 @@ -52,6 +52,7 @@ import javax.swing.JComponent; import javax.swing.plaf.metal.MetalButtonUI; +import com.redhat.thermostat.client.swing.GraphicsUtils; import com.redhat.thermostat.client.ui.Palette; class ActionButtonUI extends MetalButtonUI {
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/EdtHelper.java Tue Dec 18 22:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.client.swing.components; - -import java.awt.EventQueue; -import java.lang.reflect.InvocationTargetException; -import java.util.concurrent.Callable; - -import javax.swing.SwingUtilities; - -/** - * Allows operations to be performed consistently on the Swing EDT - * irrespective of whether the caller is running on the EDT or not. - * - * @see SwingUtilities#invokeAndWait(Runnable) - * @see SwingUtilities#invokeLater(Runnable) - */ -public class EdtHelper { - - @SuppressWarnings("serial") - private static class CallableException extends RuntimeException { - - private CallableException(Exception ex) { - super(ex); - } - - } - - private static class CallableWrapper<T> implements Runnable { - - private Callable<T> callable; - private T result; - - private CallableWrapper(Callable<T> c) { - callable = c; - } - - @Override - public void run() { - try { - result = callable.call(); - } catch (Exception ex) { - throw new CallableException(ex); - } - } - - private T getResult() { - return result; - } - } - - /** - * Invoke the supplied {@link Runnable} on the EDT. - * @param r encapsulates the code to run - * @throws InvocationTargetException encapsulates the actual exception - * that occurs when executing this code. - * @throws InterruptedException - */ - public void callAndWait(Runnable r) throws InvocationTargetException, InterruptedException { - if (EventQueue.isDispatchThread()) { - try { - r.run(); - } catch (Exception ex) { - throw new InvocationTargetException(ex); - } - } else { - EventQueue.invokeAndWait(r); - } - } - - /** - * Invokes the supplied {@link Callable} on the EDT, waits until it is - * finished execution and returns the result of invoking {@link Callable#call()}. - * @param c encapsulates the code to execute - * @return the result produce by c - * @throws InvocationTargetException indicates an exception occurred when executing the callable - * @throws InterruptedException - */ - public <T> T callAndWait(Callable<T> c) throws InvocationTargetException, InterruptedException { - CallableWrapper<T> w = new CallableWrapper<>(c); - callAndWait(w); - return w.getResult(); - } - -}
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/GradientPanel.java Tue Dec 18 22:02:42 2012 +0100 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/GradientPanel.java Tue Dec 18 16:39:38 2012 -0500 @@ -45,6 +45,8 @@ import javax.swing.JPanel; +import com.redhat.thermostat.client.swing.GraphicsUtils; + /** * A {@link JPanel} filled with a gradient color as the background. */
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/GradientRoundBorder.java Tue Dec 18 22:02:42 2012 +0100 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/GradientRoundBorder.java Tue Dec 18 16:39:38 2012 -0500 @@ -50,6 +50,7 @@ import javax.swing.border.Border; import javax.swing.plaf.UIResource; +import com.redhat.thermostat.client.swing.GraphicsUtils; import com.redhat.thermostat.client.ui.Palette; /**
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/GraphicsUtils.java Tue Dec 18 22:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.client.swing.components; - -import java.awt.Color; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.GradientPaint; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Paint; -import java.awt.RenderingHints; -import java.awt.Shape; -import java.awt.geom.RoundRectangle2D; - -import javax.swing.JComponent; - -import sun.swing.SwingUtilities2; - -@SuppressWarnings("restriction") -public class GraphicsUtils { - - private static GraphicsUtils instance = new GraphicsUtils(); - public static GraphicsUtils getInstance() { - return instance; - } - - public Graphics2D createAAGraphics(Graphics g) { - Graphics2D graphics = (Graphics2D) g.create(); - graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - return graphics; - } - - public void drawStringWithShadow(JComponent component, Graphics2D graphics, String string, Color foreground, int x, int y) { - // paint it twice to give a subtle drop shadow effect - - graphics.setColor(new Color(0f, 0f, 0f, 0.1f)); - SwingUtilities2.drawString(component, graphics, string, x, y + 1); - - graphics.setColor(foreground); - SwingUtilities2.drawString(component, graphics, string, x, y); - } - - public void drawString(JComponent component, Graphics2D graphics, String string, Color foreground, int x, int y) { - graphics.setColor(foreground); - SwingUtilities2.drawString(component, graphics, string, x, y); - } - - public FontMetrics getFontMetrics(JComponent component, Font font) { - return SwingUtilities2.getFontMetrics(component, font); - } - - public Shape getRoundShape(int width, int height) { - return new RoundRectangle2D.Double(0, 0, width, height, 4, 4); - } - - public void setGradientPaint(Graphics2D g, int x, int height, Color start, Color stop) { - Paint paint = new GradientPaint(x, 0, start, 0, height, stop); - g.setPaint(paint); - } -}
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/HtmlTextBuilder.java Tue Dec 18 22:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.client.swing.components; - -public class HtmlTextBuilder { - - /* - * The api provided by this class needs to be cleaned up. - */ - - private final StringBuilder text = new StringBuilder(); - - public HtmlTextBuilder() { - // do nothing - } - - public HtmlTextBuilder(String text) { - text = escape(text); - this.text.append(text); - } - - public HtmlTextBuilder bold(boolean on) { - if (on) { - this.text.append("<b>"); - } else { - this.text.append("</b>"); - } - return this; - } - - public HtmlTextBuilder bold(String toBold) { - text.append("<b>").append(toBold).append("</b>"); - return this; - } - - public HtmlTextBuilder larger(String toAppend) { - text.append("<font size='+2'>").append(escape(toAppend)).append("</font>"); - return this; - } - - public HtmlTextBuilder huge(String toAppend) { - text.append("<font size='+6'>").append(escape(toAppend)).append("</font>"); - return this; - } - - @Override - public String toString() { - // FIXME - return null; - } - - public String toHtml() { - return "<html>" + text.toString() + "</html>"; - } - - public String toPartialHtml() { - return text.toString(); - } - - private static String escape(String toEscape) { - // FIXME implement this - return toEscape; - } - - public HtmlTextBuilder append(String toAppend) { - text.append(escape(toAppend)); - return this; - } - - public HtmlTextBuilder appendRaw(String toAppend) { - text.append(toAppend); - return this; - } - - public static String boldHtml(String toBold) { - return new HtmlTextBuilder().bold(toBold).toHtml(); - } - - public HtmlTextBuilder newLine() { - text.append("<br>"); - return this; - } - -}
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/SectionHeader.java Tue Dec 18 22:02:42 2012 +0100 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/SectionHeader.java Tue Dec 18 16:39:38 2012 -0500 @@ -39,6 +39,8 @@ import javax.swing.JLabel; import javax.swing.SwingConstants; +import com.redhat.thermostat.client.swing.HtmlTextBuilder; + /** * A {@link JLabel} that is appropriate to use as a label for grouping * the following information together.
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ShadowLabel.java Tue Dec 18 22:02:42 2012 +0100 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ShadowLabel.java Tue Dec 18 16:39:38 2012 -0500 @@ -43,6 +43,8 @@ import javax.swing.JLabel; import javax.swing.plaf.metal.MetalLabelUI; +import com.redhat.thermostat.client.swing.GraphicsUtils; + /** * A {@link JLabel} that has a shadow. */
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/StatusBar.java Tue Dec 18 22:02:42 2012 +0100 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/StatusBar.java Tue Dec 18 16:39:38 2012 -0500 @@ -125,22 +125,5 @@ public String getPrimaryStatus() { return primaryStatus; } - - public static void main(String[] args) { - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - JFrame frame = new JFrame(); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.getContentPane().setLayout(new BorderLayout()); - - StatusBar statusBar = new StatusBar(); - frame.getContentPane().add(statusBar, BorderLayout.SOUTH); - - frame.setSize(500, 500); - frame.setVisible(true); - } - }); - } + }
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ToolbarButtonBorder.java Tue Dec 18 22:02:42 2012 +0100 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ToolbarButtonBorder.java Tue Dec 18 16:39:38 2012 -0500 @@ -47,6 +47,7 @@ import javax.swing.ButtonModel; import javax.swing.plaf.UIResource; +import com.redhat.thermostat.client.swing.GraphicsUtils; import com.redhat.thermostat.client.ui.Palette; @SuppressWarnings("serial")
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/MainWindow.java Tue Dec 18 16:39:38 2012 -0500 @@ -0,0 +1,805 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.client.swing.internal; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.image.BufferedImage; +import java.io.PrintStream; +import java.lang.reflect.InvocationTargetException; +import java.nio.ByteBuffer; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTree; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; +import javax.swing.ToolTipManager; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.event.TreeWillExpandListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.ExpandVetoException; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; + +import sun.misc.Signal; + +import com.redhat.thermostat.client.core.Filter; +import com.redhat.thermostat.client.core.views.BasicView; +import com.redhat.thermostat.client.core.views.SearchFieldView.SearchAction; +import com.redhat.thermostat.client.locale.LocaleResources; +import com.redhat.thermostat.client.osgi.service.DecoratorProvider; +import com.redhat.thermostat.client.osgi.service.MenuAction; +import com.redhat.thermostat.client.osgi.service.VMContextAction; +import com.redhat.thermostat.client.swing.EdtHelper; +import com.redhat.thermostat.client.swing.HtmlTextBuilder; +import com.redhat.thermostat.client.swing.MenuHelper; +import com.redhat.thermostat.client.swing.SwingComponent; +import com.redhat.thermostat.client.swing.components.StatusBar; +import com.redhat.thermostat.client.swing.components.ThermostatPopupMenu; +import com.redhat.thermostat.client.swing.internal.components.DecoratedDefaultMutableTreeNode; +import com.redhat.thermostat.client.swing.views.SearchFieldSwingView; +import com.redhat.thermostat.client.ui.Decorator; +import com.redhat.thermostat.client.ui.IconDescriptor; +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.ActionNotifier; +import com.redhat.thermostat.common.HostsVMsLoader; +import com.redhat.thermostat.common.dao.HostRef; +import com.redhat.thermostat.common.dao.Ref; +import com.redhat.thermostat.common.dao.VmRef; +import com.redhat.thermostat.common.locale.Translate; +import com.redhat.thermostat.common.utils.StringUtils; + +public class MainWindow extends JFrame implements MainView { + + public static final String MAIN_WINDOW_NAME = "Thermostat_mainWindo_JFrame_parent#1"; + + private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer(); + + /** + * Updates a TreeModel in the background in an Swing EDT-safe manner. + */ + private static class BackgroundTreeModelWorker extends SwingWorker<DefaultMutableTreeNode, Void> { + + private JTree tree; + + private final DefaultTreeModel treeModel; + private DefaultMutableTreeNode treeRoot; + + private List<Filter<HostRef>> hostFilters; + private List<Filter<VmRef>> vmFilters; + private List<DecoratorProvider<HostRef>> hostDecorators; + private List<DecoratorProvider<VmRef>> vmDecorators; + + private HostsVMsLoader hostsVMsLoader; + + public BackgroundTreeModelWorker(DefaultTreeModel model, DefaultMutableTreeNode root, + List<Filter<HostRef>> hostFilters, List<Filter<VmRef>> vmFilters, + List<DecoratorProvider<HostRef>> hostDecorators, + List<DecoratorProvider<VmRef>> vmDecorators, + HostsVMsLoader hostsVMsLoader, JTree tree) + { + this.hostFilters = hostFilters; + this.vmFilters = vmFilters; + + this.vmDecorators = vmDecorators; + this.hostDecorators = hostDecorators; + + this.treeModel = model; + this.treeRoot = root; + this.hostsVMsLoader = hostsVMsLoader; + this.tree = tree; + } + + @Override + protected DefaultMutableTreeNode doInBackground() throws Exception { + DefaultMutableTreeNode root = new DefaultMutableTreeNode(); + + Collection<HostRef> hostsInRemoteModel = hostsVMsLoader.getHosts(); + buildHostSubTree(root, hostsInRemoteModel); + return root; + } + + private boolean buildHostSubTree(DefaultMutableTreeNode parent, Collection<HostRef> objectsInRemoteModel) { + boolean subTreeMatches = false; + for (HostRef inRemoteModel : objectsInRemoteModel) { + DecoratedDefaultMutableTreeNode inTreeNode = + new DecoratedDefaultMutableTreeNode(inRemoteModel); + + boolean shouldInsert = false; + if (hostFilters == null) { + shouldInsert = true; + } else { + shouldInsert = true; + for (Filter<HostRef> filter : hostFilters) { + if (!filter.matches(inRemoteModel)) { + shouldInsert = false; + break; + } + } + } + + Collection<VmRef> children = hostsVMsLoader.getVMs(inRemoteModel); + boolean subtreeResult = buildVmSubTree(inTreeNode, children); + if (subtreeResult) { + shouldInsert = true; + } + + if (shouldInsert) { + for (DecoratorProvider<HostRef> decorator : hostDecorators) { + Filter<HostRef> filter = decorator.getFilter(); + if (filter != null && filter.matches(inRemoteModel)) { + inTreeNode.addDecorator(decorator.getDecorator()); + } + } + + parent.add(inTreeNode); + subTreeMatches = true; + } + } + + return subTreeMatches; + } + + private boolean buildVmSubTree(DefaultMutableTreeNode parent, Collection<VmRef> objectsInRemoteModel) { + boolean subTreeMatches = false; + for (VmRef inRemoteModel : objectsInRemoteModel) { + DecoratedDefaultMutableTreeNode inTreeNode = + new DecoratedDefaultMutableTreeNode(inRemoteModel); + + boolean shouldInsert = false; + if (vmFilters == null) { + shouldInsert = true; + } else { + shouldInsert = true; + for (Filter<VmRef> filter : vmFilters) { + if (!filter.matches(inRemoteModel)) { + shouldInsert = false; + break; + } + } + } + + if (shouldInsert) { + for (DecoratorProvider<VmRef> decorator : vmDecorators) { + Filter<VmRef> filter = decorator.getFilter(); + if (filter != null && filter.matches(inRemoteModel)) { + inTreeNode.addDecorator(decorator.getDecorator()); + } + } + + parent.add(inTreeNode); + subTreeMatches = true; + } + } + + return subTreeMatches; + } + + @Override + protected void done() { + DefaultMutableTreeNode sourceRoot; + try { + sourceRoot = get(); + syncTree(sourceRoot, treeModel, treeRoot); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } + } + + private void syncTree(DefaultMutableTreeNode sourceRoot, DefaultTreeModel targetModel, DefaultMutableTreeNode targetNode) { + + @SuppressWarnings("unchecked") // We know what we put into these trees. + List<DefaultMutableTreeNode> sourceChildren = Collections.list(sourceRoot.children()); + + @SuppressWarnings("unchecked") + List<DefaultMutableTreeNode> targetChildren = Collections.list(targetNode.children()); + for (DefaultMutableTreeNode sourceChild : sourceChildren) { + Ref sourceRef = (Ref) sourceChild.getUserObject(); + DefaultMutableTreeNode targetChild = null; + for (DefaultMutableTreeNode aChild : targetChildren) { + Ref targetRef = (Ref) aChild.getUserObject(); + if (targetRef.equals(sourceRef)) { + targetChild = aChild; + if (sourceChild instanceof DecoratedDefaultMutableTreeNode) { + DecoratedDefaultMutableTreeNode source = (DecoratedDefaultMutableTreeNode) sourceChild; + ((DecoratedDefaultMutableTreeNode) targetChild).setDecorators(source.getDecorators()); + } + break; + } + } + + if (targetChild == null) { + targetChild = new DecoratedDefaultMutableTreeNode(sourceRef); + if (sourceChild instanceof DecoratedDefaultMutableTreeNode) { + DecoratedDefaultMutableTreeNode source = (DecoratedDefaultMutableTreeNode) sourceChild; + ((DecoratedDefaultMutableTreeNode) targetChild).setDecorators(source.getDecorators()); + } + targetModel.insertNodeInto(targetChild, targetNode, targetNode.getChildCount()); + } + + syncTree(sourceChild, targetModel, targetChild); + } + + for (DefaultMutableTreeNode targetChild : targetChildren) { + Ref targetRef = (Ref) targetChild.getUserObject(); + boolean matchFound = false; + for (DefaultMutableTreeNode sourceChild : sourceChildren) { + Ref sourceRef = (Ref) sourceChild.getUserObject(); + if (targetRef.equals(sourceRef)) { + matchFound = true; + break; + } + } + + if (!matchFound) { + targetModel.removeNodeFromParent(targetChild); + } + } + ensureRootIsExpanded(targetModel); + } + + private void ensureRootIsExpanded(final DefaultTreeModel model) { + DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot(); + tree.expandPath(new TreePath(root.getPath())); + } + + } + + private static final long serialVersionUID = 5608972421496808177L; + + private final JMenuBar mainMenuBar = new JMenuBar(); + private final MenuHelper mainMenuHelper = new MenuHelper(mainMenuBar); + private JPanel contentArea = null; + + private SearchFieldSwingView searchField = new SearchFieldSwingView(); + private JTree agentVmTree = null; + + private final ShutdownClient shutdownAction; + + private ActionNotifier<Action> actionNotifier = new ActionNotifier<>(this); + + private ThermostatPopupMenu vmContextMenu; + private StatusBar statusBar; + + private final DefaultMutableTreeNode publishedRoot = + new DefaultMutableTreeNode(translator.localize(LocaleResources.MAIN_WINDOW_TREE_ROOT_NAME)); + private final DefaultTreeModel publishedTreeModel = new DefaultTreeModel(publishedRoot); + + @SuppressWarnings("restriction") + public MainWindow() { + super(); + + setName(MAIN_WINDOW_NAME); + + shutdownAction = new ShutdownClient(); + + searchField.addActionListener(new ActionListener<SearchAction>() { + @Override + public void actionPerformed(ActionEvent<SearchAction> actionEvent) { + switch (actionEvent.getActionId()) { + case TEXT_CHANGED: + fireViewAction(Action.HOST_VM_TREE_FILTER); + break; + } + } + }); + agentVmTree = new JTree(publishedTreeModel); + agentVmTree.setName("agentVmTree"); + agentVmTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + agentVmTree.setCellRenderer(new AgentVmTreeCellRenderer()); + agentVmTree.addTreeWillExpandListener(new TreeWillExpandListener() { + @Override + public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException { + /* Yup, tree will expand */ + } + + @Override + public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException { + if (new TreePath(publishedRoot.getPath()).equals(event.getPath())) { + throw new ExpandVetoException(event, "root cant be collapsed"); + } + } + }); + ToolTipManager.sharedInstance().registerComponent(agentVmTree); + contentArea = new JPanel(new BorderLayout()); + + setupMenus(); + setupPanels(); + + this.setPreferredSize(new Dimension(800, 600)); + + agentVmTree.setSelectionPath(new TreePath(((DefaultMutableTreeNode) publishedTreeModel.getRoot()).getPath())); + + //agentVmTree.setLargeModel(true); + agentVmTree.setRowHeight(25); + + statusBar = new StatusBar(); + getContentPane().add(statusBar, BorderLayout.SOUTH); + + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + addWindowListener(shutdownAction); + + // Handle SIGTERM/SIGINT properly + Signal.handle(new Signal("TERM"), shutdownAction); + Signal.handle(new Signal("INT"), shutdownAction); + + addComponentListener(new ComponentAdapter() { + + @Override + public void componentShown(ComponentEvent e) { + fireViewAction(Action.VISIBLE); + } + + @Override + public void componentHidden(ComponentEvent e) { + fireViewAction(Action.HIDDEN); + } + }); + + } + + private void setupMenus() { + + JMenu fileMenu = new JMenu(translator.localize(LocaleResources.MENU_FILE)); + fileMenu.getPopupMenu().setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1)); + mainMenuBar.add(fileMenu); + + JMenuItem fileExitMenu = new JMenuItem(translator.localize(LocaleResources.MENU_FILE_EXIT)); + fileExitMenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_DOWN_MASK)); + fileExitMenu.addActionListener(shutdownAction); + fileMenu.add(fileExitMenu); + + JMenu editMenu = new JMenu(translator.localize(LocaleResources.MENU_EDIT)); + mainMenuBar.add(editMenu); + + JMenuItem configureClientMenuItem = new JMenuItem(translator.localize(LocaleResources.MENU_EDIT_CONFIGURE_CLIENT)); + configureClientMenuItem.setName("showClientConfig"); + configureClientMenuItem.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + fireViewAction(Action.SHOW_CLIENT_CONFIG); + } + }); + editMenu.add(configureClientMenuItem); + + editMenu.addSeparator(); + JMenuItem historyModeMenuItem = new JCheckBoxMenuItem(translator.localize(LocaleResources.MENU_EDIT_ENABLE_HISTORY_MODE)); + historyModeMenuItem.setName("historyModeSwitch"); + historyModeMenuItem.setSelected(false); + historyModeMenuItem.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + fireViewAction(Action.SWITCH_HISTORY_MODE); + } + }); + editMenu.add(historyModeMenuItem); + + JMenu viewMenu = new JMenu(translator.localize(LocaleResources.MENU_VIEW)); + mainMenuBar.add(viewMenu); + JMenuItem configureAgentMenuItem = new JMenuItem(translator.localize(LocaleResources.MENU_VIEW_AGENTS)); + configureAgentMenuItem.setName("showAgentConfig"); + configureAgentMenuItem.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + fireViewAction(Action.SHOW_AGENT_CONFIG); + } + }); + viewMenu.add(configureAgentMenuItem); + + JMenu helpMenu = new JMenu(translator.localize(LocaleResources.MENU_HELP)); + helpMenu.getPopupMenu().setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1)); + mainMenuBar.add(helpMenu); + + JMenuItem helpAboutMenu = new JMenuItem(translator.localize(LocaleResources.MENU_HELP_ABOUT)); + helpAboutMenu.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + fireViewAction(Action.SHOW_ABOUT_DIALOG); + } + }); + helpMenu.add(helpAboutMenu); + setJMenuBar(mainMenuBar); + } + + private void setupPanels() { + JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); + splitPane.setOneTouchExpandable(true); + + JPanel navigationPanel = new JPanel(new BorderLayout()); + + navigationPanel.add(searchField, BorderLayout.PAGE_START); + + agentVmTree.addTreeSelectionListener(new TreeSelectionListener() { + @Override + public void valueChanged(TreeSelectionEvent e) { + if (e.isAddedPath()) { + fireViewAction(Action.HOST_VM_SELECTION_CHANGED); + } + } + }); + registerContextActionListener(agentVmTree); + + JScrollPane treeScrollPane = new JScrollPane(agentVmTree); + + navigationPanel.add(treeScrollPane); + + JPanel detailsPanel = createDetailsPanel(); + + navigationPanel.setMinimumSize(new Dimension(200,500)); + detailsPanel.setMinimumSize(new Dimension(500, 500)); + + splitPane.add(navigationPanel); + splitPane.add(detailsPanel); + + getContentPane().add(splitPane); + } + + private void registerContextActionListener(JTree agentVmTree2) { + vmContextMenu = new ThermostatPopupMenu(); + agentVmTree2.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + if (e.isPopupTrigger()) { + Ref ref = getSelectedHostOrVm(); + if (ref instanceof VmRef) { + fireViewAction(Action.SHOW_VM_CONTEXT_MENU, e); + } + } + } + }); + } + + @Override + public void showVMContextActions(final List<VMContextAction> actions, final MouseEvent e) { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + vmContextMenu.removeAll(); + + for (final VMContextAction action: actions) { + JMenuItem contextAction = new JMenuItem(); + contextAction.setText(action.getName()); + contextAction.setToolTipText(action.getDescription()); + + contextAction.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + fireViewAction(Action.VM_CONTEXT_ACTION, action); + } + }); + vmContextMenu.add(contextAction); + } + + vmContextMenu.show((Component)e.getSource(), e.getX(), e.getY()); + } + + }); + } + + private JPanel createDetailsPanel() { + JPanel result = new JPanel(new BorderLayout()); + result.add(contentArea, BorderLayout.CENTER); + return result; + } + + @SuppressWarnings("restriction") + public class ShutdownClient extends WindowAdapter implements java.awt.event.ActionListener, sun.misc.SignalHandler { + + @Override + public void windowClosing(WindowEvent e) { + shutdown(); + } + + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + shutdown(); + } + + @Override + public void handle(Signal arg0) { + shutdown(); + } + + private void shutdown() { + dispose(); + fireViewAction(Action.SHUTDOWN); + } + + } + + private static class AgentVmTreeCellRenderer extends DefaultTreeCellRenderer { + private static final long serialVersionUID = 4444642511815252481L; + + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { + + Object node = ((DefaultMutableTreeNode) value).getUserObject(); + setToolTipText(createToolTipText(node)); + + Component component = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); + if (value instanceof DecoratedDefaultMutableTreeNode) { + DecoratedDefaultMutableTreeNode treeNode = (DecoratedDefaultMutableTreeNode) value; + setAnnotation(treeNode, node, component); + } + + return component; + } + + // TODO: we can cache more, for example the full icon, not just the decoration + private Map<Decorator, ImageIcon> decoratorsCache = new HashMap<>(); + private void setAnnotation(DecoratedDefaultMutableTreeNode treeNode, Object value, Component component) { + + List<Decorator> decorators = treeNode.getDecorators(); + for (Decorator dec : decorators) { + String newText = dec.getLabel(getText()); + setText(newText); + setLabelFor(component); + + ImageIcon icon = decoratorsCache.get(dec); + if (icon == null) { + //System.err.println("cache miss: " + dec); + IconDescriptor iconDescriptor = dec.getIconDescriptor(); + if (iconDescriptor != null) { + ByteBuffer data = iconDescriptor.getData(); + icon = new ImageIcon(data.array()); + decoratorsCache.put(dec, icon); + } + } + + if (icon == null) { + return; + } + + Icon currentIcon = getIcon(); + switch (dec.getQuadrant()) { + case BOTTOM_LEFT: + int y = currentIcon.getIconHeight() - icon.getIconHeight(); + paintCustomIcon(currentIcon, icon, y); + break; + + case TOP_LEFT: + paintCustomIcon(currentIcon, icon, 0); + break; + + case MAIN: + default: + setIcon(icon); + break; + } + } + } + + private void paintCustomIcon(Icon currentIcon, ImageIcon icon, int y) { + BufferedImage image = new BufferedImage(currentIcon.getIconWidth(), + currentIcon.getIconHeight(), + BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics = (Graphics2D) image.getGraphics(); + + currentIcon.paintIcon(null, graphics, 0, 0); + graphics.drawImage(icon.getImage(), 0, y, null); + + setIcon(new ImageIcon(image)); + } + + private String createToolTipText(Object value) { + if (value instanceof HostRef) { + HostRef hostRef = (HostRef) value; + String hostNameHtml = new HtmlTextBuilder().bold(hostRef.getHostName()).toPartialHtml(); + String agentIdHtml = new HtmlTextBuilder().bold(hostRef.getAgentId()).toPartialHtml(); + HtmlTextBuilder builder = new HtmlTextBuilder() + .appendRaw(translator.localize(LocaleResources.TREE_HOST_TOOLTIP_HOST_NAME, hostNameHtml)) + .newLine() + .appendRaw(translator.localize(LocaleResources.TREE_HOST_TOOLTIP_AGENT_ID, agentIdHtml)); + return builder.toHtml(); + } else if (value instanceof VmRef) { + VmRef vmRef = (VmRef) value; + String vmNameHtml= new HtmlTextBuilder().bold(vmRef.getName()).toPartialHtml(); + String vmIdHtml = new HtmlTextBuilder().bold(vmRef.getIdString()).toPartialHtml(); + HtmlTextBuilder builder = new HtmlTextBuilder() + .appendRaw(translator.localize(LocaleResources.TREE_HOST_TOOLTIP_VM_NAME, vmNameHtml)) + .newLine() + .appendRaw(translator.localize(LocaleResources.TREE_HOST_TOOLTIP_VM_ID, vmIdHtml)); + return builder.toHtml(); + } else { + return null; + } + } + } + + @Override + public JFrame getTopFrame() { + return this; + } + + @Override + public void addActionListener(ActionListener<Action> l) { + actionNotifier.addActionListener(l); + } + + public void removeViewActionListener(ActionListener<Action> l) { + actionNotifier.removeActionListener(l); + } + + private void fireViewAction(Action action) { + actionNotifier.fireAction(action); + } + + private void fireViewAction(Action action, Object payload) { + actionNotifier.fireAction(action, payload); + } + + @Override + public void updateTree(List<Filter<HostRef>> hostFilters, List<Filter<VmRef>> vmFilters, + List<DecoratorProvider<HostRef>> hostDecorators, + List<DecoratorProvider<VmRef>> vmDecorators, + HostsVMsLoader hostsVMsLoader) + { + BackgroundTreeModelWorker worker = + new BackgroundTreeModelWorker(publishedTreeModel, publishedRoot, + hostFilters, vmFilters, hostDecorators, vmDecorators, hostsVMsLoader, agentVmTree); + worker.execute(); + } + + @SuppressWarnings("unused") // Used for debugging but not in production code. + private static void printTree(PrintStream out, TreeNode node, int depth) { + out.println(StringUtils.repeat(" ", depth) + node.toString()); + @SuppressWarnings("unchecked") + List<TreeNode> children = Collections.list(node.children()); + for (TreeNode child : children) { + printTree(out, child, depth + 1); + } + } + + @Override + public void setWindowTitle(String title) { + setTitle(title); + } + + @Override + public void showMainWindow() { + try { + new EdtHelper().callAndWait(new Runnable() { + + @Override + public void run() { + pack(); + setVisible(true); + } + }); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + @Override + public void hideMainWindow() { + setVisible(false); + dispose(); + } + + @Override + public void setStatusBarPrimaryStatus(final String primaryStatus) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + statusBar.setPrimaryStatus(primaryStatus); + } + }); + } + + @Override + public void setSubView(final BasicView view) { + if (view instanceof SwingComponent) { + final SwingComponent swingComp = (SwingComponent)view; + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + contentArea.removeAll(); + Component toAdd = swingComp.getUiComponent(); + contentArea.add(toAdd); + contentArea.revalidate(); + } + }); + } + } + + @Override + public void addMenu(MenuAction action) { + mainMenuHelper.addMenuAction(action); + } + + @Override + public void removeMenu(MenuAction action) { + mainMenuHelper.removeMenuAction(action); + } + + /** + * Returns null to indicate no Ref is selected + */ + @Override + public Ref getSelectedHostOrVm() { + TreePath path = agentVmTree.getSelectionPath(); + if (path == null || path.getPathCount() == 1) { + return null; + } + return (Ref) ((DefaultMutableTreeNode) path.getLastPathComponent()).getUserObject(); + } + + @Override + public String getHostVmTreeFilterText() { + return searchField.getSearchText(); + } +}
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/UiFacadeFactoryImpl.java Tue Dec 18 22:02:42 2012 +0100 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/UiFacadeFactoryImpl.java Tue Dec 18 16:39:38 2012 -0500 @@ -48,7 +48,6 @@ import com.redhat.thermostat.client.core.views.SummaryViewProvider; import com.redhat.thermostat.client.core.views.VmInformationViewProvider; import com.redhat.thermostat.client.osgi.service.VMContextAction; -import com.redhat.thermostat.client.swing.MainWindow; import com.redhat.thermostat.client.ui.HostInformationController; import com.redhat.thermostat.client.ui.MainWindowController; import com.redhat.thermostat.client.ui.SummaryController;
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/views/ClientConfigurationSwing.java Tue Dec 18 22:02:42 2012 +0100 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/views/ClientConfigurationSwing.java Tue Dec 18 16:39:38 2012 -0500 @@ -52,7 +52,7 @@ import com.redhat.thermostat.client.core.views.ClientConfigurationView; import com.redhat.thermostat.client.locale.LocaleResources; -import com.redhat.thermostat.client.swing.components.EdtHelper; +import com.redhat.thermostat.client.swing.EdtHelper; import com.redhat.thermostat.common.ActionEvent; import com.redhat.thermostat.common.ActionListener; import com.redhat.thermostat.common.locale.Translate;
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/views/SearchFieldSwingView.java Tue Dec 18 22:02:42 2012 +0100 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/views/SearchFieldSwingView.java Tue Dec 18 16:39:38 2012 -0500 @@ -59,8 +59,8 @@ import com.redhat.thermostat.client.core.views.SearchFieldView; import com.redhat.thermostat.client.locale.LocaleResources; +import com.redhat.thermostat.client.swing.EdtHelper; import com.redhat.thermostat.client.swing.IconResource; -import com.redhat.thermostat.client.swing.components.EdtHelper; import com.redhat.thermostat.common.ActionListener; import com.redhat.thermostat.common.ActionNotifier; import com.redhat.thermostat.common.locale.Translate;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/EdtHelperTest.java Tue Dec 18 16:39:38 2012 -0500 @@ -0,0 +1,196 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.client.swing; + +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.awt.EventQueue; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.Callable; + +import javax.swing.SwingUtilities; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.client.swing.EdtHelper; + +public class EdtHelperTest { + + private class ExceptionCallable implements Callable<Object> { + + @Override + public Object call() throws Exception { + throw new Exception("fluff"); + } + + } + + private class ResultCallable implements Callable<Object> { + + private Object result; + private ResultCallable(Object r) { + result = r; + } + @Override + public Object call() throws Exception { + // By waiting here, we make sure the EDTHelper actually waits for the call. + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + if (EventQueue.isDispatchThread()) { + calledOnEDT = true; + } + return result; + } + + } + + private class TestRunnable implements Runnable { + + @Override + public void run() { + // By waiting here, we make sure the EDTHelper actually waits for the call. + try { + Thread.sleep(100); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + if (EventQueue.isDispatchThread()) { + calledOnEDT = true; + } + } + + } + + private volatile boolean calledOnEDT; + + @Before + public void setUp() { + calledOnEDT = false; + } + + @After + public void tearDown() { + calledOnEDT = false; + } + + @Test + public void testCallRunnableFromNonEDT() throws InvocationTargetException, InterruptedException { + Runnable r = new TestRunnable(); + new EdtHelper().callAndWait(r); + assertTrue(calledOnEDT); + } + + @Test + public void testCallRunnableFromEDT() throws InvocationTargetException, InterruptedException { + final Runnable r = new TestRunnable(); + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + try { + new EdtHelper().callAndWait(r); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + }); + assertTrue(calledOnEDT); + } + + @Test + public void testCallCallableFromNoEDT() throws InvocationTargetException, InterruptedException { + final Object expected = new Object(); + Callable<Object> c = new ResultCallable(expected); + Object result = new EdtHelper().callAndWait(c); + assertTrue(calledOnEDT); + assertSame(expected, result); + } + + @Test + public void testCallCallableFromEDT() throws InvocationTargetException, InterruptedException { + final Object expected = new Object(); + final Callable<Object> c = new ResultCallable(expected); + final Object[] result = new Object[1]; + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + try { + result[0] = new EdtHelper().callAndWait(c); + } catch (InvocationTargetException | InterruptedException e) { + throw new RuntimeException(); + } + } + }); + assertTrue(calledOnEDT); + assertSame(expected, result[0]); + } + + @Test(expected=InvocationTargetException.class) + public void testCallCallableFromNoEDTThrowingException() throws InvocationTargetException, InterruptedException { + Callable<Object> c = new ExceptionCallable(); + new EdtHelper().callAndWait(c); + } + + @Test + public void testCallCallableFromEDTThrowingException() throws InvocationTargetException, InterruptedException { + final boolean[] exceptionThrown = new boolean[1]; + final Callable<Object> c = new ExceptionCallable(); + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + try { + new EdtHelper().callAndWait(c); + } catch (InvocationTargetException e) { + exceptionThrown[0] = true; + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + }); + assertTrue(exceptionThrown[0]); + } +}
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/MainWindowTest.java Tue Dec 18 22:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,356 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.client.swing; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.isA; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JRadioButtonMenuItem; - -import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner; - -import org.fest.swing.annotation.GUITest; -import org.fest.swing.edt.FailOnThreadViolationRepaintManager; -import org.fest.swing.edt.GuiActionRunner; -import org.fest.swing.edt.GuiTask; -import org.fest.swing.exception.ComponentLookupException; -import org.fest.swing.fixture.FrameFixture; -import org.fest.swing.fixture.JMenuItemFixture; -import org.fest.swing.fixture.JTextComponentFixture; -import org.fest.swing.fixture.JTreeFixture; -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.junit.runner.RunWith; - -import com.redhat.thermostat.client.core.Filter; -import com.redhat.thermostat.client.core.views.SearchFieldView; -import com.redhat.thermostat.client.osgi.service.DecoratorProvider; -import com.redhat.thermostat.client.osgi.service.MenuAction; -import com.redhat.thermostat.client.swing.internal.MainView; -import com.redhat.thermostat.client.ui.Decorator; -import com.redhat.thermostat.common.ActionEvent; -import com.redhat.thermostat.common.ActionListener; -import com.redhat.thermostat.common.HostsVMsLoader; -import com.redhat.thermostat.common.dao.HostRef; - -@RunWith(CacioFESTRunner.class) -public class MainWindowTest { - - private FrameFixture frameFixture; - private MainWindow window; - private ActionListener<MainView.Action> l; - - @BeforeClass - public static void setUpOnce() { - FailOnThreadViolationRepaintManager.install(); - } - - @SuppressWarnings("unchecked") // mock(ActionListener.class) - @Before - public void setUp() { - - GuiActionRunner.execute(new GuiTask() { - - @Override - protected void executeInEDT() throws Throwable { - window = new MainWindow(); - l = mock(ActionListener.class); - window.addActionListener(l); - } - }); - - frameFixture = new FrameFixture(window); - } - - @After - public void tearDown() { - frameFixture.cleanUp(); - frameFixture = null; - window = null; - l = null; - } - - @Category(GUITest.class) - @Test - public void testHostVmSelectionChangedSupport() { - frameFixture.show(); - JTreeFixture hostVMTree = frameFixture.tree("agentVmTree"); - hostVMTree.selectRows(0); - - verify(l).actionPerformed(new ActionEvent<MainView.Action>(window, MainView.Action.HOST_VM_SELECTION_CHANGED)); - } - - @Category(GUITest.class) - @Test - public void testHostVmDecoratorsAdded() throws InterruptedException { - - List<DecoratorProvider<HostRef>> decorators = new ArrayList<>(); - @SuppressWarnings("unchecked") - DecoratorProvider<HostRef> refDecorator = mock(DecoratorProvider.class); - final Decorator decorator = mock(Decorator.class); - when(decorator.getLabel(anyString())).thenReturn("fluff"); - - when(refDecorator.getDecorator()).thenReturn(decorator); - - @SuppressWarnings("unchecked") - Filter<HostRef> filter = mock(Filter.class); - when(filter.matches(isA(HostRef.class))).thenReturn(false).thenReturn(true); - - when(refDecorator.getFilter()).thenReturn(filter); - - decorators.add(refDecorator); - - HostsVMsLoader hostsVMsLoader = mock(HostsVMsLoader.class); - Collection<HostRef> expectedHosts = new ArrayList<>(); - expectedHosts.add(new HostRef("123", "fluffhost1")); - expectedHosts.add(new HostRef("456", "fluffhost2")); - - when(hostsVMsLoader.getHosts()).thenReturn(expectedHosts); - - window.updateTree(null, null, decorators, null, hostsVMsLoader); - - Thread.sleep(50); - - frameFixture.show(); - frameFixture.requireVisible(); - - verify(decorator, times(0)).getLabel("fluffhost1"); - verify(decorator, atLeastOnce()).getLabel("fluffhost2"); - } - - @Category(GUITest.class) - @Test - public void testHostVMTreeFilterPropertySupport() { - String SEARCH_TEXT = "test"; - frameFixture.show(); - JTextComponentFixture hostVMTreeFilterField = frameFixture.textBox(SearchFieldView.VIEW_NAME); - hostVMTreeFilterField.enterText(SEARCH_TEXT); - - verify(l, times(SEARCH_TEXT.length())).actionPerformed(new ActionEvent<MainView.Action>(window, MainView.Action.HOST_VM_TREE_FILTER)); - } - - @Category(GUITest.class) - @Test - public void verifyThatCloseFiresShutdownEvent() { - - frameFixture.show(); - - frameFixture.close(); - frameFixture.requireNotVisible(); - verify(l).actionPerformed(new ActionEvent<MainView.Action>(window, MainView.Action.SHUTDOWN)); - } - - @Category(GUITest.class) - @Test - public void verifyShowMainWindowShowsWindow() { - window.showMainWindow(); - frameFixture.requireVisible(); - } - - @Category(GUITest.class) - @Test - public void verifyHideMainWindowHidesWindow() { - GuiActionRunner.execute(new GuiTask() { - @Override - protected void executeInEDT() throws Throwable { - window.showMainWindow(); - } - }); - frameFixture.requireVisible(); - GuiActionRunner.execute(new GuiTask() { - @Override - protected void executeInEDT() throws Throwable { - window.hideMainWindow(); - } - }); - frameFixture.requireNotVisible(); - } - - @Category(GUITest.class) - @Test - public void verifyThatClientPreferencesMenuItemTriggersEvent() { - frameFixture.show(); - JMenuItemFixture menuItem = frameFixture.menuItem("showClientConfig"); - menuItem.click(); - frameFixture.close(); - frameFixture.requireNotVisible(); - - verify(l).actionPerformed(new ActionEvent<MainView.Action>(window, MainView.Action.SHOW_CLIENT_CONFIG)); - } - - @Category(GUITest.class) - @Test - public void verifyThatAgentPreferencesMenuItemTriggersEvent() { - frameFixture.show(); - JMenuItemFixture menuItem = frameFixture.menuItem("showAgentConfig"); - menuItem.click(); - frameFixture.close(); - frameFixture.requireNotVisible(); - - verify(l).actionPerformed(new ActionEvent<MainView.Action>(window, MainView.Action.SHOW_AGENT_CONFIG)); - } - - - @Category(GUITest.class) - @Test - public void verifyThatHistorySwitchTriggersEvent() { - frameFixture.show(); - JMenuItemFixture menuItem = frameFixture.menuItem("historyModeSwitch"); - menuItem.click(); - frameFixture.close(); - frameFixture.requireNotVisible(); - - verify(l).actionPerformed(new ActionEvent<MainView.Action>(window, MainView.Action.SWITCH_HISTORY_MODE)); - } - - @Category(GUITest.class) - @Test - public void addRemoveMenu() { - final String PARENT_NAME = "File"; - final String MENU_NAME = "Test2"; - MenuAction action = mock(MenuAction.class); - when(action.getName()).thenReturn(MENU_NAME); - when(action.getPath()).thenReturn(new String[] {PARENT_NAME, MENU_NAME}); - when(action.getType()).thenReturn(MenuAction.Type.STANDARD); - - JMenuItemFixture menuItem; - - frameFixture.show(); - - window.addMenu(action); - - menuItem = frameFixture.menuItemWithPath(PARENT_NAME, MENU_NAME); - assertNotNull(menuItem); - menuItem.click(); - - verify(action).execute(); - - window.removeMenu(action); - - try { - menuItem = frameFixture.menuItemWithPath(PARENT_NAME, MENU_NAME); - // should not reach here - assertTrue(false); - } catch (ComponentLookupException cle) { - // expected - } - } - - @Category(GUITest.class) - @Test - public void addRadioMenu() { - final String PARENT_NAME = "File"; - final String MENU_NAME = "Test"; - MenuAction action = mock(MenuAction.class); - when(action.getName()).thenReturn(MENU_NAME); - when(action.getPath()).thenReturn(new String[] {PARENT_NAME, MENU_NAME}); - - - when(action.getType()).thenReturn(MenuAction.Type.RADIO); - - JMenuItemFixture menuItem; - - frameFixture.show(); - - window.addMenu(action); - - menuItem = frameFixture.menuItemWithPath(PARENT_NAME, MENU_NAME); - assertNotNull(menuItem); - - assertTrue(menuItem.target instanceof JRadioButtonMenuItem); - } - - @Category(GUITest.class) - @Test - public void addCheckBoxMenu() { - final String PARENT_NAME = "File"; - final String MENU_NAME = "Test"; - MenuAction action = mock(MenuAction.class); - when(action.getName()).thenReturn(MENU_NAME); - when(action.getType()).thenReturn(MenuAction.Type.CHECK); - when(action.getPath()).thenReturn(new String[] {PARENT_NAME, MENU_NAME}); - - - JMenuItemFixture menuItem; - - frameFixture.show(); - - window.addMenu(action); - - menuItem = frameFixture.menuItemWithPath(PARENT_NAME, MENU_NAME); - assertNotNull(menuItem); - - assertTrue(menuItem.target instanceof JCheckBoxMenuItem); - } - - @Category(GUITest.class) - @Test - public void testGetHostVMTreeFilter() { - frameFixture.show(); - JTextComponentFixture hostVMTreeFilterField = frameFixture.textBox(SearchFieldView.VIEW_NAME); - hostVMTreeFilterField.enterText("test"); - String actual = window.getHostVmTreeFilterText(); - assertEquals("test", actual); - } - - @Category(GUITest.class) - @Test - public void testGetSelectedHostOrVm() { - frameFixture.show(); - JTreeFixture hostVMTree = frameFixture.tree("agentVmTree"); - hostVMTree.selectRow(0); - - assertEquals(null, window.getSelectedHostOrVm()); - } - -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/ActionButtonTest.java Tue Dec 18 16:39:38 2012 -0500 @@ -0,0 +1,126 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.client.swing.components; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; + +import javax.swing.Icon; +import javax.swing.JFrame; + +import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner; + +import org.fest.swing.edt.FailOnThreadViolationRepaintManager; +import org.fest.swing.edt.GuiActionRunner; +import org.fest.swing.edt.GuiQuery; +import org.fest.swing.fixture.FrameFixture; +import org.fest.swing.fixture.JButtonFixture; +import org.junit.After; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(CacioFESTRunner.class) +public class ActionButtonTest { + + private FrameFixture frameFixture; + + @BeforeClass + public static void setUpOnce() { + FailOnThreadViolationRepaintManager.install(); + } + + @After + public void tearDown() { + if (frameFixture != null) { + frameFixture.cleanUp(); + } + } + + @Test + public void testActionButton() { + JFrame frame = GuiActionRunner.execute(new GuiQuery<JFrame>() { + @Override + protected JFrame executeInEDT() throws Throwable { + + JFrame frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + HeaderPanel header = new HeaderPanel(); + header.setHeader("Test"); + + Icon icon = new Icon() { + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + g.setColor(Color.CYAN); + g.fillRect(x, y, 16, 16); + + } + + @Override + public int getIconWidth() { + // TODO Auto-generated method stub + return 16; + } + + @Override + public int getIconHeight() { + // TODO Auto-generated method stub + return 16; + } + }; + + ActionButton button = new ActionButton(icon, "Fluff"); + button.setName("button"); + header.addToolBarButton(button); + + frame.getContentPane().add(header); + frame.setSize(500, 500); + frame.setVisible(true); + return frame; + } + }); + frameFixture = new FrameFixture(frame); + JButtonFixture actionButton = frameFixture.button("button"); + actionButton.requireText(""); + actionButton.requireEnabled(); + + } + +}
--- a/client/swing/src/test/java/com/redhat/thermostat/client/swing/components/EdtHelperTest.java Tue Dec 18 22:02:42 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,194 +0,0 @@ -/* - * Copyright 2012 Red Hat, Inc. - * - * This file is part of Thermostat. - * - * Thermostat is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * Thermostat is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Thermostat; see the file COPYING. If not see - * <http://www.gnu.org/licenses/>. - * - * Linking this code with other modules is making a combined work - * based on this code. Thus, the terms and conditions of the GNU - * General Public License cover the whole combination. - * - * As a special exception, the copyright holders of this code give - * you permission to link this code with independent modules to - * produce an executable, regardless of the license terms of these - * independent modules, and to copy and distribute the resulting - * executable under terms of your choice, provided that you also - * meet, for each linked independent module, the terms and conditions - * of the license of that module. An independent module is a module - * which is not derived from or based on this code. If you modify - * this code, you may extend this exception to your version of the - * library, but you are not obligated to do so. If you do not wish - * to do so, delete this exception statement from your version. - */ - -package com.redhat.thermostat.client.swing.components; - -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -import java.awt.EventQueue; -import java.lang.reflect.InvocationTargetException; -import java.util.concurrent.Callable; - -import javax.swing.SwingUtilities; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -public class EdtHelperTest { - - private class ExceptionCallable implements Callable<Object> { - - @Override - public Object call() throws Exception { - throw new Exception("fluff"); - } - - } - - private class ResultCallable implements Callable<Object> { - - private Object result; - private ResultCallable(Object r) { - result = r; - } - @Override - public Object call() throws Exception { - // By waiting here, we make sure the EDTHelper actually waits for the call. - try { - Thread.sleep(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - if (EventQueue.isDispatchThread()) { - calledOnEDT = true; - } - return result; - } - - } - - private class TestRunnable implements Runnable { - - @Override - public void run() { - // By waiting here, we make sure the EDTHelper actually waits for the call. - try { - Thread.sleep(100); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - if (EventQueue.isDispatchThread()) { - calledOnEDT = true; - } - } - - } - - private volatile boolean calledOnEDT; - - @Before - public void setUp() { - calledOnEDT = false; - } - - @After - public void tearDown() { - calledOnEDT = false; - } - - @Test - public void testCallRunnableFromNonEDT() throws InvocationTargetException, InterruptedException { - Runnable r = new TestRunnable(); - new EdtHelper().callAndWait(r); - assertTrue(calledOnEDT); - } - - @Test - public void testCallRunnableFromEDT() throws InvocationTargetException, InterruptedException { - final Runnable r = new TestRunnable(); - SwingUtilities.invokeAndWait(new Runnable() { - - @Override - public void run() { - try { - new EdtHelper().callAndWait(r); - } catch (InvocationTargetException e) { - throw new RuntimeException(e); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - }); - assertTrue(calledOnEDT); - } - - @Test - public void testCallCallableFromNoEDT() throws InvocationTargetException, InterruptedException { - final Object expected = new Object(); - Callable<Object> c = new ResultCallable(expected); - Object result = new EdtHelper().callAndWait(c); - assertTrue(calledOnEDT); - assertSame(expected, result); - } - - @Test - public void testCallCallableFromEDT() throws InvocationTargetException, InterruptedException { - final Object expected = new Object(); - final Callable<Object> c = new ResultCallable(expected); - final Object[] result = new Object[1]; - SwingUtilities.invokeAndWait(new Runnable() { - - @Override - public void run() { - try { - result[0] = new EdtHelper().callAndWait(c); - } catch (InvocationTargetException | InterruptedException e) { - throw new RuntimeException(); - } - } - }); - assertTrue(calledOnEDT); - assertSame(expected, result[0]); - } - - @Test(expected=InvocationTargetException.class) - public void testCallCallableFromNoEDTThrowingException() throws InvocationTargetException, InterruptedException { - Callable<Object> c = new ExceptionCallable(); - new EdtHelper().callAndWait(c); - } - - @Test - public void testCallCallableFromEDTThrowingException() throws InvocationTargetException, InterruptedException { - final boolean[] exceptionThrown = new boolean[1]; - final Callable<Object> c = new ExceptionCallable(); - SwingUtilities.invokeAndWait(new Runnable() { - - @Override - public void run() { - try { - new EdtHelper().callAndWait(c); - } catch (InvocationTargetException e) { - exceptionThrown[0] = true; - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - }); - assertTrue(exceptionThrown[0]); - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/MainWindowTest.java Tue Dec 18 16:39:38 2012 -0500 @@ -0,0 +1,357 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.client.swing.internal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JRadioButtonMenuItem; + +import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner; + +import org.fest.swing.annotation.GUITest; +import org.fest.swing.edt.FailOnThreadViolationRepaintManager; +import org.fest.swing.edt.GuiActionRunner; +import org.fest.swing.edt.GuiTask; +import org.fest.swing.exception.ComponentLookupException; +import org.fest.swing.fixture.FrameFixture; +import org.fest.swing.fixture.JMenuItemFixture; +import org.fest.swing.fixture.JTextComponentFixture; +import org.fest.swing.fixture.JTreeFixture; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; + +import com.redhat.thermostat.client.core.Filter; +import com.redhat.thermostat.client.core.views.SearchFieldView; +import com.redhat.thermostat.client.osgi.service.DecoratorProvider; +import com.redhat.thermostat.client.osgi.service.MenuAction; +import com.redhat.thermostat.client.swing.internal.MainView; +import com.redhat.thermostat.client.swing.internal.MainWindow; +import com.redhat.thermostat.client.ui.Decorator; +import com.redhat.thermostat.common.ActionEvent; +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.HostsVMsLoader; +import com.redhat.thermostat.common.dao.HostRef; + +@RunWith(CacioFESTRunner.class) +public class MainWindowTest { + + private FrameFixture frameFixture; + private MainWindow window; + private ActionListener<MainView.Action> l; + + @BeforeClass + public static void setUpOnce() { + FailOnThreadViolationRepaintManager.install(); + } + + @SuppressWarnings("unchecked") // mock(ActionListener.class) + @Before + public void setUp() { + + GuiActionRunner.execute(new GuiTask() { + + @Override + protected void executeInEDT() throws Throwable { + window = new MainWindow(); + l = mock(ActionListener.class); + window.addActionListener(l); + } + }); + + frameFixture = new FrameFixture(window); + } + + @After + public void tearDown() { + frameFixture.cleanUp(); + frameFixture = null; + window = null; + l = null; + } + + @Category(GUITest.class) + @Test + public void testHostVmSelectionChangedSupport() { + frameFixture.show(); + JTreeFixture hostVMTree = frameFixture.tree("agentVmTree"); + hostVMTree.selectRows(0); + + verify(l).actionPerformed(new ActionEvent<MainView.Action>(window, MainView.Action.HOST_VM_SELECTION_CHANGED)); + } + + @Category(GUITest.class) + @Test + public void testHostVmDecoratorsAdded() throws InterruptedException { + + List<DecoratorProvider<HostRef>> decorators = new ArrayList<>(); + @SuppressWarnings("unchecked") + DecoratorProvider<HostRef> refDecorator = mock(DecoratorProvider.class); + final Decorator decorator = mock(Decorator.class); + when(decorator.getLabel(anyString())).thenReturn("fluff"); + + when(refDecorator.getDecorator()).thenReturn(decorator); + + @SuppressWarnings("unchecked") + Filter<HostRef> filter = mock(Filter.class); + when(filter.matches(isA(HostRef.class))).thenReturn(false).thenReturn(true); + + when(refDecorator.getFilter()).thenReturn(filter); + + decorators.add(refDecorator); + + HostsVMsLoader hostsVMsLoader = mock(HostsVMsLoader.class); + Collection<HostRef> expectedHosts = new ArrayList<>(); + expectedHosts.add(new HostRef("123", "fluffhost1")); + expectedHosts.add(new HostRef("456", "fluffhost2")); + + when(hostsVMsLoader.getHosts()).thenReturn(expectedHosts); + + window.updateTree(null, null, decorators, null, hostsVMsLoader); + + Thread.sleep(50); + + frameFixture.show(); + frameFixture.requireVisible(); + + verify(decorator, times(0)).getLabel("fluffhost1"); + verify(decorator, atLeastOnce()).getLabel("fluffhost2"); + } + + @Category(GUITest.class) + @Test + public void testHostVMTreeFilterPropertySupport() { + String SEARCH_TEXT = "test"; + frameFixture.show(); + JTextComponentFixture hostVMTreeFilterField = frameFixture.textBox(SearchFieldView.VIEW_NAME); + hostVMTreeFilterField.enterText(SEARCH_TEXT); + + verify(l, times(SEARCH_TEXT.length())).actionPerformed(new ActionEvent<MainView.Action>(window, MainView.Action.HOST_VM_TREE_FILTER)); + } + + @Category(GUITest.class) + @Test + public void verifyThatCloseFiresShutdownEvent() { + + frameFixture.show(); + + frameFixture.close(); + frameFixture.requireNotVisible(); + verify(l).actionPerformed(new ActionEvent<MainView.Action>(window, MainView.Action.SHUTDOWN)); + } + + @Category(GUITest.class) + @Test + public void verifyShowMainWindowShowsWindow() { + window.showMainWindow(); + frameFixture.requireVisible(); + } + + @Category(GUITest.class) + @Test + public void verifyHideMainWindowHidesWindow() { + GuiActionRunner.execute(new GuiTask() { + @Override + protected void executeInEDT() throws Throwable { + window.showMainWindow(); + } + }); + frameFixture.requireVisible(); + GuiActionRunner.execute(new GuiTask() { + @Override + protected void executeInEDT() throws Throwable { + window.hideMainWindow(); + } + }); + frameFixture.requireNotVisible(); + } + + @Category(GUITest.class) + @Test + public void verifyThatClientPreferencesMenuItemTriggersEvent() { + frameFixture.show(); + JMenuItemFixture menuItem = frameFixture.menuItem("showClientConfig"); + menuItem.click(); + frameFixture.close(); + frameFixture.requireNotVisible(); + + verify(l).actionPerformed(new ActionEvent<MainView.Action>(window, MainView.Action.SHOW_CLIENT_CONFIG)); + } + + @Category(GUITest.class) + @Test + public void verifyThatAgentPreferencesMenuItemTriggersEvent() { + frameFixture.show(); + JMenuItemFixture menuItem = frameFixture.menuItem("showAgentConfig"); + menuItem.click(); + frameFixture.close(); + frameFixture.requireNotVisible(); + + verify(l).actionPerformed(new ActionEvent<MainView.Action>(window, MainView.Action.SHOW_AGENT_CONFIG)); + } + + + @Category(GUITest.class) + @Test + public void verifyThatHistorySwitchTriggersEvent() { + frameFixture.show(); + JMenuItemFixture menuItem = frameFixture.menuItem("historyModeSwitch"); + menuItem.click(); + frameFixture.close(); + frameFixture.requireNotVisible(); + + verify(l).actionPerformed(new ActionEvent<MainView.Action>(window, MainView.Action.SWITCH_HISTORY_MODE)); + } + + @Category(GUITest.class) + @Test + public void addRemoveMenu() { + final String PARENT_NAME = "File"; + final String MENU_NAME = "Test2"; + MenuAction action = mock(MenuAction.class); + when(action.getName()).thenReturn(MENU_NAME); + when(action.getPath()).thenReturn(new String[] {PARENT_NAME, MENU_NAME}); + when(action.getType()).thenReturn(MenuAction.Type.STANDARD); + + JMenuItemFixture menuItem; + + frameFixture.show(); + + window.addMenu(action); + + menuItem = frameFixture.menuItemWithPath(PARENT_NAME, MENU_NAME); + assertNotNull(menuItem); + menuItem.click(); + + verify(action).execute(); + + window.removeMenu(action); + + try { + menuItem = frameFixture.menuItemWithPath(PARENT_NAME, MENU_NAME); + // should not reach here + assertTrue(false); + } catch (ComponentLookupException cle) { + // expected + } + } + + @Category(GUITest.class) + @Test + public void addRadioMenu() { + final String PARENT_NAME = "File"; + final String MENU_NAME = "Test"; + MenuAction action = mock(MenuAction.class); + when(action.getName()).thenReturn(MENU_NAME); + when(action.getPath()).thenReturn(new String[] {PARENT_NAME, MENU_NAME}); + + + when(action.getType()).thenReturn(MenuAction.Type.RADIO); + + JMenuItemFixture menuItem; + + frameFixture.show(); + + window.addMenu(action); + + menuItem = frameFixture.menuItemWithPath(PARENT_NAME, MENU_NAME); + assertNotNull(menuItem); + + assertTrue(menuItem.target instanceof JRadioButtonMenuItem); + } + + @Category(GUITest.class) + @Test + public void addCheckBoxMenu() { + final String PARENT_NAME = "File"; + final String MENU_NAME = "Test"; + MenuAction action = mock(MenuAction.class); + when(action.getName()).thenReturn(MENU_NAME); + when(action.getType()).thenReturn(MenuAction.Type.CHECK); + when(action.getPath()).thenReturn(new String[] {PARENT_NAME, MENU_NAME}); + + + JMenuItemFixture menuItem; + + frameFixture.show(); + + window.addMenu(action); + + menuItem = frameFixture.menuItemWithPath(PARENT_NAME, MENU_NAME); + assertNotNull(menuItem); + + assertTrue(menuItem.target instanceof JCheckBoxMenuItem); + } + + @Category(GUITest.class) + @Test + public void testGetHostVMTreeFilter() { + frameFixture.show(); + JTextComponentFixture hostVMTreeFilterField = frameFixture.textBox(SearchFieldView.VIEW_NAME); + hostVMTreeFilterField.enterText("test"); + String actual = window.getHostVmTreeFilterText(); + assertEquals("test", actual); + } + + @Category(GUITest.class) + @Test + public void testGetSelectedHostOrVm() { + frameFixture.show(); + JTreeFixture hostVMTree = frameFixture.tree("agentVmTree"); + hostVMTree.selectRow(0); + + assertEquals(null, window.getSelectedHostOrVm()); + } + +}
--- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadTimelineChart.java Tue Dec 18 22:02:42 2012 +0100 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/SwingThreadTimelineChart.java Tue Dec 18 16:39:38 2012 -0500 @@ -57,8 +57,8 @@ import javax.swing.JPanel; import javax.swing.SwingUtilities; +import com.redhat.thermostat.client.swing.GraphicsUtils; import com.redhat.thermostat.client.swing.components.GradientRoundBorder; -import com.redhat.thermostat.client.swing.components.GraphicsUtils; import com.redhat.thermostat.client.ui.Palette; import com.redhat.thermostat.common.model.LongRange; import com.redhat.thermostat.common.model.LongRangeNormalizer;
--- a/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/ThreadTimelineLegendPanel.java Tue Dec 18 22:02:42 2012 +0100 +++ b/thread/client-swing/src/main/java/com/redhat/thermostat/thread/client/swing/impl/ThreadTimelineLegendPanel.java Tue Dec 18 16:39:38 2012 -0500 @@ -50,7 +50,7 @@ import javax.swing.SwingConstants; import javax.swing.SwingUtilities; -import com.redhat.thermostat.client.swing.components.GraphicsUtils; +import com.redhat.thermostat.client.swing.GraphicsUtils; import com.redhat.thermostat.thread.client.common.chart.ChartColors; @SuppressWarnings("serial")
--- a/vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/ObjectDetailsPanel.java Tue Dec 18 22:02:42 2012 +0100 +++ b/vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/ObjectDetailsPanel.java Tue Dec 18 16:39:38 2012 -0500 @@ -55,8 +55,8 @@ import javax.swing.JLabel; import com.redhat.thermostat.client.core.views.SearchFieldView.SearchAction; +import com.redhat.thermostat.client.swing.EdtHelper; import com.redhat.thermostat.client.swing.SwingComponent; -import com.redhat.thermostat.client.swing.components.EdtHelper; import com.redhat.thermostat.client.swing.views.SearchFieldSwingView; import com.redhat.thermostat.common.ActionListener; import com.redhat.thermostat.common.ActionEvent;
--- a/vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/ObjectRootsFrame.java Tue Dec 18 22:02:42 2012 +0100 +++ b/vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/ObjectRootsFrame.java Tue Dec 18 16:39:38 2012 -0500 @@ -58,7 +58,7 @@ import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreePath; -import com.redhat.thermostat.client.swing.components.EdtHelper; +import com.redhat.thermostat.client.swing.EdtHelper; import com.redhat.thermostat.common.ActionListener; import com.redhat.thermostat.common.ActionNotifier; import com.redhat.thermostat.common.locale.Translate;
--- a/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/HeapDetailsSwingTest.java Tue Dec 18 22:02:42 2012 +0100 +++ b/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/HeapDetailsSwingTest.java Tue Dec 18 16:39:38 2012 -0500 @@ -60,7 +60,7 @@ import org.junit.Test; import org.junit.runner.RunWith; -import com.redhat.thermostat.client.swing.components.EdtHelper; +import com.redhat.thermostat.client.swing.EdtHelper; import com.redhat.thermostat.vm.heap.analysis.client.swing.internal.HeapDetailsSwing; import com.redhat.thermostat.vm.heap.analysis.client.swing.internal.HistogramPanel; import com.redhat.thermostat.vm.heap.analysis.client.swing.internal.ObjectDetailsPanel;