|
MenuLayout |
|
1 /* 2 * 3 * Copyright (c) 1998-2003, The University of Sheffield. 4 * 5 * This file is part of GATE (see http://gate.ac.uk/), and is free 6 * software, licenced under the GNU Library General Public License, 7 * Version 2, June 1991 (in the distribution as file licence.html, 8 * and also available at http://gate.ac.uk/gate/licence.html). 9 * 10 * Valentin Tablan 20 Feb 2003 11 * 12 * $Id: MenuLayout.java,v 1.4 2003/02/21 14:10:29 valyt Exp $ 13 */ 14 15 package gate.swing; 16 17 import java.awt.*; 18 import javax.swing.*; 19 20 21 /** 22 * A layout designed to allow Java menus to make better use of the screen 23 * real-estate. It will lay out the menu components in columns going from top 24 * to bottom and from left to right. 25 */ 26 public class MenuLayout implements LayoutManager { 27 28 /** 29 * Adds the specified component to the layout. Not used by this class. 30 * @param name the name of the component 31 * @param comp the the component to be added 32 */ 33 public void addLayoutComponent(String name, Component comp) {} 34 35 /** 36 * Removes the specified component from the layout. Not used by this class. 37 * @param comp the component to remove 38 */ 39 public void removeLayoutComponent(Component comp) {} 40 41 /** 42 * Returns the preferred dimensions for this layout given the components 43 * in the specified target container. 44 * @param target the component which needs to be laid out 45 * @see Container 46 * @see #minimumLayoutSize 47 */ 48 public Dimension preferredLayoutSize(Container target) { 49 int membersCnt = target.getComponentCount(); 50 Dimension[] componentPrefSizes = new Dimension[membersCnt]; 51 //store the sizes 52 for(int i = 0; i < membersCnt; i++){ 53 componentPrefSizes[i] = target.getComponent(i).getPreferredSize(); 54 } 55 Dimension dim = getCompositeSize(target, componentPrefSizes); 56 return dim; 57 } 58 59 /** 60 * Calculates the size of the target container given the sizes of the 61 * components. 62 * If the doLayout is <b>true</b> it will also ly out the container. 63 * Used by {@link #minimumLayoutSize} and {@link #preferredLayoutSize}. 64 * @param target 65 * @param componentSizes 66 * @return 67 */ 68 protected Dimension getCompositeSize(Container target, 69 Dimension[] componentSizes){ 70 //find the origin of the popup 71 Point location = new Point(0, 0); 72 if(target.isShowing()){ 73 location = target.getLocationOnScreen(); 74 }else{ 75 if(target instanceof JPopupMenu){ 76 Component invoker = ((JPopupMenu)target).getInvoker(); 77 if(invoker != null) location = invoker.getLocationOnScreen(); 78 } 79 } 80 81 //correct offscreen showing 82 if(location.x < 0 || location.y < 0){ 83 location.x = Math.max(0, location.x); 84 location.y = Math.max(0, location.y); 85 } 86 //find the maximum size 87 Toolkit toolkit = Toolkit.getDefaultToolkit(); 88 Rectangle contentsBounds = new Rectangle(toolkit.getScreenSize()); 89 Insets screenInsets = new Insets(0, 0, 0, 0); 90 GraphicsConfiguration gc = findGraphicsConfiguration(target); 91 if (gc != null) { 92 contentsBounds = gc.getBounds(); 93 screenInsets = toolkit.getScreenInsets(gc); 94 }else{ 95 } 96 97 // take screen insets (e.g. taskbar) into account 98 contentsBounds.width -= screenInsets.left + screenInsets.right; 99 contentsBounds.height -= screenInsets.top + screenInsets.bottom; 100 //take the location into account assuming that the largest side will be used 101 contentsBounds.height = Math.max(location.y, 102 contentsBounds.height - location.y); 103 104 // take component insets into account 105 Insets insets = target.getInsets(); 106 contentsBounds.width -= insets.left + insets.right; 107 contentsBounds.height -= insets.top + insets.bottom; 108 Dimension dim = new Dimension(0, 0); 109 int previousColumnsWidth = 0; 110 int previousColumnsHeight = 0; 111 for (int i = 0; i < componentSizes.length; i++) { 112 if ( (dim.height + 113 componentSizes[i].height) <= contentsBounds.height) { 114 //we can fit the current component in the current row 115 dim.height += componentSizes[i].height; 116 dim.width = Math.max(dim.width, componentSizes[i].width); 117 } 118 else { 119 //we need to start a new column 120 previousColumnsWidth += dim.width; 121 previousColumnsHeight = Math.max(previousColumnsHeight, dim.height); 122 dim.height = componentSizes[i].height; 123 dim.width = componentSizes[i].width; 124 } 125 } 126 127 //Now dim contains the sizes for the last column 128 dim.height = Math.max(previousColumnsHeight, dim.height); 129 dim.width += previousColumnsWidth; 130 //add the target insets 131 dim.width += insets.left + insets.right; 132 dim.height += insets.top + insets.bottom; 133 return dim; 134 } 135 136 /** 137 * Find the graphics configuration for the target popup (useful in case of 138 * multiple screens). 139 * @param target the component for which the configuration needs to be found. 140 * @return a GraphicsConfiguration value. 141 */ 142 protected GraphicsConfiguration findGraphicsConfiguration(Component target){ 143 GraphicsConfiguration gc = null; 144 if(!target.isShowing()){ 145 if(target instanceof JPopupMenu){ 146 Component invoker = ((JPopupMenu)target).getInvoker(); 147 if(invoker != null) target = invoker; 148 } 149 } 150 if(target.isShowing()){ 151 Point position = target.getLocationOnScreen(); 152 Toolkit toolkit = Toolkit.getDefaultToolkit(); 153 gc = target.getGraphicsConfiguration(); 154 GraphicsEnvironment ge = 155 GraphicsEnvironment.getLocalGraphicsEnvironment(); 156 GraphicsDevice[] gd = ge.getScreenDevices(); 157 for (int i = 0; i < gd.length; i++) { 158 if (gd[i].getType() == GraphicsDevice.TYPE_RASTER_SCREEN) { 159 GraphicsConfiguration dgc = 160 gd[i].getDefaultConfiguration(); 161 if (dgc.getBounds().contains(position)) { 162 gc = dgc; 163 break; 164 } 165 } 166 } 167 } 168 return gc; 169 } 170 171 /** 172 * Returns the minimum dimensions needed to layout the components 173 * contained in the specified target container. 174 * @param target the component which needs to be laid out 175 * @see #preferredLayoutSize 176 */ 177 public Dimension minimumLayoutSize(Container target) { 178 int membersCnt = target.getComponentCount(); 179 Dimension[] componentMinSizes = new Dimension[membersCnt]; 180 //store the sizes 181 for(int i = 0; i < membersCnt; i++){ 182 componentMinSizes[i] = target.getComponent(i).getMinimumSize(); 183 } 184 return getCompositeSize(target, componentMinSizes); 185 } 186 187 188 public void layoutContainer(Container target) { 189 Insets insets = target.getInsets(); 190 Rectangle bounds = target.getBounds(); 191 //correct off-screen showing 192 if(target.isShowing()){ 193 Point locationOnScreen = target.getLocationOnScreen(); 194 if(locationOnScreen.x < 0 || locationOnScreen.y < 0){ 195 Window parent = SwingUtilities.getWindowAncestor(target); 196 int newx = Math.max(0, locationOnScreen.x); 197 int newy = Math.max(0, locationOnScreen.y); 198 parent.setLocation(newx, newy); 199 } 200 } 201 int maxheight = bounds.height - insets.bottom; 202 int compCnt = target.getComponentCount(); 203 int y = insets.top; 204 int x = insets.left; 205 int rowWidth = 0; 206 207 for (int i = 0; i < compCnt; i++) { 208 Component comp = target.getComponent(i); 209 if (comp.isVisible()) { 210 Dimension d = comp.getPreferredSize(); 211 comp.setSize(d); 212 if (y + d.height <= maxheight) { 213 comp.setLocation(x, y); 214 y += d.height; 215 rowWidth = Math.max(rowWidth, d.width); 216 } 217 else { 218 //we need to start a new column 219 x += rowWidth; 220 rowWidth = 0; 221 y = insets.top; 222 comp.setLocation(x, y); 223 y += d.height; 224 rowWidth = Math.max(rowWidth, d.width); 225 } 226 } 227 } 228 } 229 }
|
MenuLayout |
|