File: GUI.java

package info (click to toggle)
imagej 1.54g-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 6,520 kB
  • sloc: java: 132,209; sh: 286; xml: 255; makefile: 6
file content (296 lines) | stat: -rw-r--r-- 10,312 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
package ij.gui;
import ij.*;
import java.awt.*;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JTable;
import javax.swing.UIManager;

/** This class consists of static GUI utility methods. */
public class GUI {
	private static final Font DEFAULT_FONT = ImageJ.SansSerif12;
	private static Color lightGray = new Color(240,240,240);
	private static boolean isWindows8;
	private static Color scrollbarBackground = new Color(245,245,245);

	static {
		if (IJ.isWindows()) {
			String osname = System.getProperty("os.name");
			isWindows8 = osname.contains("unknown") || osname.contains("8");
		}
	}

	/** Positions the specified window in the center of the screen that contains target. */
	public static void center(Window win, Component target) {
		if (win == null)
			return;
		Rectangle bounds = getMaxWindowBounds(target);
		Dimension window = win.getSize();
		if (window.width == 0)
			return;
		int left = bounds.x + Math.max(0, (bounds.width - window.width) / 2);
		int top = bounds.y + Math.max(0, (bounds.height - window.height) / 4);
		win.setLocation(left, top);
	}
	
	/** Positions the specified window in the center of the
		 screen containing the "ImageJ" window. */
	public static void centerOnImageJScreen(Window win) {
		center(win, IJ.getInstance());
	}

	public static void center(Window win) {
		center(win, win);
	}
	
	private static java.util.List<GraphicsConfiguration> getScreenConfigs() {
		java.util.ArrayList<GraphicsConfiguration> configs = new java.util.ArrayList<GraphicsConfiguration>();
		for (GraphicsDevice device : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) {
			configs.add(device.getDefaultConfiguration());
		}
		return configs;
	}
	
	/**
	 * Get maximum bounds for the screen that contains a given point.
	 * @param point Coordinates of point.
	 * @param accountForInsets Deduct the space taken up by menu and status bars, etc. (after point is found to be inside bonds)
	 * @return Rectangle of bounds or <code>null</code> if point not inside of any screen.
	 */
	public static Rectangle getScreenBounds(Point point, boolean accountForInsets) {
		if (GraphicsEnvironment.isHeadless())
			return new Rectangle(0,0,0,0);
		for (GraphicsConfiguration config : getScreenConfigs()) {
			Rectangle bounds = config.getBounds();
			if (bounds != null && bounds.contains(point)) {
				Insets insets = accountForInsets ? Toolkit.getDefaultToolkit().getScreenInsets(config) : null;
				return shrinkByInsets(bounds, insets);
			}
		}
		return null;		
	}
	
	/**
	 * Get maximum bounds for the screen that contains a given component.
	 * @param component An AWT component located on the desired screen.
	 * If <code>null</code> is provided, the default screen is used.
	 * @param accountForInsets Deduct the space taken up by menu and status bars, etc.
	 * @return Rectangle of bounds.
	 */	
	public static Rectangle getScreenBounds(Component component, boolean accountForInsets) {
		if (GraphicsEnvironment.isHeadless())
			return new Rectangle(0,0,0,0);
		GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();		
		GraphicsConfiguration gc = component == null ? ge.getDefaultScreenDevice().getDefaultConfiguration() :
													   component.getGraphicsConfiguration();   
		Insets insets = accountForInsets ? Toolkit.getDefaultToolkit().getScreenInsets(gc) : null;
		return shrinkByInsets(gc.getBounds(), insets);
	}

	public static Rectangle getScreenBounds(Point point) {
		return getScreenBounds(point, false);
	}		

	public static Rectangle getScreenBounds(Component component) {
		return getScreenBounds(component, false);
	}			

	public static Rectangle getScreenBounds() {
		return getScreenBounds((Component)null);
	}			

	public static Rectangle getMaxWindowBounds(Point point) {
		return getScreenBounds(point, true);
	}

	public static Rectangle getMaxWindowBounds(Component component) {
		return getScreenBounds(component, true);
	}
	
	public static Rectangle getMaxWindowBounds() {
		return getMaxWindowBounds((Component)null);
	}
	
	private static Rectangle shrinkByInsets(Rectangle bounds, Insets insets) {
		Rectangle shrunk = new Rectangle(bounds);
		if (insets == null) return shrunk; 
		shrunk.x += insets.left;
		shrunk.y += insets.top;
		shrunk.width -= insets.left + insets.right;
		shrunk.height -= insets.top + insets.bottom;
		return shrunk;
	}
	
	public static Rectangle getZeroBasedMaxBounds() {
		for (GraphicsConfiguration config : getScreenConfigs()) {
			Rectangle bounds = config.getBounds();
			if (bounds != null && bounds.x == 0 && bounds.y == 0)
				return bounds;
		}
		return null;
	}
	
	public static Rectangle getUnionOfBounds() {
		Rectangle unionOfBounds = new Rectangle();
		for (GraphicsConfiguration config : getScreenConfigs()) {
			unionOfBounds = unionOfBounds.union(config.getBounds());
		}
		return unionOfBounds;
	}
	
    static private Frame frame;
    
    /** Obsolete */
    public static Image createBlankImage(int width, int height) {
        if (width==0 || height==0)
            throw new IllegalArgumentException("");
		if (frame==null) {
			frame = new Frame();
			frame.pack();
			frame.setBackground(Color.white);
		}
        Image img = frame.createImage(width, height);
        return img;
    }
    
    /** Lightens overly dark scrollbar background on Windows 8. */
    public static void fix(Scrollbar sb) {
    }
    
    public static boolean showCompositeAdvisory(ImagePlus imp, String title) {
    	if (imp==null || imp.getCompositeMode()!=IJ.COMPOSITE || imp.getNChannels()==1 || IJ.macroRunning())
    		return true;
    	String msg = "Channel "+imp.getC()+" of this color composite image will be processed.";
		GenericDialog gd = new GenericDialog(title);
		gd.addMessage(msg);
		gd.showDialog();
		return !gd.wasCanceled();
	}
	
	/**
	 * Scales an AWT component according to {@link Prefs#getGuiScale()}.
	 * @param component the AWT component to be scaled. If a container, scaling is applied to all its child components
	 */
	public static void scale(final Component component) {
		final float scale = (float)Prefs.getGuiScale();
		if (scale==1f)
			return;
		if (component instanceof Container)
			scaleComponents((Container)component, scale);
		else
			scaleComponent(component, scale);
	}

	private static void scaleComponents(final Container container, final float scale) {
		for (final Component child : container.getComponents()) {
			if (child instanceof Container)
				scaleComponents((Container) child, scale);
			else
				scaleComponent(child, scale);
		}
	}

	private static void scaleComponent(final Component component, final float scale) {
		Font font = component.getFont();
		if (font == null)
			font = DEFAULT_FONT;
		font = font.deriveFont(scale*font.getSize());
		component.setFont(font);
	}

	public static void scalePopupMenu(final PopupMenu popup) {
		//System.out.println("scalePopupMenu1: "+popup);
		if (Menus.getFontSize()!=0) {
            popup.setFont(Menus.getFont(false));
			//System.out.println("scalePopupMenu2: "+popup.getFont());
            return;
        }
		final float scale = (float)Prefs.getGuiScale();
		if (scale==1f)
			return;
		Font font=popup.getFont();
		if (font==null)
			font = new Font("SansSerif", Font.PLAIN, (int)(scale*13));
		else
			font = font.deriveFont(scale*font.getSize());
		popup.setFont(font);
		//System.out.println("scalePopupMenu3: "+popup.getFont());
	}
	
	/**
	 * Tries to detect if a Swing component is unscaled and scales it it according
	 * to {@link #getGuiScale()}.
	 * <p>
	 * This is mainly relevant to linux: Swing components scale automatically on
	 * most platforms, specially since Java 8. However there are still exceptions to
	 * this on linux: e.g., In Ubuntu, Swing components do scale, but only under the
	 * GTK L&F. (On the other hand AWT components do not scale <i>at all</i> on
	 * hiDPI screens on linux).
	 * </p>
	 * <p>
	 * This method tries to avoid exaggerated font sizes by detecting if a component
	 * has been already scaled by the UIManager, applying only
	 * {@link #getGuiScale()} to the component's font if not.
	 * </p>
	 *
	 * @param component the component to be scaled
	 * @return true, if component's font was resized
	 */
	public static boolean scale(final JComponent component) {
		final double guiScale = Prefs.getGuiScale();
		if (guiScale == 1d)
			return false;
		Font font = component.getFont();
		if (font == null && component instanceof JList)
			font = UIManager.getFont("List.font");
		else if (font == null && component instanceof JTable)
			font = UIManager.getFont("Table.font");
		else if (font == null)
			font = UIManager.getFont("Label.font");
		if (font.getSize() > DEFAULT_FONT.getSize())
			return false;
		if (component instanceof JTable)
			((JTable) component).setRowHeight((int) (((JTable) component).getRowHeight() * guiScale * 0.9));
		else if (component instanceof JList)
			((JList<?>) component).setFixedCellHeight((int) (((JList<?>) component).getFixedCellHeight() * guiScale * 0.9));
		component.setFont(font.deriveFont((float) guiScale * font.getSize()));
		return true;
	}
	
	/** Works around an OpenJDK bug on Windows that
	 * causes the scrollbar thumb color and background
	 * color to be almost identical.
	*/
	public static final void fixScrollbar(Scrollbar sb) {
		if (IJ.isWindows())
			sb.setBackground(scrollbarBackground);
	}
	
	/** Returns a new NonBlockingGenericDialog with the given title,
	 *  except when Java is running in headless mode, in which case
	 *  a GenericDialog is be returned.
	*/
	public static GenericDialog newNonBlockingDialog(String title) {
		if (GraphicsEnvironment.isHeadless())
			return new GenericDialog(title);
		else
			return new NonBlockingGenericDialog(title);
	}

	/** Returns a new NonBlockingGenericDialog with the given title
	 * if Prefs.nonBlockingFilterDialogs is 'true' and 'imp' is
	 * displayed, otherwise returns a GenericDialog.
	 * @param title Dialog title
	 * @param imp The image associated with this dialog
	*/
	public static GenericDialog newNonBlockingDialog(String title, ImagePlus imp) {
		if (Prefs.nonBlockingFilterDialogs && imp!=null && imp.getWindow()!=null) {
			NonBlockingGenericDialog gd = new NonBlockingGenericDialog(title);
			gd.imp = imp;
			return gd;
		} else
			return new GenericDialog(title);
	}

	
}