Mercurial > hg > release > thermostat-0.15
changeset 1260:aebcf2e03dc5
New VMTree (part I)
review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-September/008321.html
reviewed-by: omajid
line wrap: on
line diff
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/EmptyIcon.java Mon Sep 30 16:38:48 2013 +0200 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/EmptyIcon.java Mon Sep 30 16:38:49 2013 +0200 @@ -39,14 +39,11 @@ import java.awt.Component; import java.awt.Graphics; -import javax.swing.Icon; -import javax.swing.ImageIcon; - /** * A blank {@link Icon}. */ @SuppressWarnings("serial") -public class EmptyIcon extends ImageIcon { +public class EmptyIcon extends Icon { private int width; private int height;
--- a/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/FontAwesomeIcon.java Mon Sep 30 16:38:48 2013 +0200 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/FontAwesomeIcon.java Mon Sep 30 16:38:49 2013 +0200 @@ -65,6 +65,8 @@ private Font font; + private Color color; + static { try { InputStream stream = @@ -77,6 +79,10 @@ } /** + * Creates a new {@link FontAwesomeIcon} painted in {@link Color#BLACK}. + * + * <br /><br /> + * * Please, refer to: * <a href='http://fortawesome.github.io/Font-Awesome/cheatsheet/'> * Font-Awesome Website</a> for the actual @@ -85,11 +91,28 @@ * @see {@link http://fortawesome.github.io/Font-Awesome/cheatsheet/} */ public FontAwesomeIcon(char iconID, int size) { + this(iconID, size, Color.BLACK); + } + + /** + * Creates a new {@link FontAwesomeIcon} painted in the given {@link Color}. + * + * <br /><br /> + * + * Please, refer to: + * <a href='http://fortawesome.github.io/Font-Awesome/cheatsheet/'> + * Font-Awesome Website</a> for the actual + * values accepted as {@code iconID}. + * + * @see {@link http://fortawesome.github.io/Font-Awesome/cheatsheet/} + */ + public FontAwesomeIcon(char iconID, int size, Color color) { this.iconID = iconID; this.size = size; font = awesome.deriveFont(Font.PLAIN, size); + this.color = color; } - + @Override public synchronized void paintIcon(Component c, Graphics g, int x, int y) { @@ -100,9 +123,11 @@ Graphics2D graphics = (Graphics2D) buffer.getGraphics(); graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - + graphics.setRenderingHint(RenderingHints.KEY_RENDERING, + RenderingHints.VALUE_RENDER_QUALITY); + graphics.setFont(font); - graphics.setColor(Color.BLACK); + graphics.setColor(color); int stringY = getIconHeight() - (getIconHeight()/4) + 1; graphics.drawString(String.valueOf(iconID), 0, stringY);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ThermostatScrollBar.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,55 @@ +/* + * Copyright 2012, 2013 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 com.redhat.thermostat.client.swing.components.ThermostatThinScrollBar; + +/** + * This widget implements standard sized scrollbars. + */ +@SuppressWarnings("serial") +class ThermostatScrollBar extends ThermostatThinScrollBar { + public ThermostatScrollBar() { + this(ThermostatScrollBar.VERTICAL); + } + + public ThermostatScrollBar(int orientation) { + super(orientation); + setOpaque(false); + setUI(new ThermostatScrollBarUI()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ThermostatScrollBarUI.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,132 @@ +/* + * Copyright 2012, 2013 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.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.RoundRectangle2D; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JScrollBar; +import javax.swing.plaf.basic.BasicScrollBarUI; + +import com.redhat.thermostat.client.swing.GraphicsUtils; +import com.redhat.thermostat.client.ui.Palette; + +class ThermostatScrollBarUI extends BasicScrollBarUI { + + // TODO: move to common UIResources class + private static final Color FG_COLOR = Palette.EARL_GRAY.getColor(); + + @SuppressWarnings("serial") + private class EmptyButton extends JButton { + + public EmptyButton() { + setOpaque(false); + setMaximumSize(new Dimension(0, 0)); + } + + @Override + public void paint(Graphics g) {} + } + + @Override + protected void installDefaults() { + super.installDefaults(); + + scrollBarWidth = 16; + incrGap = 0; + decrGap = 0; + } + + @Override + protected JButton createDecreaseButton(int orientation) { + return new EmptyButton(); + } + + @Override + protected JButton createIncreaseButton(int orientation) { + return new EmptyButton(); + } + + @Override + protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) {} + + @Override + protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) { + if(thumbBounds.isEmpty() || !scrollbar.isEnabled()) { + return; + } + + int x = 0; + int y = 0; + + int w = 0; + int h = 0; + + GraphicsUtils utils = GraphicsUtils.getInstance(); + Graphics2D graphics = utils.createAAGraphics(g); + if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { + x = thumbBounds.x + 4; + y = thumbBounds.y; + + w = 8; + h = thumbBounds.height - 1; + + } else { + x = thumbBounds.x; + y = thumbBounds.y + 4; + + w = thumbBounds.width - 1; + h = 8; + } + + graphics.translate(x, y); + + Shape shape = new RoundRectangle2D.Double(0, 0, w, h, 4, 4); + + graphics.setColor(FG_COLOR); + graphics.fill(shape); + + graphics.dispose(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/ThermostatScrollPane.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright 2012, 2013 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 javax.swing.JComponent; +import javax.swing.JScrollPane; + +@SuppressWarnings("serial") +public class ThermostatScrollPane extends JScrollPane { + + public ThermostatScrollPane(JComponent view) { + super(view); + + setVerticalScrollBar(new ThermostatScrollBar(ThermostatThinScrollBar.VERTICAL)); + setHorizontalScrollBar(new ThermostatScrollBar(ThermostatThinScrollBar.HORIZONTAL)); + + setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + setBorder(null); + + setViewportBorder(null); + getViewport().setOpaque(false); + setOpaque(false); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/components/VerticalLayout.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,74 @@ +/* + * Copyright 2012, 2013 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.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Rectangle; + +/** + * A layout that lays components in a vertical stack according to + * the component hierarchy preferred height. + */ +public class VerticalLayout extends AbstractLayout { + + @Override + protected void doLayout(Container parent) { + Rectangle rect = new Rectangle(); + for (Component component : parent.getComponents()) { + Dimension dim = component.getPreferredSize(); + rect.width = parent.getWidth(); + rect.height = dim.height; + component.setBounds(rect); + rect.y += dim.height; + } + } + + @Override + public Dimension preferredLayoutSize(Container parent) { + + Dimension size = new Dimension(); + for (Component component : parent.getComponents()) { + Dimension dim = component.getPreferredSize(); + size.width = Math.max(dim.width, size.width); + size.height += dim.height; + } + + return size; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/accordion/Accordion.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,227 @@ +/* + * Copyright 2012, 2013 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.accordion; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JScrollPane; + +import com.redhat.thermostat.client.swing.components.ThermostatScrollPane; +import com.redhat.thermostat.client.swing.components.VerticalLayout; + +/** + * An Accordion widget. H and C types represent Header and Component and are + * added and managed for the accordion via the {@link AccordionModel} class. + * + * <br /><br /> + * + * H and C do not have to be widgets themselves, since the + * {@link AccordionComponentFactory} is responsible to create the specific + * widget to be used inside the Accordion. + * + */ +@SuppressWarnings("serial") +public class Accordion<H, C> extends JPanel { + + public static final int ICON_SIZE = 24; + + static final int MIN_HEIGHT = ICON_SIZE; + static final int MIN_WIDTH = 200; + + private JScrollPane scrollPane; + + private AccordionModel<H, C> model; + private HashMap<H, TitledPane> panes; + private HashMap<H, Map<C, Component>> components; + + private AccordionComponentFactory<H, C> componentFactory; + + private AccordionContentPane contentPane; + + private AccordionComponentController componentController; + + public Accordion(AccordionComponentFactory<H, C> componentFactory) { + + this.componentFactory = componentFactory; + componentController = new AccordionComponentController(); + + setLayout(new BorderLayout()); + + contentPane = new AccordionContentPane(); + contentPane.setLayout(new VerticalLayout()); + + model = new AccordionModel<>(); + model.addAccordionModelChangeListener(new AccordionModelChangeListenerImpl()); + panes = new HashMap<>(); + components = new HashMap<>(); + + scrollPane = new ThermostatScrollPane(contentPane); + + add(scrollPane, BorderLayout.CENTER); + } + + public AccordionModel<H, C> getModel() { + return model; + } + + @Override + public Dimension getPreferredSize() { + Dimension dim = new Dimension(); + dim.width = Accordion.MIN_WIDTH; + for (Component comp : getComponents()) { + Dimension pref = comp.getPreferredSize(); + if (dim.width < pref.width) { + dim.width = pref.width; + } + dim.height += pref.height; + } + return dim; + } + + private class AccordionComponentClickEventModel extends MouseAdapter { + private AccordionComponent referenceComponent; + public AccordionComponentClickEventModel(AccordionComponent referenceComponent) { + this.referenceComponent = referenceComponent; + } + + @Override + public void mouseClicked(MouseEvent e) { + componentController.setSelectedItem(referenceComponent); + } + } + + private class AccordionHeaderClickEventModel extends MouseAdapter { + private TitledPane referenceComponent; + public AccordionHeaderClickEventModel(TitledPane referenceComponent) { + this.referenceComponent = referenceComponent; + } + + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() >= 2) { + referenceComponent.setExpanded(!referenceComponent.isExpanded()); + } + } + } + + private class AccordionModelChangeListenerImpl implements AccordionModelChangeListener<H, C> { + + @Override + public void headerAdded(AccordionHeaderEvent<H> e) { + H header = e.getHeader(); + TitledPane pane = componentFactory.createHeader(header); + + pane.addMouseListener(new AccordionComponentClickEventModel(pane)); + pane.addMouseListener(new AccordionHeaderClickEventModel(pane)); + panes.put(header, pane); + + Accordion.this.contentPane.add(pane); + Accordion.this.contentPane.revalidate(); + } + + @Override + public void componentAdded(AccordionComponentEvent<H, C> e) { + C component = e.getComponent(); + H header = e.getHeader(); + AccordionComponent comp = componentFactory.createComponent(header, component); + + TitledPane pane = panes.get(header); + JComponent content = pane.getContent(); + if (content == null) { + content = new AccordionContentPane(); + content.setLayout(new VerticalLayout()); + pane.setContent(content); + } + + Component contentUnit = comp.getUiComponent(); + contentUnit.addMouseListener(new AccordionComponentClickEventModel(comp)); + + content.add(contentUnit); + content.revalidate(); + + Map<C, Component> componentsMap = components.get(header); + if (componentsMap == null) { + componentsMap = new HashMap<>(); + components.put(header, componentsMap); + } + componentsMap.put(component, contentUnit); + } + + @Override + public void componentRemoved(AccordionComponentEvent<H, C> e) { + C component = e.getComponent(); + H header = e.getHeader(); + + Map<C, Component> componentsMap = components.get(header); + Component contentUnit = componentsMap.remove(component); + if (componentsMap.isEmpty()) { + components.remove(header); + } + + TitledPane pane = panes.get(header); + JComponent content = pane.getContent(); + content.remove(contentUnit); + content.revalidate(); + } + + @Override + public void headerRemoved(AccordionHeaderEvent<H> e) { + H header = e.getHeader(); + + components.remove(header); + TitledPane pane = panes.remove(header); + Accordion.this.contentPane.remove(pane); + Accordion.this.contentPane.revalidate(); + } + } + + public void addAccordionItemSelectedChangeListener(AccordionItemSelectedChangeListener l) { + componentController.addAccordionItemSelectedChangeListener(l); + } + + public void removeAccordionItemSelectedChangeListener(AccordionItemSelectedChangeListener l) { + componentController.removeAccordionItemSelectedChangeListener(l); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/accordion/AccordionComponent.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,46 @@ +/* + * Copyright 2012, 2013 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.accordion; + +import com.redhat.thermostat.client.swing.SwingComponent; + +/** + * Represents a {@link Selectable} {@link SwingComponent} inside the + * {@link Accordion}. + */ +public interface AccordionComponent extends SwingComponent, Selectable { +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/accordion/AccordionComponentController.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,86 @@ +/* + * Copyright 2012, 2013 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.accordion; + +import javax.swing.event.EventListenerList; + +class AccordionComponentController { + + protected EventListenerList listenerList; + + private AccordionComponent selectedComponent; + + public AccordionComponentController() { + listenerList = new EventListenerList(); + } + + void setSelectedItem(AccordionComponent selectedComponent) { + AccordionComponent oldSelected = this.selectedComponent; + this.selectedComponent = selectedComponent; + + if (oldSelected != null) { + oldSelected.setSelected(false); + } + + if (selectedComponent != null) { + selectedComponent.setSelected(true); + } + + if (oldSelected != this.selectedComponent) { + fireItemSelectedChanged(oldSelected, selectedComponent); + } + } + + void addAccordionItemSelectedChangeListener(AccordionItemSelectedChangeListener l) { + listenerList.add(AccordionItemSelectedChangeListener.class, l); + } + + void removeAccordionItemSelectedChangeListener(AccordionItemSelectedChangeListener l) { + listenerList.remove(AccordionItemSelectedChangeListener.class, l); + } + + private void fireItemSelectedChanged(AccordionComponent oldComp, AccordionComponent newComp) { + Object[] listeners = listenerList.getListenerList(); + + ItemSelectedEvent event = new ItemSelectedEvent(oldComp, newComp); + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == AccordionItemSelectedChangeListener.class) { + ((AccordionItemSelectedChangeListener) listeners[i + 1]).itemSelected(event); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/accordion/AccordionComponentEvent.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,58 @@ +/* + * Copyright 2012, 2013 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.accordion; + +import java.util.EventObject; + +@SuppressWarnings("serial") +public class AccordionComponentEvent<H, C> extends EventObject { + + private H header; + public AccordionComponentEvent(H header, C component) { + super(component); + this.header = header; + } + + public H getHeader() { + return header; + } + + @SuppressWarnings("unchecked") + public C getComponent() { + return (C) getSource(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/accordion/AccordionComponentFactory.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright 2012, 2013 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.accordion; + +/** + * Factory class for the creation of {@link Accordion} components (header and + * main components). + */ +public interface AccordionComponentFactory<H, C> { + + TitledPane createHeader(H header); + AccordionComponent createComponent(H header, C component); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/accordion/AccordionContentPane.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright 2012, 2013 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.accordion; + +import java.awt.Component; +import java.awt.Dimension; + +import javax.swing.JPanel; + +@SuppressWarnings("serial") +class AccordionContentPane extends JPanel { + + @Override + public Dimension getPreferredSize() { + Dimension dim = new Dimension(); + dim.width = Accordion.MIN_WIDTH; + for (Component comp : getComponents()) { + Dimension pref = comp.getPreferredSize(); + dim.width = Math.max(dim.width, pref.width); + dim.height += pref.height; + } + + return dim; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/accordion/AccordionHeaderEvent.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,52 @@ +/* + * Copyright 2012, 2013 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.accordion; + +import java.util.EventObject; + +@SuppressWarnings("serial") +public class AccordionHeaderEvent<H> extends EventObject { + + public AccordionHeaderEvent(H source) { + super(source); + } + + @SuppressWarnings("unchecked") + public H getHeader() { + return (H) getSource(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/accordion/AccordionItemSelectedChangeListener.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,43 @@ +/* + * Copyright 2012, 2013 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.accordion; + +import java.util.EventListener; + +public interface AccordionItemSelectedChangeListener extends EventListener { + public void itemSelected(ItemSelectedEvent event); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/accordion/AccordionModel.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,175 @@ +/* + * Copyright 2012, 2013 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.accordion; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import javax.swing.event.EventListenerList; + +/** + * A Model class for the {@link Accordion} widget. The model represents the + * collection of H (header) and C (components under header) instances that + * are added to the {@link Accordion}. As noted in the {@link Accordion} + * javadoc, H and C do not have to be widgets themselves, since the + * {@link AccordionComponentFactory} is responsible to create the specific + * widget to be used inside the Accordion. + * + * <strong>Note</strong>: H and C must be usable as hash keys. + */ +public class AccordionModel<H, C> { + + protected EventListenerList listenerList; + + private HashMap<H, List<C>> components; + + public AccordionModel() { + components = new HashMap<>(); + listenerList = new EventListenerList(); + } + + private List<C> addOrGetHeader(H header) { + List<C> _components = components.get(header); + if (_components == null) { + _components = new ArrayList<>(); + components.put(header, _components); + + fireHeaderAddedEvent(header); + } + return _components; + } + + public boolean addHeader(H header) { + boolean result = components.containsKey(header); + addOrGetHeader(header); + return result; + } + + public boolean removeHeader(H header) { + List<C> _components = components.remove(header); + boolean result = (_components != null); + if (result) { + for (C component :_components) { + fireComponentRemovedEvent(header, component); + } + fireHeaderRemovedEvent(header); + } + return result; + } + + public boolean addComponent(H header, C component) { + List<C> _components = addOrGetHeader(header); + boolean result = _components.add(component); + fireComponentAddedEvent(header, component); + return result; + } + + public boolean removeComponent(H header, C component) { + List<C> _components = components.get(header); + boolean result = false; + if (_components != null) { + result = _components.remove(component); + fireComponentRemovedEvent(header, component); + } + return result; + } + + public int headerSize() { + return components.size(); + } + + public int size() { + int size = components.size(); + for (List<C> comp : components.values()) { + size += comp.size(); + } + return size; + } + + public void addAccordionModelChangeListener(AccordionModelChangeListener l) { + listenerList.add(AccordionModelChangeListener.class, l); + } + + private void fireHeaderRemovedEvent(H header) { + Object[] listeners = listenerList.getListenerList(); + + AccordionHeaderEvent<H> event = new AccordionHeaderEvent<>(header); + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == AccordionModelChangeListener.class) { + ((AccordionModelChangeListener) listeners[i + 1]).headerRemoved(event); + } + } + } + + private void fireHeaderAddedEvent(H header) { + Object[] listeners = listenerList.getListenerList(); + + AccordionHeaderEvent<H> event = new AccordionHeaderEvent<>(header); + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == AccordionModelChangeListener.class) { + ((AccordionModelChangeListener) listeners[i + 1]).headerAdded(event); + } + } + } + + private void fireComponentAddedEvent(H header, C component) { + Object[] listeners = listenerList.getListenerList(); + + AccordionComponentEvent<H, C> event = new AccordionComponentEvent<>(header, component); + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == AccordionModelChangeListener.class) { + ((AccordionModelChangeListener) listeners[i + 1]).componentAdded(event); + } + } + } + + private void fireComponentRemovedEvent(H header, C component) { + Object[] listeners = listenerList.getListenerList(); + + AccordionComponentEvent<H, C> event = new AccordionComponentEvent<>(header, component); + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == AccordionModelChangeListener.class) { + ((AccordionModelChangeListener) listeners[i + 1]).componentRemoved(event); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/accordion/AccordionModelChangeListener.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,48 @@ +/* + * Copyright 2012, 2013 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.accordion; + +import java.util.EventListener; + +public interface AccordionModelChangeListener<H, C> extends EventListener { + + public void headerAdded(AccordionHeaderEvent<H> e); + public void headerRemoved(AccordionHeaderEvent<H> e); + + public void componentAdded(AccordionComponentEvent<H, C> e); + public void componentRemoved(AccordionComponentEvent<H, C> e); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/accordion/ItemSelectedEvent.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,66 @@ +/* + * Copyright 2012, 2013 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.accordion; + +import java.util.EventObject; + +/** + * + */ +@SuppressWarnings("serial") +public class ItemSelectedEvent extends EventObject { + + private AccordionComponent oldComp; + + public ItemSelectedEvent(AccordionComponent oldComp, AccordionComponent newComp) { + super(newComp); + this.oldComp = oldComp; + } + + public AccordionComponent getPreviousSelected() { + return oldComp; + } + + @Override + public AccordionComponent getSource() { + return (AccordionComponent) super.getSource(); + } + + public AccordionComponent getSelected() { + return getSource(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/accordion/Selectable.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,45 @@ +/* + * Copyright 2012, 2013 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.accordion; + +/** + * Represents an object that can be selected. + */ +public interface Selectable { + void setSelected(boolean selected); + boolean isSelected(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/accordion/TitledPane.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,316 @@ +/* + * Copyright 2012, 2013 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.accordion; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.event.ContainerEvent; +import java.awt.event.ContainerListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingConstants; + +import com.redhat.thermostat.client.swing.GraphicsUtils; +import com.redhat.thermostat.client.swing.components.EmptyIcon; +import com.redhat.thermostat.client.swing.components.FontAwesomeIcon; +import com.redhat.thermostat.client.swing.components.Icon; +import com.redhat.thermostat.client.swing.components.ShadowLabel; +import com.redhat.thermostat.client.swing.components.VerticalLayout; +import com.redhat.thermostat.client.ui.Palette; + +/** + * The TitledPane is responsible to render the header component of a new + * entry in an {@link Accordion}. By default the header is rendered as a + * {@link ShadowLabel} widget, but can be fine tuned passing appropriate + * instances of {@link TitledPanePainter} and {@link AccordionComponent} + * to the constructor. + */ +@SuppressWarnings("serial") +public class TitledPane extends JPanel implements AccordionComponent { + + public static final Color SELECTED_FG = Palette.EARL_GRAY.getColor(); + public static final Color UNSELECTED_FG = Palette.DARK_GRAY.getColor(); + + private Color selectedColor; + private Color unselectedColor; + + public static final String EXPANDED_PROPERTY = "EXPANDED_PROPERTY"; + + private boolean expanded; + + private boolean selected; + + private Icon expandedIcon; + private Icon expandedSelectedIcon; + + private Icon collapsedIcon; + private Icon collapsedIconSelectedIcon; + + private Icon emptyIcon; + + private JLabel iconLabel; + + private JPanel titlePane; + + private JComponent content; + + private TitledPanePainter backgroundPainter; + + private class DefaultTitleComponent implements AccordionComponent { + private ShadowLabel titleLabel; + public DefaultTitleComponent(String title) { + titleLabel = new ShadowLabel(); + titleLabel.setText(title); + titleLabel.setName(title + "_label"); + titleLabel.setForeground(unselectedColor); + } + + @Override + public Component getUiComponent() { + return titleLabel; + } + + @Override + public void setSelected(boolean selected) { + if (selected) { + titleLabel.setForeground(selectedColor); + } else { + titleLabel.setForeground(unselectedColor); + } + } + + @Override + public boolean isSelected() { + return TitledPane.this.isSelected(); + } + } + + private AccordionComponent titleComponent; + + public TitledPane(String title, TitledPanePainter backgroundPainter) { + this(title, backgroundPainter, null); + } + + public TitledPane(String title, TitledPanePainter backgroundPainter, + AccordionComponent titleComponent) + { + setLayout(new VerticalLayout()); + setName(title); + + titlePane = new JPanel(); + titlePane.setLayout(new BorderLayout()); + + if (backgroundPainter != null) { + + this.backgroundPainter = backgroundPainter; + + selectedColor = backgroundPainter.getSelectedForeground(); + unselectedColor = backgroundPainter.getUnselectedForeground(); + titlePane.setOpaque(false); + + } else { + selectedColor = SELECTED_FG; + unselectedColor = UNSELECTED_FG; + } + + if (titleComponent == null) { + titleComponent = new DefaultTitleComponent(title); + } + this.titleComponent = titleComponent; + + expanded = false; + + // TODO: move in UIDefault or something class + int iconSize = 24; + + emptyIcon = new EmptyIcon(iconSize, iconSize); + + // TODO: move in UIDefault too, especially the constants + expandedIcon = new FontAwesomeIcon('\uf107', iconSize, unselectedColor); + expandedSelectedIcon = new FontAwesomeIcon('\uf107', iconSize, selectedColor); + + collapsedIcon = new FontAwesomeIcon('\uf105', iconSize, unselectedColor); + collapsedIconSelectedIcon = new FontAwesomeIcon('\uf105', iconSize, selectedColor); + + iconLabel = new JLabel(emptyIcon); + iconLabel.setText(" "); + iconLabel.setHorizontalTextPosition(SwingConstants.LEFT); + + iconLabel.setName(title + "_ExpanderIcon"); + iconLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + setExpanded(!isExpanded()); + } + }); + + titlePane.add(iconLabel, BorderLayout.WEST); + titlePane.add(this.titleComponent.getUiComponent(), BorderLayout.CENTER); + + add(titlePane); + } + + public TitledPane(String title) { + this(title, null); + } + + private void updateState() { + + titleComponent.setSelected(isSelected()); + if (isExpanded()) { + if (isSelected()) { + iconLabel.setIcon(expandedSelectedIcon); + } else { + iconLabel.setIcon(expandedIcon); + } + } else { + if (isSelected()) { + iconLabel.setIcon(collapsedIconSelectedIcon); + } else { + iconLabel.setIcon(collapsedIcon); + } + } + + if (!hasContent()) { + iconLabel.setIcon(emptyIcon); + } + + repaint(); + } + + protected AccordionComponent getTitleComponent() { + return titleComponent; + } + + public boolean isExpanded() { + return expanded; + } + + public void setExpanded(boolean expanded) { + if (hasContent()) { + boolean oldExpaned = this.expanded; + this.expanded = expanded; + updateState(); + if (oldExpaned != expanded) { + if (expanded) { + add(content); + } else { + remove(content); + } + revalidate(); + firePropertyChange(EXPANDED_PROPERTY, oldExpaned, expanded); + } + } + } + + @Override + public void setSelected(boolean selected) { + this.selected = selected; + updateState(); + } + + private boolean hasContent() { + return content != null && content.getComponentCount() != 0; + } + + @Override + public boolean isSelected() { + return selected; + } + + public JComponent getContent() { + return content; + } + + private void collapse() { + remove(content); + expanded = false; + revalidate(); + } + + public void setContent(JComponent content) { + JComponent oldContent = this.content; + this.content = content; + if (content != null) { + content.addContainerListener(new ContainerListener() { + @Override + public void componentAdded(ContainerEvent e) { + updateState(); + } + + @Override + public void componentRemoved(ContainerEvent e) { + if (!hasContent()) { + collapse(); + } + updateState(); + } + }); + } + + if (isExpanded()) { + if (oldContent != null) { + remove(this.content); + } + setExpanded(true); + } + + updateState(); + } + + @Override + public Component getUiComponent() { + return this; + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + if (backgroundPainter != null) { + Graphics2D graphics = GraphicsUtils.getInstance().createAAGraphics(g); + backgroundPainter.paint(graphics, this, getWidth(), getHeight()); + graphics.dispose(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/main/java/com/redhat/thermostat/client/swing/internal/accordion/TitledPanePainter.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,57 @@ +/* + * Copyright 2012, 2013 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.accordion; + +import java.awt.Color; + +import javax.swing.Painter; + +/** + * {@link Painter} interface to render the background of the {@link TitledPane}. + * + * <br /><br /> + * + * Instances of this class are used to render the background panel of the + * {@link TitledPane} either when customising the selected/unselected look + * and feel of the default widget or to provide a matching painter when + * using a dedicated widget for the header component. + */ +public interface TitledPanePainter extends Painter<AccordionComponent> { + + Color getSelectedForeground(); + Color getUnselectedForeground(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/accordion/AccordionModelTest.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,109 @@ +/* + * Copyright 2012, 2013 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.accordion; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class AccordionModelTest { + + @Test + public void testAddRemove() { + + final int [] results = new int[4]; + final Object [] resultsComponents = new Object[results.length]; + + AccordionModelChangeListener<String, String> l = + new AccordionModelChangeListener<String, String>() { + + @Override + public void headerAdded(AccordionHeaderEvent<String> e) { + results[2]++; + resultsComponents[2] = e.getSource(); + } + + @Override + public void componentAdded(AccordionComponentEvent<String, String> e) { + results[1]++; + resultsComponents[1] = e.getSource(); + } + + @Override + public void componentRemoved(AccordionComponentEvent<String, String> e) { + results[0]++; + resultsComponents[0] = e.getSource(); + } + + @Override + public void headerRemoved(AccordionHeaderEvent<String> e) { + results[3]++; + resultsComponents[3] = e.getSource(); + } + }; + + AccordionModel<String, String> testModel = new AccordionModel<>(); + testModel.addAccordionModelChangeListener(l); + + boolean result = testModel.addComponent("test", "testComponent"); + assertTrue(result); + + assertEquals(2, testModel.size()); + assertEquals(1, testModel.headerSize()); + + result = testModel.removeComponent("test", "testComponent"); + assertTrue(result); + + assertEquals(1, testModel.size()); + assertEquals(1, testModel.headerSize()); + + assertEquals(1, results[0]); + assertEquals(1, results[1]); + assertEquals(1, results[2]); + + assertEquals("testComponent", resultsComponents[0]); + assertEquals("testComponent", resultsComponents[1]); + assertEquals("test", resultsComponents[2]); + + result = testModel.removeHeader("test"); + assertTrue(result); + assertEquals(1, results[0]); + assertEquals(1, results[1]); + assertEquals(1, results[2]); + assertEquals(1, results[3]); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/accordion/AccordionTest.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,321 @@ +/* + * Copyright 2012, 2013 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.accordion; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; + +import java.awt.Component; +import java.awt.Dimension; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.JFrame; +import javax.swing.JLabel; + +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.GuiQuery; +import org.fest.swing.edt.GuiTask; +import org.fest.swing.fixture.FrameFixture; +import org.fest.swing.fixture.JLabelFixture; +import org.fest.swing.fixture.JPanelFixture; +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.swing.components.EmptyIcon; + +@RunWith(CacioFESTRunner.class) +public class AccordionTest { + + private FrameFixture fixture; + private Accordion<String, String> accordion; + + private static class AccordionComponentImpl implements AccordionComponent { + + private boolean selected; + private JLabel component; + + public AccordionComponentImpl(final String text, final String header, final AccordionModel<String, String> model) { + component = new JLabel(text); + component.setName(text); + } + + @Override + public Component getUiComponent() { + return component; + } + + @Override + public boolean isSelected() { + return selected; + } + + @Override + public void setSelected(boolean selected) { + this.selected = selected; + } + } + + private static class AccordionComponentFactoryImpl implements AccordionComponentFactory<String, String> { + + AccordionModel<String, String> model; + + @Override + public TitledPane createHeader(final String header) { + TitledPane pane = new TitledPane(header); + pane.setName(header); + return pane; + } + + @Override + public AccordionComponent createComponent(String header, final String component) { + return new AccordionComponentImpl(component, header, model); + } + + public void setModel(AccordionModel<String, String> model) { + this.model = model; + } + } + + @BeforeClass + public static void setUpOnce() { + FailOnThreadViolationRepaintManager.install(); + } + + @Before + public void setUp() { + JFrame frame = GuiActionRunner.execute(new GuiQuery<JFrame>() { + @Override + protected JFrame executeInEDT() throws Throwable { + JFrame frame = new JFrame(); + + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setMinimumSize(new Dimension(500, 500)); + AccordionComponentFactoryImpl impl = new AccordionComponentFactoryImpl(); + accordion = new Accordion<>(impl); + AccordionModel<String, String> model = accordion.getModel(); + impl.setModel(model); + frame.add(accordion); + + return frame; + } + }); + fixture = new FrameFixture(frame); + } + + @After + public void tearDown() { + fixture.cleanUp(); + fixture = null; + } + + @Category(GUITest.class) + @GUITest + @Test + public void testSelectionListeners() { + fixture.show(); + GuiActionRunner.execute(new GuiTask() { + @Override + protected void executeInEDT() throws Throwable { + AccordionModel<String, String> model = accordion.getModel(); + model.addHeader("Test0"); + model.addHeader("Test1"); + model.addHeader("Test2"); + + model.addComponent("Test0", "TestComponent0"); + model.addComponent("Test0", "TestComponent1"); + + model.addComponent("Test1", "TestComponent2"); + model.addComponent("Test1", "TestComponent3"); + } + }); + + JPanelFixture titlePane0 = fixture.panel("Test0"); + titlePane0.doubleClick(); + + JPanelFixture titlePane1 = fixture.panel("Test1"); + titlePane1.doubleClick(); + + JPanelFixture titlePane2 = fixture.panel("Test2"); + titlePane2.click(); + + final List<ItemSelectedEvent> events = new ArrayList<>(); + + GuiActionRunner.execute(new GuiTask() { + @Override + protected void executeInEDT() throws Throwable { + accordion.addAccordionItemSelectedChangeListener(new AccordionItemSelectedChangeListener() { + @Override + public void itemSelected(ItemSelectedEvent event) { + events.add(event); + } + }); + } + }); + + fixture.robot.waitForIdle(); + + assertEquals(0, events.size()); + + titlePane0.label("Test0_label").click(); + fixture.robot.waitForIdle(); + + assertEquals(1, events.size()); + + ItemSelectedEvent event = events.get(0); + assertSame(titlePane2.target, event.getPreviousSelected()); + assertSame(titlePane0.target, event.getSelected()); + + assertTrue(event.getSelected().isSelected()); + assertFalse(event.getPreviousSelected().isSelected()); + + titlePane1.label("Test1_label").click(); + fixture.robot.waitForIdle(); + + assertEquals(2, events.size()); + + event = events.get(1); + assertSame(titlePane0.target, event.getPreviousSelected()); + assertSame(titlePane1.target, event.getSelected()); + + assertTrue(event.getSelected().isSelected()); + assertFalse(event.getPreviousSelected().isSelected()); + + titlePane2.label("Test2_label").click(); + fixture.robot.waitForIdle(); + + assertEquals(3, events.size()); + + event = events.get(2); + assertSame(titlePane1.target, event.getPreviousSelected()); + assertSame(titlePane2.target, event.getSelected()); + + assertTrue(event.getSelected().isSelected()); + assertFalse(event.getPreviousSelected().isSelected()); + + JLabelFixture component1 = titlePane0.label("TestComponent1"); + component1.click(); + fixture.robot.waitForIdle(); + + assertEquals(4, events.size()); + event = events.get(3); + assertSame(titlePane2.target, event.getPreviousSelected()); + assertSame(component1.target, event.getSelected().getUiComponent()); + + // now those should both be unselected, last event clicked on + // TestComponent1, which is a different component than + // its parent header Test0 + event = events.get(0); + assertFalse(event.getSelected().isSelected()); + assertFalse(event.getPreviousSelected().isSelected()); + } + + @Category(GUITest.class) + @GUITest + @Test + public void testComponets() { + + fixture.show(); + GuiActionRunner.execute(new GuiTask() { + @Override + protected void executeInEDT() throws Throwable { + AccordionModel<String, String> model = accordion.getModel(); + model.addHeader("Test0"); + model.addHeader("Test1"); + model.addHeader("Test2"); + + model.addComponent("Test0", "TestComponent0"); + model.addComponent("Test0", "TestComponent1"); + + model.addComponent("Test1", "TestComponent2"); + model.addComponent("Test1", "TestComponent3"); + } + }); + + // check if things are added as expected + JPanelFixture titlePane = fixture.panel("Test0"); + titlePane.requireVisible(); + + JLabelFixture iconFixture = titlePane.label("Test0_ExpanderIcon"); + iconFixture.requireVisible(); + assertNotNull(iconFixture.target.getIcon()); + assertFalse(iconFixture.target.getIcon() instanceof EmptyIcon); + + // open it up + titlePane.doubleClick(); + + JLabelFixture component = titlePane.label("TestComponent0"); + component.requireVisible(); + component = titlePane.label("TestComponent1"); + component.requireVisible(); + + titlePane = fixture.panel("Test1"); + titlePane.requireVisible(); + titlePane.doubleClick(); + + iconFixture = titlePane.label("Test1_ExpanderIcon"); + iconFixture.requireVisible(); + assertNotNull(iconFixture.target.getIcon()); + assertFalse(iconFixture.target.getIcon() instanceof EmptyIcon); + + component = titlePane.label("TestComponent2"); + component.requireVisible(); + + component = titlePane.label("TestComponent3"); + component.requireVisible(); + + titlePane = fixture.panel("Test2"); + titlePane.requireVisible(); + titlePane.doubleClick(); + + iconFixture = titlePane.label("Test2_ExpanderIcon"); + iconFixture.requireVisible(); + assertNotNull(iconFixture.target.getIcon()); + assertTrue(iconFixture.target.getIcon() instanceof EmptyIcon); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/swing/src/test/java/com/redhat/thermostat/client/swing/internal/accordion/TitledPaneTest.java Mon Sep 30 16:38:49 2013 +0200 @@ -0,0 +1,191 @@ +/* + * Copyright 2012, 2013 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.accordion; + +import static org.junit.Assert.assertSame; + +import java.awt.Color; +import java.awt.Graphics2D; + +import javax.swing.JFrame; +import javax.swing.JPanel; + +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.edt.GuiTask; +import org.fest.swing.fixture.FrameFixture; +import org.fest.swing.fixture.JLabelFixture; +import org.fest.swing.fixture.JPanelFixture; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +import com.redhat.thermostat.client.swing.components.VerticalLayout; + +@RunWith(CacioFESTRunner.class) +public class TitledPaneTest { + + private FrameFixture fixture; + + private static class TitleBGPainter1 implements TitledPanePainter { + + @Override + public void paint(Graphics2D g, AccordionComponent pane, int width, int height) { + if (pane.isSelected()) { + g.setColor(Color.BLACK); + } else { + g.setColor(Color.BLUE); + } + g.fillRect(0, 0, width, height); + } + + @Override + public Color getSelectedForeground() { + return Color.BLACK; + } + + @Override + public Color getUnselectedForeground() { + return Color.RED; + } + } + + private static class TitleBGPainter2 implements TitledPanePainter { + + @Override + public void paint(Graphics2D g, AccordionComponent pane, int width, int height) { + if (pane.isSelected()) { + g.setColor(Color.BLACK); + } else { + g.setColor(Color.BLUE); + } + g.fillRect(0, 0, width, height); + } + + @Override + public Color getSelectedForeground() { + return Color.BLACK; + } + + @Override + public Color getUnselectedForeground() { + return Color.RED; + } + } + + @BeforeClass + public static void setUpOnce() { + FailOnThreadViolationRepaintManager.install(); + } + + @Before + public void setUp() { + JFrame frame = GuiActionRunner.execute(new GuiQuery<JFrame>() { + @Override + protected JFrame executeInEDT() throws Throwable { + JFrame frame = new JFrame(); + + JPanel container = new JPanel(); + container.setLayout(new VerticalLayout()); + + TitledPane pane1 = new TitledPane("test1", new TitleBGPainter1()); + TitledPane pane2 = new TitledPane("test2", new TitleBGPainter2()); + + container.add(pane1); + container.add(pane2); + + frame.add(container); + + return frame; + } + }); + fixture = new FrameFixture(frame); + } + + @After + public void tearDown() { + fixture.cleanUp(); + fixture = null; + } + + @Test + public void testColorDifferences() { + + fixture.show(); + final JPanelFixture titlePane1 = fixture.panel("test1"); + final JPanelFixture titlePane2 = fixture.panel("test2"); + + GuiActionRunner.execute(new GuiTask() { + @Override + protected void executeInEDT() throws Throwable { + // TitledPane do not (yet) have a model to keep track of + // selection, this is done currently in the Accordion + // component controller + TitledPane pane1 = (TitledPane) titlePane1.target; + pane1.setSelected(true); + + TitledPane pane2 = (TitledPane) titlePane2.target; + pane2.setSelected(false); + } + }); + + JLabelFixture label1 = titlePane1.label("test1_label"); + JLabelFixture label2 = titlePane2.label("test2_label"); + + assertSame(Color.BLACK, label1.foreground().target()); + assertSame(Color.RED, label2.foreground().target()); + + GuiActionRunner.execute(new GuiTask() { + @Override + protected void executeInEDT() throws Throwable { + TitledPane pane1 = (TitledPane) titlePane1.target; + pane1.setSelected(false); + + TitledPane pane2 = (TitledPane) titlePane2.target; + pane2.setSelected(true); + } + }); + + assertSame(Color.RED, label1.foreground().target()); + assertSame(Color.BLACK, label2.foreground().target()); + } +}