package org.japura.gui; import java.awt.Component; import java.awt.Dimension; import java.awt.Insets; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.util.LinkedHashMap; import java.util.Random; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JLayeredPane; import javax.swing.JScrollPane; /** * Copyright (C) 2008-2011 Carlos Eduardo Leite de Andrade * <P> * This library is free software: you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * <P> * This program 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 Lesser General Public License for more * details. * <P> * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <A * HREF="www.gnu.org/licenses/">www.gnu.org/licenses/</A> * <P> * For more information, contact: <A HREF="www.japura.org">www.japura.org</A> * <P> * * @author Carlos Eduardo Leite de Andrade */ public class Decorator extends JLayeredPane{ private static final long serialVersionUID = -3654610014150907569L; public static final Direction VERTICAL = Direction.VERTICAL; public static final Direction HORIZONTAL = Direction.HORIZONTAL; private LinkedHashMap<String, Component> decorations; private Component component; private Anchor anchor; private Direction direction; private Insets margin; private int gap = 3; public Decorator(Component component) { this(component, Anchor.SOUTH_EAST, Direction.HORIZONTAL); } public Decorator(Component component, Anchor anchor) { this(component, anchor, Direction.HORIZONTAL); } public Decorator(Component component, Anchor anchor, Direction direction) { decorations = new LinkedHashMap<String, Component>(); this.component = component; this.anchor = anchor; this.direction = direction; this.margin = new Insets(0, 0, 0, 0); super.add(component); if (component instanceof JScrollPane) { JScrollPane sp = (JScrollPane) component; sp.getViewport().addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent arg0) { revalidate(); } }); } } public final Direction getDirection() { return direction; } public final void setDecorationVisible(String id, boolean visibled) { if (decorations.containsKey(id)) { decorations.get(id).setVisible(visibled); } } public final void setDecorationsVisible(boolean visibled) { for (String id : decorations.keySet()) { decorations.get(id).setVisible(visibled); } } public final void addDecoration(String id, ImageIcon image) { put(id, new JLabel(image)); } public final String addDecoration(ImageIcon image) { return addWithRandomID(new JLabel(image)); } public final void addDecoration(String id, Component component) { put(id, component); } public final String addDecoration(Component component) { return addWithRandomID(component); } public final void removeDecoration(String id) { if (decorations.containsKey(id)) { Component comp = decorations.remove(id); super.remove(comp); } } public final void removeDecorations() { for (Component c : decorations.values()) { super.remove(c); } decorations.clear(); } private void put(String key, Component component) { if (key != null && decorations.containsKey(key) == false) { decorations.put(key, component); super.add(component, Integer.valueOf(JLayeredPane.MODAL_LAYER - 1)); } } public Component getComponent() { return component; } public Insets getMargin() { return margin; } public Anchor getAnchor() { return anchor; } public final void setMargin(Insets margin) { if (margin != null) { margin.bottom = Math.max(0, margin.bottom); margin.left = Math.max(0, margin.left); margin.right = Math.max(0, margin.right); margin.top = Math.max(0, margin.top); this.margin = margin; } else { this.margin = new Insets(0, 0, 0, 0); } } @Override public Dimension getMinimumSize() { return getPreferredSize(); } @Override public final Dimension getPreferredSize() { Dimension dim = component.getPreferredSize(); dim.height += margin.bottom + margin.top; dim.width += margin.left + margin.right; return dim; } @Override public final Component add(Component comp, int index) { addWithRandomID(comp); return null; } @Override public final void add(Component comp, Object constraints, int index) { addWithRandomID(comp); } @Override public final void add(Component comp, Object constraints) { addWithRandomID(comp); } @Override public final Component add(Component comp) { addWithRandomID(comp); return null; } @Override public final Component add(String name, Component comp) { addWithRandomID(comp); return null; } private String addWithRandomID(Component comp) { Random random = new Random(); String id = Long.toString(random.nextLong()); while (decorations.containsKey(id)) { id = Long.toString(random.nextLong()); } addDecoration(id, comp); return id; } @Override public final void remove(Component comp) {} public final void removeAll() {} @Override public final void doLayout() { Dimension dim = getSize(); component.setBounds(margin.left, margin.top, dim.width - (margin.left + margin.right), dim.height - (margin.bottom + margin.top)); if (component instanceof JScrollPane) { JScrollPane sp = (JScrollPane) component; dim = sp.getSize(); if (sp.getVerticalScrollBar().isShowing()) { dim.width -= sp.getVerticalScrollBar().getSize().width; } if (sp.getHorizontalScrollBar().isShowing()) { dim.height -= sp.getHorizontalScrollBar().getSize().height; } } if (direction.equals(Direction.HORIZONTAL)) { int count = 0; int width = 0; for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); width += cdim.width; count++; } } width += gap * (count - 1); if (anchor.equals(Anchor.CENTER)) { int x = (dim.width - width) / 2; for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); int y = (dim.height - cdim.height) / 2; c.setBounds(x, y, cdim.width, cdim.height); x += (gap + cdim.width); } } } else if (anchor.equals(Anchor.NORTH)) { int x = (dim.width - width) / 2; for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); c.setBounds(x, 0, cdim.width, cdim.height); x += (gap + cdim.width); } } } else if (anchor.equals(Anchor.SOUTH)) { int x = (dim.width - width) / 2; for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); c.setBounds(x, dim.height - cdim.height - 1, cdim.width, cdim.height); x += (gap + cdim.width); } } } else if (anchor.equals(Anchor.EAST)) { for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); int x = dim.width - width - 1; int y = (dim.height - cdim.height) / 2; c.setBounds(x, y, cdim.width, cdim.height); width -= (gap + cdim.width); } } } else if (anchor.equals(Anchor.NORTH_EAST)) { for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); int x = dim.width - width - 1; c.setBounds(x, 0, cdim.width, cdim.height); width -= (gap + cdim.width); } } } else if (anchor.equals(Anchor.SOUTH_EAST)) { for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); int x = dim.width - width - 1; int y = dim.height - cdim.height - 1; c.setBounds(x, y, cdim.width, cdim.height); width -= (gap + cdim.width); } } } else if (anchor.equals(Anchor.WEST)) { int x = 0; for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); int y = (dim.height - cdim.height) / 2; c.setBounds(x, y, cdim.width, cdim.height); x += (gap + cdim.width); } } } else if (anchor.equals(Anchor.NORTH_WEST)) { int x = 0; for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); c.setBounds(x, 0, cdim.width, cdim.height); x += (gap + cdim.width); } } } else if (anchor.equals(Anchor.SOUTH_WEST)) { int x = 0; for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); c.setBounds(x, dim.height - cdim.height - 1, cdim.width, cdim.height); x += (gap + cdim.width); } } } } else { int count = 0; int height = 0; for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); height += cdim.height; count++; } } height += gap * (count - 1); if (anchor.equals(Anchor.SOUTH_EAST)) { for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); c.setBounds(dim.width - cdim.width - 1, dim.height - height - 1, cdim.width, cdim.height); height -= (gap + cdim.height); } } } else if (anchor.equals(Anchor.EAST)) { int y = (dim.height - height) / 2; for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); c.setBounds(dim.width - cdim.width - 1, y, cdim.width, cdim.height); y += (gap + cdim.height); } } } else if (anchor.equals(Anchor.NORTH_EAST)) { int y = 0; for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); c.setBounds(dim.width - cdim.width - 1, y, cdim.width, cdim.height); y += (gap + cdim.height); } } } else if (anchor.equals(Anchor.SOUTH)) { for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); int x = (dim.width - cdim.width) / 2; c.setBounds(x, dim.height - height - 1, cdim.width, cdim.height); height -= (gap + cdim.height); } } } else if (anchor.equals(Anchor.CENTER)) { int y = (dim.height - height) / 2; for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); int x = (dim.width - cdim.width) / 2; c.setBounds(x, y, cdim.width, cdim.height); y += (gap + cdim.height); } } } else if (anchor.equals(Anchor.NORTH)) { int y = 0; for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); int x = (dim.width - cdim.width) / 2; c.setBounds(x, y, cdim.width, cdim.height); y += (gap + cdim.height); } } } else if (anchor.equals(Anchor.SOUTH_WEST)) { for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); c.setBounds(0, dim.height - height - 1, cdim.width, cdim.height); height -= (gap + cdim.height); } } } else if (anchor.equals(Anchor.WEST)) { int y = (dim.height - height) / 2; for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); c.setBounds(0, y, cdim.width, cdim.height); y += (gap + cdim.height); } } } else if (anchor.equals(Anchor.NORTH_WEST)) { int y = 0; for (Component c : decorations.values()) { if (c.isVisible()) { Dimension cdim = c.getPreferredSize(); c.setBounds(0, y, cdim.width, cdim.height); y += (gap + cdim.height); } } } } } public static enum Direction { VERTICAL, HORIZONTAL; } }