/* * The MIT License (MIT) * * Copyright (c) 2007-2015 Broad Institute * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.broad.igv.charts; import java.awt.*; /** * Layout manager for chart panels, based loosely on BorderLayout */ public class ChartLayout implements LayoutManager2, java.io.Serializable { public static final String CHART = "Chart"; public static final String XAXIS = "XAxis"; public static final String YAXIS = "YAxis"; public static final String TITLE = "Title"; public static final String LEGEND = "Legend"; int hgap = 2; int vgap = 2; Component title; Component yAxis; Component legend; Component xAxis; Component chart; public void addLayoutComponent(Component comp, Object constraints) { synchronized (comp.getTreeLock()) { if ((constraints == null) || (constraints instanceof String)) { addLayoutComponent((String) constraints, comp); } else { throw new IllegalArgumentException("cannot add to layout: constraint must be a string (or null)"); } } } public void addLayoutComponent(String name, Component comp) { synchronized (comp.getTreeLock()) { if (CHART.equals(name)) { chart = comp; } else if (TITLE.equals(name)) { title = comp; } else if (XAXIS.equals(name)) { xAxis = comp; } else if (YAXIS.equals(name)) { yAxis = comp; } else if (LEGEND.equals(name)) { legend = comp; } else { throw new IllegalArgumentException("Unknown chart component: " + name); } } } /** * Removes the specified component from this border layout. This * method is called when a container calls its <code>remove</code> or * <code>removeAll</code> methods. Most applications do not call this * method directly. * * @param comp the component to be removed. * @see java.awt.Container#remove(java.awt.Component) * @see java.awt.Container#removeAll() */ public void removeLayoutComponent(Component comp) { synchronized (comp.getTreeLock()) { if (comp == chart) { chart = null; } else if (comp == title) { title = null; } else if (comp == xAxis) { xAxis = null; } else if (comp == legend) { legend = null; } else if (comp == yAxis) { yAxis = null; } } } /** * Determines the minimum size of the <code>target</code> container * using this layout manager. * <p/> * This method is called when a container calls its * <code>getMinimumSize</code> method. Most applications do not call * this method directly. * * @param target the container in which to do the layout. * @return the minimum dimensions needed to lay out the subcomponents * of the specified container. * @see java.awt.Container * @see java.awt.BorderLayout#preferredLayoutSize * @see java.awt.Container#getMinimumSize() */ public Dimension minimumLayoutSize(Container target) { synchronized (target.getTreeLock()) { Dimension dim = new Dimension(0, 0); if (legend != null) { Dimension d = legend.getMinimumSize(); dim.width += d.width + hgap; dim.height = Math.max(d.height, dim.height); } if (xAxis != null) { Dimension d = xAxis.getMinimumSize(); dim.width += d.width + hgap; dim.height = Math.max(d.height, dim.height); } if (chart != null) { Dimension d = chart.getMinimumSize(); dim.width += d.width; dim.height = Math.max(d.height, dim.height); } if (title != null) { Dimension d = title.getMinimumSize(); //dim.width = Math.max(d.width, dim.width); dim.height += d.height + vgap; } if (yAxis != null) { Dimension d = yAxis.getMinimumSize(); dim.width = Math.max(d.width, dim.width); dim.height += d.height + vgap; } Insets insets = target.getInsets(); dim.width += insets.left + insets.right; dim.height += insets.top + insets.bottom; return dim; } } /** * Determines the preferred size of the <code>target</code> * container using this layout manager, based on the components * in the container. * <p/> * Most applications do not call this method directly. This method * is called when a container calls its <code>getPreferredSize</code> * method. * * @param target the container in which to do the layout. * @return the preferred dimensions to lay out the subcomponents * of the specified container. * @see java.awt.Container * @see java.awt.BorderLayout#minimumLayoutSize * @see java.awt.Container#getPreferredSize() */ public Dimension preferredLayoutSize(Container target) { synchronized (target.getTreeLock()) { Dimension dim = new Dimension(0, 0); if (legend != null) { Dimension d = legend.getPreferredSize(); dim.width += d.width + hgap; dim.height = Math.max(d.height, dim.height); } if (xAxis != null) { Dimension d = xAxis.getPreferredSize(); dim.width += d.width + hgap; dim.height = Math.max(d.height, dim.height); } if (chart != null) { Dimension d = chart.getPreferredSize(); dim.width += d.width; dim.height = Math.max(d.height, dim.height); } if (title != null) { Dimension d = title.getPreferredSize(); //dim.width = Math.max(d.width, dim.width); dim.height += d.height + vgap; } if (yAxis != null) { Dimension d = yAxis.getPreferredSize(); dim.width = Math.max(d.width, dim.width); dim.height += d.height + vgap; } Insets insets = target.getInsets(); dim.width += insets.left + insets.right; dim.height += insets.top + insets.bottom; return dim; } } /** * Returns the maximum dimensions for this layout given the components * in the specified target container. * * @param target the component which needs to be laid out * @see Container * @see #minimumLayoutSize * @see #preferredLayoutSize */ public Dimension maximumLayoutSize(Container target) { return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } /** * Returns the alignment along the x axis. This specifies how * the component would like to be aligned relative to other * components. The value should be a number between 0 and 1 * where 0 represents alignment along the origin, 1 is aligned * the furthest away from the origin, 0.5 is centered, etc. */ public float getLayoutAlignmentX(Container parent) { return 0.5f; } /** * Returns the alignment along the y axis. This specifies how * the component would like to be aligned relative to other * components. The value should be a number between 0 and 1 * where 0 represents alignment along the origin, 1 is aligned * the furthest away from the origin, 0.5 is centered, etc. */ public float getLayoutAlignmentY(Container parent) { return 0.5f; } /** * Invalidates the layout, indicating that if the layout manager * has cached information it should be discarded. */ public void invalidateLayout(Container target) { } /** * Lays out the container argument. The preferred width and height of the components are used selectively * as follows * * Heights: title, xAxis * Widths: yAxis, legend * * The chart gets whatever is left over. * * * @param target the container in which to do the layout. * @see java.awt.Container * @see java.awt.Container#doLayout() */ public void layoutContainer(Container target) { synchronized (target.getTreeLock()) { Insets insets = target.getInsets(); int top = insets.top; int bottom = target.getHeight() - insets.bottom; int left = insets.left; int right = target.getWidth() - insets.right; int titleHeight = title == null ? 0 : title.getPreferredSize().height; int xAxisHeight = xAxis == null ? 0 : xAxis.getPreferredSize().height; int yAxisWidth = yAxis == null ? 0 : yAxis.getPreferredSize().width; int legendWidth = legend == null ? 0 : legend.getPreferredSize().width; int x1 = left + yAxisWidth + (yAxisWidth == 0 ? 0 : hgap); int x2 = right - legendWidth - (legendWidth == 0 ? 0 : hgap); int y1 = top + titleHeight + (titleHeight == 0 ? 0 : vgap); int y2 = bottom - xAxisHeight - (xAxisHeight == 0 ? 0 : vgap); if (title != null) { title.setBounds(left, top, right - left, titleHeight); } if (xAxis != null) { // xAxis.setSize(new Dimension(x2-x1, xAxisHeight)); // xAxis.setSize(x2-x1, xAxisHeight); xAxis.setBounds(x1, y2 + vgap, x2 - x1, xAxisHeight); } if (legend != null) { legend.setBounds(right - legendWidth, y1, legendWidth, y2 - y1); } if (yAxis != null) { yAxis.setBounds(left, y1, yAxisWidth, y2 - y1); } if (chart != null) { // chart.setSize(new Dimension(x2-x1, y2-y1)); // chart.setSize(x2-x1, y2-y1); chart.setBounds(x1, y1, x2 - x1, y2 - y1); } } } }