source: trunk/src/org/expeditee/gio/swing/SwingGraphicsManager.java@ 1545

Last change on this file since 1545 was 1545, checked in by bnemhaus, 3 years ago

Expeditee now respects the users antialiasing setting. The previous system

  1. Attempted to respect antialiasing by checking the setting and enabling it if the setting was true
  2. In the process of painting the frame some special items (link marks etc) want to use antialiasing reguardless of setting. This was achieved by turning antialiasing on, doing the thing and then turning it off. This unfortunately meant that, in the scenario that the users antialiasing setting is on, it gets turned off after drawing one of these special items and doesn't get turn on again until all items have been drawn.

The new system still always turns antialiasing on for these special items, but instead of turning it off after, it returns it to the setting it was previously on. This is achieved with two new functions: setTransientAntialiasingOn() and setTransientAntialiasingOff().

On a related note, there was also an issue with some polygons being drawn with a thickness of 0.0f, which was causing them to antialias badly. They now have a thickness of 1.0f.

File size: 19.5 KB
Line 
1package org.expeditee.gio.swing;
2
3import java.awt.AlphaComposite;
4import java.awt.Component;
5import java.awt.Container;
6import java.awt.FontMetrics;
7import java.awt.Graphics;
8import java.awt.Graphics2D;
9import java.awt.GraphicsEnvironment;
10import java.awt.RenderingHints;
11import java.awt.Toolkit;
12import java.awt.event.ComponentListener;
13import java.awt.event.KeyListener;
14import java.awt.event.WindowListener;
15import java.awt.event.WindowStateListener;
16import java.awt.geom.AffineTransform;
17import java.awt.image.ImageObserver;
18
19import javax.swing.JFrame;
20import javax.swing.JLayeredPane;
21import javax.swing.JMenuBar;
22import javax.swing.JOptionPane;
23import javax.swing.RepaintManager;
24import javax.swing.SwingUtilities;
25import javax.swing.TransferHandler;
26
27import org.expeditee.core.Clip;
28import org.expeditee.core.Colour;
29import org.expeditee.core.Cursor;
30import org.expeditee.core.Dimension;
31import org.expeditee.core.Fill;
32import org.expeditee.core.Font;
33import org.expeditee.core.GradientFill;
34import org.expeditee.core.Image;
35import org.expeditee.core.Point;
36import org.expeditee.core.Stroke;
37import org.expeditee.core.TextLayout;
38import org.expeditee.core.bounds.PolygonBounds;
39import org.expeditee.gio.GraphicsManager;
40import org.expeditee.gio.GraphicsSurfaceStack;
41import org.expeditee.gio.swing.SwingImageManager.BlockingImageObserver;
42import org.expeditee.gio.swing.SwingImageManager.SelfAnimatingImageObserver;
43import org.expeditee.gui.DisplayController;
44import org.expeditee.items.widgets.SwingWidget;
45import org.expeditee.items.widgets.Widget;
46
47// TODO: Make stack thread-safe
48public class SwingGraphicsManager extends GraphicsManager {
49
50 private static SwingGraphicsManager _instance;
51
52 public static SwingGraphicsManager getInstance() {
53 if (_instance == null) {
54 try {
55 SwingUtilities.invokeAndWait(new Runnable() {
56 @Override
57 public void run() {
58 _instance = new SwingGraphicsManager();
59 }
60 });
61 } catch (Exception e) {
62 System.err.println("Error while initialising GraphicsManager. Aborting...");
63 e.printStackTrace(System.err);
64 System.exit(1);
65 }
66
67 // Block until the window is ready
68
69 }
70
71 return _instance;
72 }
73
74 private JFrame _jFrame;
75
76 private GraphicsSurfaceStack<Graphics2D> _surfaceStack;
77
78 private SwingGraphicsManager() {
79 _jFrame = new JFrame() {
80 private static final long serialVersionUID = 5179259234365906415L;
81
82 // Override the paint() method so that Expeditee's graphics are drawn
83 // when the window refreshes.
84 @Override
85 public void paint(Graphics g) {
86 DisplayController.requestRefresh(false);
87 }
88 };
89
90 setWindowIcon();
91
92 /*
93 * See Java bug ID 4016934. They say that window closed events are called once
94 * the JFrame is disposed.
95 */
96 _jFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
97
98 // Expeditee handles its own repainting of AWT/Swing components
99 RepaintManager.setCurrentManager(ExpediteeRepaintManager.getInstance());
100
101 // required to accept TAB key
102 _jFrame.setFocusTraversalKeysEnabled(false);
103
104 _jFrame.pack();
105
106 // Moved to here to work with JFXPanel
107 // TODO: Is the above comment still relevant? cts16
108 _jFrame.getContentPane().setLayout(new AbsoluteLayout());
109
110 // Set visible must be just after DisplayIO.Init for the message box to be the
111 // right size
112 // TODO: Is the above comment still relevant? cts16
113 _jFrame.setVisible(true);
114
115 // Create the surface stack
116 _surfaceStack = new GraphicsSurfaceStack<Graphics2D>() {
117 @Override
118 public Graphics2D getSurfaceFromImage(Image image) {
119 return SwingMiscManager.getIfUsingSwingImageManager().getImageGraphics(image);
120 }
121
122 @Override
123 public void setSurfaceClip(Graphics2D surface, Clip clip) {
124 if (surface == null) {
125 return;
126 }
127
128 if (clip == null) {
129 surface.setClip(null);
130 return;
131 }
132
133 if (clip.isFullyClipped()) {
134 return;
135 }
136
137 surface.setClip(SwingConversions.toSwingRectangle(clip.getBounds()));
138 }
139 };
140 refreshRootSurface();
141 }
142
143 @Override
144 protected GraphicsSurfaceStack<?> getGraphicsSurfaceStack() {
145 return _surfaceStack;
146 }
147
148 @Override
149 public Dimension getScreenSize() {
150 java.awt.Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
151
152 return SwingConversions.fromSwingDimension(size);
153 }
154
155 @Override
156 public Point getWindowLocation() {
157 return SwingConversions.fromSwingPoint(_jFrame.getContentPane().getLocationOnScreen());
158 }
159
160 @Override
161 public void setWindowLocation(Point p) {
162 _jFrame.setLocation(p.getX(), p.getY());
163 }
164
165 @Override
166 public Dimension getWindowSize() {
167 return SwingConversions.fromSwingDimension(_jFrame.getContentPane().getSize());
168 }
169
170 @Override
171 public void setWindowSize(Dimension d) {
172 _jFrame.setSize(d.width, d.height);
173 _jFrame.setPreferredSize(SwingConversions.toSwingDimension(d));
174 // Issue a command to graphics so that the JFrame draws itself white.
175 _jFrame.getGraphics().clearRect(0, 0, d.width, d.height);
176 }
177
178 @Override
179 public void requestFocus() {
180 _jFrame.requestFocus();
181 }
182
183 @Override
184 public void setCompositeAlpha(float alpha) {
185 _surfaceStack.getCurrentSurface().setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
186 }
187
188 private boolean frameUsingAntialiasing = false;
189
190 @Override
191 public void setAntialiasing(boolean on) {
192 setAntialiasing(_surfaceStack.getCurrentSurface(), on);
193 }
194
195 private void setAntialiasing(Graphics2D surface, boolean on) {
196 if (surface == null) {
197 return;
198 }
199
200 if (on) {
201 surface.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
202 frameUsingAntialiasing = true;
203 } else {
204 surface.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
205 frameUsingAntialiasing = false;
206 }
207 }
208
209 @Override
210 public void setTransientAntialiasingOn() {
211 if (!frameUsingAntialiasing) {
212 Graphics2D surface = _surfaceStack.getCurrentSurface();
213 surface.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
214 }
215 }
216
217 @Override
218 public void setTransientAntialiasingOff() {
219 if (!frameUsingAntialiasing) {
220 Graphics2D surface = _surfaceStack.getCurrentSurface();
221 surface.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
222 }
223 }
224
225 @Override
226 public void setFont(Font font) {
227 _surfaceStack.getCurrentSurface().setFont(SwingMiscManager.getIfUsingSwingFontManager().getInternalFont(font));
228 }
229
230 @Override
231 public void drawImage(Image image, Point topLeft, Dimension size, double angle, Point cropTopLeft,
232 Dimension cropSize) {
233 // Can't draw nothing
234 if (image == null) {
235 return;
236 }
237
238 // Can't draw nowhere
239 if (topLeft == null) {
240 return;
241 }
242
243 // If the cropped area is degenerate, abort
244 if (cropSize != null && (cropSize.width <= 0 || cropSize.height <= 0)) {
245 return;
246 }
247
248 // If the crop area is the entire image, pretend we are not cropping
249 if (Point.ORIGIN.equals(cropTopLeft) && image.getSize().equals(cropSize)) {
250 cropTopLeft = null;
251 cropSize = null;
252 }
253
254 SwingImageManager manager = SwingMiscManager.getIfUsingSwingImageManager();
255
256 ImageObserver animator = null;
257 if (image.isAnimated()) {
258 animator = manager.getAnimator(image);
259 if (animator != null) {
260 ((SelfAnimatingImageObserver) animator).activate();
261 }
262 } else {
263 animator = new SwingImageManager.LoadCompletedImageObserver();
264 }
265
266 // Default is the entire image
267 Image croppedImage = image;
268
269 // If we are cropping, do this now into a temporary image
270 if (cropTopLeft != null && cropSize != null) {
271 croppedImage = manager.createImage(cropSize.width, cropSize.height);
272 manager.getInternalImage(croppedImage).getGraphics().drawImage(manager.getInternalImage(image), 0, 0,
273 cropSize.width - 1, cropSize.height - 1, cropTopLeft.getX(), cropTopLeft.getY(),
274 cropTopLeft.getX() + cropSize.width - 1, cropTopLeft.getY() + cropSize.height - 1, animator);
275 animator = new BlockingImageObserver();
276 }
277
278 // Transform the image
279 AffineTransform tx = new AffineTransform();
280 if (size != null) {
281 tx.scale(((double) size.width) / croppedImage.getWidth(),
282 ((double) size.height) / croppedImage.getHeight());
283 }
284 if (angle != 0.0) {
285 tx.rotate(angle);
286 }
287 if (topLeft != null) {
288 tx.translate(topLeft.getX(), topLeft.getY());
289 }
290
291 // Draw the image to the current surface
292 boolean drawn = _surfaceStack.getCurrentSurface().drawImage(manager.getInternalImage(croppedImage), tx,
293 animator);
294
295 // If the draw didn't succeed, try again after waiting for the image to load
296 if (!drawn && animator instanceof BlockingImageObserver) {
297 ((BlockingImageObserver) animator).attemptWait();
298 _surfaceStack.getCurrentSurface().drawImage(manager.getInternalImage(croppedImage), tx, animator);
299 }
300 }
301
302 @Override
303 public void drawRectangle(Point topLeft, Dimension size, double angle, Fill fill, Colour borderColour,
304 Stroke borderStroke, Dimension cornerRadius) {
305 Graphics2D g = (Graphics2D) _surfaceStack.getCurrentSurface().create();
306
307 if (angle != 0.0) {
308 AffineTransform tx = new AffineTransform();
309 tx.rotate(angle);
310 g.transform(tx);
311 }
312
313 if (fill != null) {
314 if (fill instanceof GradientFill) {
315 g.setPaint(SwingConversions.toSwingGradientPaint((GradientFill) fill));
316 } else {
317 g.setColor(SwingConversions.toSwingColor(fill.getColour()));
318 }
319
320 if (cornerRadius != null) {
321 g.fillRoundRect(topLeft.getX(), topLeft.getY(), size.width, size.height, cornerRadius.width, cornerRadius.height);
322 } else {
323 g.fillRect(topLeft.getX(), topLeft.getY(), size.width, size.height);
324 }
325 }
326
327 if (borderColour != null && borderStroke != null) {
328 g.setColor(SwingConversions.toSwingColor(borderColour));
329 g.setStroke(SwingConversions.toSwingStroke(borderStroke));
330
331 if (cornerRadius != null) {
332 g.drawRoundRect(topLeft.getX(), topLeft.getY(), size.width, size.height, cornerRadius.width, cornerRadius.height);
333 } else {
334 g.drawRect(topLeft.getX(), topLeft.getY(), size.width, size.height);
335 }
336 }
337
338 g.dispose();
339 }
340
341 @Override
342 public void drawOval(Point centre, Dimension diameters, double angle, Fill fill, Colour borderColour,
343 Stroke borderStroke) {
344 Graphics2D g = (Graphics2D) _surfaceStack.getCurrentSurface().create();
345
346 if (angle != 0.0) {
347 AffineTransform tx = new AffineTransform();
348 tx.rotate(angle);
349 g.transform(tx);
350 }
351
352 Point topLeft = new Point(centre.getX() - diameters.width / 2, centre.getY() - diameters.height / 2);
353
354 if (fill != null) {
355 if (fill instanceof GradientFill) {
356 g.setPaint(SwingConversions.toSwingGradientPaint((GradientFill) fill));
357 } else {
358 g.setColor(SwingConversions.toSwingColor(fill.getColour()));
359 }
360
361 g.fillOval(topLeft.getX(), topLeft.getY(), diameters.width, diameters.height);
362 }
363
364 if (borderColour != null && borderStroke != null) {
365 g.setColor(SwingConversions.toSwingColor(borderColour));
366 g.setStroke(SwingConversions.toSwingStroke(borderStroke));
367
368 g.drawOval(topLeft.getX(), topLeft.getY(), diameters.width, diameters.height);
369 }
370
371 g.dispose();
372 }
373
374 @Override
375 public void drawPolygon(PolygonBounds points, Point offset, Dimension scale, double angle, Fill fill,
376 Colour borderColour, Stroke borderStroke) {
377 if (points == null || points.getPointCount() < 2) {
378 return;
379 }
380 if (fill == null && (borderColour == null || borderStroke == null)) {
381 return;
382 }
383
384 Graphics2D g = (Graphics2D) _surfaceStack.getCurrentSurface().create();
385
386 AffineTransform tx = new AffineTransform();
387 Point centre = points.getCentre();
388 tx.translate(-centre.getX(), -centre.getY());
389 if (angle != 0.0) {
390 tx.rotate(angle);
391 }
392 if (scale != null) {
393 double xScale = ((double) scale.width) / (points.getMaxX() - points.getMinX());
394 double yScale = ((double) scale.height) / (points.getMaxY() - points.getMinY());
395 tx.scale(xScale, yScale);
396 }
397 tx.translate(centre.getX(), centre.getY());
398 if (offset != null) {
399 tx.translate(offset.getX(), offset.getY());
400 }
401 g.transform(tx);
402
403 if (fill != null) {
404 if (fill instanceof GradientFill) {
405 g.setPaint(SwingConversions.toSwingGradientPaint((GradientFill) fill));
406 } else {
407 g.setColor(SwingConversions.toSwingColor(fill.getColour()));
408 }
409
410 g.fillPolygon(SwingConversions.toSwingPolygon(points));
411 }
412
413 if (borderColour != null && borderStroke != null) {
414 g.setColor(SwingConversions.toSwingColor(borderColour));
415 g.setStroke(SwingConversions.toSwingStroke(borderStroke));
416
417 if (points.isClosed()) {
418 g.drawPolygon(SwingConversions.toSwingPolygon(points));
419 } else {
420 int nPoints = points.getPointCount();
421 int[] xPoints = new int[nPoints];
422 int[] yPoints = new int[nPoints];
423
424 for (int i = 0; i < nPoints; i++) {
425 Point point = points.getPoint(i);
426 xPoints[i] = point.getX();
427 yPoints[i] = point.getY();
428 }
429
430 g.drawPolyline(xPoints, yPoints, nPoints);
431 }
432 }
433
434 g.dispose();
435 }
436
437 @Override
438 public void drawLine(int x1, int y1, int x2, int y2, Colour colour, Stroke stroke) {
439 if (colour == null || stroke == null) {
440 return;
441 }
442
443 Graphics2D g = (Graphics2D) _surfaceStack.getCurrentSurface().create();
444 g.setColor(SwingConversions.toSwingColor(colour));
445 g.setStroke(SwingConversions.toSwingStroke(stroke));
446
447 g.drawLine(x1, y1, x2, y2);
448
449 g.dispose();
450 }
451
452 @Override
453 public void drawString(String string, Point position, Font font, Colour colour) {
454 if (string == null || position == null || font == null || colour == null) {
455 return;
456 }
457
458 Graphics2D g = (Graphics2D) _surfaceStack.getCurrentSurface().create();
459 g.setColor(SwingConversions.toSwingColor(colour));
460 g.setFont(SwingMiscManager.getIfUsingSwingFontManager().getInternalFont(font));
461
462 g.drawString(string, position.getX(), position.getY());
463
464 g.dispose();
465 }
466
467 @Override
468 public void drawTextLayout(TextLayout layout, Point position, Colour colour) {
469 if (layout == null) {
470 return;
471 }
472
473 SwingTextLayoutManager layoutManager = SwingMiscManager.getIfUsingSwingTextLayoutManager();
474 if (layoutManager == null) {
475 drawString(layout.getLine(), position, layout.getFont(), colour);
476 return;
477 }
478
479 java.awt.font.TextLayout swingLayout = layoutManager.getInternalLayout(layout);
480
481 Graphics2D g = (Graphics2D) _surfaceStack.getCurrentSurface().create();
482 g.setColor(SwingConversions.toSwingColor(colour));
483
484 swingLayout.draw(g, position.getX(), position.getY());
485 }
486
487 private Dimension _preFullscreenSize = null;
488 private boolean _fullScreenTransitionPending = false;
489
490 /**
491 * Whether or not we are in the middle of transitioning to/from fullscreen.
492 */
493 public boolean isFullscreenTransitionPending() {
494 return _fullScreenTransitionPending;
495 }
496
497 /**
498 * Should be called when the SwingInputManager is notified that the fullscreen
499 * transition has finished.
500 */
501 public void finishFullscreenTransition() {
502 _fullScreenTransitionPending = false;
503 }
504
505 @Override
506 public boolean canGoFullscreen() {
507 return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().isFullScreenSupported();
508 }
509
510 @Override
511 public boolean isFullscreen() {
512 return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()
513 .getFullScreenWindow() == _jFrame;
514 }
515
516 @Override
517 public void goFullscreen() {
518 if (!canGoFullscreen()) {
519 System.err.println("Warning: GraphicsManager::goFullScreen() called when not available -- ignoring");
520 return;
521 }
522
523 _preFullscreenSize = getWindowSize();
524
525 _fullScreenTransitionPending = true;
526
527 _jFrame.dispose();
528 _jFrame.setUndecorated(true);
529 _jFrame.pack();
530 _jFrame.setVisible(true);
531
532 GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(_jFrame);
533 }
534
535 @Override
536 public void exitFullscreen() {
537 _fullScreenTransitionPending = true;
538
539 _jFrame.dispose();
540 _jFrame.setUndecorated(false);
541
542 GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(null);
543 _jFrame.pack();
544 _jFrame.setVisible(true);
545 setWindowSize(_preFullscreenSize);
546 }
547
548 @Override
549 public void setCursor(Cursor cursor) {
550 if (cursor == null) {
551 return;
552 }
553
554 java.awt.Cursor swingCursor;
555 if (cursor.getType() == Cursor.CursorType.CUSTOM) {
556 SwingImageManager imageManager = SwingMiscManager.getIfUsingSwingImageManager();
557
558 if (imageManager == null) {
559 return;
560 }
561
562 swingCursor = Toolkit.getDefaultToolkit().createCustomCursor(
563 imageManager.getInternalImage(cursor.getImage()),
564 SwingConversions.toSwingPoint(cursor.getHotspot()), cursor.getName());
565 } else {
566 swingCursor = new java.awt.Cursor(SwingConversions.toSwingCursorType(cursor.getType()));
567 }
568
569 _jFrame.setCursor(swingCursor);
570 }
571
572 @Override
573 public Dimension getBestCursorSize(Dimension desiredSize) {
574 Toolkit toolkit = Toolkit.getDefaultToolkit();
575 java.awt.Dimension best_cursor_dim = toolkit.getBestCursorSize(desiredSize.width, desiredSize.height);
576 return SwingConversions.fromSwingDimension(best_cursor_dim);
577 }
578
579 @Override
580 public void setWindowTitle(String title) {
581 _jFrame.setTitle(title);
582 }
583
584 @Override
585 public boolean showDialog(String title, String message) {
586 int result = JOptionPane.showConfirmDialog(_jFrame, message, title, JOptionPane.OK_CANCEL_OPTION,
587 JOptionPane.WARNING_MESSAGE);
588 return result == JOptionPane.OK_OPTION;
589 }
590
591 @Override
592 public Dimension getCurrentDrawingSurfaceSize() {
593 Image currentImage = _surfaceStack.getCurrentImage();
594
595 if (currentImage != null) {
596 return currentImage.getSize();
597 } else {
598 return getWindowSize();
599 }
600 }
601
602 public void refreshRootSurface() {
603 Graphics2D rootSurface = (Graphics2D) _jFrame.getContentPane().getGraphics();
604 rootSurface.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
605 final java.awt.Font rootSurfaceFont = rootSurface.getFont().deriveFont(40f);
606 rootSurface.setFont(rootSurfaceFont);
607 _surfaceStack.setRootSurface(rootSurface);
608 }
609
610 public JFrame getJFrame() {
611 return _jFrame;
612 }
613
614 public Container getContentPane() {
615 return _jFrame.getContentPane();
616 }
617
618 public JLayeredPane getLayeredPane() {
619 return _jFrame.getLayeredPane();
620 }
621
622 public void setTransferHandler(TransferHandler newHandler) {
623 _jFrame.setTransferHandler(newHandler);
624 }
625
626 public void addWindowListener(WindowListener l) {
627 _jFrame.addWindowListener(l);
628 }
629
630 public void addWindowStateListener(WindowStateListener l) {
631 _jFrame.addWindowStateListener(l);
632 }
633
634 public void addKeyListener(KeyListener l) {
635 _jFrame.addKeyListener(l);
636 }
637
638 public void addComponentListener(ComponentListener l) {
639 _jFrame.addComponentListener(l);
640 }
641
642 public void setGlassPane(Component glassPane) {
643 _jFrame.setGlassPane(glassPane);
644 }
645
646 public Component getGlassPane() {
647 return _jFrame.getGlassPane();
648 }
649
650 public JMenuBar getJMenuBar() {
651 return _jFrame.getJMenuBar();
652 }
653
654 public FontMetrics getFontMetrics(java.awt.Font font) {
655 return _jFrame.getFontMetrics(font);
656 }
657
658 public java.awt.Font getFont() {
659 return _jFrame.getFont();
660 }
661
662 public Graphics2D getCurrentSurface() {
663 return _surfaceStack.getCurrentSurface();
664 }
665
666 @Override
667 public boolean addInteractiveWidget(Widget iw) {
668 if (super.addInteractiveWidget(iw)) {
669 _jFrame.getContentPane().add(((SwingWidget) iw).getComponent());
670 return true;
671 }
672
673 return false;
674 }
675
676 @Override
677 public boolean removeInteractiveWidget(Widget iw) {
678 if (super.removeInteractiveWidget(iw)) {
679 _jFrame.getContentPane().remove(((SwingWidget) iw).getComponent());
680 return true;
681 }
682
683 return false;
684 }
685
686 @Override
687 protected void setWindowIcon(Image image) {
688 SwingImageManager imageManager = SwingMiscManager.getIfUsingSwingImageManager();
689
690 if (imageManager != null) {
691 _jFrame.setIconImage(imageManager.getInternalImage(image));
692 }
693 }
694
695 @Override
696 public int getFontHeight(final Font font) {
697 final java.awt.Font awtFont = SwingFontManager.getInstance().getInternalFont(font);
698 final FontMetrics fontMetrics = _jFrame.getGraphics().getFontMetrics(awtFont);
699 return fontMetrics.getHeight();
700 }
701}
Note: See TracBrowser for help on using the repository browser.