Crossfire JXClient, Trunk  R20561
Gui.java
Go to the documentation of this file.
1 /*
2  * This file is part of JXClient, the Fullscreen Java Crossfire Client.
3  *
4  * JXClient is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * JXClient is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with JXClient; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  *
18  * Copyright (C) 2005-2008 Yann Chachkoff.
19  * Copyright (C) 2006-2011 Andreas Kirschbaum.
20  */
21 
22 package com.realtime.crossfire.jxclient.gui.gui;
23 
27 import java.awt.Component;
28 import java.awt.Dimension;
29 import java.awt.event.KeyEvent;
30 import java.util.Collection;
31 import java.util.EnumSet;
32 import javax.swing.JComponent;
33 import org.jetbrains.annotations.NotNull;
34 import org.jetbrains.annotations.Nullable;
35 
43 public class Gui extends JComponent {
44 
48  private static final long serialVersionUID = 1L;
49 
53  @NotNull
54  private final KeyBindings keyBindings;
55 
60  @Nullable
61  private Extent autoSize;
62 
66  private boolean saveDialog;
67 
71  private boolean modal;
72 
76  @NotNull
77  private final Collection<RendererGuiState> hideInStates = EnumSet.noneOf(RendererGuiState.class);
78 
83  @Nullable
85 
90  @Nullable
92 
96  private boolean initialPositionSet;
97 
102  @Nullable
104 
109  @Nullable
111 
116  @Nullable
118 
123  public Gui(@NotNull final KeyBindings keyBindings) {
124  this.keyBindings = keyBindings;
125  }
126 
132  public void setPosition(final int x, final int y) {
133  if (initialPositionSet && getX() == x && getY() == y) {
134  return;
135  }
136 
137  if ((getWidth() == 0 || getHeight() == 0) && (initialPositionSet || x != 0 || y != 0)) {
138  throw new IllegalStateException("width="+getWidth()+", height="+getHeight()+", initialPositionSet="+initialPositionSet+", x="+x+", y="+y);
139  }
140 
141  initialPositionSet = true;
142  setLocation(x, y);
143  }
144 
150  public void setAutoSize(@Nullable final Extent autoSize) {
151  this.autoSize = autoSize;
152  }
153 
159  public boolean isAutoSize() {
160  return autoSize != null;
161  }
162 
167  public void setModal(final boolean modal) {
168  this.modal = modal;
169  }
170 
175  public boolean isModal() {
176  return modal;
177  }
178 
183  @Nullable
185  final int count = getComponentCount();
186  for (int i = 0; i < count; i++) {
187  final Component component = getComponent(i);
188  if (component.isVisible() && component instanceof ActivatableGUIElement) {
189  final ActivatableGUIElement element = (ActivatableGUIElement)component;
190  if (element.isDefault()) {
191  return element;
192  }
193  }
194  }
195 
196  return null;
197  }
198 
202  public void activateDefaultElement() {
203  final ActivatableGUIElement defaultElement = getDefaultElement();
204  if (defaultElement != null) {
205  defaultElement.setActive(true);
206  }
207  }
208 
217  @Nullable
218  public <T extends GUIElement> T getFirstElementEndingWith(@NotNull final Class<T> class_, @NotNull final String ending) {
219  final int count = getComponentCount();
220  for (int i = 0; i < count; i++) {
221  final Component component = getComponent(i);
222  if (component.isVisible() && component instanceof GUIElement) {
223  final GUIElement element = (GUIElement)component;
224  if (class_.isAssignableFrom(element.getClass()) && element.getName().endsWith(ending)) {
225  return class_.cast(element);
226  }
227  }
228  }
229 
230  return null;
231  }
232 
241  @Nullable
242  public <T extends GUIElement> T getFirstElementNotEndingWith(@NotNull final Class<T> class_, @NotNull final String ending) {
243  final int count = getComponentCount();
244  for (int i = 0; i < count; i++) {
245  final Component component = getComponent(i);
246  if (component.isVisible() && component instanceof GUIElement) {
247  final GUIElement element = (GUIElement)component;
248  if (class_.isAssignableFrom(element.getClass()) && !element.getName().endsWith(ending)) {
249  return class_.cast(element);
250  }
251  }
252  }
253 
254  return null;
255  }
256 
263  @Nullable
264  public <T extends GUIElement> T getFirstElement(@NotNull final Class<T> class_) {
265  final int count = getComponentCount();
266  for (int i = 0; i < count; i++) {
267  final Component component = getComponent(i);
268  if (component.isVisible() && component instanceof GUIElement) {
269  final GUIElement element = (GUIElement)component;
270  if (class_.isAssignableFrom(element.getClass())) {
271  return class_.cast(element);
272  }
273  }
274  }
275 
276  return null;
277  }
278 
286  @Nullable
287  public AbstractGUIElement getElementFromPoint(final int x, final int y) {
288  Component component = findComponentAt(x, y);
289  while (component != null) {
290  if (component instanceof AbstractGUIElement) {
291  return (AbstractGUIElement)component;
292  }
293  component = component.getParent();
294  }
295  return null;
296  }
297 
303  public void setActiveElement(@NotNull final ActivatableGUIElement activeElement, final boolean active) {
304  final ActivatableGUIElement previousActiveElement = this.activeElement;
305  if (active) {
306  if (forcedActive != null && forcedActive != activeElement) {
307  return;
308  }
309 
310  if (isActiveElement(activeElement)) {
311  return;
312  }
313 
314  this.activeElement = activeElement;
315  if (previousActiveElement != null) {
316  previousActiveElement.activeChanged();
317  }
318  assert this.activeElement != null;
319  this.activeElement.activeChanged();
320 
321  guiAutoCloseListener = null;
322  } else {
323  if (!isActiveElement(activeElement)) {
324  return;
325  }
326 
327  this.activeElement = null;
328  assert previousActiveElement != null;
329  previousActiveElement.activeChanged();
330 
331  if (guiAutoCloseListener != null) {
333  guiAutoCloseListener = null;
334  listener.autoClosed();
335  }
336  }
337  }
338 
345  public boolean isActiveElement(@Nullable final ActivatableGUIElement activeElement) {
346  return this.activeElement != null && this.activeElement == activeElement;
347  }
348 
354  public void setActiveElementActive(final boolean active) {
355  if (activeElement != null) {
356  activeElement.setActive(active);
357  }
358  }
359 
365  public boolean handleKeyPress(@NotNull final KeyEvent2 e) {
366  if (activeElement != null && activeElement instanceof KeyPressedHandler && ((KeyPressedHandler)activeElement).keyPressed(e)) {
367  return true;
368  }
369 
370  if (activeElement instanceof KeyPressedHandler) {
371  final KeyPressedHandler keyListener = (KeyPressedHandler)activeElement;
372  if (keyListener.keyPressed(e)) {
373  return true;
374  }
375  }
376 
377  switch (e.getKeyCode()) {
378  case KeyEvent.VK_ENTER:
379  case KeyEvent.VK_SPACE:
380  final ActivatableGUIElement defaultElement = getDefaultElement();
381  if (defaultElement != null) {
382  defaultElement.execute();
383  return true;
384  }
385  break;
386  }
387 
388  return keyBindings.handleKeyPress(e);
389  }
390 
397  public boolean deactivateCommandInput() {
398  if (activeElement == null) {
399  return false;
400  }
401 
402  final GUIElement textArea = activeElement;
403  if (!textArea.getName().equals("command")) {
404  return false;
405  }
406 
407  assert activeElement != null;
408  activeElement.setActive(false);
409  return true;
410  }
411 
420  @Nullable
421  public <T extends GUIElement> T getFirstElement(@NotNull final Class<T> class_, @NotNull final String name) {
422  final int count = getComponentCount();
423  for (int i = 0; i < count; i++) {
424  final Component component = getComponent(i);
425  if (component.isVisible() && component instanceof GUIElement) {
426  final GUIElement element = (GUIElement)component;
427  if (class_.isAssignableFrom(element.getClass()) && element.getName().equals(name)) {
428  return class_.cast(element);
429  }
430  }
431  }
432  return null;
433  }
434 
439  @NotNull
441  return keyBindings;
442  }
443 
448  public void hideInState(@NotNull final RendererGuiState state) {
449  hideInStates.add(state);
450  }
451 
457  public boolean isHidden(@NotNull final RendererGuiState state) {
458  return hideInStates.contains(state);
459  }
460 
466  public void setGuiAutoCloseListener(@Nullable final GuiAutoCloseListener guiAutoCloseListener) {
467  this.guiAutoCloseListener = guiAutoCloseListener;
468  }
469 
476  public boolean isWithinDrawingArea(final int x, final int y) {
477  return getX() <= x && x < getX()+getWidth() && getY() <= y && y < getY()+getHeight();
478  }
479 
485  public void setForcedActive(@Nullable final ActivatableGUIElement forcedActive) {
486  this.forcedActive = forcedActive;
487  }
488 
492  @NotNull
493  @Override
494  public String toString() {
495  final String name = getName();
496  return (name == null ? "" : name)+"["+getWidth()+"x"+getHeight()+"]";
497  }
498 
504  public void autoSize(final int screenWidth, final int screenHeight) {
506  final Extent extent = autoSize;
507  if (extent != null) {
508  final Dimension preferredSize = getPreferredSize();
509  setBounds(extent.getX(screenWidth, screenHeight, preferredSize.width, preferredSize.height), extent.getY(screenWidth, screenHeight, preferredSize.width, preferredSize.height), extent.getW(screenWidth, screenHeight, preferredSize.width, preferredSize.height), extent.getH(screenWidth, screenHeight, preferredSize.width, preferredSize.height));
510  } else if (!initialPositionSet) {
511  final Dimension preferredSize = getPreferredSize();
512  final int x;
513  //noinspection IfMayBeConditional
514  if (defaultX == null) {
515  x = (screenWidth-preferredSize.width)/2;
516  } else {
517  x = defaultX.evaluate(screenWidth, screenHeight, preferredSize.width, preferredSize.height);
518  }
519  final int y;
520  //noinspection IfMayBeConditional
521  if (defaultY == null) {
522  y = (screenHeight-preferredSize.height)/2;
523  } else {
524  y = defaultY.evaluate(screenWidth, screenHeight, preferredSize.width, preferredSize.height);
525  }
526  setSize(preferredSize.width, preferredSize.height);
527  if (defaultX != null && defaultY != null) {
528  setPosition(x-preferredSize.width/2, y-preferredSize.height/2);
529  }
530  }
531  });
532 
533  showDialog(getX(), getY(), screenWidth, screenHeight);
534  }
535 
541  public void setDefaultPosition(@NotNull final Expression defaultX, @NotNull final Expression defaultY) {
542  this.defaultX = defaultX;
543  this.defaultY = defaultY;
544  }
545 
550  public boolean isSaveDialog() {
551  return saveDialog;
552  }
553 
557  public void setSaveDialog() {
558  saveDialog = true;
559  }
560 
569  public void showDialog(final int x, final int y, final int windowWidth, final int windowHeight) {
570  final int newX;
571  final int newY;
572  if (isAutoSize()) {
573  newX = x;
574  newY = y;
575  } else {
576  newX = Math.max(Math.min(x, windowWidth-getWidth()), 0);
577  newY = Math.max(Math.min(y, windowHeight-getHeight()), 0);
578  }
579  setPosition(newX, newY);
580  }
581 
582 }
boolean saveDialog
Whether this dialog retains its position across restarts.
Definition: Gui.java:66
static final long serialVersionUID
The serial version UID.
Definition: Gui.java:48
Interface for clients interested in auto-close events of Gui instances.
AbstractGUIElement getElementFromPoint(final int x, final int y)
Determines the GUIElement for a given coordinate.
Definition: Gui.java:287
void activateDefaultElement()
Activates the first default gui element of this gui.
Definition: Gui.java:202
Combines a list of GUIElements to for a gui.
Definition: Gui.java:43
KeyBindings getKeyBindings()
Returns the key bindings instance for this gui.
Definition: Gui.java:440
void setDefaultPosition(@NotNull final Expression defaultX, @NotNull final Expression defaultY)
Sets the default position for this dialog.
Definition: Gui.java:541
void setForcedActive(@Nullable final ActivatableGUIElement forcedActive)
Sets an ActivatableGUIElement that is always active.
Definition: Gui.java:485
Encapsulates the extent of a GUI element.
Definition: Extent.java:31
final KeyBindings keyBindings
The KeyBindings for this gui.
Definition: Gui.java:54
void setAutoSize(@Nullable final Extent autoSize)
Sets the auto-size state.
Definition: Gui.java:150
boolean keyPressed(@NotNull KeyEvent2 e)
Invoked when a key has been pressed.
void showDialog(final int x, final int y, final int windowWidth, final int windowHeight)
Sets the position of a dialog but makes sure the dialog is fully visible.
Definition: Gui.java:569
boolean isSaveDialog()
Returns whether this dialog retains its position across restarts.
Definition: Gui.java:550
int evaluate(final int width, final int height, final int prefWidth, final int prefHeight)
Evaluates the expression into a constant.
Definition: Expression.java:97
void setModal(final boolean modal)
Sets the modal state.
Definition: Gui.java:167
Gui(@NotNull final KeyBindings keyBindings)
Creates a new instance.
Definition: Gui.java:123
final Collection< RendererGuiState > hideInStates
The gui states that do not show this dialog.
Definition: Gui.java:77
String getName()
Returns the internal name of this gui element.
boolean isModal()
Returns the modal state.
Definition: Gui.java:175
boolean isActiveElement(@Nullable final ActivatableGUIElement activeElement)
Returns whether a given gui element is the active element of this dialog.
Definition: Gui.java:345
boolean isWithinDrawingArea(final int x, final int y)
Returns whether a given point is within this dialog&#39;s drawing area.
Definition: Gui.java:476
void setActive(final boolean active)
Sets the active state of a GUI element.
void setActiveElementActive(final boolean active)
Activates or deactivates the GUI element owning the focus.
Definition: Gui.java:354
boolean modal
Whether this dialog is modal.
Definition: Gui.java:71
void autoClosed()
Called when a dialog has been auto-closed.
Represents a pressed or released key.
Definition: KeyEvent2.java:33
boolean initialPositionSet
Whether an initial position has been set.
Definition: Gui.java:96
Expression defaultY
The default y-coordinate for this dialog.
Definition: Gui.java:117
void autoSize(final int screenWidth, final int screenHeight)
Auto-resizes the dialog.
Definition: Gui.java:504
An expression yielding an integer value derived from a screen resolution.
Definition: Expression.java:30
Interface defining an abstract GUI element.
Definition: GUIElement.java:32
void setPosition(final int x, final int y)
Sets the position of this dialog.
Definition: Gui.java:132
boolean handleKeyPress(@NotNull final KeyEvent2 e)
Dispatches a key press KeyEvent.
Definition: Gui.java:365
A GUIElement that can be set to active or inactive.
int getY(final int width, final int height, final int prefWidth, final int prefHeight)
Returns the y coordinate.
Definition: Extent.java:91
int getW(final int width, final int height, final int prefWidth, final int prefHeight)
Returns the width.
Definition: Extent.java:103
void setActiveElement(@NotNull final ActivatableGUIElement activeElement, final boolean active)
Sets the gui element owning the focus.
Definition: Gui.java:303
ActivatableGUIElement getDefaultElement()
Returns the first default gui element of this gui.
Definition: Gui.java:184
int getX(final int width, final int height, final int prefWidth, final int prefHeight)
Returns the x coordinate.
Definition: Extent.java:79
void setGuiAutoCloseListener(@Nullable final GuiAutoCloseListener guiAutoCloseListener)
Sets the GuiAutoCloseListener to be notified when this dialog becomes inactive.
Definition: Gui.java:466
void hideInState(@NotNull final RendererGuiState state)
Hides the dialog in a state.
Definition: Gui.java:448
boolean isAutoSize()
Returns whether this dialog is an auto-size dialog.
Definition: Gui.java:159
int getH(final int width, final int height, final int prefWidth, final int prefHeight)
Returns the height.
Definition: Extent.java:115
Utility class for Swing related functions.
boolean deactivateCommandInput()
Deactivates the command text input field of this dialog.
Definition: Gui.java:397
boolean isHidden(@NotNull final RendererGuiState state)
Returns whether this gui is visible in a state.
Definition: Gui.java:457
Abstract base class for GUI elements to be shown in Guis.
abstract void activeChanged()
Will be called whenever the active state has changed.
GuiAutoCloseListener guiAutoCloseListener
If set, the auto-close listener to notify if this dialog looses the active gui element.
Definition: Gui.java:103
Interface for classes that may handle "pressed" key events.
ActivatableGUIElement activeElement
The gui element which has the focus.
Definition: Gui.java:91
Extent autoSize
The extent of the dialog if it is auto-sizing or.
Definition: Gui.java:61
boolean isDefault()
Returns whether this element is the default element.The default element is selected with the ENTER ke...
boolean handleKeyPress(@NotNull final KeyEvent2 e)
Executes a "key press" event.
Expression defaultX
The default x-coordinate for this dialog.
Definition: Gui.java:110
void setSaveDialog()
Makes this dialog retain its position across restarts.
Definition: Gui.java:557
static void invokeAndWait(@NotNull final Runnable runnable)
Calls SwingUtilities#invokeAndWait(Runnable) if not on the EDT or calls the Runnable directly if on t...
abstract void execute()
Executes the actions associated with this GUI element.
ActivatableGUIElement forcedActive
If non-.
Definition: Gui.java:84