From 5ee58d727a1c99b198387b7e034ad55ac081f6ca Mon Sep 17 00:00:00 2001 From: spr Date: Wed, 21 Aug 2013 01:13:26 +0000 Subject: [PATCH] - New forge menu bar (part 1 of 2). Includes common Forge and Help menus. --- .gitattributes | 5 + src/main/java/forge/control/FControl.java | 13 +- .../forge/gui/framework/SResizingUtil.java | 813 +++++++++--------- src/main/java/forge/gui/menubar/FMenuBar.java | 51 ++ .../java/forge/gui/menubar/IMenuProvider.java | 19 + src/main/java/forge/gui/menubar/MenuUtil.java | 61 ++ src/main/java/forge/gui/menus/ForgeMenu.java | 70 ++ src/main/java/forge/gui/menus/HelpMenu.java | 124 +++ .../forge/gui/toolbox/imaging/ImageUtil.java | 9 + .../forge/properties/ForgeLookAndFeel.java | 68 ++ .../forge/properties/ForgePreferences.java | 1 + 11 files changed, 827 insertions(+), 407 deletions(-) create mode 100644 src/main/java/forge/gui/menubar/FMenuBar.java create mode 100644 src/main/java/forge/gui/menubar/IMenuProvider.java create mode 100644 src/main/java/forge/gui/menubar/MenuUtil.java create mode 100644 src/main/java/forge/gui/menus/ForgeMenu.java create mode 100644 src/main/java/forge/gui/menus/HelpMenu.java diff --git a/.gitattributes b/.gitattributes index 6a71c67f353..d9cee3024c1 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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/VStack.java -text 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/toolbox/CardFaceSymbols.java svneol=native#text/plain src/main/java/forge/gui/toolbox/FAbsolutePositioner.java -text diff --git a/src/main/java/forge/control/FControl.java b/src/main/java/forge/control/FControl.java index 3a345e83ee8..efce9c8f6a6 100644 --- a/src/main/java/forge/control/FControl.java +++ b/src/main/java/forge/control/FControl.java @@ -60,6 +60,8 @@ import forge.gui.match.controllers.CMessage; import forge.gui.match.controllers.CStack; import forge.gui.match.nonsingleton.VField; import forge.gui.match.views.VAntes; +import forge.gui.menubar.FMenuBar; +import forge.gui.menubar.MenuUtil; import forge.gui.toolbox.FSkin; import forge.net.FServer; import forge.properties.ForgeLookAndFeel; @@ -81,7 +83,8 @@ import forge.view.FView; */ public enum FControl { instance; - + + private FMenuBar menuBar; private List shortcuts; private JLayeredPane display; private Screens state = Screens.UNKNOWN; @@ -171,6 +174,8 @@ public enum FControl { // and any GUI controls being created. FSkin.setProgessBarMessage("Setting look and feel..."); setForgeLookAndFeel(); + + createMenuBar(); this.shortcuts = KeyboardShortcuts.attachKeyboardShortcuts(); this.display = FView.SINGLETON_INSTANCE.getLpnDocument(); @@ -210,6 +215,12 @@ public enum FControl { ForgeLookAndFeel laf = new ForgeLookAndFeel(); 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. diff --git a/src/main/java/forge/gui/framework/SResizingUtil.java b/src/main/java/forge/gui/framework/SResizingUtil.java index 7bdc95cbcc3..65837a0dd4f 100644 --- a/src/main/java/forge/gui/framework/SResizingUtil.java +++ b/src/main/java/forge/gui/framework/SResizingUtil.java @@ -1,406 +1,407 @@ -package forge.gui.framework; - -import java.awt.Component; -import java.awt.Cursor; -import java.awt.Rectangle; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.ComponentListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionAdapter; -import java.awt.event.MouseMotionListener; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import javax.swing.JPanel; - -import forge.gui.FNetOverlay; -import forge.gui.toolbox.FAbsolutePositioner; -import forge.gui.toolbox.FOverlay; -import forge.view.FView; - -/** - * Package-private utilities for resizing drag behavior using - * the draggable panels registered in FView. - * - *

(S at beginning of class name denotes a static factory.) - */ -public final class SResizingUtil { - private static final List LEFT_PANELS = new ArrayList(); - private static final List RIGHT_PANELS = new ArrayList(); - private static final List TOP_PANELS = new ArrayList(); - private static final List BOTTOM_PANELS = new ArrayList(); - - private static int dX; - private static int evtX; - private static int dY; - private static int evtY; - - /** Minimum cell width. */ - public static final int W_MIN = 100; - /** Minimum cell height. */ - public static final int H_MIN = 75; - - private static final MouseListener MAD_RESIZE_X = new MouseAdapter() { - @Override - public void mouseEntered(final MouseEvent e) { - FView.SINGLETON_INSTANCE.getLpnDocument().setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)); - } - - @Override - public void mouseExited(final MouseEvent e) { - FView.SINGLETON_INSTANCE.getLpnDocument().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - - @Override - public void mousePressed(final MouseEvent e) { - SResizingUtil.startResizeX(e); - } - - @Override - public void mouseReleased(final MouseEvent e) { - SResizingUtil.endResize(); - } - }; - - private static final MouseListener MAD_RESIZE_Y = new MouseAdapter() { - @Override - public void mouseEntered(final MouseEvent e) { - FView.SINGLETON_INSTANCE.getLpnDocument().setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)); - } - - @Override - public void mouseExited(final MouseEvent e) { - FView.SINGLETON_INSTANCE.getLpnDocument().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - - @Override - public void mousePressed(final MouseEvent e) { - SResizingUtil.startResizeY(e); - } - - @Override - public void mouseReleased(final MouseEvent e) { - SResizingUtil.endResize(); - } - }; - - private static final MouseMotionListener MMA_DRAG_X = new MouseMotionAdapter() { - @Override - public void mouseDragged(final MouseEvent e) { - SResizingUtil.resizeX(e); - } - }; - - private static final MouseMotionListener MMA_DRAG_Y = new MouseMotionAdapter() { - @Override - public void mouseDragged(final MouseEvent e) { - SResizingUtil.resizeY(e); - } - }; - - private static final ComponentListener CAD_RESIZE = new ComponentAdapter() { - @Override - public void componentResized(final ComponentEvent e) { - resizeWindow(); - SRearrangingUtil.updateBorders(); - } - }; - - public static void resizeWindow() { - final List cells = FView.SINGLETON_INSTANCE.getDragCells(); - final JPanel pnlContent = FView.SINGLETON_INSTANCE.getPnlContent(); - final JPanel pnlInsets = FView.SINGLETON_INSTANCE.getPnlInsets(); - - Rectangle mainBounds = FView.SINGLETON_INSTANCE.getFrame().getContentPane().getBounds(); - FAbsolutePositioner.SINGLETON_INSTANCE.containerResized(mainBounds); - FOverlay.SINGLETON_INSTANCE.getPanel().setBounds(mainBounds); - FNetOverlay.SINGLETON_INSTANCE.containerResized(mainBounds); - - pnlInsets.setBounds(mainBounds); - pnlInsets.validate(); - - final int w = pnlContent.getWidth(); - final int h = pnlContent.getHeight(); - - double roughVal = 0; - int smoothVal = 0; - - Set existingComponents = new HashSet(); - for (Component c : pnlContent.getComponents()) { - existingComponents.add(c); - } - - // This is the core of the pixel-perfect layout. To avoid ±1 px errors on borders - // from rounding individual panels, the intermediate values (exactly accurate, in %) - // for width and height are rounded based on comparison to other panels in the - // layout. This is to avoid errors such as: - // 10% = 9.8px -> 10px -> x 3 = 30px - // 30% = 29.4px -> 29px (!) - for (final DragCell cellA : cells) { - RectangleOfDouble cellSizeA = cellA.getRoughBounds(); - roughVal = cellSizeA.getX() * w + cellSizeA.getW() * w; - - smoothVal = (int) Math.round(roughVal); - for (final DragCell cellB : cells) { - RectangleOfDouble cellSizeB = cellB.getRoughBounds(); - 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)); - - roughVal = cellSizeA.getY() * h + cellSizeA.getH() * h; - smoothVal = (int) Math.round(roughVal); - for (final DragCell cellB : cells) { - RectangleOfDouble cellSizeB = cellB.getRoughBounds(); - 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)); - - // X and Y coordinate can be rounded as usual. - 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 - if (!existingComponents.contains(cellA)) { - pnlContent.add(cellA); - } - } - - // Lock in final bounds and build heads. - for (final DragCell t : cells) { - t.setSmoothBounds(); - t.validate(); - t.refresh(); - } - - cells.clear(); - } - - /** @param e   {@link java.awt.event.MouseEvent} */ - public static void resizeX(final MouseEvent e) { - dX = (int) e.getLocationOnScreen().getX() - evtX; - evtX = (int) e.getLocationOnScreen().getX(); - 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 : RIGHT_PANELS) { - if ((t.getW() - dX) < W_MIN) { rightLock = true; break; } - } - - 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()); - t.refresh(); - } - - for (final DragCell t : RIGHT_PANELS) { - 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) { - dY = (int) e.getLocationOnScreen().getY() - evtY; - evtY = (int) e.getLocationOnScreen().getY(); - 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 : BOTTOM_PANELS) { - if ((t.getH() - dY) < H_MIN) { bottomLock = true; break; } - } - - 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); - t.revalidate(); - t.repaintSelf(); - } - - for (final DragCell t : BOTTOM_PANELS) { - t.setBounds(t.getX(), t.getY() + dY, t.getW(), t.getH() - dY); - t.revalidate(); - t.repaintSelf(); - } - } - - /** @param e   {@link java.awt.event.MouseEvent} */ - public static void startResizeX(final MouseEvent e) { - evtX = (int) e.getLocationOnScreen().getX(); - LEFT_PANELS.clear(); - RIGHT_PANELS.clear(); - - final DragCell src = (DragCell) ((JPanel) e.getSource()).getParent(); - final int srcX2 = src.getAbsX2(); - - int limTop = -1; - int limBottom = Integer.MAX_VALUE; - int tempX = -1; - int tempX2 = -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. - for (final DragCell t : FView.SINGLETON_INSTANCE.getDragCells()) { - tempX = t.getAbsX(); - tempX2 = t.getAbsX2(); - - 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) { - if (pnlL.equals(src)) { continue; } - tempY = pnlL.getAbsY(); - tempY2 = pnlL.getAbsY2(); - - for (final DragCell pnlR : RIGHT_PANELS) { - // Upper edges match? Set a bottom limit. - 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) { - limTop = tempY2; - } - } - } - - // Remove non-contiguous panels from left side using limits. - final Iterator itrLeft = LEFT_PANELS.iterator(); - while (itrLeft.hasNext()) { - final DragCell t = itrLeft.next(); - - if (t.getAbsY() >= limBottom || t.getAbsY2() <= limTop) { - itrLeft.remove(); - } - } - - // Remove non-contiguous panels from right side using limits. - final Iterator itrRight = RIGHT_PANELS.iterator(); - while (itrRight.hasNext()) { - final DragCell t = itrRight.next(); - - if (t.getAbsY() >= limBottom || t.getAbsY2() <= limTop) { - itrRight.remove(); - } - } - } - - /** @param e   {@link java.awt.event.MouseEvent} */ - public static void startResizeY(final MouseEvent e) { - evtY = (int) e.getLocationOnScreen().getY(); - TOP_PANELS.clear(); - BOTTOM_PANELS.clear(); - - final DragCell src = (DragCell) ((JPanel) e.getSource()).getParent(); - final int srcY2 = src.getAbsY2(); - - int limLeft = -1; - int limRight = Integer.MAX_VALUE; - int tempX = -1; - int tempX2 = -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. - for (final DragCell t : FView.SINGLETON_INSTANCE.getDragCells()) { - tempY = t.getAbsY(); - tempY2 = t.getAbsY2(); - - 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) { - if (pnlT.equals(src)) { continue; } - tempX = pnlT.getAbsX(); - tempX2 = pnlT.getAbsX2(); - - for (final DragCell pnlB : BOTTOM_PANELS) { - // Right edges match? Set a right limit. - 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) { - limLeft = tempX2; - } - } - } - - // Remove non-contiguous panels from left side using limits. - final Iterator itrTop = TOP_PANELS.iterator(); - while (itrTop.hasNext()) { - final DragCell t = itrTop.next(); - if (t.getAbsX() >= limRight || t.getAbsX2() <= limLeft) { - itrTop.remove(); - } - } - - // Remove non-contiguous panels from right side using limits. - final Iterator itrBottom = BOTTOM_PANELS.iterator(); - while (itrBottom.hasNext()) { - final DragCell t = itrBottom.next(); - if (t.getAbsX() >= limRight || t.getAbsX2() <= limLeft) { - itrBottom.remove(); - } - } - } - - /** */ - public static void endResize() { - SLayoutIO.saveLayout(null); - } - - /** @return {@link java.awt.event.MouseListener} */ - public static MouseListener getResizeXListener() { - return MAD_RESIZE_X; - } - - /** @return {@link java.awt.event.MouseListener} */ - public static MouseListener getResizeYListener() { - return MAD_RESIZE_Y; - } - - /** @return {@link java.awt.event.MouseMotionListener} */ - public static MouseMotionListener getDragXListener() { - return MMA_DRAG_X; - } - - /** @return {@link java.awt.event.MouseMotionListener} */ - public static MouseMotionListener getDragYListener() { - return MMA_DRAG_Y; - } - - /** @return {@link java.awt.event.ComponentListener} */ - public static ComponentListener getWindowResizeListener() { - return CAD_RESIZE; - } -} +package forge.gui.framework; + +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Rectangle; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionAdapter; +import java.awt.event.MouseMotionListener; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import javax.swing.JPanel; + +import forge.gui.FNetOverlay; +import forge.gui.toolbox.FAbsolutePositioner; +import forge.gui.toolbox.FOverlay; +import forge.view.FView; + +/** + * Package-private utilities for resizing drag behavior using + * the draggable panels registered in FView. + * + *

(S at beginning of class name denotes a static factory.) + */ +public final class SResizingUtil { + private static final List LEFT_PANELS = new ArrayList(); + private static final List RIGHT_PANELS = new ArrayList(); + private static final List TOP_PANELS = new ArrayList(); + private static final List BOTTOM_PANELS = new ArrayList(); + + private static int dX; + private static int evtX; + private static int dY; + private static int evtY; + + /** Minimum cell width. */ + public static final int W_MIN = 100; + /** Minimum cell height. */ + public static final int H_MIN = 75; + + private static final MouseListener MAD_RESIZE_X = new MouseAdapter() { + @Override + public void mouseEntered(final MouseEvent e) { + FView.SINGLETON_INSTANCE.getLpnDocument().setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)); + } + + @Override + public void mouseExited(final MouseEvent e) { + FView.SINGLETON_INSTANCE.getLpnDocument().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + + @Override + public void mousePressed(final MouseEvent e) { + SResizingUtil.startResizeX(e); + } + + @Override + public void mouseReleased(final MouseEvent e) { + SResizingUtil.endResize(); + } + }; + + private static final MouseListener MAD_RESIZE_Y = new MouseAdapter() { + @Override + public void mouseEntered(final MouseEvent e) { + FView.SINGLETON_INSTANCE.getLpnDocument().setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)); + } + + @Override + public void mouseExited(final MouseEvent e) { + FView.SINGLETON_INSTANCE.getLpnDocument().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + + @Override + public void mousePressed(final MouseEvent e) { + SResizingUtil.startResizeY(e); + } + + @Override + public void mouseReleased(final MouseEvent e) { + SResizingUtil.endResize(); + } + }; + + private static final MouseMotionListener MMA_DRAG_X = new MouseMotionAdapter() { + @Override + public void mouseDragged(final MouseEvent e) { + SResizingUtil.resizeX(e); + } + }; + + private static final MouseMotionListener MMA_DRAG_Y = new MouseMotionAdapter() { + @Override + public void mouseDragged(final MouseEvent e) { + SResizingUtil.resizeY(e); + } + }; + + private static final ComponentListener CAD_RESIZE = new ComponentAdapter() { + @Override + public void componentResized(final ComponentEvent e) { + resizeWindow(); + SRearrangingUtil.updateBorders(); + } + }; + + public static void resizeWindow() { + final List cells = FView.SINGLETON_INSTANCE.getDragCells(); + final JPanel pnlContent = FView.SINGLETON_INSTANCE.getPnlContent(); + final JPanel pnlInsets = FView.SINGLETON_INSTANCE.getPnlInsets(); + + Rectangle mainBounds = FView.SINGLETON_INSTANCE.getFrame().getContentPane().getBounds(); + mainBounds.y = 0; // Play nicely with MenuBar if visible or not. + FAbsolutePositioner.SINGLETON_INSTANCE.containerResized(mainBounds); + FOverlay.SINGLETON_INSTANCE.getPanel().setBounds(mainBounds); + FNetOverlay.SINGLETON_INSTANCE.containerResized(mainBounds); + + pnlInsets.setBounds(mainBounds); + pnlInsets.validate(); + + final int w = pnlContent.getWidth(); + final int h = pnlContent.getHeight(); + + double roughVal = 0; + int smoothVal = 0; + + Set existingComponents = new HashSet(); + for (Component c : pnlContent.getComponents()) { + existingComponents.add(c); + } + + // This is the core of the pixel-perfect layout. To avoid ±1 px errors on borders + // from rounding individual panels, the intermediate values (exactly accurate, in %) + // for width and height are rounded based on comparison to other panels in the + // layout. This is to avoid errors such as: + // 10% = 9.8px -> 10px -> x 3 = 30px + // 30% = 29.4px -> 29px (!) + for (final DragCell cellA : cells) { + RectangleOfDouble cellSizeA = cellA.getRoughBounds(); + roughVal = cellSizeA.getX() * w + cellSizeA.getW() * w; + + smoothVal = (int) Math.round(roughVal); + for (final DragCell cellB : cells) { + RectangleOfDouble cellSizeB = cellB.getRoughBounds(); + 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)); + + roughVal = cellSizeA.getY() * h + cellSizeA.getH() * h; + smoothVal = (int) Math.round(roughVal); + for (final DragCell cellB : cells) { + RectangleOfDouble cellSizeB = cellB.getRoughBounds(); + 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)); + + // X and Y coordinate can be rounded as usual. + 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 + if (!existingComponents.contains(cellA)) { + pnlContent.add(cellA); + } + } + + // Lock in final bounds and build heads. + for (final DragCell t : cells) { + t.setSmoothBounds(); + t.validate(); + t.refresh(); + } + + cells.clear(); + } + + /** @param e   {@link java.awt.event.MouseEvent} */ + public static void resizeX(final MouseEvent e) { + dX = (int) e.getLocationOnScreen().getX() - evtX; + evtX = (int) e.getLocationOnScreen().getX(); + 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 : RIGHT_PANELS) { + if ((t.getW() - dX) < W_MIN) { rightLock = true; break; } + } + + 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()); + t.refresh(); + } + + for (final DragCell t : RIGHT_PANELS) { + 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) { + dY = (int) e.getLocationOnScreen().getY() - evtY; + evtY = (int) e.getLocationOnScreen().getY(); + 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 : BOTTOM_PANELS) { + if ((t.getH() - dY) < H_MIN) { bottomLock = true; break; } + } + + 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); + t.revalidate(); + t.repaintSelf(); + } + + for (final DragCell t : BOTTOM_PANELS) { + t.setBounds(t.getX(), t.getY() + dY, t.getW(), t.getH() - dY); + t.revalidate(); + t.repaintSelf(); + } + } + + /** @param e   {@link java.awt.event.MouseEvent} */ + public static void startResizeX(final MouseEvent e) { + evtX = (int) e.getLocationOnScreen().getX(); + LEFT_PANELS.clear(); + RIGHT_PANELS.clear(); + + final DragCell src = (DragCell) ((JPanel) e.getSource()).getParent(); + final int srcX2 = src.getAbsX2(); + + int limTop = -1; + int limBottom = Integer.MAX_VALUE; + int tempX = -1; + int tempX2 = -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. + for (final DragCell t : FView.SINGLETON_INSTANCE.getDragCells()) { + tempX = t.getAbsX(); + tempX2 = t.getAbsX2(); + + 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) { + if (pnlL.equals(src)) { continue; } + tempY = pnlL.getAbsY(); + tempY2 = pnlL.getAbsY2(); + + for (final DragCell pnlR : RIGHT_PANELS) { + // Upper edges match? Set a bottom limit. + 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) { + limTop = tempY2; + } + } + } + + // Remove non-contiguous panels from left side using limits. + final Iterator itrLeft = LEFT_PANELS.iterator(); + while (itrLeft.hasNext()) { + final DragCell t = itrLeft.next(); + + if (t.getAbsY() >= limBottom || t.getAbsY2() <= limTop) { + itrLeft.remove(); + } + } + + // Remove non-contiguous panels from right side using limits. + final Iterator itrRight = RIGHT_PANELS.iterator(); + while (itrRight.hasNext()) { + final DragCell t = itrRight.next(); + + if (t.getAbsY() >= limBottom || t.getAbsY2() <= limTop) { + itrRight.remove(); + } + } + } + + /** @param e   {@link java.awt.event.MouseEvent} */ + public static void startResizeY(final MouseEvent e) { + evtY = (int) e.getLocationOnScreen().getY(); + TOP_PANELS.clear(); + BOTTOM_PANELS.clear(); + + final DragCell src = (DragCell) ((JPanel) e.getSource()).getParent(); + final int srcY2 = src.getAbsY2(); + + int limLeft = -1; + int limRight = Integer.MAX_VALUE; + int tempX = -1; + int tempX2 = -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. + for (final DragCell t : FView.SINGLETON_INSTANCE.getDragCells()) { + tempY = t.getAbsY(); + tempY2 = t.getAbsY2(); + + 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) { + if (pnlT.equals(src)) { continue; } + tempX = pnlT.getAbsX(); + tempX2 = pnlT.getAbsX2(); + + for (final DragCell pnlB : BOTTOM_PANELS) { + // Right edges match? Set a right limit. + 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) { + limLeft = tempX2; + } + } + } + + // Remove non-contiguous panels from left side using limits. + final Iterator itrTop = TOP_PANELS.iterator(); + while (itrTop.hasNext()) { + final DragCell t = itrTop.next(); + if (t.getAbsX() >= limRight || t.getAbsX2() <= limLeft) { + itrTop.remove(); + } + } + + // Remove non-contiguous panels from right side using limits. + final Iterator itrBottom = BOTTOM_PANELS.iterator(); + while (itrBottom.hasNext()) { + final DragCell t = itrBottom.next(); + if (t.getAbsX() >= limRight || t.getAbsX2() <= limLeft) { + itrBottom.remove(); + } + } + } + + /** */ + public static void endResize() { + SLayoutIO.saveLayout(null); + } + + /** @return {@link java.awt.event.MouseListener} */ + public static MouseListener getResizeXListener() { + return MAD_RESIZE_X; + } + + /** @return {@link java.awt.event.MouseListener} */ + public static MouseListener getResizeYListener() { + return MAD_RESIZE_Y; + } + + /** @return {@link java.awt.event.MouseMotionListener} */ + public static MouseMotionListener getDragXListener() { + return MMA_DRAG_X; + } + + /** @return {@link java.awt.event.MouseMotionListener} */ + public static MouseMotionListener getDragYListener() { + return MMA_DRAG_Y; + } + + /** @return {@link java.awt.event.ComponentListener} */ + public static ComponentListener getWindowResizeListener() { + return CAD_RESIZE; + } +} diff --git a/src/main/java/forge/gui/menubar/FMenuBar.java b/src/main/java/forge/gui/menubar/FMenuBar.java new file mode 100644 index 00000000000..6032fc4d881 --- /dev/null +++ b/src/main/java/forge/gui/menubar/FMenuBar.java @@ -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. + *

+ * Note: Disabling a component does not disable its children. + */ + public void setMenuBarEnabled(boolean isEnabled) { + setEnabled(isEnabled); + for (Component c : getComponents()) { + c.setEnabled(isEnabled); + } + } + +} diff --git a/src/main/java/forge/gui/menubar/IMenuProvider.java b/src/main/java/forge/gui/menubar/IMenuProvider.java new file mode 100644 index 00000000000..061aacf03c3 --- /dev/null +++ b/src/main/java/forge/gui/menubar/IMenuProvider.java @@ -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 getMenus(); + +} diff --git a/src/main/java/forge/gui/menubar/MenuUtil.java b/src/main/java/forge/gui/menubar/MenuUtil.java new file mode 100644 index 00000000000..35912930709 --- /dev/null +++ b/src/main/java/forge/gui/menubar/MenuUtil.java @@ -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); + } + +} diff --git a/src/main/java/forge/gui/menus/ForgeMenu.java b/src/main/java/forge/gui/menus/ForgeMenu.java new file mode 100644 index 00000000000..50019ff512c --- /dev/null +++ b/src/main/java/forge/gui/menus/ForgeMenu.java @@ -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; + } + +} diff --git a/src/main/java/forge/gui/menus/HelpMenu.java b/src/main/java/forge/gui/menus/HelpMenu.java new file mode 100644 index 00000000000..7a3264cd298 --- /dev/null +++ b/src/main/java/forge/gui/menus/HelpMenu.java @@ -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); + } + }; + } + +} diff --git a/src/main/java/forge/gui/toolbox/imaging/ImageUtil.java b/src/main/java/forge/gui/toolbox/imaging/ImageUtil.java index 5a5de1f8cd4..a943521e6fc 100644 --- a/src/main/java/forge/gui/toolbox/imaging/ImageUtil.java +++ b/src/main/java/forge/gui/toolbox/imaging/ImageUtil.java @@ -19,6 +19,9 @@ package forge.gui.toolbox.imaging; import java.awt.Dimension; +import java.awt.Image; + +import javax.swing.ImageIcon; /** * Useful general imaging routines. @@ -29,6 +32,12 @@ import java.awt.Dimension; public final class 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. *

diff --git a/src/main/java/forge/properties/ForgeLookAndFeel.java b/src/main/java/forge/properties/ForgeLookAndFeel.java index b24b315d15e..9d2e51ea9e3 100644 --- a/src/main/java/forge/properties/ForgeLookAndFeel.java +++ b/src/main/java/forge/properties/ForgeLookAndFeel.java @@ -2,10 +2,15 @@ package forge.properties; import java.awt.Color; import java.awt.Font; +import java.util.ArrayList; + +import javax.swing.BorderFactory; import javax.swing.JFrame; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.border.Border; + import forge.Singletons; import forge.gui.toolbox.FSkin; 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 BACK_COLOR = FSkin.getColor(FSkin.Colors.CLR_THEME2); 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. @@ -27,6 +34,7 @@ public final class ForgeLookAndFeel { public void setForgeLookAndFeel(JFrame appFrame) { if (isUIManagerEnabled()) { if (setMetalLookAndFeel(appFrame)) { + setMenusLookAndFeel(); setComboBoxLookAndFeel(); setTabbedPaneLookAndFeel(); setButtonLookAndFeel(); @@ -52,6 +60,56 @@ public final class ForgeLookAndFeel { } 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() { UIManager.put("TabbedPane.selected", HIGHLIGHT_COLOR); @@ -95,4 +153,14 @@ public final class ForgeLookAndFeel { return FSkin.getFont(UIManager.getFont(component).getSize()); } + private ArrayList getColorGradients(Color bottom, Color top) { + ArrayList gradients = new ArrayList<>(); + gradients.add(0.0); + gradients.add(0.0); + gradients.add(top); + gradients.add(bottom); + gradients.add(bottom); + return gradients; + } + } diff --git a/src/main/java/forge/properties/ForgePreferences.java b/src/main/java/forge/properties/ForgePreferences.java index a76344cf22b..1d579414b91 100644 --- a/src/main/java/forge/properties/ForgePreferences.java +++ b/src/main/java/forge/properties/ForgePreferences.java @@ -61,6 +61,7 @@ public class ForgePreferences extends PreferencesStore { UI_CLONE_MODE_SOURCE ("false"), /** */ UI_MATCH_IMAGE_VISIBLE ("true"), UI_THEMED_COMBOBOX ("true"), + UI_HIDE_MENUBAR ("false"), // Dev setting only - cannot be set from GUI. UI_FOR_TOUCHSCREN("false"),