23 package com.realtime.crossfire.jxclient.gui.misc;
43 import java.awt.Color;
44 import java.awt.Component;
45 import java.awt.Container;
46 import java.awt.Dimension;
47 import java.awt.DisplayMode;
48 import java.awt.Frame;
49 import java.awt.Graphics;
50 import java.awt.GraphicsConfiguration;
51 import java.awt.GraphicsDevice;
52 import java.awt.GraphicsEnvironment;
53 import java.awt.Insets;
54 import java.awt.Point;
55 import java.awt.Rectangle;
56 import java.awt.Toolkit;
57 import java.awt.Window;
58 import java.awt.event.ComponentEvent;
59 import java.awt.event.ComponentListener;
60 import java.awt.event.KeyEvent;
61 import java.awt.event.MouseEvent;
62 import java.awt.event.MouseWheelEvent;
63 import java.awt.event.MouseWheelListener;
64 import java.awt.image.BufferStrategy;
65 import java.io.IOException;
66 import java.io.Writer;
67 import java.time.LocalDateTime;
68 import java.time.format.DateTimeFormatter;
69 import java.util.Collection;
70 import java.util.Iterator;
71 import java.util.List;
72 import java.util.ListIterator;
73 import java.util.Locale;
74 import java.util.concurrent.CopyOnWriteArrayList;
75 import javax.swing.JFrame;
76 import javax.swing.JLayeredPane;
77 import javax.swing.JViewport;
78 import javax.swing.RootPaneContainer;
79 import javax.swing.event.MouseInputListener;
80 import org.jetbrains.annotations.NotNull;
81 import org.jetbrains.annotations.Nullable;
120 private static final long serialVersionUID = 1L;
123 public void paint(@NotNull
final Graphics g) {
170 private final Rectangle
maximumWindowBounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
179 public void mouseClicked(
final MouseEvent e) {
184 public void mousePressed(
final MouseEvent e) {
189 public void mouseReleased(
final MouseEvent e) {
194 public void mouseEntered(
final MouseEvent e) {
199 public void mouseExited(
final MouseEvent e) {
204 public void mouseDragged(
final MouseEvent e) {
209 public void mouseMoved(
final MouseEvent e) {
222 public void mouseWheelMoved(
final MouseWheelEvent e) {
252 private final List<Gui>
openDialogs =
new CopyOnWriteArrayList<>();
271 private final Collection<GUIMap>
maps =
new CopyOnWriteArrayList<>();
278 private final Collection<GUIFloorList>
floorLists =
new CopyOnWriteArrayList<>();
316 private static final DateTimeFormatter
FORMATTER = DateTimeFormatter.ofPattern(
"yyyy-MM-dd HH:mm:ss,SSS ", Locale.ENGLISH);
325 public void componentResized(
final ComponentEvent e) {
326 final RootPaneContainer tmpFrame =
frame;
327 assert tmpFrame !=
null;
328 final int width = tmpFrame.getContentPane().getWidth();
329 final int height = tmpFrame.getContentPane().getHeight();
335 public void componentMoved(
final ComponentEvent e) {
340 public void componentShown(
final ComponentEvent e) {
345 public void componentHidden(
final ComponentEvent e) {
376 debugScreenWrite(
"setFullScreenMode: resolution="+(resolution ==
null ?
"default" : resolution));
387 final Dimension dimension;
388 if (resolution ==
null) {
389 dimension =
new Dimension(currentDisplayMode.getWidth(), currentDisplayMode.getHeight());
390 debugScreenWrite(
"setFullScreenMode: full-screen requested, dimension="+dimension+
" [using current display resolution]");
392 dimension =
new Dimension(resolution.getWidth(), resolution.getHeight());
393 debugScreenWrite(
"setFullScreenMode: full-screen requested, dimension="+dimension+
" [using user-specified resolution]");
395 frame.setPreferredSize(dimension);
396 frame.setResizable(
false);
397 frame.setUndecorated(
true);
408 if (resolution ==
null || resolution.equalsDisplayMode(currentDisplayMode)) {
409 debugScreenWrite(
"setFullScreenMode: requested resolution matches screen resolution");
417 final DisplayMode newDisplayMode =
new DisplayMode(resolution.getWidth(), resolution.getHeight(), DisplayMode.BIT_DEPTH_MULTI, DisplayMode.REFRESH_RATE_UNKNOWN);
420 }
catch (
final IllegalArgumentException ex) {
421 debugScreenWrite(
"setFullScreenMode: setting screen resolution failed: "+ex.getMessage());
430 if (this.frame !=
null) {
449 debugScreenWrite(
"setWindowMode: resolution="+(resolution ==
null ?
"default" : resolution)+
", minResolution="+minResolution+
", fixedSize="+fixedSize);
461 frame.setUndecorated(
false);
462 frame.setResizable(!fixedSize);
464 final Dimension dimension;
466 if (resolution ==
null) {
467 dimension =
new Dimension(currentDisplayMode.getWidth(), currentDisplayMode.getHeight());
469 dimension = resolution.asDimension();
471 final int x = centerPoint.x-dimension.width/2;
472 final int y = centerPoint.y-dimension.height/2;
474 frame.setLocation(x, y);
476 frame.setVisible(
true);
477 final Insets frameInsets =
frame.getInsets();
478 debugScreenWrite(
"setResolutionPre: frame insets: top="+frameInsets.top+
", bottom="+frameInsets.bottom+
", left="+frameInsets.left+
", right="+frameInsets.right);
481 debugScreenWrite(
"setResolutionPre: maximum window dimension: "+maxDimension.width+
"x"+maxDimension.height);
482 if (dimension.width > maxDimension.width || dimension.height > maxDimension.height) {
484 if (resolution ==
null) {
485 final int tmpWidth = dimension.width;
486 final int tmpHeight = dimension.height;
487 dimension.width = Math.max(minResolution.getWidth()+frameInsets.left+frameInsets.right, maxDimension.width);
488 dimension.height = Math.max(minResolution.getHeight()+frameInsets.top+frameInsets.bottom, maxDimension.height);
489 debugScreenWrite(
"setResolutionPre: window size "+tmpWidth+
"x"+tmpHeight+
" exceeds maximum allowed size "+maxDimension.width+
"x"+maxDimension.height+
", reducing to "+dimension.width+
"x"+dimension.height);
491 debugScreenWrite(
"setResolutionPre: window size "+dimension.width+
"x"+dimension.height+
" exceeds maximum allowed size "+maxDimension.width+
"x"+maxDimension.height+
", ignoring");
497 frame.setPreferredSize(dimension);
498 frame.setSize(dimension);
501 final int x2 = centerPoint.x-dimension.width/2-frameInsets.left;
502 final int y2 = centerPoint.y-dimension.height/2-frameInsets.top;
503 debugScreenWrite(
"setResolutionPre: moving window to ("+frameInsets.left+
"+"+dimension.width+
"+"+frameInsets.right+
")x("+frameInsets.top+
"+"+dimension.height+
"+"+frameInsets.bottom+
")+"+x2+
"+"+y2);
504 frame.setBounds(x2, y2, dimension.width+frameInsets.left+frameInsets.right, dimension.height+frameInsets.top+frameInsets.bottom);
508 if (this.frame !=
null) {
542 frame.createBufferStrategy(2);
545 final Insets insets =
frame.getInsets();
548 debugScreenWrite(
"setResolutionPost: offset="+
offsetX+
"x"+
offsetY+
" insets: top="+insets.top+
", bottom="+insets.bottom+
", left="+insets.left+
", right="+insets.right);
551 frame.requestFocusInWindow();
583 debugScreenWrite(
"updateWindowSize: gui size="+this.windowWidth+
"x"+this.windowHeight);
599 final GraphicsConfiguration graphicsConfiguration =
graphicsDevice.getDefaultConfiguration();
600 final Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(graphicsConfiguration);
601 debugScreenWrite(
"getMaxWindowDimension: screen insets: top="+screenInsets.top+
", bottom="+screenInsets.bottom+
", left="+screenInsets.left+
", right="+screenInsets.right);
603 final int maxWidth =
maximumWindowBounds.width-screenInsets.left-screenInsets.right-frameInsets.left-frameInsets.right;
604 final int maxHeight =
maximumWindowBounds.height-screenInsets.top-screenInsets.bottom-frameInsets.top-frameInsets.bottom;
605 debugScreenWrite(
"getMaxWindowDimension: maximum window dimension: "+maxWidth+
"x"+maxHeight);
606 return new Dimension(maxWidth, maxHeight);
618 assert
frame !=
null;
620 assert
frame !=
null;
622 assert
frame !=
null;
624 assert
frame !=
null;
634 public void redraw(@NotNull
final Graphics g) {
644 for (
int ig = 0; ig < 3; ig++) {
659 g.setColor(Color.BLACK);
660 assert
frame !=
null;
661 final int width =
frame.getWidth();
662 assert
frame !=
null;
663 final int height =
frame.getHeight();
664 g.fillRect(0, 0, width, height);
675 public boolean openDialog(@NotNull
final Gui dialog,
final boolean autoCloseOnDeactivate) {
686 dialog.activateDefaultElement();
687 dialog.setGuiAutoCloseListener(autoCloseOnDeactivate ? () ->
closeDialog(dialog) :
null);
739 return OpenDialogsIterator::new;
779 dialog.setActiveElementActive(
false);
795 dialog.setActiveElementActive(
false);
800 dialog.setGuiAutoCloseListener(
null);
802 dialog.activateDefaultElement();
812 if (this.tooltip !=
null) {
816 if (this.tooltip !=
null) {
837 if (dialog.isHidden(prevRendererGuiState)) {
881 final Point mouse =
frame ==
null ? null :
frame.getMousePosition(
true);
888 if (dialog.isWithinDrawingArea(mouse.x, mouse.y)) {
889 final MouseEvent mouseEvent =
new MouseEvent(
frame, 0, System.currentTimeMillis(), 0, mouse.x, mouse.y, 0,
false);
928 final Point mouse =
frame ==
null ? null :
frame.getMousePosition(
true);
935 assert
frame !=
null;
939 if (dialog.isWithinDrawingArea(mouse.x, mouse.y)) {
940 final MouseEvent mouseEvent =
new MouseEvent(
frame, 0, System.currentTimeMillis(), 0, mouse.x, mouse.y, 0,
false);
947 assert
frame !=
null;
957 assert
frame !=
null;
974 if (dialog.deactivateCommandInput()) {
977 if (dialog.isModal()) {
996 if (buffer !=
null) {
999 if (dialog.isModal()) {
1017 return buffer ==
null ? null : buffer.
getBuffer();
1027 if (metaElementList !=
null) {
1043 if (textArea1 !=
null) {
1051 if (textArea2 !=
null) {
1056 if (dialog.isModal()) {
1088 return it.hasPrevious();
1094 return it.previous();
1098 public void remove() {
1099 throw new UnsupportedOperationException(
"remove() not implemented");
1128 for (Component result = component; result !=
null; result = result.getParent()) {
1132 if (result instanceof JViewport) {
1133 final JViewport viewport = (JViewport)result;
1134 final Point position = viewport.getViewPosition();
1135 mouseEvent.translatePoint(-position.x, -position.y);
1150 final MouseEvent ce = e;
1153 final int eX = ce.getX();
1154 final int eY = ce.getY();
1157 elected =
getElementFromPoint(dialog, eX-dialog.getComponent().getX(), eY-dialog.getComponent().getY());
1159 if (elected !=
null) {
1163 if (dialog.isModal()) {
1168 if (elected ==
null) {
1189 return gui.getElementFromPoint(x, y);
1206 }
catch (
final IOException ex) {
1207 System.err.println(
"Cannot write screen debug: "+ex.getMessage());
1209 throw new AssertionError(ex);
1219 private void addToLayeredPane(@NotNull
final Component component,
final int layer,
final int index) {
1270 if (component instanceof Container) {
1271 final Container container = (Container)component;
1272 for (
int i = 0; i < container.getComponentCount(); i++) {
1285 if (component instanceof Container) {
1286 final Container container = (Container)component;
1287 for (
int i = 0; i < container.getComponentCount(); i++) {
1299 if (component instanceof
GUIMap) {
1307 if (component instanceof Container) {
1308 final Container container = (Container)component;
1309 for (
int i = 0; i < container.getComponentCount(); i++) {
1321 if (component instanceof
GUIMap) {
1329 if (component instanceof Container) {
1330 final Container container = (Container)component;
1331 for (
int i = 0; i < container.getComponentCount(); i++) {
1360 width = Math.max(width, map.getPreferredMapWidth());
1361 height = Math.max(height, map.getPreferredMapHeight());
1363 return new Dimension(width, height);
1371 int minNumLookObjects = Integer.MAX_VALUE;
1373 minNumLookObjects = Math.min(minNumLookObjects, floorList.getNumLookObjects());
1375 if (minNumLookObjects < Integer.MAX_VALUE) {
1376 return minNumLookObjects;
1391 if (textArea ==
null) {
1395 if (!textArea.
getName().equals(
"command")) {
1408 final boolean result =
graphicsDevice.isDisplayChangeSupported();
1418 debugScreenWrite(
"setDisplayMode("+displayMode.getWidth()+
"x"+displayMode.getHeight()+
")");
1429 debugScreenWrite(
"getDisplayMode: "+displayMode.getWidth()+
"x"+displayMode.getHeight());