usr/src/java/vpanels/app/usermgr/com/oracle/solaris/vp/panels/usermgr/client/swing/DoubleTreesLayout.java
changeset 847 a8e124b894b8
equal deleted inserted replaced
846:0a2af4721353 847:a8e124b894b8
       
     1 /*
       
     2  * CDDL HEADER START
       
     3  *
       
     4  * The contents of this file are subject to the terms of the
       
     5  * Common Development and Distribution License (the "License").
       
     6  * You may not use this file except in compliance with the License.
       
     7  *
       
     8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
       
     9  * or http://www.opensolaris.org/os/licensing.
       
    10  * See the License for the specific language governing permissions
       
    11  * and limitations under the License.
       
    12  *
       
    13  * When distributing Covered Code, include this CDDL HEADER in each
       
    14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
       
    15  * If applicable, add the following below this CDDL HEADER, with the
       
    16  * fields enclosed by brackets "[]" replaced with your own identifying
       
    17  * information: Portions Copyright [yyyy] [name of copyright owner]
       
    18  *
       
    19  * CDDL HEADER END
       
    20  */
       
    21 
       
    22 /*
       
    23  * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
       
    24  */
       
    25 
       
    26 
       
    27 package com.oracle.solaris.vp.panels.usermgr.client.swing;
       
    28 
       
    29 import java.awt.*;
       
    30 import javax.swing.*;
       
    31 import java.util.*;
       
    32 
       
    33 import com.oracle.solaris.vp.util.misc.finder.Finder;
       
    34 
       
    35 /**
       
    36  * SMC code adapted for Visual Panels
       
    37  *
       
    38  * This class provides the <code>DoubleTreesLayout</code> manager used
       
    39  * by the <code>DoubleTrees</code> component. The layout manager assumes
       
    40  * that the <code>DoubleTrees</code> component contains the following
       
    41  * interior components.
       
    42  * <br>
       
    43  * <code>
       
    44  * +---------------------------------------------------+
       
    45  * |  LEFT_LABEL                          RIGHT_LABEL  |
       
    46  * |  +----------------+           +----------------+  |
       
    47  * |  |LEFT_SCROLLPANE |           |RIGHT_SCROLLPANE|  |
       
    48  * |  |                | +-------+ |                |  |
       
    49  * |  |                | |BUTTONS| |                |  |
       
    50  * |  |                | |       | |                |  |
       
    51  * |  |                | |       | |                |  |
       
    52  * |  |                | +-------+ |                |  |
       
    53  * |  |                |           |                |  |
       
    54  * |  +----------------+           +----------------+  |
       
    55  * |                                                   |
       
    56  * +---------------------------------------------------+
       
    57  * </code>
       
    58  * <br>
       
    59  * Each component is laid out and sized with respect to its own
       
    60  * <code>DoubleTreesConstraints</code> object.
       
    61  *
       
    62  */
       
    63 public class DoubleTreesLayout implements LayoutManager2, java.io.Serializable {
       
    64 
       
    65     protected final static Dimension ZERO_SIZE = new Dimension(0, 0);
       
    66     protected final static Dimension MAXIMUM_SIZE =
       
    67 			new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
       
    68 
       
    69     protected Dimension size;
       
    70     protected Dimension minimumSize = new Dimension(400, 250);
       
    71     protected Dimension preferredSize = minimumSize;
       
    72     protected Dimension maximumSize;
       
    73     protected DoubleTreesConstraints defaultConstraints;
       
    74 
       
    75     /**
       
    76      * Constraints location to component map. Location key is wrapped in an
       
    77      * <code>Integer</code>.
       
    78      */
       
    79     protected HashMap<Integer, Component> componentsMap;
       
    80 
       
    81     /**
       
    82      * Component to constraints map.
       
    83      */
       
    84     protected HashMap<Component, DoubleTreesConstraints> constraintsMap;
       
    85 
       
    86 // ----------------------------------------------------------------------
       
    87 
       
    88     /**
       
    89      * Construct a <code>DoubleTreesLayout<code> manager with default values.
       
    90      */
       
    91     public DoubleTreesLayout() {
       
    92 	size = ZERO_SIZE;
       
    93 	maximumSize = MAXIMUM_SIZE;
       
    94 	defaultConstraints = new DoubleTreesConstraints();
       
    95 	componentsMap = new HashMap<Integer, Component>();
       
    96 	constraintsMap = new HashMap<Component, DoubleTreesConstraints>();
       
    97     }
       
    98 
       
    99 // ----------------------------------------------------------------------
       
   100 
       
   101     /**
       
   102      * Set the constraints for a given component. If the component has
       
   103      * not previously been added to the layout, setting the components
       
   104      * constraints will add the component to the layout.
       
   105      *
       
   106      * @param component
       
   107      *	Component.
       
   108      * @param constraints
       
   109      *	Components constraints.
       
   110      */
       
   111     public void setConstraints(
       
   112 	    Component component,
       
   113 	    DoubleTreesConstraints constraints) {
       
   114 	addLayoutComponent(component, constraints);
       
   115     }
       
   116 
       
   117     /**
       
   118      * Get the constraints for a given component. If the component has
       
   119      * not had previously added to the layout the default constraints
       
   120      * are returned.
       
   121      *
       
   122      * @param component
       
   123      *	Component.
       
   124      * @param constraints
       
   125      *	Components constraints.
       
   126      */
       
   127     public DoubleTreesConstraints getConstraints(Component component) {
       
   128 	if (constraintsMap.containsKey(component)) {
       
   129 	    return constraintsMap.get(component);
       
   130 	} else {
       
   131 	    return defaultConstraints;
       
   132 	}
       
   133     }
       
   134 
       
   135     public void addLayoutComponent(String name, Component component) {
       
   136 	// Copied from GridBayLayout.
       
   137 	throw new RuntimeException("Not used by this layout manager");
       
   138     }
       
   139 
       
   140     public void addLayoutComponent(Component component, Object object) {
       
   141 	if (object == null) {
       
   142 	    if (!constraintsMap.containsKey(component)) {
       
   143 		// No constraints for component.
       
   144 		object = defaultConstraints;
       
   145 	    } else {
       
   146 		// Don't add again.
       
   147 		return;
       
   148 	    }
       
   149 	}
       
   150 
       
   151 	// Can only deal with our own constraints objects.
       
   152 	if (!(object instanceof DoubleTreesConstraints)) {
       
   153 	    throw new RuntimeException(
       
   154 		    "Constraints not sub class of DoubleTreesConstraints");
       
   155 	}
       
   156 
       
   157 	/**
       
   158 	 * Clone constraints in case caller is re-using the same constraints
       
   159 	 * object.
       
   160 	 */
       
   161 	DoubleTreesConstraints constraints =
       
   162 	    (DoubleTreesConstraints) ((DoubleTreesConstraints) object).clone();
       
   163 
       
   164 	// Update maps.
       
   165 	componentsMap.put(new Integer(constraints.location), component);
       
   166 	constraintsMap.put(component, constraints);
       
   167 
       
   168     }
       
   169 
       
   170     public void removeLayoutComponent(Component component) {
       
   171 	DoubleTreesConstraints constraints =
       
   172 	    constraintsMap.get(component);
       
   173 
       
   174 	if (constraints != null) {
       
   175 	    componentsMap.remove(new Integer(constraints.location));
       
   176 	}
       
   177 
       
   178 	constraintsMap.remove(component);
       
   179     }
       
   180 
       
   181     public Dimension preferredLayoutSize(Container parent) {
       
   182 	return preferredSize;
       
   183     }
       
   184 
       
   185     public Dimension minimumLayoutSize(Container parent) {
       
   186 	return minimumSize;
       
   187     }
       
   188 
       
   189     public Dimension maximumLayoutSize(Container parent) {
       
   190 	return maximumSize;
       
   191     }
       
   192 
       
   193     public float getLayoutAlignmentX(Container parent) {
       
   194 	return 0.5f;
       
   195     }
       
   196 
       
   197     public float getLayoutAlignmentY(Container parent) {
       
   198 	return 0.5f;
       
   199     }
       
   200 
       
   201     public void invalidateLayout(Container target) {
       
   202     }
       
   203 
       
   204     public void layoutContainer(Container parent) {
       
   205 	synchronized (parent.getTreeLock()) {
       
   206 	    doLayoutContainer(parent);
       
   207 	}
       
   208     }
       
   209 
       
   210     /**
       
   211      * Layout the components.
       
   212      *
       
   213      * @param parent
       
   214      *	Container component where the <code>DoubleTrees</code> component
       
   215      *  resides.
       
   216      */
       
   217     private void doLayoutContainer(Container parent) {
       
   218 	size = parent.getSize();
       
   219 
       
   220 	JComponent ll = (JComponent) componentsMap.get(
       
   221 		new Integer(DoubleTreesConstraints.LEFT_LABEL));
       
   222 	DoubleTreesConstraints llc =
       
   223 	    constraintsMap.get(ll);
       
   224 
       
   225 	JComponent rl = (JComponent) componentsMap.get(
       
   226 		new Integer(DoubleTreesConstraints.RIGHT_LABEL));
       
   227 	DoubleTreesConstraints rlc = constraintsMap.get(rl);
       
   228 
       
   229 	Component b = componentsMap.get(
       
   230 		new Integer(DoubleTreesConstraints.BUTTONS));
       
   231 	DoubleTreesConstraints bc = constraintsMap.get(b);
       
   232 
       
   233 	Component ls = componentsMap.get(
       
   234 		new Integer(DoubleTreesConstraints.LEFT_SCROLLPANE));
       
   235 	DoubleTreesConstraints lsc = constraintsMap.get(ls);
       
   236 
       
   237 	Component rs = componentsMap.get(
       
   238 		new Integer(DoubleTreesConstraints.RIGHT_SCROLLPANE));
       
   239 	DoubleTreesConstraints rsc = constraintsMap.get(rs);
       
   240 
       
   241 	double pw = parent.getSize().getWidth();
       
   242 	double ph = parent.getSize().getHeight();
       
   243 
       
   244 	double llw = ll.getPreferredSize().getWidth();
       
   245 	double llh = ll.getPreferredSize().getHeight();
       
   246 
       
   247 	double lsw = ls.getPreferredSize().getWidth();
       
   248 	double lsh = ls.getPreferredSize().getHeight();
       
   249 
       
   250 	double rlw = rl.getPreferredSize().getWidth();
       
   251 	double rlh = rl.getPreferredSize().getHeight();
       
   252 
       
   253 	double rsw = rs.getPreferredSize().getWidth();
       
   254 	double rsh = rs.getPreferredSize().getHeight();
       
   255 
       
   256 	double bw = b.getPreferredSize().getWidth();
       
   257 	double bh = b.getPreferredSize().getHeight();
       
   258 
       
   259 	// button w and h inc. insets
       
   260 
       
   261 	bw += bc.insets.left + bc.insets.right;
       
   262 	bh += bc.insets.top + bc.insets.bottom;
       
   263 
       
   264 	// leave button w fixed, give rest of parent w to scroll panes
       
   265 
       
   266 	lsw = rsw = (pw - bw) / 2.0;
       
   267 
       
   268 	// left label w must not exceed left scroll pane w
       
   269 
       
   270 	ls.setSize(new Dimension((int) lsw, (int) lsh));
       
   271 
       
   272 	ll.setMaximumSize(setDimensionAxis(ll.getMaximumSize(), lsw, true));
       
   273 
       
   274 	llw = lsw - llc.insets.left - llc.insets.right;
       
   275 
       
   276 	ll.setSize(setDimensionAxis(ll.getSize(), llw, true));
       
   277 
       
   278 	llw = ll.getPreferredSize().getWidth();
       
   279 	llh = ll.getPreferredSize().getHeight();
       
   280 
       
   281 	// right label w must not exceed right scroll pane w
       
   282 
       
   283 	rs.setSize(new Dimension((int) rsw, (int) rsh));
       
   284 
       
   285 	rl.setMaximumSize(setDimensionAxis(ll.getMaximumSize(), rsw, true));
       
   286 
       
   287 	llw = lsw - llc.insets.left - llc.insets.right;
       
   288 
       
   289 	rl.setSize(setDimensionAxis(rl.getSize(), rlw, true));
       
   290 
       
   291 	rlw = rl.getPreferredSize().getWidth();
       
   292 	rlh = rl.getPreferredSize().getHeight();
       
   293 
       
   294 	// both label h must be equal and accomodate both labels
       
   295 
       
   296 	double lh = Math.max(
       
   297 		llh + llc.insets.top + llc.insets.bottom,
       
   298 		rlh + rlc.insets.top + rlc.insets.bottom);
       
   299 
       
   300 	ll.setSize(new Dimension((int) lsw, (int) lh));
       
   301 
       
   302 	rl.setSize(new Dimension((int) rsw, (int) lh));
       
   303 
       
   304 	// both label w must not exceed scroll pane w
       
   305 
       
   306 	llw = lsw;
       
   307 	rlw = rsw;
       
   308 
       
   309 	// scroll pane h gets rest of parent h after label h allocated
       
   310 
       
   311 	lsh = rsh = ph - lh;
       
   312 
       
   313 	ls.setSize(new Dimension((int) lsw, (int) lsh));
       
   314 	rs.setSize(new Dimension((int) rsw, (int) rsh));
       
   315 	b.setSize(new Dimension((int) bw, (int) bh));
       
   316 
       
   317 	// see if we have a preferred size > minimum size
       
   318 
       
   319 	if (preferredSize == minimumSize) {
       
   320 	    int w = (int) (lsw + bw + rsw);
       
   321 	    int h = (int) (lh + lsh);
       
   322 
       
   323 	    w = Math.max(w, (int) minimumSize.getWidth());
       
   324 	    h = Math.max(h, (int) minimumSize.getHeight());
       
   325 
       
   326 	    preferredSize = new Dimension(w, h);
       
   327 	}
       
   328 
       
   329 	// set locations for labels, scroll panes and buttons
       
   330 
       
   331 	int llx = 0;
       
   332 	int lly = 0;
       
   333 
       
   334 	int lsx = 0;
       
   335 	int lsy = lly + (int) lh;
       
   336 
       
   337 	int bx = lsx + (int) lsw;
       
   338 	int by = (int) (lh + (lsh - bh) / 2);
       
   339 
       
   340 	int rlx = bx + (int) bw;
       
   341 	int rly = 0;
       
   342 
       
   343 	int rsx = bx + (int) bw;
       
   344 	int rsy = rly + (int) lh;
       
   345 
       
   346 	ll.setLocation(llx, lly);
       
   347 	ls.setLocation(lsx, lsy);
       
   348 	rs.setLocation(rsx, rsy);
       
   349 	rl.setLocation(rlx, rly);
       
   350 	b.setLocation(bx, by);
       
   351 
       
   352 	// adjust size and locations to accomodate insets
       
   353 
       
   354 	includeInsets(ll, llc.insets);
       
   355 	includeInsets(rl, rlc.insets);
       
   356 	includeInsets(ls, lsc.insets);
       
   357 	includeInsets(rs, rsc.insets);
       
   358 	includeInsets(b, bc.insets);
       
   359     }
       
   360 
       
   361     /**
       
   362      * Adjust components size and location to accomodate an <code>Inset</code>.
       
   363      *
       
   364      * @param component
       
   365      *	Component to be resized and relocated.
       
   366      * @param insets
       
   367      *	Inserts that must surround the component.
       
   368      */
       
   369     private void includeInsets(Component component, Insets insets) {
       
   370 	Point location = component.getLocation();
       
   371 	Dimension size = component.getSize();
       
   372 
       
   373 	double x = location.getX();
       
   374 	double y = location.getY();
       
   375 	double width = size.getWidth();
       
   376 	double height = size.getHeight();
       
   377 
       
   378 	component.setLocation(
       
   379 		(int) (x + insets.left),
       
   380 		(int) (y + insets.top));
       
   381 	component.setSize(
       
   382 		(int) (width - insets.left - insets.right),
       
   383 		(int) (height - insets.top - insets.bottom));
       
   384     }
       
   385 
       
   386 // ----------------------------------------------------------------------
       
   387 
       
   388     /**
       
   389      * Get axis of a <code>Dimension</code>.
       
   390      *
       
   391      * @param dimension
       
   392      *	<code>Dimension</code> being inspected.
       
   393      * @param xAxis
       
   394      *	True if the width (X axis) is required, otherwise false if the
       
   395      *  height (Y axis) is required.
       
   396      * @return
       
   397      *	Required axis value.
       
   398      */
       
   399     private double getDimensionAxis(Dimension dimension, boolean xAxis) {
       
   400 	if (xAxis) {
       
   401 	    return dimension.getWidth();
       
   402 	} else {
       
   403 	    return dimension.getHeight();
       
   404 	}
       
   405     }
       
   406 
       
   407     /**
       
   408      * Set axis of a <code>Dimension</code>.
       
   409      *
       
   410      * @param dimension
       
   411      *	<code>Dimension</code> being modified.
       
   412      * @param value
       
   413      *	New axis value.
       
   414      * @param xAxis
       
   415      *	True if the width (X axis) is required, otherwise false if the
       
   416      *  height (Y axis) is required.
       
   417      * @return
       
   418      *	The modified <code>Dimension</code>.
       
   419      */
       
   420     private Dimension setDimensionAxis(
       
   421 	    Dimension dimension,
       
   422 	    double value,
       
   423 	    boolean xAxis) {
       
   424 	if (xAxis) {
       
   425 	    dimension.setSize(value, dimension.getHeight());
       
   426 	} else {
       
   427 	    dimension.setSize(dimension.getWidth(), value);
       
   428 	}
       
   429 
       
   430 	return dimension;
       
   431     }
       
   432 
       
   433     /**
       
   434      * Set axis of a <code>Dimension</code>.
       
   435      *
       
   436      * @param dimension
       
   437      *	<code>Dimension</code> being modified.
       
   438      * @param value
       
   439      *	New axis value.
       
   440      * @param xAxis
       
   441      *	True if the width (X axis) is required, otherwise false if the
       
   442      *  height (Y axis) is required.
       
   443      * @return
       
   444      *	The modified <code>Dimension</code>.
       
   445      */
       
   446     private Dimension setDimensionAxis(
       
   447 	    Dimension dimension,
       
   448 	    int value,
       
   449 	    boolean xAxis) {
       
   450 	return setDimensionAxis(dimension, (double) value, xAxis);
       
   451     }
       
   452 
       
   453 }