- make button-like FLabels act more like buttons

- can tab focus
  - space/enter to select
  - brighten on hover
- use previous "hover" border for focus indicator
- fix various layout and style bugs (e.g. too-short widths and missing hoverable properties)
This commit is contained in:
myk
2013-02-07 21:31:42 +00:00
parent ead67174e2
commit b08eaf18f5
13 changed files with 81 additions and 47 deletions

View File

@@ -68,7 +68,7 @@ public class PlayerOutcome {
switch(lossState){ switch(lossState){
case Conceded: return "conceded"; case Conceded: return "conceded";
case Milled: return "lost trying to draw cards from empty library"; case Milled: return "lost trying to draw cards from empty library";
case LifeReachedZero: return "lost because ran out of lives"; case LifeReachedZero: return "lost because life total reached 0";
case Poisoned: return "lost because of obtaining 10 poison counters"; case Poisoned: return "lost because of obtaining 10 poison counters";
case OpponentWon: return "lost because an opponent has won by spell '" + loseConditionSpell + "'"; case OpponentWon: return "lost because an opponent has won by spell '" + loseConditionSpell + "'";
case SpellEffect: return "lost due to effect of spell '" + loseConditionSpell + "'"; case SpellEffect: return "lost due to effect of spell '" + loseConditionSpell + "'";

View File

@@ -107,6 +107,11 @@ public enum CDeckEditorUI implements CardContainer {
private void moveSelectedCards( private void moveSelectedCards(
EditorTableView<InventoryItem> table, _MoveAction moveAction, int maxQty) { EditorTableView<InventoryItem> table, _MoveAction moveAction, int maxQty) {
List<InventoryItem> items = table.getSelectedCards(); List<InventoryItem> items = table.getSelectedCards();
if (items.isEmpty()) {
return;
}
for (InventoryItem item : items) { for (InventoryItem item : items) {
moveAction.move(item, Math.min(maxQty, table.getCardCount(item))); moveAction.move(item, Math.min(maxQty, table.getCardCount(item)));
} }

View File

@@ -45,7 +45,7 @@ public enum VCurrentDeck implements IVDoc<CCurrentDeck>, ITableContainer {
.fontSize(14) .fontSize(14)
.tooltip("Save (in default directory)") .tooltip("Save (in default directory)")
.iconInBackground(true) .iconInBackground(true)
.iconAlignX(SwingConstants.CENTER).iconAlpha(1.0f) .iconAlignX(SwingConstants.CENTER)
.icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_SAVE)) .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_SAVE))
.text(" ").hoverable(true).build(); .text(" ").hoverable(true).build();
@@ -53,7 +53,7 @@ public enum VCurrentDeck implements IVDoc<CCurrentDeck>, ITableContainer {
.fontSize(14) .fontSize(14)
.tooltip("Save As") .tooltip("Save As")
.iconInBackground(true) .iconInBackground(true)
.iconAlignX(SwingConstants.CENTER).iconAlpha(1.0f) .iconAlignX(SwingConstants.CENTER)
.icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_SAVEAS)) .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_SAVEAS))
.text(" ").hoverable(true).build(); .text(" ").hoverable(true).build();
@@ -61,7 +61,7 @@ public enum VCurrentDeck implements IVDoc<CCurrentDeck>, ITableContainer {
.fontSize(14) .fontSize(14)
.tooltip("Load") .tooltip("Load")
.iconInBackground(true) .iconInBackground(true)
.iconAlignX(SwingConstants.CENTER).iconAlpha(1.0f) .iconAlignX(SwingConstants.CENTER)
.icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_OPEN)) .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_OPEN))
.text(" ").hoverable(true).build(); .text(" ").hoverable(true).build();
@@ -69,7 +69,7 @@ public enum VCurrentDeck implements IVDoc<CCurrentDeck>, ITableContainer {
.fontSize(14) .fontSize(14)
.tooltip("New Deck") .tooltip("New Deck")
.iconInBackground(true) .iconInBackground(true)
.iconAlignX(SwingConstants.CENTER).iconAlpha(1.0f) .iconAlignX(SwingConstants.CENTER)
.icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_NEW)) .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_NEW))
.text(" ").hoverable(true).build(); .text(" ").hoverable(true).build();
@@ -77,7 +77,7 @@ public enum VCurrentDeck implements IVDoc<CCurrentDeck>, ITableContainer {
.fontSize(14) .fontSize(14)
.tooltip("Print Proxies") .tooltip("Print Proxies")
.iconInBackground(true) .iconInBackground(true)
.iconAlignX(SwingConstants.CENTER).iconAlpha(1.0f) .iconAlignX(SwingConstants.CENTER)
.icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_PRINT)) .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_PRINT))
.text(" ").hoverable(true).build(); .text(" ").hoverable(true).build();
@@ -89,21 +89,21 @@ public enum VCurrentDeck implements IVDoc<CCurrentDeck>, ITableContainer {
.text("Remove card") .text("Remove card")
.tooltip("Remove selected card from current deck (or double click the row or hit the spacebar)") .tooltip("Remove selected card from current deck (or double click the row or hit the spacebar)")
.icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_MINUS)) .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_MINUS))
.iconScaleAuto(false).hoverable(true).build(); .iconScaleAuto(false).hoverable().build();
private final FLabel btnRemove4 = new FLabel.Builder() private final FLabel btnRemove4 = new FLabel.Builder()
.fontSize(14) .fontSize(14)
.text("Remove 4 of card") .text("Remove 4 of card")
.tooltip("Remove up to 4 of selected card to current deck") .tooltip("Remove up to 4 of selected card to current deck")
.icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_MINUS)) .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_MINUS))
.iconScaleAuto(false).hoverable(true).build(); .iconScaleAuto(false).hoverable().build();
private final JLabel btnDoSideboard = new FLabel.Builder() private final JLabel btnDoSideboard = new FLabel.Builder()
.fontSize(14) .fontSize(14)
.text("Deck/Sideboard") .text("Deck/Sideboard")
.tooltip("Edit the sideboard for this deck") .tooltip("Toggle between editing the deck and the sideboard for this deck")
.icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_EDIT)) .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_EDIT))
.iconScaleAuto(false).hoverable(true).build(); .iconScaleAuto(false).hoverable().build();
private final JTextField txfTitle = new FTextField.Builder().text("[New Deck]").build(); private final JTextField txfTitle = new FTextField.Builder().text("[New Deck]").build();

View File

@@ -108,7 +108,7 @@ public enum VSubmenuGauntletBuild implements IVSubmenu<CSubmenuGauntletBuild> {
.fontSize(14) .fontSize(14)
.tooltip("Save this gauntlet") .tooltip("Save this gauntlet")
.iconInBackground(true) .iconInBackground(true)
.iconAlignX(SwingConstants.CENTER).iconAlpha(1.0f) .iconAlignX(SwingConstants.CENTER)
.icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_SAVE)) .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_SAVE))
.text(" ").hoverable(true).build(); .text(" ").hoverable(true).build();
@@ -116,7 +116,7 @@ public enum VSubmenuGauntletBuild implements IVSubmenu<CSubmenuGauntletBuild> {
.fontSize(14) .fontSize(14)
.tooltip("Build a new gauntlet") .tooltip("Build a new gauntlet")
.iconInBackground(true) .iconInBackground(true)
.iconAlignX(SwingConstants.CENTER).iconAlpha(1.0f) .iconAlignX(SwingConstants.CENTER)
.icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_NEW)) .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_NEW))
.text(" ").hoverable(true).build(); .text(" ").hoverable(true).build();
@@ -124,7 +124,7 @@ public enum VSubmenuGauntletBuild implements IVSubmenu<CSubmenuGauntletBuild> {
.fontSize(14) .fontSize(14)
.tooltip("Load a gauntlet") .tooltip("Load a gauntlet")
.iconInBackground(true) .iconInBackground(true)
.iconAlignX(SwingConstants.CENTER).iconAlpha(1.0f) .iconAlignX(SwingConstants.CENTER)
.icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_OPEN)) .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_OPEN))
.text(" ").hoverable(true).build(); .text(" ").hoverable(true).build();

View File

@@ -50,7 +50,7 @@ public enum VSubmenuConstructed implements IVSubmenu<CSubmenuConstructed> {
lblTitle.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2)); lblTitle.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
final String strCheckboxConstraints = "w 200px!, h 30px!, gap 0 20px 0 0"; final String strCheckboxConstraints = "h 30px!, gap 0 20px 0 0";
pnlStart.setOpaque(false); pnlStart.setOpaque(false);
pnlStart.add(cbSingletons, strCheckboxConstraints); pnlStart.add(cbSingletons, strCheckboxConstraints);
pnlStart.add(btnStart, "span 1 3, growx, pushx, align center"); pnlStart.add(btnStart, "span 1 3, growx, pushx, align center");

View File

@@ -151,7 +151,7 @@ public enum VSubmenuAvatars implements IVSubmenu<CSubmenuAvatars> {
@SuppressWarnings("serial") @SuppressWarnings("serial")
private FLabel makeAvatarLabel(final Image img0, final int index0) { private FLabel makeAvatarLabel(final Image img0, final int index0) {
final FLabel lbl = new FLabel.Builder().icon(new ImageIcon(img0)).iconScaleFactor(1.0) final FLabel lbl = new FLabel.Builder().icon(new ImageIcon(img0)).iconScaleFactor(1.0)
.iconAlpha(0.7f).iconInBackground(true).hoverable(true).build(); .iconInBackground(true).hoverable(true).build();
final Dimension size = new Dimension(100, 100); final Dimension size = new Dimension(100, 100);
lbl.setPreferredSize(size); lbl.setPreferredSize(size);

View File

@@ -165,7 +165,7 @@ public enum VSubmenuArchenemy implements IVSubmenu<CSubmenuArchenemy> {
} }
} }
final String strCheckboxConstraints = "w 200px!, h 30px!, gap 0 20px 0 0"; final String strCheckboxConstraints = "h 30px!, gap 0 20px 0 0";
pnlStart.setOpaque(false); pnlStart.setOpaque(false);
pnlStart.add(cbSingletons, strCheckboxConstraints); pnlStart.add(cbSingletons, strCheckboxConstraints);
pnlStart.add(btnStart, "span 1 3, growx, pushx, align center"); pnlStart.add(btnStart, "span 1 3, growx, pushx, align center");

View File

@@ -161,7 +161,7 @@ public enum VSubmenuPlanechase implements IVSubmenu<CSubmenuPlanechase> {
} }
} }
final String strCheckboxConstraints = "w 200px!, h 30px!, gap 0 20px 0 0"; final String strCheckboxConstraints = "h 30px!, gap 0 20px 0 0";
pnlStart.setOpaque(false); pnlStart.setOpaque(false);
pnlStart.add(cbSingletons, strCheckboxConstraints); pnlStart.add(cbSingletons, strCheckboxConstraints);
pnlStart.add(btnStart, "span 1 3, growx, pushx, align center"); pnlStart.add(btnStart, "span 1 3, growx, pushx, align center");

View File

@@ -203,7 +203,7 @@ public enum VSubmenuVanguard implements IVSubmenu<CSubmenuVanguard> {
} }
} }
final String strCheckboxConstraints = "w 200px!, h 30px!, gap 0 20px 0 0"; final String strCheckboxConstraints = "h 30px!, gap 0 20px 0 0";
pnlStart.setOpaque(false); pnlStart.setOpaque(false);
pnlStart.add(cbSingletons, strCheckboxConstraints); pnlStart.add(cbSingletons, strCheckboxConstraints);
pnlStart.add(btnStart, "span 1 3, growx, pushx, align center"); pnlStart.add(btnStart, "span 1 3, growx, pushx, align center");

View File

@@ -120,7 +120,6 @@ public class ControlWinLose {
for (Player p : Singletons.getModel().getGame().getRegisteredPlayers()) { for (Player p : Singletons.getModel().getGame().getRegisteredPlayers()) {
if (!p.getName().equals(lastGame.getWinner().getName())) { if (!p.getName().equals(lastGame.getWinner().getName())) {
continue; // not a loser continue; // not a loser
} }

View File

@@ -192,7 +192,12 @@ public class CField implements ICDoc {
((FLabel) this.view.getLblExile()).setHoverable(true); ((FLabel) this.view.getLblExile()).setHoverable(true);
this.view.getLblExile().addMouseListener(madExiled); this.view.getLblExile().addMouseListener(madExiled);
if (Preferences.DEV_MODE) {
((FLabel) this.view.getLblLibrary()).setHoverable(true);
}
this.view.getLblLibrary().addMouseListener(madLibrary); this.view.getLblLibrary().addMouseListener(madLibrary);
((FLabel) this.view.getLblHand()).setHoverable(true);
this.view.getLblHand().addMouseListener(madHand); this.view.getLblHand().addMouseListener(madHand);
((FLabel) this.view.getLblFlashback()).setHoverable(true); ((FLabel) this.view.getLblFlashback()).setHoverable(true);
@@ -208,11 +213,9 @@ public class CField implements ICDoc {
this.view.getLblGreen().addMouseListener(madGreen); this.view.getLblGreen().addMouseListener(madGreen);
((FLabel) this.view.getLblRed()).setHoverable(true); ((FLabel) this.view.getLblRed()).setHoverable(true);
this.view.getLblRed().removeMouseListener(madRed);
this.view.getLblRed().addMouseListener(madRed); this.view.getLblRed().addMouseListener(madRed);
((FLabel) this.view.getLblWhite()).setHoverable(true); ((FLabel) this.view.getLblWhite()).setHoverable(true);
this.view.getLblWhite().removeMouseListener(madWhite);
this.view.getLblWhite().addMouseListener(madWhite); this.view.getLblWhite().addMouseListener(madWhite);
((FLabel) this.view.getLblColorless()).setHoverable(true); ((FLabel) this.view.getLblColorless()).setHoverable(true);

View File

@@ -313,7 +313,7 @@ public class VField implements IVDoc<CField> {
private FLabel getBuiltFLabel(SkinProp p0, String s0, String s1) { private FLabel getBuiltFLabel(SkinProp p0, String s0, String s1) {
return new FLabel.Builder().icon(new ImageIcon(FSkin.getImage(p0))) return new FLabel.Builder().icon(new ImageIcon(FSkin.getImage(p0)))
.opaque(false).fontSize(14) .opaque(false).fontSize(14)
.fontStyle(Font.BOLD).iconAlpha(0.6f).iconInBackground(true) .fontStyle(Font.BOLD).iconInBackground()
.text(s0).tooltip(s1).fontAlign(SwingConstants.RIGHT).build(); .text(s0).tooltip(s1).fontAlign(SwingConstants.RIGHT).build();
} }

View File

@@ -14,6 +14,10 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter; import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent; import java.awt.event.ComponentEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter; import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
@@ -57,7 +61,7 @@ public class FLabel extends JLabel implements ILocalRepaint {
private double bldIconScaleFactor = 0.8; private double bldIconScaleFactor = 0.8;
private int bldFontStyle = Font.PLAIN; private int bldFontStyle = Font.PLAIN;
private int bldFontSize = 14; private int bldFontSize = 14;
private float bldIconAlpha = 1.0f; private float bldUnhoveredAlpha = 0.7f;
private int bldIconAlignX = SwingConstants.LEFT; private int bldIconAlignX = SwingConstants.LEFT;
private Point bldIconInsets = new Point(0, 0); private Point bldIconInsets = new Point(0, 0);
@@ -143,10 +147,11 @@ public class FLabel extends JLabel implements ILocalRepaint {
/**@param b0 &emsp; boolean, icon will be drawn independent of text /**@param b0 &emsp; boolean, icon will be drawn independent of text
* @return {@link forge.gui.toolbox.Builder} */ * @return {@link forge.gui.toolbox.Builder} */
public Builder iconInBackground(final boolean b0) { this.bldIconInBackground = b0; return this; } public Builder iconInBackground(final boolean b0) { this.bldIconInBackground = b0; return this; }
public Builder iconInBackground() { iconInBackground(true); return this; }
/**@param f0 &emsp; 0.0f - 1.0f. If icon is in background, this alpha is applied. /**@param f0 &emsp; 0.0f - 1.0f. alpha factor applied when label is hoverable but not currently hovered.
* @return {@link forge.gui.toolbox.Builder} */ * @return {@link forge.gui.toolbox.Builder} */
public Builder iconAlpha(final float f0) { this.bldIconAlpha = f0; return this; } public Builder unhoveredAlpha(final float f0) { this.bldUnhoveredAlpha = f0; return this; }
/**@param i0 &emsp; Int. Only available for background icon. /**@param i0 &emsp; Int. Only available for background icon.
* SwingConstants.HORIZONTAL .VERTICAL or .CENTER * SwingConstants.HORIZONTAL .VERTICAL or .CENTER
@@ -188,16 +193,33 @@ public class FLabel extends JLabel implements ILocalRepaint {
this.setFontStyle(b0.bldFontStyle); this.setFontStyle(b0.bldFontStyle);
this.setFontSize(b0.bldFontSize); this.setFontSize(b0.bldFontSize);
this.setIconAlpha(b0.bldIconAlpha); this.setUnhoveredAlpha(b0.bldUnhoveredAlpha);
this.setCommand(b0.bldCmd); this.setCommand(b0.bldCmd);
this.setReactOnMouseDown(b0.reactOnMouseDown); this.setReactOnMouseDown(b0.reactOnMouseDown);
this.setFontAlign(b0.bldFontAlign); this.setFontAlign(b0.bldFontAlign);
this.setToolTipText(b0.bldToolTip); this.setToolTipText(b0.bldToolTip);
this.setHoverable(b0.bldHoverable); this.setHoverable(b0.bldHoverable);
// Call this last; to allow the properties which affect icons to already be in place. // Call this last; to allow the properties which affect icons to already be in place.
this.setIcon(b0.bldIcon); this.setIcon(b0.bldIcon);
// If the label has button-like properties, interpret keypresses like a button
if (b0.bldSelectable || b0.bldHoverable) {
this.setFocusable(true);
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(final KeyEvent e) {
if (e.getKeyChar() == ' ' || e.getKeyCode() == 10) { _doMouseAction(); }
}
});
this.addFocusListener(new FocusListener() {
@Override public void focusLost(FocusEvent arg0) { repaintSelf(); }
@Override public void focusGained(FocusEvent arg0) { repaintSelf(); }
});
}
// Non-custom display properties // Non-custom display properties
this.setForeground(clrText); this.setForeground(clrText);
this.setBackground(clrMain); this.setBackground(clrMain);
@@ -269,25 +291,23 @@ public class FLabel extends JLabel implements ILocalRepaint {
} }
}; };
private void _doMouseAction() {
if (selectable) { setSelected(!selected); }
if (cmdClick != null && FLabel.this.isEnabled()) { cmdClick.execute(); }
}
// Mouse event handler // Mouse event handler
private final MouseAdapter madEvents = new MouseAdapter() { private final MouseAdapter madEvents = new MouseAdapter() {
@Override @Override
public void mouseEntered(final MouseEvent e) { public void mouseEntered(final MouseEvent e) {
if (hoverable) { hovered = true;
hovered = true; repaintSelf(); repaintSelf();
}
} }
@Override @Override
public void mouseExited(final MouseEvent e) { public void mouseExited(final MouseEvent e) {
if (hoverable) { hovered = false;
hovered = false; repaintSelf(); repaintSelf();
}
}
private void _doMouseAction() {
if (selectable) { setSelected(!selected); }
if (cmdClick != null && FLabel.this.isEnabled()) { cmdClick.execute(); }
} }
@Override @Override
@@ -328,7 +348,7 @@ public class FLabel extends JLabel implements ILocalRepaint {
/** Sets alpha if icon is in background. /** Sets alpha if icon is in background.
* @param f0 &emsp; float */ * @param f0 &emsp; float */
// NOT public; must be set when label is built. // NOT public; must be set when label is built.
private void setIconAlpha(final float f0) { private void setUnhoveredAlpha(final float f0) {
this.alphaDim = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, f0); this.alphaDim = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, f0);
this.alphaStrong = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f); this.alphaStrong = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f);
} }
@@ -426,6 +446,12 @@ public class FLabel extends JLabel implements ILocalRepaint {
int w = getWidth(); int w = getWidth();
int h = getHeight(); int h = getHeight();
boolean paintWithHover = hoverable && hovered && isEnabled();
Composite oldComp = g2d.getComposite();
if (hoverable) {
g2d.setComposite(paintWithHover ? alphaStrong : alphaDim);
}
if (opaque) { if (opaque) {
if (selected) { if (selected) {
paintDown(g2d, w, h); paintDown(g2d, w, h);
@@ -440,10 +466,6 @@ public class FLabel extends JLabel implements ILocalRepaint {
} }
} }
if (hoverable && hovered && isEnabled()) {
paintHover(g2d, w, h);
}
// Icon in background // Icon in background
if (iconInBackground) { if (iconInBackground) {
int sh = (int) (h * iconScaleFactor); int sh = (int) (h * iconScaleFactor);
@@ -455,16 +477,21 @@ public class FLabel extends JLabel implements ILocalRepaint {
int y = (int) (((h - sh) / 2) + iconInsets.getY()); int y = (int) (((h - sh) / 2) + iconInsets.getY());
Composite oldComp = g2d.getComposite();
g2d.setComposite(hoverable && hovered && !selected ? alphaStrong : alphaDim);
g2d.drawImage(img, x, y, sw + x, sh + y, 0, 0, iw, ih, null); g2d.drawImage(img, x, y, sw + x, sh + y, 0, 0, iw, ih, null);
g2d.setComposite(oldComp);
} }
super.paintComponent(g); super.paintComponent(g);
if (hoverable) {
g2d.setComposite(oldComp);
}
if (hasFocus() && isEnabled()) {
paintFocus(g2d, w, h);
}
} }
private void paintHover(final Graphics2D g, int w, int h) { private void paintFocus(final Graphics2D g, int w, int h) {
g.setColor(clrHover); g.setColor(clrHover);
g.drawRect(0, 0, w - 2, h - 2); g.drawRect(0, 0, w - 2, h - 2);
g.setColor(l30); g.setColor(l30);