2 * Jexer - Java Text User Interface
4 * The MIT License (MIT)
6 * Copyright (C) 2019 Kevin Lamonte
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
29 package jexer
.backend
;
31 import java
.awt
.Color
;
32 import java
.awt
.Cursor
;
34 import java
.awt
.Graphics
;
35 import java
.awt
.Insets
;
36 import java
.awt
.Point
;
37 import java
.awt
.Toolkit
;
38 import java
.awt
.event
.ComponentListener
;
39 import java
.awt
.event
.KeyListener
;
40 import java
.awt
.event
.MouseListener
;
41 import java
.awt
.event
.MouseMotionListener
;
42 import java
.awt
.event
.MouseWheelListener
;
43 import java
.awt
.event
.WindowListener
;
44 import java
.awt
.image
.BufferedImage
;
45 import java
.awt
.image
.BufferStrategy
;
46 import javax
.swing
.JComponent
;
47 import javax
.swing
.JFrame
;
50 * Wrapper for integrating with Swing, because JFrame and JComponent have
51 * separate hierarchies.
53 class SwingComponent
{
55 // ------------------------------------------------------------------------
56 // Variables --------------------------------------------------------------
57 // ------------------------------------------------------------------------
60 * If true, use triple buffering when drawing to a JFrame.
62 public static boolean tripleBuffer
= true;
65 * The frame reference, if we are drawing to a JFrame.
70 * The component reference, if we are drawing to a JComponent.
72 private JComponent component
;
75 * An optional border in pixels to add.
77 private static final int BORDER
= 1;
80 * Adjustable Insets for this component. This has the effect of adding a
81 * black border around the drawing area.
83 Insets adjustInsets
= new Insets(BORDER
+ 5, BORDER
, BORDER
, BORDER
);
85 // ------------------------------------------------------------------------
86 // Constructors -----------------------------------------------------------
87 // ------------------------------------------------------------------------
90 * Construct using a JFrame.
92 * @param frame the JFrame to draw to
94 public SwingComponent(final JFrame frame
) {
100 * Construct using a JComponent.
102 * @param component the JComponent to draw to
104 public SwingComponent(final JComponent component
) {
105 this.component
= component
;
109 // ------------------------------------------------------------------------
110 // SwingComponent ---------------------------------------------------------
111 // ------------------------------------------------------------------------
114 * Get the BufferStrategy object needed for triple-buffering.
116 * @return the BufferStrategy
117 * @throws IllegalArgumentException if this function is called when
118 * not rendering to a JFrame
120 public BufferStrategy
getBufferStrategy() {
122 return frame
.getBufferStrategy();
124 throw new IllegalArgumentException("BufferStrategy not used " +
125 "for JComponent access");
130 * Get the JFrame reference.
132 * @return the frame, or null if this is drawing to a JComponent
134 public JFrame
getFrame() {
139 * Get the JComponent reference.
141 * @return the component, or null if this is drawing to a JFrame
143 public JComponent
getComponent() {
148 * Setup to render to an existing JComponent.
150 public void setupComponent() {
151 component
.setBackground(Color
.black
);
153 // Kill the X11 cursor
154 // Transparent 16 x 16 pixel cursor image.
155 BufferedImage cursorImg
= new BufferedImage(16, 16,
156 BufferedImage
.TYPE_INT_ARGB
);
157 // Create a new blank cursor.
158 Cursor blankCursor
= Toolkit
.getDefaultToolkit().createCustomCursor(
159 cursorImg
, new Point(0, 0), "blank cursor");
160 component
.setCursor(blankCursor
);
162 // Be capable of seeing Tab / Shift-Tab
163 component
.setFocusTraversalKeysEnabled(false);
167 * Setup to render to an existing JFrame.
169 public void setupFrame() {
170 frame
.setTitle("Jexer Application");
171 frame
.setBackground(Color
.black
);
174 // Kill the X11 cursor
175 // Transparent 16 x 16 pixel cursor image.
176 BufferedImage cursorImg
= new BufferedImage(16, 16,
177 BufferedImage
.TYPE_INT_ARGB
);
178 // Create a new blank cursor.
179 Cursor blankCursor
= Toolkit
.getDefaultToolkit().createCustomCursor(
180 cursorImg
, new Point(0, 0), "blank cursor");
181 frame
.setCursor(blankCursor
);
183 // Be capable of seeing Tab / Shift-Tab
184 frame
.setFocusTraversalKeysEnabled(false);
186 // Setup triple-buffering
188 frame
.setIgnoreRepaint(true);
189 frame
.createBufferStrategy(3);
194 * Set the window title.
196 * @param title the new title
198 public void setTitle(final String title
) {
200 frame
.setTitle(title
);
205 * Paints this component.
207 * @param g the graphics context to use for painting
209 public void paint(Graphics g
) {
218 * Repaints this component.
220 public void repaint() {
229 * Repaints the specified rectangle of this component.
231 * @param x the x coordinate
232 * @param y the y coordinate
233 * @param width the width
234 * @param height the height
236 public void repaint(int x
, int y
, int width
, int height
) {
238 frame
.repaint(x
, y
, width
, height
);
240 component
.repaint(x
, y
, width
, height
);
245 * If a border has been set on this component, returns the border's
246 * insets; otherwise calls super.getInsets.
248 * @return the value of the insets property
250 public Insets
getInsets() {
251 Insets swingInsets
= null;
253 swingInsets
= frame
.getInsets();
255 swingInsets
= component
.getInsets();
257 Insets result
= new Insets(swingInsets
.top
+ adjustInsets
.top
,
258 swingInsets
.left
+ adjustInsets
.left
,
259 swingInsets
.bottom
+ adjustInsets
.bottom
,
260 swingInsets
.right
+ adjustInsets
.right
);
265 * Returns the current width of this component.
267 * @return the current width of this component
269 public int getWidth() {
271 return frame
.getWidth();
273 return component
.getWidth();
278 * Returns the current height of this component.
280 * @return the current height of this component
282 public int getHeight() {
284 return frame
.getHeight();
286 return component
.getHeight();
291 * Gets the font of this component.
293 * @return this component's font; if a font has not been set for this
294 * component, the font of its parent is returned
296 public Font
getFont() {
298 return frame
.getFont();
300 return component
.getFont();
305 * Sets the font of this component.
307 * @param f the font to become this component's font; if this parameter
308 * is null then this component will inherit the font of its parent
310 public void setFont(final Font f
) {
314 component
.setFont(f
);
319 * Shows or hides this Window depending on the value of parameter b.
321 * @param b if true, make visible, else make invisible
323 public void setVisible(final boolean b
) {
327 component
.setVisible(b
);
332 * Creates a graphics context for this component. This method will return
333 * null if this component is currently not displayable.
335 * @return a graphics context for this component, or null if it has none
337 public Graphics
getGraphics() {
339 return frame
.getGraphics();
341 return component
.getGraphics();
346 * Releases all of the native screen resources used by this Window, its
347 * subcomponents, and all of its owned children. That is, the resources
348 * for these Components will be destroyed, any memory they consume will
349 * be returned to the OS, and they will be marked as undisplayable.
351 public void dispose() {
355 component
.getParent().remove(component
);
360 * Resize the component to match the font dimensions.
362 * @param width the new width in pixels
363 * @param height the new height in pixels
365 public void setDimensions(final int width
, final int height
) {
366 // Figure out the thickness of borders and use that to set the final
369 Insets insets
= getInsets();
370 frame
.setSize(width
+ insets
.left
+ insets
.right
,
371 height
+ insets
.top
+ insets
.bottom
);
373 Insets insets
= getInsets();
374 component
.setSize(width
+ insets
.left
+ insets
.right
,
375 height
+ insets
.top
+ insets
.bottom
);
380 * Adds the specified component listener to receive component events from
381 * this component. If listener l is null, no exception is thrown and no
382 * action is performed.
384 * @param l the component listener
386 public void addComponentListener(ComponentListener l
) {
388 frame
.addComponentListener(l
);
390 component
.addComponentListener(l
);
395 * Adds the specified key listener to receive key events from this
396 * component. If l is null, no exception is thrown and no action is
399 * @param l the key listener.
401 public void addKeyListener(KeyListener l
) {
403 frame
.addKeyListener(l
);
405 component
.addKeyListener(l
);
410 * Adds the specified mouse listener to receive mouse events from this
411 * component. If listener l is null, no exception is thrown and no action
414 * @param l the mouse listener
416 public void addMouseListener(MouseListener l
) {
418 frame
.addMouseListener(l
);
420 component
.addMouseListener(l
);
425 * Adds the specified mouse motion listener to receive mouse motion
426 * events from this component. If listener l is null, no exception is
427 * thrown and no action is performed.
429 * @param l the mouse motion listener
431 public void addMouseMotionListener(MouseMotionListener l
) {
433 frame
.addMouseMotionListener(l
);
435 component
.addMouseMotionListener(l
);
440 * Adds the specified mouse wheel listener to receive mouse wheel events
441 * from this component. Containers also receive mouse wheel events from
444 * @param l the mouse wheel listener
446 public void addMouseWheelListener(MouseWheelListener l
) {
448 frame
.addMouseWheelListener(l
);
450 component
.addMouseWheelListener(l
);
455 * Adds the specified window listener to receive window events from this
456 * window. If l is null, no exception is thrown and no action is
459 * @param l the window listener
461 public void addWindowListener(WindowListener l
) {
463 frame
.addWindowListener(l
);