mirror of
https://github.com/jneug/zeichenmaschine.git
synced 2026-04-14 06:33:34 +02:00
Verantwortlichkeiten für Layout und Aufgaben klarer getrennt
This commit is contained in:
@@ -14,6 +14,14 @@ import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Ein Zeichenfenster ist das Programmfenster für die Zeichenmaschine.
|
||||
* <p>
|
||||
* Das Zeichenfenster implementiert hilfreiche Funktionen, um ein
|
||||
* Programmfenster mit einer Zeichenleinwand als zentrales Element zu erstellen.
|
||||
* Ein Zeichenfenster kann auch ohne eine Zeichenmaschine verwendet werden, um
|
||||
* eigene Programmabläufe zu implementieren.
|
||||
*/
|
||||
public class Zeichenfenster extends JFrame {
|
||||
|
||||
public static final void setLookAndFeel() {
|
||||
@@ -46,24 +54,22 @@ public class Zeichenfenster extends JFrame {
|
||||
}
|
||||
|
||||
/**
|
||||
* Das Anzeigefenster, auf dem die ZM gestartet wurde (muss nicht gleich
|
||||
* dem Aktuellen sein, wenn das Fenster verschoben wurde).
|
||||
* Das Anzeigefenster, auf dem die ZM gestartet wurde (muss nicht gleich dem
|
||||
* Aktuellen sein, wenn das Fenster verschoben wurde).
|
||||
*/
|
||||
private GraphicsDevice displayDevice;
|
||||
|
||||
private int canvasWidth, canvasHeight;
|
||||
|
||||
/**
|
||||
* Höhe und Breite der Zeichenmaschine, bevor sie mit
|
||||
* {@link #setFullscreen(boolean)} in den Vollbild-Modus versetzt wurde.
|
||||
* Wird verwendet, um die Fenstergröße wiederherzustellen, sobald der
|
||||
* Vollbild-Modus verlassen wird.
|
||||
* Bevorzugte Abmessungen der Zeichenleinwand. Für das Zeichenfenster hat
|
||||
* es Priorität die Leinwand auf dieser Größe zu halten. Gegebenenfalls unter
|
||||
* Missachtung anderer Größenvorgaben. Allerdings kann das Fenster keine
|
||||
* Garantie für die Größe der Leinwand übernehmen.
|
||||
*/
|
||||
private int initialWidth, initialHeight;
|
||||
private int canvasPreferredWidth, canvasPreferredHeight;
|
||||
|
||||
/**
|
||||
* Speichert, ob die Zeichenmaschine mit {@link #setFullscreen(boolean)}
|
||||
* in den Vollbildmodus versetzt wurde.
|
||||
* Speichert, ob die Zeichenmaschine mit {@link #setFullscreen(boolean)} in
|
||||
* den Vollbildmodus versetzt wurde.
|
||||
*/
|
||||
private boolean fullscreen = false;
|
||||
|
||||
@@ -85,15 +91,32 @@ public class Zeichenfenster extends JFrame {
|
||||
private Zeichenleinwand canvas;
|
||||
|
||||
public Zeichenfenster( int width, int height, String title ) {
|
||||
this(width, height, title, getGraphicsDevice());
|
||||
this(new Zeichenleinwand(width, height), title, getGraphicsDevice());
|
||||
}
|
||||
|
||||
public Zeichenfenster( int width, int height, String title, GraphicsDevice displayDevice ) {
|
||||
this(new Zeichenleinwand(width, height), title, displayDevice);
|
||||
}
|
||||
|
||||
public Zeichenfenster( Zeichenleinwand canvas, String title ) {
|
||||
this(canvas, title, getGraphicsDevice());
|
||||
}
|
||||
|
||||
public Zeichenfenster( Zeichenleinwand canvas, String title, GraphicsDevice displayDevice ) {
|
||||
super(Validator.requireNotNull(displayDevice).getDefaultConfiguration());
|
||||
this.displayDevice = displayDevice;
|
||||
|
||||
Validator.requireNotNull(canvas, "Every Zeichenfenster needs a Zeichenleinwand, but got <null>.");
|
||||
|
||||
this.canvasPreferredWidth = canvas.getWidth();
|
||||
this.canvasPreferredHeight = canvas.getHeight();
|
||||
//this.add(canvas, BorderLayout.CENTER);
|
||||
this.add(canvas);
|
||||
this.canvas = canvas;
|
||||
|
||||
// Konfiguration des Frames
|
||||
this.setTitle(title);
|
||||
this.setTitle(title == null ? "Zeichenfenster " + Constants.APP_VERSION: title);
|
||||
// Kann vom Aufrufenden überschrieben werden
|
||||
this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||
|
||||
// Das Icon des Fensters ändern
|
||||
@@ -118,68 +141,51 @@ public class Zeichenfenster extends JFrame {
|
||||
// Dock Icon in macOS konnte nicht gesetzt werden :(
|
||||
LOG.warn("Could not set dock icon: %s", macex.getMessage());
|
||||
}
|
||||
|
||||
this.canvasWidth = width;
|
||||
this.canvasHeight = height;
|
||||
|
||||
// Fenster zusammenbauen, auf dem Bildschirm zentrieren ...
|
||||
// Fenster zusammenbauen, auf dem Bildschirm positionieren ...
|
||||
this.pack();
|
||||
this.setResizable(false);
|
||||
this.centerFrame();
|
||||
this.setLocationByPlatform(true);
|
||||
// this.centerFrame();
|
||||
}
|
||||
|
||||
public void addCanvas( Zeichenleinwand canvas ) {
|
||||
this.canvas = canvas;
|
||||
this.add(canvas, 0);
|
||||
|
||||
this.canvasWidth = canvas.getWidth();
|
||||
this.canvasHeight = canvas.getHeight();
|
||||
this.pack();
|
||||
public GraphicsDevice getDisplayDevice() {
|
||||
return displayDevice;
|
||||
}
|
||||
|
||||
public java.awt.Rectangle getScreenBounds() {
|
||||
public Rectangle getScreenBounds() {
|
||||
return displayDevice.getDefaultConfiguration().getBounds();
|
||||
}
|
||||
|
||||
public java.awt.Rectangle getCanvasBounds() {
|
||||
java.awt.Insets insets = getInsets();
|
||||
return new java.awt.Rectangle(insets.top, insets.left, canvasWidth, canvasHeight);
|
||||
public Zeichenleinwand getCanvas() {
|
||||
return canvas;
|
||||
}
|
||||
|
||||
public Rectangle getCanvasBounds() {
|
||||
return canvas.getBounds();
|
||||
}
|
||||
/**
|
||||
* Zentriert das Zeichenfenster auf dem aktuellen Bildschirm.
|
||||
*/
|
||||
public final void centerFrame() {
|
||||
java.awt.Rectangle bounds = getScreenBounds();
|
||||
java.awt.Insets insets = getInsets();
|
||||
java.awt.Rectangle screenBounds = getScreenBounds();
|
||||
java.awt.Rectangle frameBounds = getBounds();
|
||||
this.setLocation(
|
||||
(int) (bounds.x + (bounds.width - canvasWidth) / 2.0 - insets.left),
|
||||
(int) (bounds.y + (bounds.height - canvasHeight) / 2.0- insets.top)
|
||||
(int) (screenBounds.x + (screenBounds.width - frameBounds.width) / 2.0),
|
||||
(int) (screenBounds.y + (screenBounds.height - frameBounds.height) / 2.0)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSize( int newWidth, int newHeight ) {
|
||||
java.awt.Rectangle bounds = getScreenBounds();
|
||||
java.awt.Insets insets = this.getInsets();
|
||||
|
||||
public void setCanvasSize( int newWidth, int newHeight ) {
|
||||
// TODO: (ngb) Put constains on max/min frame/canvas size
|
||||
if( fullscreen ) {
|
||||
initialWidth = Math.min(newWidth, bounds.width - insets.left - insets.right);
|
||||
initialHeight = Math.min(newHeight, bounds.height - insets.top - insets.bottom);
|
||||
canvasPreferredWidth = newWidth;
|
||||
canvasPreferredHeight = newHeight;
|
||||
setFullscreen(false);
|
||||
} else {
|
||||
canvasWidth = Math.min(newWidth, bounds.width - insets.left - insets.right);
|
||||
canvasHeight = Math.min(newHeight, bounds.height - insets.top - insets.bottom);
|
||||
|
||||
if( canvas != null ) {
|
||||
canvas.setSize(canvasWidth, canvasHeight);
|
||||
}
|
||||
|
||||
/*super.setSize(
|
||||
width + insets.left + insets.right,
|
||||
height + insets.top + insets.bottom
|
||||
);*/
|
||||
super.pack();
|
||||
canvas.setSize(newWidth, newHeight);
|
||||
canvasPreferredWidth = canvas.getWidth();
|
||||
canvasPreferredHeight = canvas.getHeight();
|
||||
this.pack();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,16 +206,13 @@ public class Zeichenfenster extends JFrame {
|
||||
// See https://docs.oracle.com/javase/tutorial/extra/fullscreen/index.html
|
||||
if( displayDevice.isFullScreenSupported() ) {
|
||||
if( pEnable && !fullscreen ) {
|
||||
// Store width / height
|
||||
initialWidth = getWidth();
|
||||
initialHeight = getHeight();
|
||||
|
||||
// frame.setUndecorated(true);
|
||||
this.setResizable(false); // Should be set anyway
|
||||
displayDevice.setFullScreenWindow(this);
|
||||
|
||||
java.awt.Rectangle bounds = getScreenBounds();
|
||||
this.setSize(bounds.width, bounds.height);
|
||||
// TODO: (ngb) We need to switch layouts to allow the LayoutManger to maximize the canvas
|
||||
canvas.setSize(bounds.width, bounds.height);
|
||||
// Register ESC to exit fullscreen
|
||||
canvas.addKeyListener(fullscreenExitListener);
|
||||
|
||||
@@ -219,7 +222,7 @@ public class Zeichenfenster extends JFrame {
|
||||
|
||||
canvas.removeKeyListener(fullscreenExitListener);
|
||||
displayDevice.setFullScreenWindow(null);
|
||||
this.setSize(initialWidth, initialHeight);
|
||||
canvas.setSize(canvasPreferredWidth, canvasPreferredHeight);
|
||||
this.pack();
|
||||
// frame.setUndecorated(false);
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
package schule.ngb.zm;
|
||||
|
||||
import schule.ngb.zm.layers.ColorLayer;
|
||||
import schule.ngb.zm.layers.ShapesLayer;
|
||||
import schule.ngb.zm.util.Log;
|
||||
|
||||
import java.awt.Canvas;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferStrategy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
/**
|
||||
* Eine Leinwand ist die Hauptkomponente einer Zeichenmaschine. Sie besteht aus
|
||||
@@ -37,8 +37,8 @@ public class Zeichenleinwand extends Canvas {
|
||||
*/
|
||||
public Zeichenleinwand( int width, int height ) {
|
||||
super.setSize(width, height);
|
||||
this.setPreferredSize(this.getSize());
|
||||
this.setMinimumSize(this.getSize());
|
||||
this.setPreferredSize(getSize());
|
||||
this.setMinimumSize(getSize());
|
||||
this.setBackground(Constants.DEFAULT_BACKGROUND.getJavaColor());
|
||||
|
||||
// Liste der Ebenen initialisieren und die Standardebenen einfügen
|
||||
@@ -60,8 +60,8 @@ public class Zeichenleinwand extends Canvas {
|
||||
@Override
|
||||
public void setSize( int width, int height ) {
|
||||
super.setSize(width, height);
|
||||
this.setPreferredSize(this.getSize());
|
||||
this.setMinimumSize(this.getSize());
|
||||
this.setPreferredSize(getSize());
|
||||
this.setMinimumSize(getSize());
|
||||
|
||||
synchronized( layers ) {
|
||||
for( Layer layer : layers ) {
|
||||
|
||||
@@ -275,21 +275,21 @@ public class Zeichenmaschine extends Constants {
|
||||
public Zeichenmaschine( int width, int height, String title, boolean run_once ) {
|
||||
LOG.info("Starting " + APP_NAME + " " + APP_VERSION);
|
||||
|
||||
// Erstellen des Zeichenfensters
|
||||
frame = createFrame(width, height, title);
|
||||
|
||||
// Wir kennen nun den Bildschirm und können die Breite / Höhe abrufen.
|
||||
this.canvasWidth = width;
|
||||
this.canvasHeight = height;
|
||||
java.awt.Rectangle displayBounds = frame.getScreenBounds();
|
||||
this.screenWidth = (int) displayBounds.getWidth();
|
||||
this.screenHeight = (int) displayBounds.getHeight();
|
||||
|
||||
// Erstellen der Leinwand
|
||||
canvas = new Zeichenleinwand(width, height);
|
||||
frame.addCanvas(canvas);
|
||||
|
||||
// Die drei Standardebenen merken, für den einfachen Zugriff aus unterklassen.
|
||||
// Erstellen des Zeichenfensters
|
||||
frame = createFrame(canvas, title);
|
||||
|
||||
// Wir kennen nun den Bildschirm und können die Breite / Höhe abrufen.
|
||||
java.awt.Rectangle canvasBounds = frame.getCanvasBounds();
|
||||
this.canvasWidth = canvasBounds.width;
|
||||
this.canvasHeight = canvasBounds.height;
|
||||
java.awt.Rectangle displayBounds = frame.getScreenBounds();
|
||||
this.screenWidth = displayBounds.width;
|
||||
this.screenHeight = displayBounds.height;
|
||||
|
||||
// Die drei Standardebenen merken, für den einfachen Zugriff aus Unterklassen.
|
||||
background = getBackgroundLayer();
|
||||
drawing = getDrawingLayer();
|
||||
shapes = getShapesLayer();
|
||||
@@ -333,7 +333,7 @@ public class Zeichenmaschine extends Constants {
|
||||
}
|
||||
});
|
||||
|
||||
// Fesnter anzeigen
|
||||
// Fenster anzeigen
|
||||
frame.setVisible(true);
|
||||
|
||||
// Nach dem Anzeigen kann die Pufferstrategie erstellt werden.
|
||||
@@ -357,14 +357,22 @@ public class Zeichenmaschine extends Constants {
|
||||
*
|
||||
* @param title
|
||||
*/
|
||||
// TODO: Implement in conjunction with Zeichenfenster
|
||||
private final Zeichenfenster createFrame( int width, int height, String title ) {
|
||||
// Setzen des Look&Feel
|
||||
// TODO: (ngb) Ist das überhaupt notwendig oder eh schon der Default?
|
||||
private final Zeichenfenster createFrame( Zeichenleinwand c, String title ) {
|
||||
while( frame == null ) {
|
||||
try {
|
||||
TaskRunner.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Zeichenfenster.setLookAndFeel();
|
||||
|
||||
Zeichenfenster frame = new Zeichenfenster(width, height, title);
|
||||
|
||||
frame = new Zeichenfenster(canvas, title);
|
||||
}
|
||||
}).get();
|
||||
} catch( InterruptedException e ) {
|
||||
} catch( ExecutionException e ) {
|
||||
LOG.error(e, "Error initializing application frame: %s", e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user