001 /* 002 * $Id: StackLayout.java,v 1.2 2006/04/19 23:42:08 gfx Exp $ 003 * 004 * Copyright 2005 Sun Microsystems, Inc., 4150 Network Circle, 005 * Santa Clara, California 95054, U.S.A. All rights reserved. 006 */ 007 008 package org.jdesktop.swingx; 009 010 import java.awt.Component; 011 import java.awt.Container; 012 import java.awt.Dimension; 013 import java.awt.Insets; 014 import java.awt.LayoutManager2; 015 import java.awt.Rectangle; 016 import java.util.LinkedList; 017 import java.util.List; 018 019 /** 020 * <p><code>StackLayout</code> is a Swing layout aimed to act as the layers 021 * stack of most popuplar graphics editing tools like <i>The GIMP</i> or 022 * <i>Photoshop</i>. While similar to <code>CardLayout</code>, this layout 023 * displays all the components of the container. If you are using non-rectangular 024 * components (i.e. transparent) you will see them from top to bottom of the 025 * stack.</p> 026 * <p>When using this layout, each component can be added in the container 027 * either on top of the stack or at the bootom:</p> 028 * <pre> 029 * JPanel panel = new JPanel(new StackLayout()); 030 * panel.add(new JLabel("On top"), StackLayout.TOP); 031 * panel.add(new JLabel("At bottom"), StackLayout.BOTTOM); 032 * </pre> 033 * If you don't specify the constraint, the component will be added at the top 034 * of the components stack.</p> 035 * <p>All the components managed by this layout will be given the same size as 036 * the container itself. The minimum, maximum and preferred size of the 037 * container are based upon the largest minimum, maximum and preferred size of 038 * the children components.</p> 039 * <p><code>StackLayout</code> works only with JSE 1.5 and Java SE 6 and 040 * greater.</p> 041 * 042 * @author Romain Guy <romain.guy@mac.com> 043 */ 044 045 public class StackLayout implements LayoutManager2 { 046 /** Use this constraint to add a component at the bottom of the stack. */ 047 public static final String BOTTOM = "bottom"; 048 /** Use this contrainst to add a component at the top of the stack. */ 049 public static final String TOP = "top"; 050 051 // removing components does not happen often compared to adding components 052 // hence we choose a linked list to make insertion at the bottom faster 053 private List<Component> components = new LinkedList<Component>(); 054 055 /** 056 * {@inheritDoc} 057 */ 058 public void addLayoutComponent(final Component comp, 059 final Object constraints) { 060 synchronized (comp.getTreeLock()) { 061 if (BOTTOM.equals(constraints)) { 062 components.add(0, comp); 063 } else if (TOP.equals(constraints)) { 064 components.add(comp); 065 } else { 066 components.add(comp); 067 } 068 } 069 } 070 071 /** 072 * {@inheritDoc} 073 */ 074 public void addLayoutComponent(final String name, final Component comp) { 075 addLayoutComponent(comp, TOP); 076 } 077 078 /** 079 * {@inheritDoc} 080 */ 081 public void removeLayoutComponent(final Component comp) { 082 synchronized (comp.getTreeLock()) { 083 components.remove(comp); 084 } 085 } 086 087 /** 088 * {@inheritDoc} 089 */ 090 public float getLayoutAlignmentX(final Container target) { 091 return 0.5f; 092 } 093 094 /** 095 * {@inheritDoc} 096 */ 097 public float getLayoutAlignmentY(final Container target) { 098 return 0.5f; 099 } 100 101 /** 102 * {@inheritDoc} 103 */ 104 public void invalidateLayout(final Container target) { 105 } 106 107 /** 108 * {@inheritDoc} 109 */ 110 public Dimension preferredLayoutSize(final Container parent) { 111 synchronized (parent.getTreeLock()) { 112 int width = 0; 113 int height = 0; 114 115 for (Component comp: components) { 116 Dimension size = comp.getPreferredSize(); 117 width = Math.max(size.width, width); 118 height = Math.max(size.height, height); 119 } 120 121 Insets insets = parent.getInsets(); 122 width += insets.left + insets.right; 123 height += insets.top + insets.bottom; 124 125 return new Dimension(width, height); 126 } 127 } 128 129 /** 130 * {@inheritDoc} 131 */ 132 public Dimension minimumLayoutSize(final Container parent) { 133 synchronized (parent.getTreeLock()) { 134 int width = 0; 135 int height = 0; 136 137 for (Component comp: components) { 138 Dimension size = comp.getMinimumSize(); 139 width = Math.max(size.width, width); 140 height = Math.max(size.height, height); 141 } 142 143 Insets insets = parent.getInsets(); 144 width += insets.left + insets.right; 145 height += insets.top + insets.bottom; 146 147 return new Dimension(width, height); 148 } 149 } 150 151 /** 152 * {@inheritDoc} 153 */ 154 public Dimension maximumLayoutSize(final Container target) { 155 return new Dimension(Integer.MAX_VALUE, 156 Integer.MAX_VALUE); 157 } 158 159 /** 160 * {@inheritDoc} 161 */ 162 public void layoutContainer(final Container parent) { 163 synchronized (parent.getTreeLock()) { 164 int width = parent.getWidth(); 165 int height = parent.getHeight(); 166 167 Rectangle bounds = new Rectangle(0, 0, width, height); 168 169 int componentsCount = components.size(); 170 171 for (int i = 0; i < componentsCount; i++) { 172 Component comp = components.get(i); 173 comp.setBounds(bounds); 174 parent.setComponentZOrder(comp, componentsCount - i - 1); 175 } 176 } 177 } 178 }