X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fjexer%2Fio%2FAWTScreen.java;h=308a285c38074f5055bf8db292df0202e27b9f5b;hb=bd8d51fa0a33d6d27dba088c57791e1650512fc0;hp=d7951b6b3b5287159bc2d4a19aeab84e7fad6f72;hpb=30bd4abd2a85c162bdf0a1cc687b366345182bc1;p=fanfix.git diff --git a/src/jexer/io/AWTScreen.java b/src/jexer/io/AWTScreen.java index d7951b6..308a285 100644 --- a/src/jexer/io/AWTScreen.java +++ b/src/jexer/io/AWTScreen.java @@ -47,6 +47,8 @@ import java.awt.Toolkit; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.InputStream; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; /** * This Screen implementation draws to a Java AWT Frame. @@ -103,7 +105,7 @@ public final class AWTScreen extends Screen { /** * AWTFrame is our top-level hook into the AWT system. */ - class AWTFrame extends Frame { + class AWTFrame extends JFrame { /** * The terminus font resource filename. @@ -236,7 +238,7 @@ public final class AWTScreen extends Screen { setDOSColors(); setTitle("Jexer Application"); - setBackground(java.awt.Color.black); + setBackground(Color.black); // setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); // setFont(new Font("Liberation Mono", Font.BOLD, 16)); // setFont(new Font(Font.MONOSPACED, Font.PLAIN, 16)); @@ -253,8 +255,7 @@ public final class AWTScreen extends Screen { // setFont(new Font("Liberation Mono", Font.PLAIN, 24)); setFont(new Font(Font.MONOSPACED, Font.PLAIN, 24)); } - setVisible(true); - resizeToScreen(); + pack(); // Kill the X11 cursor // Transparent 16 x 16 pixel cursor image. @@ -265,12 +266,13 @@ public final class AWTScreen extends Screen { Cursor blankCursor = Toolkit.getDefaultToolkit().createCustomCursor( cursorImg, new Point(0, 0), "blank cursor"); setCursor(blankCursor); + getFontDimensions(); } /** - * Resize to font dimensions. + * Figure out my font dimensions. */ - public void resizeToScreen() { + private void getFontDimensions() { Graphics gr = getGraphics(); FontMetrics fm = gr.getFontMetrics(); maxDescent = fm.getMaxDescent(); @@ -281,7 +283,12 @@ public final class AWTScreen extends Screen { // This also produces the same number, but works better for ugly // monospace. textHeight = fm.getMaxAscent() + maxDescent - leading; + } + /** + * Resize to font dimensions. + */ + public void resizeToScreen() { // Figure out the thickness of borders and use that to set the // final size. Insets insets = getInsets(); @@ -290,11 +297,6 @@ public final class AWTScreen extends Screen { setSize(textWidth * screen.width + insets.left + insets.right, textHeight * screen.height + insets.top + insets.bottom); - - /* - System.err.printf("W: %d H: %d MD: %d L: %d\n", textWidth, - textHeight, maxDescent, leading); - */ } /** @@ -316,60 +318,101 @@ public final class AWTScreen extends Screen { */ @Override public void paint(final Graphics gr) { + // Do nothing until the screen reference has been set. + if (screen == null) { + return; + } + if (screen.frame == null) { + return; + } + + int xCellMin = 0; + int xCellMax = screen.width; + int yCellMin = 0; + int yCellMax = screen.height; + Rectangle bounds = gr.getClipBounds(); + if (bounds != null) { + // Only update what is in the bounds + xCellMin = screen.textColumn(bounds.x); + xCellMax = screen.textColumn(bounds.x + bounds.width); + if (xCellMax > screen.width) { + xCellMax = screen.width; + } + if (xCellMin >= xCellMax) { + xCellMin = xCellMax - 2; + } + if (xCellMin < 0) { + xCellMin = 0; + } + yCellMin = screen.textRow(bounds.y); + yCellMax = screen.textRow(bounds.y + bounds.height); + if (yCellMax > screen.height) { + yCellMax = screen.height; + } + if (yCellMin >= yCellMax) { + yCellMin = yCellMax - 2; + } + if (yCellMin < 0) { + yCellMin = 0; + } + } else { + // We need a total repaint + reallyCleared = true; + } - for (int y = 0; y < screen.height; y++) { - for (int x = 0; x < screen.width; x++) { - int xPixel = x * textWidth + left; - int yPixel = y * textHeight + top; - - Cell lCell = screen.logical[x][y]; - Cell pCell = screen.physical[x][y]; - - boolean inBounds = true; - if (bounds != null) { - if (bounds.contains(xPixel, yPixel) - || bounds.contains(xPixel + textWidth, yPixel) - || bounds.contains(xPixel, yPixel + textHeight) - || bounds.contains(xPixel + textWidth, - yPixel + textHeight) - ) { - // This area is damaged and will definitely be - // redrawn. - inBounds = true; + // Prevent updates to the screen's data from the TApplication + // threads. + synchronized (screen) { + /* + System.err.printf("bounds %s X %d %d Y %d %d\n", + bounds, xCellMin, xCellMax, yCellMin, yCellMax); + */ + + for (int y = yCellMin; y < yCellMax; y++) { + for (int x = xCellMin; x < xCellMax; x++) { + + int xPixel = x * textWidth + left; + int yPixel = y * textHeight + top; + + Cell lCell = screen.logical[x][y]; + Cell pCell = screen.physical[x][y]; + + if (!lCell.equals(pCell) || reallyCleared) { + // Draw the background rectangle, then the + // foreground character. + gr.setColor(attrToBackgroundColor(lCell)); + gr.fillRect(xPixel, yPixel, textWidth, textHeight); + gr.setColor(attrToForegroundColor(lCell)); + char [] chars = new char[1]; + chars[0] = lCell.getChar(); + gr.drawChars(chars, 0, 1, xPixel, + yPixel + textHeight - maxDescent); + + // Physical is always updated + physical[x][y].setTo(lCell); } } + } - if (!lCell.equals(pCell) || inBounds) { - // Draw the background rectangle, then the foreground - // character. - gr.setColor(attrToBackgroundColor(lCell)); - gr.fillRect(xPixel, yPixel, textWidth, textHeight); - gr.setColor(attrToForegroundColor(lCell)); - char [] chars = new char[1]; - chars[0] = lCell.getChar(); - gr.drawChars(chars, 0, 1, xPixel, - yPixel + textHeight - maxDescent); - - // Physical is always updated - physical[x][y].setTo(lCell); - } + // Draw the cursor if it is visible + if ((cursorVisible) + && (cursorY <= screen.height - 1) + && (cursorX <= screen.width - 1) + ) { + int xPixel = cursorX * textWidth + left; + int yPixel = cursorY * textHeight + top; + Cell lCell = screen.logical[cursorX][cursorY]; + gr.setColor(attrToForegroundColor(lCell)); + gr.fillRect(xPixel, yPixel + textHeight - 2, textWidth, 2); } - } - // Draw the cursor if it is visible - if ((cursorVisible) - && (cursorY <= screen.height - 1) - && (cursorX <= screen.width - 1) - ) { - int xPixel = cursorX * textWidth + left; - int yPixel = cursorY * textHeight + top; - Cell lCell = screen.logical[cursorX][cursorY]; - gr.setColor(attrToForegroundColor(lCell)); - gr.fillRect(xPixel, yPixel + textHeight - 2, textWidth, 2); - } + dirty = false; + reallyCleared = false; + } // synchronized (screen) } - } + + } // class AWTFrame /** * The raw AWT Frame. Note package private access. @@ -380,17 +423,38 @@ public final class AWTScreen extends Screen { * Public constructor. */ public AWTScreen() { - frame = new AWTFrame(this); + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + AWTScreen.this.frame = new AWTFrame(AWTScreen.this); + AWTScreen.this.sessionInfo = + new AWTSessionInfo(AWTScreen.this.frame, + frame.textWidth, + frame.textHeight); + + AWTScreen.this.setDimensions(sessionInfo.getWindowWidth(), + sessionInfo.getWindowHeight()); + + AWTScreen.this.frame.resizeToScreen(); + AWTScreen.this.frame.setVisible(true); + } + } ); + } catch (Exception e) { + e.printStackTrace(); + } } + /** + * The sessionInfo. + */ + private AWTSessionInfo sessionInfo; + /** * Create the AWTSessionInfo. Note package private access. * * @return the sessionInfo */ AWTSessionInfo getSessionInfo() { - AWTSessionInfo sessionInfo = new AWTSessionInfo(frame, frame.textWidth, - frame.textHeight); return sessionInfo; } @@ -399,42 +463,67 @@ public final class AWTScreen extends Screen { */ @Override public void flushPhysical() { + + if (reallyCleared) { + // Really refreshed, do it all + frame.repaint(); + return; + } + + // Do nothing if nothing happened. + if (!dirty) { + return; + } + // Request a repaint, let the frame's repaint/update methods do the // right thing. + // Find the minimum-size damaged region. int xMin = frame.getWidth(); int xMax = 0; int yMin = frame.getHeight(); int yMax = 0; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - Cell lCell = logical[x][y]; - Cell pCell = physical[x][y]; - int xPixel = x * frame.textWidth + frame.left; - int yPixel = y * frame.textHeight + frame.top; - - if (!lCell.equals(pCell) - || ((x == cursorX) && (y == cursorY)) - ) { - if (xPixel < xMin) { - xMin = xPixel; - } - if (xPixel + frame.textWidth > xMax) { - xMax = xPixel + frame.textWidth; - } - if (yPixel < yMin) { - yMin = yPixel; - } - if (yPixel + frame.textHeight > yMax) { - yMax = yPixel + frame.textHeight; + synchronized (this) { + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + Cell lCell = logical[x][y]; + Cell pCell = physical[x][y]; + + int xPixel = x * frame.textWidth + frame.left; + int yPixel = y * frame.textHeight + frame.top; + + if (!lCell.equals(pCell) + || ((x == cursorX) + && (y == cursorY) + && cursorVisible) + ) { + if (xPixel < xMin) { + xMin = xPixel; + } + if (xPixel + frame.textWidth > xMax) { + xMax = xPixel + frame.textWidth; + } + if (yPixel < yMin) { + yMin = yPixel; + } + if (yPixel + frame.textHeight > yMax) { + yMax = yPixel + frame.textHeight; + } } } } } + if (xMin + frame.textWidth >= xMax) { + xMax += frame.textWidth; + } + if (yMin + frame.textHeight >= yMax) { + yMax += frame.textHeight; + } - // Ask for a repaint sometime in the next 10 millis. - frame.repaint(10, xMin, yMin, xMax - xMin, yMax - yMin); + // Repaint the desired area + frame.repaint(xMin, yMin, xMax - xMin, yMax - yMin); + // System.err.printf("REPAINT X %d %d Y %d %d\n", xMin, xMax, yMin, yMax); } /** @@ -451,14 +540,34 @@ public final class AWTScreen extends Screen { && (cursorX <= width - 1) ) { // Make the current cursor position dirty - if (physical[cursorX][cursorY].getChar() == ' ') { + if (physical[cursorX][cursorY].getChar() == 'Q') { physical[cursorX][cursorY].setChar('X'); } else { - physical[cursorX][cursorY].setChar(' '); + physical[cursorX][cursorY].setChar('Q'); } } super.putCursor(visible, x, y); } + /** + * Convert pixel column position to text cell column position. + * + * @param x pixel column position + * @return text cell column position + */ + public int textColumn(final int x) { + return ((x - frame.left) / frame.textWidth); + } + + /** + * Convert pixel row position to text cell row position. + * + * @param y pixel row position + * @return text cell row position + */ + public int textRow(final int y) { + return ((y - frame.top) / frame.textHeight); + } + }