mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
- New forge menu bar (part 1 of 2). Includes common Forge and Help menus.
This commit is contained in:
5
.gitattributes
vendored
5
.gitattributes
vendored
@@ -14986,6 +14986,11 @@ src/main/java/forge/gui/match/views/VPicture.java -text
|
|||||||
src/main/java/forge/gui/match/views/VPlayers.java -text
|
src/main/java/forge/gui/match/views/VPlayers.java -text
|
||||||
src/main/java/forge/gui/match/views/VStack.java -text
|
src/main/java/forge/gui/match/views/VStack.java -text
|
||||||
src/main/java/forge/gui/match/views/package-info.java svneol=native#text/plain
|
src/main/java/forge/gui/match/views/package-info.java svneol=native#text/plain
|
||||||
|
src/main/java/forge/gui/menubar/FMenuBar.java -text
|
||||||
|
src/main/java/forge/gui/menubar/IMenuProvider.java -text
|
||||||
|
src/main/java/forge/gui/menubar/MenuUtil.java -text
|
||||||
|
src/main/java/forge/gui/menus/ForgeMenu.java -text
|
||||||
|
src/main/java/forge/gui/menus/HelpMenu.java -text
|
||||||
src/main/java/forge/gui/package-info.java svneol=native#text/plain
|
src/main/java/forge/gui/package-info.java svneol=native#text/plain
|
||||||
src/main/java/forge/gui/toolbox/CardFaceSymbols.java svneol=native#text/plain
|
src/main/java/forge/gui/toolbox/CardFaceSymbols.java svneol=native#text/plain
|
||||||
src/main/java/forge/gui/toolbox/FAbsolutePositioner.java -text
|
src/main/java/forge/gui/toolbox/FAbsolutePositioner.java -text
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ import forge.gui.match.controllers.CMessage;
|
|||||||
import forge.gui.match.controllers.CStack;
|
import forge.gui.match.controllers.CStack;
|
||||||
import forge.gui.match.nonsingleton.VField;
|
import forge.gui.match.nonsingleton.VField;
|
||||||
import forge.gui.match.views.VAntes;
|
import forge.gui.match.views.VAntes;
|
||||||
|
import forge.gui.menubar.FMenuBar;
|
||||||
|
import forge.gui.menubar.MenuUtil;
|
||||||
import forge.gui.toolbox.FSkin;
|
import forge.gui.toolbox.FSkin;
|
||||||
import forge.net.FServer;
|
import forge.net.FServer;
|
||||||
import forge.properties.ForgeLookAndFeel;
|
import forge.properties.ForgeLookAndFeel;
|
||||||
@@ -81,7 +83,8 @@ import forge.view.FView;
|
|||||||
*/
|
*/
|
||||||
public enum FControl {
|
public enum FControl {
|
||||||
instance;
|
instance;
|
||||||
|
|
||||||
|
private FMenuBar menuBar;
|
||||||
private List<Shortcut> shortcuts;
|
private List<Shortcut> shortcuts;
|
||||||
private JLayeredPane display;
|
private JLayeredPane display;
|
||||||
private Screens state = Screens.UNKNOWN;
|
private Screens state = Screens.UNKNOWN;
|
||||||
@@ -171,6 +174,8 @@ public enum FControl {
|
|||||||
// and any GUI controls being created.
|
// and any GUI controls being created.
|
||||||
FSkin.setProgessBarMessage("Setting look and feel...");
|
FSkin.setProgessBarMessage("Setting look and feel...");
|
||||||
setForgeLookAndFeel();
|
setForgeLookAndFeel();
|
||||||
|
|
||||||
|
createMenuBar();
|
||||||
|
|
||||||
this.shortcuts = KeyboardShortcuts.attachKeyboardShortcuts();
|
this.shortcuts = KeyboardShortcuts.attachKeyboardShortcuts();
|
||||||
this.display = FView.SINGLETON_INSTANCE.getLpnDocument();
|
this.display = FView.SINGLETON_INSTANCE.getLpnDocument();
|
||||||
@@ -210,6 +215,12 @@ public enum FControl {
|
|||||||
ForgeLookAndFeel laf = new ForgeLookAndFeel();
|
ForgeLookAndFeel laf = new ForgeLookAndFeel();
|
||||||
laf.setForgeLookAndFeel(Singletons.getView().getFrame());
|
laf.setForgeLookAndFeel(Singletons.getView().getFrame());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createMenuBar() {
|
||||||
|
if (MenuUtil.isMenuBarVisible()) {
|
||||||
|
this.menuBar = new FMenuBar(Singletons.getView().getFrame());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switches between display states in top level JFrame.
|
* Switches between display states in top level JFrame.
|
||||||
|
|||||||
@@ -1,406 +1,407 @@
|
|||||||
package forge.gui.framework;
|
package forge.gui.framework;
|
||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Cursor;
|
import java.awt.Cursor;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.event.ComponentAdapter;
|
import java.awt.event.ComponentAdapter;
|
||||||
import java.awt.event.ComponentEvent;
|
import java.awt.event.ComponentEvent;
|
||||||
import java.awt.event.ComponentListener;
|
import java.awt.event.ComponentListener;
|
||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.awt.event.MouseListener;
|
import java.awt.event.MouseListener;
|
||||||
import java.awt.event.MouseMotionAdapter;
|
import java.awt.event.MouseMotionAdapter;
|
||||||
import java.awt.event.MouseMotionListener;
|
import java.awt.event.MouseMotionListener;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
import forge.gui.FNetOverlay;
|
import forge.gui.FNetOverlay;
|
||||||
import forge.gui.toolbox.FAbsolutePositioner;
|
import forge.gui.toolbox.FAbsolutePositioner;
|
||||||
import forge.gui.toolbox.FOverlay;
|
import forge.gui.toolbox.FOverlay;
|
||||||
import forge.view.FView;
|
import forge.view.FView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Package-private utilities for resizing drag behavior using
|
* Package-private utilities for resizing drag behavior using
|
||||||
* the draggable panels registered in FView.
|
* the draggable panels registered in FView.
|
||||||
*
|
*
|
||||||
* <br><br><i>(S at beginning of class name denotes a static factory.)</i>
|
* <br><br><i>(S at beginning of class name denotes a static factory.)</i>
|
||||||
*/
|
*/
|
||||||
public final class SResizingUtil {
|
public final class SResizingUtil {
|
||||||
private static final List<DragCell> LEFT_PANELS = new ArrayList<DragCell>();
|
private static final List<DragCell> LEFT_PANELS = new ArrayList<DragCell>();
|
||||||
private static final List<DragCell> RIGHT_PANELS = new ArrayList<DragCell>();
|
private static final List<DragCell> RIGHT_PANELS = new ArrayList<DragCell>();
|
||||||
private static final List<DragCell> TOP_PANELS = new ArrayList<DragCell>();
|
private static final List<DragCell> TOP_PANELS = new ArrayList<DragCell>();
|
||||||
private static final List<DragCell> BOTTOM_PANELS = new ArrayList<DragCell>();
|
private static final List<DragCell> BOTTOM_PANELS = new ArrayList<DragCell>();
|
||||||
|
|
||||||
private static int dX;
|
private static int dX;
|
||||||
private static int evtX;
|
private static int evtX;
|
||||||
private static int dY;
|
private static int dY;
|
||||||
private static int evtY;
|
private static int evtY;
|
||||||
|
|
||||||
/** Minimum cell width. */
|
/** Minimum cell width. */
|
||||||
public static final int W_MIN = 100;
|
public static final int W_MIN = 100;
|
||||||
/** Minimum cell height. */
|
/** Minimum cell height. */
|
||||||
public static final int H_MIN = 75;
|
public static final int H_MIN = 75;
|
||||||
|
|
||||||
private static final MouseListener MAD_RESIZE_X = new MouseAdapter() {
|
private static final MouseListener MAD_RESIZE_X = new MouseAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void mouseEntered(final MouseEvent e) {
|
public void mouseEntered(final MouseEvent e) {
|
||||||
FView.SINGLETON_INSTANCE.getLpnDocument().setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
|
FView.SINGLETON_INSTANCE.getLpnDocument().setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseExited(final MouseEvent e) {
|
public void mouseExited(final MouseEvent e) {
|
||||||
FView.SINGLETON_INSTANCE.getLpnDocument().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
FView.SINGLETON_INSTANCE.getLpnDocument().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mousePressed(final MouseEvent e) {
|
public void mousePressed(final MouseEvent e) {
|
||||||
SResizingUtil.startResizeX(e);
|
SResizingUtil.startResizeX(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseReleased(final MouseEvent e) {
|
public void mouseReleased(final MouseEvent e) {
|
||||||
SResizingUtil.endResize();
|
SResizingUtil.endResize();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final MouseListener MAD_RESIZE_Y = new MouseAdapter() {
|
private static final MouseListener MAD_RESIZE_Y = new MouseAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void mouseEntered(final MouseEvent e) {
|
public void mouseEntered(final MouseEvent e) {
|
||||||
FView.SINGLETON_INSTANCE.getLpnDocument().setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR));
|
FView.SINGLETON_INSTANCE.getLpnDocument().setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseExited(final MouseEvent e) {
|
public void mouseExited(final MouseEvent e) {
|
||||||
FView.SINGLETON_INSTANCE.getLpnDocument().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
FView.SINGLETON_INSTANCE.getLpnDocument().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mousePressed(final MouseEvent e) {
|
public void mousePressed(final MouseEvent e) {
|
||||||
SResizingUtil.startResizeY(e);
|
SResizingUtil.startResizeY(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseReleased(final MouseEvent e) {
|
public void mouseReleased(final MouseEvent e) {
|
||||||
SResizingUtil.endResize();
|
SResizingUtil.endResize();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final MouseMotionListener MMA_DRAG_X = new MouseMotionAdapter() {
|
private static final MouseMotionListener MMA_DRAG_X = new MouseMotionAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void mouseDragged(final MouseEvent e) {
|
public void mouseDragged(final MouseEvent e) {
|
||||||
SResizingUtil.resizeX(e);
|
SResizingUtil.resizeX(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final MouseMotionListener MMA_DRAG_Y = new MouseMotionAdapter() {
|
private static final MouseMotionListener MMA_DRAG_Y = new MouseMotionAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void mouseDragged(final MouseEvent e) {
|
public void mouseDragged(final MouseEvent e) {
|
||||||
SResizingUtil.resizeY(e);
|
SResizingUtil.resizeY(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final ComponentListener CAD_RESIZE = new ComponentAdapter() {
|
private static final ComponentListener CAD_RESIZE = new ComponentAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void componentResized(final ComponentEvent e) {
|
public void componentResized(final ComponentEvent e) {
|
||||||
resizeWindow();
|
resizeWindow();
|
||||||
SRearrangingUtil.updateBorders();
|
SRearrangingUtil.updateBorders();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void resizeWindow() {
|
public static void resizeWindow() {
|
||||||
final List<DragCell> cells = FView.SINGLETON_INSTANCE.getDragCells();
|
final List<DragCell> cells = FView.SINGLETON_INSTANCE.getDragCells();
|
||||||
final JPanel pnlContent = FView.SINGLETON_INSTANCE.getPnlContent();
|
final JPanel pnlContent = FView.SINGLETON_INSTANCE.getPnlContent();
|
||||||
final JPanel pnlInsets = FView.SINGLETON_INSTANCE.getPnlInsets();
|
final JPanel pnlInsets = FView.SINGLETON_INSTANCE.getPnlInsets();
|
||||||
|
|
||||||
Rectangle mainBounds = FView.SINGLETON_INSTANCE.getFrame().getContentPane().getBounds();
|
Rectangle mainBounds = FView.SINGLETON_INSTANCE.getFrame().getContentPane().getBounds();
|
||||||
FAbsolutePositioner.SINGLETON_INSTANCE.containerResized(mainBounds);
|
mainBounds.y = 0; // Play nicely with MenuBar if visible or not.
|
||||||
FOverlay.SINGLETON_INSTANCE.getPanel().setBounds(mainBounds);
|
FAbsolutePositioner.SINGLETON_INSTANCE.containerResized(mainBounds);
|
||||||
FNetOverlay.SINGLETON_INSTANCE.containerResized(mainBounds);
|
FOverlay.SINGLETON_INSTANCE.getPanel().setBounds(mainBounds);
|
||||||
|
FNetOverlay.SINGLETON_INSTANCE.containerResized(mainBounds);
|
||||||
pnlInsets.setBounds(mainBounds);
|
|
||||||
pnlInsets.validate();
|
pnlInsets.setBounds(mainBounds);
|
||||||
|
pnlInsets.validate();
|
||||||
final int w = pnlContent.getWidth();
|
|
||||||
final int h = pnlContent.getHeight();
|
final int w = pnlContent.getWidth();
|
||||||
|
final int h = pnlContent.getHeight();
|
||||||
double roughVal = 0;
|
|
||||||
int smoothVal = 0;
|
double roughVal = 0;
|
||||||
|
int smoothVal = 0;
|
||||||
Set<Component> existingComponents = new HashSet<Component>();
|
|
||||||
for (Component c : pnlContent.getComponents()) {
|
Set<Component> existingComponents = new HashSet<Component>();
|
||||||
existingComponents.add(c);
|
for (Component c : pnlContent.getComponents()) {
|
||||||
}
|
existingComponents.add(c);
|
||||||
|
}
|
||||||
// This is the core of the pixel-perfect layout. To avoid <20>1 px errors on borders
|
|
||||||
// from rounding individual panels, the intermediate values (exactly accurate, in %)
|
// This is the core of the pixel-perfect layout. To avoid <20>1 px errors on borders
|
||||||
// for width and height are rounded based on comparison to other panels in the
|
// from rounding individual panels, the intermediate values (exactly accurate, in %)
|
||||||
// layout. This is to avoid errors such as:
|
// for width and height are rounded based on comparison to other panels in the
|
||||||
// 10% = 9.8px -> 10px -> x 3 = 30px
|
// layout. This is to avoid errors such as:
|
||||||
// 30% = 29.4px -> 29px (!)
|
// 10% = 9.8px -> 10px -> x 3 = 30px
|
||||||
for (final DragCell cellA : cells) {
|
// 30% = 29.4px -> 29px (!)
|
||||||
RectangleOfDouble cellSizeA = cellA.getRoughBounds();
|
for (final DragCell cellA : cells) {
|
||||||
roughVal = cellSizeA.getX() * w + cellSizeA.getW() * w;
|
RectangleOfDouble cellSizeA = cellA.getRoughBounds();
|
||||||
|
roughVal = cellSizeA.getX() * w + cellSizeA.getW() * w;
|
||||||
smoothVal = (int) Math.round(roughVal);
|
|
||||||
for (final DragCell cellB : cells) {
|
smoothVal = (int) Math.round(roughVal);
|
||||||
RectangleOfDouble cellSizeB = cellB.getRoughBounds();
|
for (final DragCell cellB : cells) {
|
||||||
if ((cellSizeB.getX() * w + cellSizeB.getW() * w) == roughVal) {
|
RectangleOfDouble cellSizeB = cellB.getRoughBounds();
|
||||||
cellB.setSmoothW(smoothVal - (int) Math.round(cellSizeB.getX() * w));
|
if ((cellSizeB.getX() * w + cellSizeB.getW() * w) == roughVal) {
|
||||||
}
|
cellB.setSmoothW(smoothVal - (int) Math.round(cellSizeB.getX() * w));
|
||||||
}
|
}
|
||||||
cellA.setSmoothW(smoothVal - (int) Math.round(cellSizeA.getX() * w));
|
}
|
||||||
|
cellA.setSmoothW(smoothVal - (int) Math.round(cellSizeA.getX() * w));
|
||||||
roughVal = cellSizeA.getY() * h + cellSizeA.getH() * h;
|
|
||||||
smoothVal = (int) Math.round(roughVal);
|
roughVal = cellSizeA.getY() * h + cellSizeA.getH() * h;
|
||||||
for (final DragCell cellB : cells) {
|
smoothVal = (int) Math.round(roughVal);
|
||||||
RectangleOfDouble cellSizeB = cellB.getRoughBounds();
|
for (final DragCell cellB : cells) {
|
||||||
if (cellSizeB.getY() * h + cellSizeB.getH() * h == roughVal) {
|
RectangleOfDouble cellSizeB = cellB.getRoughBounds();
|
||||||
cellB.setSmoothH(smoothVal - (int) Math.round(cellSizeB.getY() * h));
|
if (cellSizeB.getY() * h + cellSizeB.getH() * h == roughVal) {
|
||||||
}
|
cellB.setSmoothH(smoothVal - (int) Math.round(cellSizeB.getY() * h));
|
||||||
}
|
}
|
||||||
cellA.setSmoothH(smoothVal - (int) Math.round(cellSizeA.getY() * h));
|
}
|
||||||
|
cellA.setSmoothH(smoothVal - (int) Math.round(cellSizeA.getY() * h));
|
||||||
// X and Y coordinate can be rounded as usual.
|
|
||||||
cellA.setSmoothX((int) Math.round(cellSizeA.getX() * w));
|
// X and Y coordinate can be rounded as usual.
|
||||||
cellA.setSmoothY((int) Math.round(cellSizeA.getY() * h));
|
cellA.setSmoothX((int) Math.round(cellSizeA.getX() * w));
|
||||||
|
cellA.setSmoothY((int) Math.round(cellSizeA.getY() * h));
|
||||||
// only add component if not already in container; otherwise the keyboard focus
|
|
||||||
// jumps around to the most recenly added component
|
// only add component if not already in container; otherwise the keyboard focus
|
||||||
if (!existingComponents.contains(cellA)) {
|
// jumps around to the most recenly added component
|
||||||
pnlContent.add(cellA);
|
if (!existingComponents.contains(cellA)) {
|
||||||
}
|
pnlContent.add(cellA);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Lock in final bounds and build heads.
|
|
||||||
for (final DragCell t : cells) {
|
// Lock in final bounds and build heads.
|
||||||
t.setSmoothBounds();
|
for (final DragCell t : cells) {
|
||||||
t.validate();
|
t.setSmoothBounds();
|
||||||
t.refresh();
|
t.validate();
|
||||||
}
|
t.refresh();
|
||||||
|
}
|
||||||
cells.clear();
|
|
||||||
}
|
cells.clear();
|
||||||
|
}
|
||||||
/** @param e   {@link java.awt.event.MouseEvent} */
|
|
||||||
public static void resizeX(final MouseEvent e) {
|
/** @param e   {@link java.awt.event.MouseEvent} */
|
||||||
dX = (int) e.getLocationOnScreen().getX() - evtX;
|
public static void resizeX(final MouseEvent e) {
|
||||||
evtX = (int) e.getLocationOnScreen().getX();
|
dX = (int) e.getLocationOnScreen().getX() - evtX;
|
||||||
boolean leftLock = false;
|
evtX = (int) e.getLocationOnScreen().getX();
|
||||||
boolean rightLock = false;
|
boolean leftLock = false;
|
||||||
|
boolean rightLock = false;
|
||||||
for (final DragCell t : LEFT_PANELS) {
|
|
||||||
if ((t.getW() + dX) < W_MIN) { leftLock = true; break; }
|
for (final DragCell t : LEFT_PANELS) {
|
||||||
}
|
if ((t.getW() + dX) < W_MIN) { leftLock = true; break; }
|
||||||
|
}
|
||||||
for (final DragCell t : RIGHT_PANELS) {
|
|
||||||
if ((t.getW() - dX) < W_MIN) { rightLock = true; break; }
|
for (final DragCell t : RIGHT_PANELS) {
|
||||||
}
|
if ((t.getW() - dX) < W_MIN) { rightLock = true; break; }
|
||||||
|
}
|
||||||
if (dX < 0 && leftLock) { return; }
|
|
||||||
if (dX > 0 && rightLock) { return; }
|
if (dX < 0 && leftLock) { return; }
|
||||||
|
if (dX > 0 && rightLock) { return; }
|
||||||
for (final DragCell t : LEFT_PANELS) {
|
|
||||||
t.setBounds(t.getX(), t.getY(), t.getW() + dX, t.getH());
|
for (final DragCell t : LEFT_PANELS) {
|
||||||
t.refresh();
|
t.setBounds(t.getX(), t.getY(), t.getW() + dX, t.getH());
|
||||||
}
|
t.refresh();
|
||||||
|
}
|
||||||
for (final DragCell t : RIGHT_PANELS) {
|
|
||||||
t.setBounds(t.getX() + dX, t.getY(), t.getW() - dX, t.getH());
|
for (final DragCell t : RIGHT_PANELS) {
|
||||||
t.refresh();
|
t.setBounds(t.getX() + dX, t.getY(), t.getW() - dX, t.getH());
|
||||||
}
|
t.refresh();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/** @param e   {@link java.awt.event.MouseEvent} */
|
|
||||||
public static void resizeY(final MouseEvent e) {
|
/** @param e   {@link java.awt.event.MouseEvent} */
|
||||||
dY = (int) e.getLocationOnScreen().getY() - evtY;
|
public static void resizeY(final MouseEvent e) {
|
||||||
evtY = (int) e.getLocationOnScreen().getY();
|
dY = (int) e.getLocationOnScreen().getY() - evtY;
|
||||||
boolean topLock = false;
|
evtY = (int) e.getLocationOnScreen().getY();
|
||||||
boolean bottomLock = false;
|
boolean topLock = false;
|
||||||
|
boolean bottomLock = false;
|
||||||
for (final DragCell t : TOP_PANELS) {
|
|
||||||
if ((t.getH() + dY) < H_MIN) { topLock = true; break; }
|
for (final DragCell t : TOP_PANELS) {
|
||||||
}
|
if ((t.getH() + dY) < H_MIN) { topLock = true; break; }
|
||||||
|
}
|
||||||
for (final DragCell t : BOTTOM_PANELS) {
|
|
||||||
if ((t.getH() - dY) < H_MIN) { bottomLock = true; break; }
|
for (final DragCell t : BOTTOM_PANELS) {
|
||||||
}
|
if ((t.getH() - dY) < H_MIN) { bottomLock = true; break; }
|
||||||
|
}
|
||||||
if (dY < 0 && topLock) { return; }
|
|
||||||
if (dY > 0 && bottomLock) { return; }
|
if (dY < 0 && topLock) { return; }
|
||||||
|
if (dY > 0 && bottomLock) { return; }
|
||||||
for (final DragCell t : TOP_PANELS) {
|
|
||||||
t.setBounds(t.getX(), t.getY(), t.getW(), t.getH() + dY);
|
for (final DragCell t : TOP_PANELS) {
|
||||||
t.revalidate();
|
t.setBounds(t.getX(), t.getY(), t.getW(), t.getH() + dY);
|
||||||
t.repaintSelf();
|
t.revalidate();
|
||||||
}
|
t.repaintSelf();
|
||||||
|
}
|
||||||
for (final DragCell t : BOTTOM_PANELS) {
|
|
||||||
t.setBounds(t.getX(), t.getY() + dY, t.getW(), t.getH() - dY);
|
for (final DragCell t : BOTTOM_PANELS) {
|
||||||
t.revalidate();
|
t.setBounds(t.getX(), t.getY() + dY, t.getW(), t.getH() - dY);
|
||||||
t.repaintSelf();
|
t.revalidate();
|
||||||
}
|
t.repaintSelf();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/** @param e   {@link java.awt.event.MouseEvent} */
|
|
||||||
public static void startResizeX(final MouseEvent e) {
|
/** @param e   {@link java.awt.event.MouseEvent} */
|
||||||
evtX = (int) e.getLocationOnScreen().getX();
|
public static void startResizeX(final MouseEvent e) {
|
||||||
LEFT_PANELS.clear();
|
evtX = (int) e.getLocationOnScreen().getX();
|
||||||
RIGHT_PANELS.clear();
|
LEFT_PANELS.clear();
|
||||||
|
RIGHT_PANELS.clear();
|
||||||
final DragCell src = (DragCell) ((JPanel) e.getSource()).getParent();
|
|
||||||
final int srcX2 = src.getAbsX2();
|
final DragCell src = (DragCell) ((JPanel) e.getSource()).getParent();
|
||||||
|
final int srcX2 = src.getAbsX2();
|
||||||
int limTop = -1;
|
|
||||||
int limBottom = Integer.MAX_VALUE;
|
int limTop = -1;
|
||||||
int tempX = -1;
|
int limBottom = Integer.MAX_VALUE;
|
||||||
int tempX2 = -1;
|
int tempX = -1;
|
||||||
int tempY = -1;
|
int tempX2 = -1;
|
||||||
int tempY2 = -1;
|
int tempY = -1;
|
||||||
|
int tempY2 = -1;
|
||||||
// Add all panels who share a left or right edge with the
|
|
||||||
// same coordinate as the right edge of the source panel.
|
// Add all panels who share a left or right edge with the
|
||||||
for (final DragCell t : FView.SINGLETON_INSTANCE.getDragCells()) {
|
// same coordinate as the right edge of the source panel.
|
||||||
tempX = t.getAbsX();
|
for (final DragCell t : FView.SINGLETON_INSTANCE.getDragCells()) {
|
||||||
tempX2 = t.getAbsX2();
|
tempX = t.getAbsX();
|
||||||
|
tempX2 = t.getAbsX2();
|
||||||
if (srcX2 == tempX) { RIGHT_PANELS.add(t); }
|
|
||||||
else if (srcX2 == tempX2) { LEFT_PANELS.add(t); }
|
if (srcX2 == tempX) { RIGHT_PANELS.add(t); }
|
||||||
}
|
else if (srcX2 == tempX2) { LEFT_PANELS.add(t); }
|
||||||
|
}
|
||||||
// Set limits at panels which are level at intersections.
|
|
||||||
for (final DragCell pnlL : LEFT_PANELS) {
|
// Set limits at panels which are level at intersections.
|
||||||
if (pnlL.equals(src)) { continue; }
|
for (final DragCell pnlL : LEFT_PANELS) {
|
||||||
tempY = pnlL.getAbsY();
|
if (pnlL.equals(src)) { continue; }
|
||||||
tempY2 = pnlL.getAbsY2();
|
tempY = pnlL.getAbsY();
|
||||||
|
tempY2 = pnlL.getAbsY2();
|
||||||
for (final DragCell pnlR : RIGHT_PANELS) {
|
|
||||||
// Upper edges match? Set a bottom limit.
|
for (final DragCell pnlR : RIGHT_PANELS) {
|
||||||
if (tempY >= src.getAbsY2() && tempY == pnlR.getAbsY() && tempY < limBottom) {
|
// Upper edges match? Set a bottom limit.
|
||||||
limBottom = tempY;
|
if (tempY >= src.getAbsY2() && tempY == pnlR.getAbsY() && tempY < limBottom) {
|
||||||
}
|
limBottom = tempY;
|
||||||
// Lower edges match? Set an upper limit.
|
}
|
||||||
else if (tempY2 <= src.getAbsY() && tempY2 == pnlR.getAbsY2() && tempY2 > limTop) {
|
// Lower edges match? Set an upper limit.
|
||||||
limTop = tempY2;
|
else if (tempY2 <= src.getAbsY() && tempY2 == pnlR.getAbsY2() && tempY2 > limTop) {
|
||||||
}
|
limTop = tempY2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Remove non-contiguous panels from left side using limits.
|
|
||||||
final Iterator<DragCell> itrLeft = LEFT_PANELS.iterator();
|
// Remove non-contiguous panels from left side using limits.
|
||||||
while (itrLeft.hasNext()) {
|
final Iterator<DragCell> itrLeft = LEFT_PANELS.iterator();
|
||||||
final DragCell t = itrLeft.next();
|
while (itrLeft.hasNext()) {
|
||||||
|
final DragCell t = itrLeft.next();
|
||||||
if (t.getAbsY() >= limBottom || t.getAbsY2() <= limTop) {
|
|
||||||
itrLeft.remove();
|
if (t.getAbsY() >= limBottom || t.getAbsY2() <= limTop) {
|
||||||
}
|
itrLeft.remove();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Remove non-contiguous panels from right side using limits.
|
|
||||||
final Iterator<DragCell> itrRight = RIGHT_PANELS.iterator();
|
// Remove non-contiguous panels from right side using limits.
|
||||||
while (itrRight.hasNext()) {
|
final Iterator<DragCell> itrRight = RIGHT_PANELS.iterator();
|
||||||
final DragCell t = itrRight.next();
|
while (itrRight.hasNext()) {
|
||||||
|
final DragCell t = itrRight.next();
|
||||||
if (t.getAbsY() >= limBottom || t.getAbsY2() <= limTop) {
|
|
||||||
itrRight.remove();
|
if (t.getAbsY() >= limBottom || t.getAbsY2() <= limTop) {
|
||||||
}
|
itrRight.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/** @param e   {@link java.awt.event.MouseEvent} */
|
|
||||||
public static void startResizeY(final MouseEvent e) {
|
/** @param e   {@link java.awt.event.MouseEvent} */
|
||||||
evtY = (int) e.getLocationOnScreen().getY();
|
public static void startResizeY(final MouseEvent e) {
|
||||||
TOP_PANELS.clear();
|
evtY = (int) e.getLocationOnScreen().getY();
|
||||||
BOTTOM_PANELS.clear();
|
TOP_PANELS.clear();
|
||||||
|
BOTTOM_PANELS.clear();
|
||||||
final DragCell src = (DragCell) ((JPanel) e.getSource()).getParent();
|
|
||||||
final int srcY2 = src.getAbsY2();
|
final DragCell src = (DragCell) ((JPanel) e.getSource()).getParent();
|
||||||
|
final int srcY2 = src.getAbsY2();
|
||||||
int limLeft = -1;
|
|
||||||
int limRight = Integer.MAX_VALUE;
|
int limLeft = -1;
|
||||||
int tempX = -1;
|
int limRight = Integer.MAX_VALUE;
|
||||||
int tempX2 = -1;
|
int tempX = -1;
|
||||||
int tempY = -1;
|
int tempX2 = -1;
|
||||||
int tempY2 = -1;
|
int tempY = -1;
|
||||||
|
int tempY2 = -1;
|
||||||
// Add all panels who share a top or bottom edge with the
|
|
||||||
// same coordinate as the bottom edge of the source panel.
|
// Add all panels who share a top or bottom edge with the
|
||||||
for (final DragCell t : FView.SINGLETON_INSTANCE.getDragCells()) {
|
// same coordinate as the bottom edge of the source panel.
|
||||||
tempY = t.getAbsY();
|
for (final DragCell t : FView.SINGLETON_INSTANCE.getDragCells()) {
|
||||||
tempY2 = t.getAbsY2();
|
tempY = t.getAbsY();
|
||||||
|
tempY2 = t.getAbsY2();
|
||||||
if (srcY2 == tempY) { BOTTOM_PANELS.add(t); }
|
|
||||||
else if (srcY2 == tempY2) { TOP_PANELS.add(t); }
|
if (srcY2 == tempY) { BOTTOM_PANELS.add(t); }
|
||||||
}
|
else if (srcY2 == tempY2) { TOP_PANELS.add(t); }
|
||||||
|
}
|
||||||
// Set limits at panels which are level at intersections.
|
|
||||||
for (final DragCell pnlT : TOP_PANELS) {
|
// Set limits at panels which are level at intersections.
|
||||||
if (pnlT.equals(src)) { continue; }
|
for (final DragCell pnlT : TOP_PANELS) {
|
||||||
tempX = pnlT.getAbsX();
|
if (pnlT.equals(src)) { continue; }
|
||||||
tempX2 = pnlT.getAbsX2();
|
tempX = pnlT.getAbsX();
|
||||||
|
tempX2 = pnlT.getAbsX2();
|
||||||
for (final DragCell pnlB : BOTTOM_PANELS) {
|
|
||||||
// Right edges match? Set a right limit.
|
for (final DragCell pnlB : BOTTOM_PANELS) {
|
||||||
if (tempX >= src.getAbsX2() && tempX == pnlB.getAbsX() && tempX < limRight) {
|
// Right edges match? Set a right limit.
|
||||||
limRight = tempX;
|
if (tempX >= src.getAbsX2() && tempX == pnlB.getAbsX() && tempX < limRight) {
|
||||||
}
|
limRight = tempX;
|
||||||
// Left edges match? Set an left limit.
|
}
|
||||||
else if (tempX2 <= src.getAbsX() && tempX2 == pnlB.getAbsX2() && tempX2 > limLeft) {
|
// Left edges match? Set an left limit.
|
||||||
limLeft = tempX2;
|
else if (tempX2 <= src.getAbsX() && tempX2 == pnlB.getAbsX2() && tempX2 > limLeft) {
|
||||||
}
|
limLeft = tempX2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Remove non-contiguous panels from left side using limits.
|
|
||||||
final Iterator<DragCell> itrTop = TOP_PANELS.iterator();
|
// Remove non-contiguous panels from left side using limits.
|
||||||
while (itrTop.hasNext()) {
|
final Iterator<DragCell> itrTop = TOP_PANELS.iterator();
|
||||||
final DragCell t = itrTop.next();
|
while (itrTop.hasNext()) {
|
||||||
if (t.getAbsX() >= limRight || t.getAbsX2() <= limLeft) {
|
final DragCell t = itrTop.next();
|
||||||
itrTop.remove();
|
if (t.getAbsX() >= limRight || t.getAbsX2() <= limLeft) {
|
||||||
}
|
itrTop.remove();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Remove non-contiguous panels from right side using limits.
|
|
||||||
final Iterator<DragCell> itrBottom = BOTTOM_PANELS.iterator();
|
// Remove non-contiguous panels from right side using limits.
|
||||||
while (itrBottom.hasNext()) {
|
final Iterator<DragCell> itrBottom = BOTTOM_PANELS.iterator();
|
||||||
final DragCell t = itrBottom.next();
|
while (itrBottom.hasNext()) {
|
||||||
if (t.getAbsX() >= limRight || t.getAbsX2() <= limLeft) {
|
final DragCell t = itrBottom.next();
|
||||||
itrBottom.remove();
|
if (t.getAbsX() >= limRight || t.getAbsX2() <= limLeft) {
|
||||||
}
|
itrBottom.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/** */
|
|
||||||
public static void endResize() {
|
/** */
|
||||||
SLayoutIO.saveLayout(null);
|
public static void endResize() {
|
||||||
}
|
SLayoutIO.saveLayout(null);
|
||||||
|
}
|
||||||
/** @return {@link java.awt.event.MouseListener} */
|
|
||||||
public static MouseListener getResizeXListener() {
|
/** @return {@link java.awt.event.MouseListener} */
|
||||||
return MAD_RESIZE_X;
|
public static MouseListener getResizeXListener() {
|
||||||
}
|
return MAD_RESIZE_X;
|
||||||
|
}
|
||||||
/** @return {@link java.awt.event.MouseListener} */
|
|
||||||
public static MouseListener getResizeYListener() {
|
/** @return {@link java.awt.event.MouseListener} */
|
||||||
return MAD_RESIZE_Y;
|
public static MouseListener getResizeYListener() {
|
||||||
}
|
return MAD_RESIZE_Y;
|
||||||
|
}
|
||||||
/** @return {@link java.awt.event.MouseMotionListener} */
|
|
||||||
public static MouseMotionListener getDragXListener() {
|
/** @return {@link java.awt.event.MouseMotionListener} */
|
||||||
return MMA_DRAG_X;
|
public static MouseMotionListener getDragXListener() {
|
||||||
}
|
return MMA_DRAG_X;
|
||||||
|
}
|
||||||
/** @return {@link java.awt.event.MouseMotionListener} */
|
|
||||||
public static MouseMotionListener getDragYListener() {
|
/** @return {@link java.awt.event.MouseMotionListener} */
|
||||||
return MMA_DRAG_Y;
|
public static MouseMotionListener getDragYListener() {
|
||||||
}
|
return MMA_DRAG_Y;
|
||||||
|
}
|
||||||
/** @return {@link java.awt.event.ComponentListener} */
|
|
||||||
public static ComponentListener getWindowResizeListener() {
|
/** @return {@link java.awt.event.ComponentListener} */
|
||||||
return CAD_RESIZE;
|
public static ComponentListener getWindowResizeListener() {
|
||||||
}
|
return CAD_RESIZE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
51
src/main/java/forge/gui/menubar/FMenuBar.java
Normal file
51
src/main/java/forge/gui/menubar/FMenuBar.java
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package forge.gui.menubar;
|
||||||
|
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JMenu;
|
||||||
|
import javax.swing.JMenuBar;
|
||||||
|
|
||||||
|
import forge.gui.menus.ForgeMenu;
|
||||||
|
import forge.gui.menus.HelpMenu;
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class FMenuBar extends JMenuBar {
|
||||||
|
|
||||||
|
public FMenuBar(JFrame f) {
|
||||||
|
f.setJMenuBar(this);
|
||||||
|
setPreferredSize(new Dimension(f.getWidth(), 26));
|
||||||
|
setupMenuBar(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setupMenuBar(IMenuProvider provider) {
|
||||||
|
removeAll();
|
||||||
|
add(ForgeMenu.getMenu());
|
||||||
|
addProviderMenus(provider);
|
||||||
|
add(HelpMenu.getMenu());
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addProviderMenus(IMenuProvider provider) {
|
||||||
|
if (provider != null && provider.getMenus() != null) {
|
||||||
|
for (JMenu m : provider.getMenus()) {
|
||||||
|
m.setBorderPainted(false);
|
||||||
|
add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or disables the MenuBar.
|
||||||
|
* <p>
|
||||||
|
* Note: Disabling a component does not disable its children.
|
||||||
|
*/
|
||||||
|
public void setMenuBarEnabled(boolean isEnabled) {
|
||||||
|
setEnabled(isEnabled);
|
||||||
|
for (Component c : getComponents()) {
|
||||||
|
c.setEnabled(isEnabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
19
src/main/java/forge/gui/menubar/IMenuProvider.java
Normal file
19
src/main/java/forge/gui/menubar/IMenuProvider.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package forge.gui.menubar;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.swing.JMenu;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By implementing this interface a class can add menus to the menu bar
|
||||||
|
* by calling the {@code MenuBarManager.SetupMenuBar()} method.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface IMenuProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of JMenu objects for display in MenuBar.
|
||||||
|
*/
|
||||||
|
List<JMenu> getMenus();
|
||||||
|
|
||||||
|
}
|
||||||
61
src/main/java/forge/gui/menubar/MenuUtil.java
Normal file
61
src/main/java/forge/gui/menubar/MenuUtil.java
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
package forge.gui.menubar;
|
||||||
|
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.swing.ImageIcon;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
import javax.swing.KeyStroke;
|
||||||
|
|
||||||
|
import forge.Singletons;
|
||||||
|
import forge.gui.toolbox.FSkin;
|
||||||
|
import forge.gui.toolbox.FSkin.SkinProp;
|
||||||
|
import forge.gui.toolbox.imaging.ImageUtil;
|
||||||
|
import forge.properties.ForgePreferences;
|
||||||
|
import forge.properties.ForgePreferences.FPref;
|
||||||
|
|
||||||
|
public final class MenuUtil {
|
||||||
|
private MenuUtil() { }
|
||||||
|
|
||||||
|
private static ForgePreferences prefs = Singletons.getModel().getPreferences();
|
||||||
|
|
||||||
|
// Get appropriate OS standard accelerator key for menu shortcuts.
|
||||||
|
private static final int DEFAULT_MenuShortcutKeyMask =
|
||||||
|
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
|
||||||
|
|
||||||
|
public static boolean isMenuBarVisible() {
|
||||||
|
return !prefs.getPrefBoolean(FPref.UI_HIDE_MENUBAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void openUrlInBrowser(String url) {
|
||||||
|
try {
|
||||||
|
java.awt.Desktop.getDesktop().browse(java.net.URI.create(url));
|
||||||
|
} catch (IOException e) {
|
||||||
|
// Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ImageIcon getMenuIcon(SkinProp ico) {
|
||||||
|
return ImageUtil.getMenuIcon(FSkin.getIcon(ico));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KeyStroke getAcceleratorKey(int key) {
|
||||||
|
return KeyStroke.getKeyStroke(key, DEFAULT_MenuShortcutKeyMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean getUserConfirmation(String prompt, String dialogTitle) {
|
||||||
|
Object[] options = {"Yes", "No"};
|
||||||
|
int reply = JOptionPane.showOptionDialog(
|
||||||
|
null,
|
||||||
|
prompt,
|
||||||
|
dialogTitle,
|
||||||
|
JOptionPane.YES_NO_OPTION,
|
||||||
|
JOptionPane.QUESTION_MESSAGE,
|
||||||
|
null,
|
||||||
|
options,
|
||||||
|
options[1]);
|
||||||
|
return (reply == JOptionPane.YES_OPTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
70
src/main/java/forge/gui/menus/ForgeMenu.java
Normal file
70
src/main/java/forge/gui/menus/ForgeMenu.java
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package forge.gui.menus;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
|
import javax.swing.JMenu;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
|
import forge.Singletons;
|
||||||
|
import forge.control.RestartUtil;
|
||||||
|
import forge.control.FControl.Screens;
|
||||||
|
import forge.gui.menubar.MenuUtil;
|
||||||
|
|
||||||
|
public final class ForgeMenu {
|
||||||
|
private ForgeMenu() { }
|
||||||
|
|
||||||
|
public static JMenu getMenu() {
|
||||||
|
JMenu menu = new JMenu("Forge");
|
||||||
|
menu.setMnemonic(KeyEvent.VK_F);
|
||||||
|
menu.add(getMenuItem_Restart());
|
||||||
|
menu.add(getMenuItem_Exit());
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JMenuItem getMenuItem_Exit() {
|
||||||
|
JMenuItem menuItem = new JMenuItem("Exit");
|
||||||
|
menuItem.addActionListener(getExitAction());
|
||||||
|
return menuItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ActionListener getExitAction() {
|
||||||
|
return new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (!isHomeScreenActive()) {
|
||||||
|
String userPrompt = "Please confirm you want to close Forge.\n\n";
|
||||||
|
if (!MenuUtil.getUserConfirmation(userPrompt, "Exit Forge")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JMenuItem getMenuItem_Restart() {
|
||||||
|
JMenuItem menuItem = new JMenuItem("Restart");
|
||||||
|
menuItem.addActionListener(getRestartAction());
|
||||||
|
return menuItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ActionListener getRestartAction() {
|
||||||
|
return new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (!isHomeScreenActive()) {
|
||||||
|
String userPrompt = "Please confirm you want to restart Forge.\n\n";
|
||||||
|
if (!MenuUtil.getUserConfirmation(userPrompt, "Restart Forge")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RestartUtil.restartApplication(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isHomeScreenActive() {
|
||||||
|
return Singletons.getControl().getState() == Screens.HOME_SCREEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
124
src/main/java/forge/gui/menus/HelpMenu.java
Normal file
124
src/main/java/forge/gui/menus/HelpMenu.java
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
package forge.gui.menus;
|
||||||
|
|
||||||
|
import java.awt.Desktop;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.swing.JMenu;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
|
|
||||||
|
import forge.gui.menubar.MenuUtil;
|
||||||
|
import forge.util.FileUtil;
|
||||||
|
|
||||||
|
public final class HelpMenu {
|
||||||
|
private HelpMenu() { }
|
||||||
|
|
||||||
|
public static JMenu getMenu() {
|
||||||
|
JMenu menu = new JMenu("Help");
|
||||||
|
menu.setMnemonic(KeyEvent.VK_H);
|
||||||
|
menu.add(getMenu_GettingStarted());
|
||||||
|
menu.add(getMenu_Articles());
|
||||||
|
menu.add(getMenu_Troubleshooting());
|
||||||
|
menu.addSeparator();
|
||||||
|
menu.add(getMenuItem_ReleaseNotes());
|
||||||
|
menu.add(getMenuItem_License());
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JMenu getMenu_Troubleshooting() {
|
||||||
|
JMenu mnu = new JMenu("Troubleshooting");
|
||||||
|
mnu.add(getMenuItem_UrlLink("How to Provide a Useful Bug Report", "http://www.slightlymagic.net/forum/viewtopic.php?f=26&t=9621"));
|
||||||
|
mnu.addSeparator();
|
||||||
|
mnu.add(getMenuItem_ReadMeFile());
|
||||||
|
return mnu;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JMenu getMenu_Articles() {
|
||||||
|
JMenu mnu = new JMenu("Articles");
|
||||||
|
mnu.add(getMenuItem_UrlLink("HOW-TO: Customize your Sealed Deck games with fantasy blocks", "http://www.slightlymagic.net/forum/viewtopic.php?f=26&t=8164"));
|
||||||
|
mnu.add(getMenuItem_UrlLink("Quest Mode: Guide to Formats, Worlds, and everything", "http://www.slightlymagic.net/forum/viewtopic.php?f=26&t=9258"));
|
||||||
|
return mnu;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JMenu getMenu_GettingStarted() {
|
||||||
|
JMenu mnu = new JMenu("Getting Started");
|
||||||
|
mnu.add(getMenuItem_UrlLink("Forge Wiki", "http://www.slightlymagic.net/wiki/Forge"));
|
||||||
|
mnu.add(getMenuItem_UrlLink("What is Forge?", "http://www.slightlymagic.net/forum/viewtopic.php?f=26&t=468"));
|
||||||
|
return mnu;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JMenuItem getMenuItem_ReadMeFile() {
|
||||||
|
JMenuItem menuItem = new JMenuItem("README.txt");
|
||||||
|
menuItem.addActionListener(getOpenFileAction(getFile("README.txt")));
|
||||||
|
return menuItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JMenuItem getMenuItem_License() {
|
||||||
|
JMenuItem menuItem = new JMenuItem("Forge License");
|
||||||
|
menuItem.addActionListener(getOpenFileAction(getFile("LICENSE.txt")));
|
||||||
|
return menuItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JMenuItem getMenuItem_ReleaseNotes() {
|
||||||
|
JMenuItem menuItem = new JMenuItem("Release Notes");
|
||||||
|
menuItem.addActionListener(getOpenFileAction(getFile("CHANGES.txt")));
|
||||||
|
return menuItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ActionListener getOpenFileAction(final File file) {
|
||||||
|
return new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
try {
|
||||||
|
openFile(file);
|
||||||
|
} catch (IOException e1) {
|
||||||
|
// Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
|
||||||
|
e1.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static File getFile(String filename) {
|
||||||
|
// !! Linux is case-sensitive so file name and extension need to match exactly !!
|
||||||
|
File file = null;
|
||||||
|
String filePath = FileUtil.pathCombine(System.getProperty("user.dir"), filename);
|
||||||
|
if (FileUtil.doesFileExist(filePath)) {
|
||||||
|
file = new File(filePath);
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see http://stackoverflow.com/questions/6273221/open-a-text-file-in-the-default-text-editor-via-java
|
||||||
|
*/
|
||||||
|
private static void openFile(File file) throws IOException {
|
||||||
|
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
|
||||||
|
String cmd = "rundll32 url.dll,FileProtocolHandler " + file.getCanonicalPath();
|
||||||
|
Runtime.getRuntime().exec(cmd);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Desktop.getDesktop().open(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static JMenuItem getMenuItem_UrlLink(String caption, String url) {
|
||||||
|
JMenuItem menuItem = new JMenuItem(caption);
|
||||||
|
menuItem.addActionListener(getLaunchUrlAction(url));
|
||||||
|
return menuItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ActionListener getLaunchUrlAction(final String url) {
|
||||||
|
return new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
MenuUtil.openUrlInBrowser(url);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -19,6 +19,9 @@
|
|||||||
package forge.gui.toolbox.imaging;
|
package forge.gui.toolbox.imaging;
|
||||||
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Image;
|
||||||
|
|
||||||
|
import javax.swing.ImageIcon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Useful general imaging routines.
|
* Useful general imaging routines.
|
||||||
@@ -29,6 +32,12 @@ import java.awt.Dimension;
|
|||||||
public final class ImageUtil {
|
public final class ImageUtil {
|
||||||
private ImageUtil() {}
|
private ImageUtil() {}
|
||||||
|
|
||||||
|
public static ImageIcon getMenuIcon(ImageIcon sourceIcon) {
|
||||||
|
Image img = sourceIcon.getImage();
|
||||||
|
Image newimg = img.getScaledInstance(16, 16, java.awt.Image.SCALE_SMOOTH);
|
||||||
|
return new ImageIcon(newimg);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the nearest rotation for a requested rotation.
|
* Gets the nearest rotation for a requested rotation.
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -2,10 +2,15 @@ package forge.properties;
|
|||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.UnsupportedLookAndFeelException;
|
import javax.swing.UnsupportedLookAndFeelException;
|
||||||
|
import javax.swing.border.Border;
|
||||||
|
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.gui.toolbox.FSkin;
|
import forge.gui.toolbox.FSkin;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
@@ -20,6 +25,8 @@ public final class ForgeLookAndFeel {
|
|||||||
private Color FORE_COLOR = FSkin.getColor(FSkin.Colors.CLR_TEXT);
|
private Color FORE_COLOR = FSkin.getColor(FSkin.Colors.CLR_TEXT);
|
||||||
private Color BACK_COLOR = FSkin.getColor(FSkin.Colors.CLR_THEME2);
|
private Color BACK_COLOR = FSkin.getColor(FSkin.Colors.CLR_THEME2);
|
||||||
private Color HIGHLIGHT_COLOR = BACK_COLOR.brighter();
|
private Color HIGHLIGHT_COLOR = BACK_COLOR.brighter();
|
||||||
|
private Border LINE_BORDER = BorderFactory.createLineBorder(FORE_COLOR.darker(), 1);
|
||||||
|
private Border EMPTY_BORDER = BorderFactory.createEmptyBorder(2,2,2,2);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the look and feel of the GUI based on the selected Forge theme.
|
* Sets the look and feel of the GUI based on the selected Forge theme.
|
||||||
@@ -27,6 +34,7 @@ public final class ForgeLookAndFeel {
|
|||||||
public void setForgeLookAndFeel(JFrame appFrame) {
|
public void setForgeLookAndFeel(JFrame appFrame) {
|
||||||
if (isUIManagerEnabled()) {
|
if (isUIManagerEnabled()) {
|
||||||
if (setMetalLookAndFeel(appFrame)) {
|
if (setMetalLookAndFeel(appFrame)) {
|
||||||
|
setMenusLookAndFeel();
|
||||||
setComboBoxLookAndFeel();
|
setComboBoxLookAndFeel();
|
||||||
setTabbedPaneLookAndFeel();
|
setTabbedPaneLookAndFeel();
|
||||||
setButtonLookAndFeel();
|
setButtonLookAndFeel();
|
||||||
@@ -52,6 +60,56 @@ public final class ForgeLookAndFeel {
|
|||||||
}
|
}
|
||||||
return isMetalLafSet;
|
return isMetalLafSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the look and feel for a JMenuBar, JMenu, JMenuItem & variations.
|
||||||
|
*/
|
||||||
|
private void setMenusLookAndFeel() {
|
||||||
|
// JMenuBar
|
||||||
|
Color clrTheme = FSkin.getColor(FSkin.Colors.CLR_THEME);
|
||||||
|
Color backgroundColor = FSkin.stepColor(clrTheme, 0);
|
||||||
|
Color menuBarEdgeColor = FSkin.stepColor(clrTheme, -80);
|
||||||
|
UIManager.put("MenuBar.foreground", FORE_COLOR);
|
||||||
|
UIManager.put("MenuBar.gradient", getColorGradients(backgroundColor.darker(), backgroundColor));
|
||||||
|
UIManager.put("MenuBar.border", BorderFactory.createMatteBorder(0, 0, 1, 0, menuBarEdgeColor));
|
||||||
|
// JMenu
|
||||||
|
UIManager.put("Menu.foreground", FORE_COLOR);
|
||||||
|
UIManager.put("Menu.background", BACK_COLOR);
|
||||||
|
UIManager.put("Menu.borderPainted", false);
|
||||||
|
UIManager.put("Menu.selectionBackground", HIGHLIGHT_COLOR);
|
||||||
|
UIManager.put("Menu.selectionForeground", FORE_COLOR);
|
||||||
|
UIManager.put("Menu.border", EMPTY_BORDER);
|
||||||
|
UIManager.put("Menu.opaque", false);
|
||||||
|
// JPopupMenu
|
||||||
|
UIManager.put("PopupMenu.border", LINE_BORDER);
|
||||||
|
UIManager.put("PopupMenu.background", BACK_COLOR);
|
||||||
|
UIManager.put("PopupMenu.foreground", FORE_COLOR);
|
||||||
|
// JMenuItem
|
||||||
|
UIManager.put("MenuItem.foreground", FORE_COLOR);
|
||||||
|
UIManager.put("MenuItem.background", BACK_COLOR);
|
||||||
|
UIManager.put("MenuItem.border", EMPTY_BORDER);
|
||||||
|
UIManager.put("MenuItem.selectionBackground", HIGHLIGHT_COLOR);
|
||||||
|
UIManager.put("MenuItem.selectionForeground", FORE_COLOR);
|
||||||
|
UIManager.put("MenuItem.acceleratorForeground", FORE_COLOR.darker());
|
||||||
|
UIManager.put("MenuItem.opaque", true);
|
||||||
|
// JSeparator (needs to be opaque!).
|
||||||
|
UIManager.put("Separator.foreground", FORE_COLOR.darker());
|
||||||
|
UIManager.put("Separator.background", BACK_COLOR);
|
||||||
|
// JRadioButtonMenuItem
|
||||||
|
UIManager.put("RadioButtonMenuItem.foreground", FORE_COLOR);
|
||||||
|
UIManager.put("RadioButtonMenuItem.background", BACK_COLOR);
|
||||||
|
UIManager.put("RadioButtonMenuItem.selectionBackground", HIGHLIGHT_COLOR);
|
||||||
|
UIManager.put("RadioButtonMenuItem.selectionForeground", FORE_COLOR);
|
||||||
|
UIManager.put("RadioButtonMenuItem.border", EMPTY_BORDER);
|
||||||
|
UIManager.put("RadioButtonMenuItem.acceleratorForeground", FORE_COLOR.darker());
|
||||||
|
// JCheckboxMenuItem
|
||||||
|
UIManager.put("CheckBoxMenuItem.foreground", FORE_COLOR);
|
||||||
|
UIManager.put("CheckBoxMenuItem.background", BACK_COLOR);
|
||||||
|
UIManager.put("CheckBoxMenuItem.selectionBackground", HIGHLIGHT_COLOR);
|
||||||
|
UIManager.put("CheckBoxMenuItem.selectionForeground", FORE_COLOR);
|
||||||
|
UIManager.put("CheckBoxMenuItem.border", EMPTY_BORDER);
|
||||||
|
UIManager.put("CheckBoxMenuItem.acceleratorForeground", FORE_COLOR.darker());
|
||||||
|
}
|
||||||
|
|
||||||
private void setTabbedPaneLookAndFeel() {
|
private void setTabbedPaneLookAndFeel() {
|
||||||
UIManager.put("TabbedPane.selected", HIGHLIGHT_COLOR);
|
UIManager.put("TabbedPane.selected", HIGHLIGHT_COLOR);
|
||||||
@@ -95,4 +153,14 @@ public final class ForgeLookAndFeel {
|
|||||||
return FSkin.getFont(UIManager.getFont(component).getSize());
|
return FSkin.getFont(UIManager.getFont(component).getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ArrayList<Object> getColorGradients(Color bottom, Color top) {
|
||||||
|
ArrayList<Object> gradients = new ArrayList<>();
|
||||||
|
gradients.add(0.0);
|
||||||
|
gradients.add(0.0);
|
||||||
|
gradients.add(top);
|
||||||
|
gradients.add(bottom);
|
||||||
|
gradients.add(bottom);
|
||||||
|
return gradients;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ public class ForgePreferences extends PreferencesStore<ForgePreferences.FPref> {
|
|||||||
UI_CLONE_MODE_SOURCE ("false"), /** */
|
UI_CLONE_MODE_SOURCE ("false"), /** */
|
||||||
UI_MATCH_IMAGE_VISIBLE ("true"),
|
UI_MATCH_IMAGE_VISIBLE ("true"),
|
||||||
UI_THEMED_COMBOBOX ("true"),
|
UI_THEMED_COMBOBOX ("true"),
|
||||||
|
UI_HIDE_MENUBAR ("false"), // Dev setting only - cannot be set from GUI.
|
||||||
|
|
||||||
UI_FOR_TOUCHSCREN("false"),
|
UI_FOR_TOUCHSCREN("false"),
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user