2 * Jexer - Java Text User Interface
4 * The MIT License (MIT)
6 * Copyright (C) 2017 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
;
74 // ------------------------------------------------------------------------
75 // Constructors -----------------------------------------------------------
76 // ------------------------------------------------------------------------
79 * Construct using a JFrame.
81 * @param frame the JFrame to draw to
83 public SwingComponent(final JFrame frame
) {
89 * Construct using a JComponent.
91 * @param component the JComponent to draw to
93 public SwingComponent(final JComponent component
) {
94 this.component
= component
;
98 // ------------------------------------------------------------------------
99 // SwingComponent ---------------------------------------------------------
100 // ------------------------------------------------------------------------
103 * Get the BufferStrategy object needed for triple-buffering.
105 * @return the BufferStrategy
106 * @throws IllegalArgumentException if this function is called when
107 * not rendering to a JFrame
109 public BufferStrategy
getBufferStrategy() {
111 return frame
.getBufferStrategy();
113 throw new IllegalArgumentException("BufferStrategy not used " +
114 "for JComponent access");
119 * Get the JFrame reference.
121 * @return the frame, or null if this is drawing to a JComponent
123 public JFrame
getFrame() {
128 * Get the JComponent reference.
130 * @return the component, or null if this is drawing to a JFrame
132 public JComponent
getComponent() {
137 * Setup to render to an existing JComponent.
139 public void setupComponent() {
140 component
.setBackground(Color
.black
);
142 // Kill the X11 cursor
143 // Transparent 16 x 16 pixel cursor image.
144 BufferedImage cursorImg
= new BufferedImage(16, 16,
145 BufferedImage
.TYPE_INT_ARGB
);
146 // Create a new blank cursor.
147 Cursor blankCursor
= Toolkit
.getDefaultToolkit().createCustomCursor(
148 cursorImg
, new Point(0, 0), "blank cursor");
149 component
.setCursor(blankCursor
);
151 // Be capable of seeing Tab / Shift-Tab
152 component
.setFocusTraversalKeysEnabled(false);
156 * Setup to render to an existing JFrame.
158 public void setupFrame() {
159 frame
.setTitle("Jexer Application");
160 frame
.setBackground(Color
.black
);
163 // Kill the X11 cursor
164 // Transparent 16 x 16 pixel cursor image.
165 BufferedImage cursorImg
= new BufferedImage(16, 16,
166 BufferedImage
.TYPE_INT_ARGB
);
167 // Create a new blank cursor.
168 Cursor blankCursor
= Toolkit
.getDefaultToolkit().createCustomCursor(
169 cursorImg
, new Point(0, 0), "blank cursor");
170 frame
.setCursor(blankCursor
);
172 // Be capable of seeing Tab / Shift-Tab
173 frame
.setFocusTraversalKeysEnabled(false);
175 // Setup triple-buffering
177 frame
.setIgnoreRepaint(true);
178 frame
.createBufferStrategy(3);
183 * Set the window title.
185 * @param title the new title
187 public void setTitle(final String title
) {
189 frame
.setTitle(title
);
194 * Paints this component.
196 * @param g the graphics context to use for painting
198 public void paint(Graphics g
) {
207 * Repaints this component.
209 public void repaint() {
218 * Repaints the specified rectangle of this component.
220 * @param x the x coordinate
221 * @param y the y coordinate
222 * @param width the width
223 * @param height the height
225 public void repaint(int x
, int y
, int width
, int height
) {
227 frame
.repaint(x
, y
, width
, height
);
229 component
.repaint(x
, y
, width
, height
);
234 * If a border has been set on this component, returns the border's
235 * insets; otherwise calls super.getInsets.
237 * @return the value of the insets property
239 public Insets
getInsets() {
241 return frame
.getInsets();
243 return component
.getInsets();
248 * Returns the current width of this component.
250 * @return the current width of this component
252 public int getWidth() {
254 return frame
.getWidth();
256 return component
.getWidth();
261 * Returns the current height of this component.
263 * @return the current height of this component
265 public int getHeight() {
267 return frame
.getHeight();
269 return component
.getHeight();
274 * Gets the font of this component.
276 * @return this component's font; if a font has not been set for this
277 * component, the font of its parent is returned
279 public Font
getFont() {
281 return frame
.getFont();
283 return component
.getFont();
288 * Sets the font of this component.
290 * @param f the font to become this component's font; if this parameter
291 * is null then this component will inherit the font of its parent
293 public void setFont(final Font f
) {
297 component
.setFont(f
);
302 * Shows or hides this Window depending on the value of parameter b.
304 * @param b if true, make visible, else make invisible
306 public void setVisible(final boolean b
) {
310 component
.setVisible(b
);
315 * Creates a graphics context for this component. This method will return
316 * null if this component is currently not displayable.
318 * @return a graphics context for this component, or null if it has none
320 public Graphics
getGraphics() {
322 return frame
.getGraphics();
324 return component
.getGraphics();
329 * Releases all of the native screen resources used by this Window, its
330 * subcomponents, and all of its owned children. That is, the resources
331 * for these Components will be destroyed, any memory they consume will
332 * be returned to the OS, and they will be marked as undisplayable.
334 public void dispose() {
338 component
.getParent().remove(component
);
343 * Resize the component to match the font dimensions.
345 * @param width the new width in pixels
346 * @param height the new height in pixels
348 public void setDimensions(final int width
, final int height
) {
349 // Figure out the thickness of borders and use that to set the final
351 Insets insets
= getInsets();
354 frame
.setSize(width
+ insets
.left
+ insets
.right
,
355 height
+ insets
.top
+ insets
.bottom
);
357 component
.setSize(width
+ insets
.left
+ insets
.right
,
358 height
+ insets
.top
+ insets
.bottom
);
363 * Adds the specified component listener to receive component events from
364 * this component. If listener l is null, no exception is thrown and no
365 * action is performed.
367 * @param l the component listener
369 public void addComponentListener(ComponentListener l
) {
371 frame
.addComponentListener(l
);
373 component
.addComponentListener(l
);
378 * Adds the specified key listener to receive key events from this
379 * component. If l is null, no exception is thrown and no action is
382 * @param l the key listener.
384 public void addKeyListener(KeyListener l
) {
386 frame
.addKeyListener(l
);
388 component
.addKeyListener(l
);
393 * Adds the specified mouse listener to receive mouse events from this
394 * component. If listener l is null, no exception is thrown and no action
397 * @param l the mouse listener
399 public void addMouseListener(MouseListener l
) {
401 frame
.addMouseListener(l
);
403 component
.addMouseListener(l
);
408 * Adds the specified mouse motion listener to receive mouse motion
409 * events from this component. If listener l is null, no exception is
410 * thrown and no action is performed.
412 * @param l the mouse motion listener
414 public void addMouseMotionListener(MouseMotionListener l
) {
416 frame
.addMouseMotionListener(l
);
418 component
.addMouseMotionListener(l
);
423 * Adds the specified mouse wheel listener to receive mouse wheel events
424 * from this component. Containers also receive mouse wheel events from
427 * @param l the mouse wheel listener
429 public void addMouseWheelListener(MouseWheelListener l
) {
431 frame
.addMouseWheelListener(l
);
433 component
.addMouseWheelListener(l
);
438 * Adds the specified window listener to receive window events from this
439 * window. If l is null, no exception is thrown and no action is
442 * @param l the window listener
444 public void addWindowListener(WindowListener l
) {
446 frame
.addWindowListener(l
);