mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 04:08:01 +00:00
Move arrow buttons support to FScrollPane to allow better separation of FScrollPane and FScrollPanel
This commit is contained in:
@@ -47,6 +47,7 @@ import forge.gui.toolbox.FMouseAdapter;
|
|||||||
import forge.gui.toolbox.FOptionPane;
|
import forge.gui.toolbox.FOptionPane;
|
||||||
import forge.gui.toolbox.FPanel;
|
import forge.gui.toolbox.FPanel;
|
||||||
import forge.gui.toolbox.FRadioButton;
|
import forge.gui.toolbox.FRadioButton;
|
||||||
|
import forge.gui.toolbox.FScrollPane;
|
||||||
import forge.gui.toolbox.FScrollPanel;
|
import forge.gui.toolbox.FScrollPanel;
|
||||||
import forge.gui.toolbox.FSkin;
|
import forge.gui.toolbox.FSkin;
|
||||||
import forge.gui.toolbox.FSkin.SkinColor;
|
import forge.gui.toolbox.FSkin.SkinColor;
|
||||||
@@ -142,7 +143,7 @@ public enum VSubmenuConstructed implements IVSubmenu<CSubmenuConstructed> {
|
|||||||
variantsPanel.add(vntArchenemy);
|
variantsPanel.add(vntArchenemy);
|
||||||
comboArchenemy.addTo(variantsPanel);
|
comboArchenemy.addTo(variantsPanel);
|
||||||
|
|
||||||
constructedFrame.add(new FScrollPanel(variantsPanel, true,
|
constructedFrame.add(new FScrollPane(variantsPanel, true,
|
||||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
|
||||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED),
|
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED),
|
||||||
"w 100%, gapbottom 10px, spanx 2, wrap");
|
"w 100%, gapbottom 10px, spanx 2, wrap");
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import forge.gui.framework.DragTab;
|
|||||||
import forge.gui.framework.EDocID;
|
import forge.gui.framework.EDocID;
|
||||||
import forge.gui.framework.IVDoc;
|
import forge.gui.framework.IVDoc;
|
||||||
import forge.gui.match.controllers.CDev;
|
import forge.gui.match.controllers.CDev;
|
||||||
import forge.gui.toolbox.FScrollPanel;
|
import forge.gui.toolbox.FScrollPane;
|
||||||
import forge.gui.toolbox.FSkin;
|
import forge.gui.toolbox.FSkin;
|
||||||
import forge.gui.toolbox.FSkin.SkinnedLabel;
|
import forge.gui.toolbox.FSkin.SkinnedLabel;
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ public enum VDev implements IVDoc<CDev> {
|
|||||||
|
|
||||||
// Top-level containers
|
// Top-level containers
|
||||||
private final JPanel viewport = new JPanel(new MigLayout("wrap, insets 0, ax center"));
|
private final JPanel viewport = new JPanel(new MigLayout("wrap, insets 0, ax center"));
|
||||||
private final FScrollPanel scroller = new FScrollPanel(viewport, true,
|
private final FScrollPane scroller = new FScrollPane(viewport, true,
|
||||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
|
||||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import forge.gui.match.controllers.CPrompt;
|
|||||||
import forge.gui.toolbox.FButton;
|
import forge.gui.toolbox.FButton;
|
||||||
import forge.gui.toolbox.FHtmlViewer;
|
import forge.gui.toolbox.FHtmlViewer;
|
||||||
import forge.gui.toolbox.FLabel;
|
import forge.gui.toolbox.FLabel;
|
||||||
import forge.gui.toolbox.FScrollPanel;
|
import forge.gui.toolbox.FScrollPane;
|
||||||
import forge.gui.toolbox.FSkin;
|
import forge.gui.toolbox.FSkin;
|
||||||
import forge.properties.ForgePreferences;
|
import forge.properties.ForgePreferences;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
@@ -60,7 +60,7 @@ public enum VPrompt implements IVDoc<CPrompt> {
|
|||||||
private final JButton btnOK = new FButton("OK");
|
private final JButton btnOK = new FButton("OK");
|
||||||
private final JButton btnCancel = new FButton("Cancel");
|
private final JButton btnCancel = new FButton("Cancel");
|
||||||
private final FHtmlViewer tarMessage = new FHtmlViewer();
|
private final FHtmlViewer tarMessage = new FHtmlViewer();
|
||||||
private final FScrollPanel messageScroller = new FScrollPanel(tarMessage, false,
|
private final FScrollPane messageScroller = new FScrollPane(tarMessage,
|
||||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
private final JLabel lblGames;
|
private final JLabel lblGames;
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ import forge.gui.framework.IVDoc;
|
|||||||
import forge.gui.match.CMatchUI;
|
import forge.gui.match.CMatchUI;
|
||||||
import forge.gui.match.controllers.CStack;
|
import forge.gui.match.controllers.CStack;
|
||||||
import forge.gui.toolbox.FMouseAdapter;
|
import forge.gui.toolbox.FMouseAdapter;
|
||||||
import forge.gui.toolbox.FScrollPanel;
|
import forge.gui.toolbox.FScrollPane;
|
||||||
import forge.gui.toolbox.FSkin;
|
import forge.gui.toolbox.FSkin;
|
||||||
import forge.gui.toolbox.FSkin.SkinnedTextArea;
|
import forge.gui.toolbox.FSkin.SkinnedTextArea;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
@@ -75,7 +75,7 @@ public enum VStack implements IVDoc<CStack> {
|
|||||||
private final DragTab tab = new DragTab("Stack");
|
private final DragTab tab = new DragTab("Stack");
|
||||||
|
|
||||||
// Top-level containers
|
// Top-level containers
|
||||||
private final FScrollPanel scroller = new FScrollPanel(new JPanel(), true,
|
private final FScrollPane scroller = new FScrollPane(null, true,
|
||||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
private final StackArea stackArea = new StackArea(scroller);
|
private final StackArea stackArea = new StackArea(scroller);
|
||||||
|
|
||||||
@@ -363,7 +363,7 @@ public enum VStack implements IVDoc<CStack> {
|
|||||||
|
|
||||||
private Dimension size;
|
private Dimension size;
|
||||||
|
|
||||||
public StackArea(final FScrollPanel scrollPane) {
|
public StackArea(final FScrollPane scrollPane) {
|
||||||
super(scrollPane);
|
super(scrollPane);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,44 +1,266 @@
|
|||||||
package forge.gui.toolbox;
|
package forge.gui.toolbox;
|
||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
|
import javax.swing.JScrollBar;
|
||||||
import javax.swing.ScrollPaneConstants;
|
import javax.swing.ScrollPaneConstants;
|
||||||
|
import javax.swing.Timer;
|
||||||
|
import javax.swing.border.Border;
|
||||||
|
|
||||||
|
import forge.gui.toolbox.FSkin.SkinColor;
|
||||||
import forge.gui.toolbox.FSkin.SkinnedScrollPane;
|
import forge.gui.toolbox.FSkin.SkinnedScrollPane;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A very basic extension of JScrollPane to centralize common styling changes.
|
* An extension of JScrollPane to centralize common styling changes
|
||||||
|
* and supports using arrow buttons to scroll instead of scrollbars
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class FScrollPane extends SkinnedScrollPane {
|
public class FScrollPane extends SkinnedScrollPane {
|
||||||
|
private static final SkinColor arrowColor = FSkin.getColor(FSkin.Colors.CLR_TEXT);
|
||||||
|
private final ArrowButton[] arrowButtons;
|
||||||
|
|
||||||
public FScrollPane() {
|
public FScrollPane() {
|
||||||
this(null);
|
this(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A very basic extension of JScrollPane to centralize common styling changes.
|
|
||||||
* This constructor assumes "as needed" for horizontal and vertical scroll policies.
|
|
||||||
*
|
|
||||||
* @param c0 {@link java.awt.Component}
|
|
||||||
*/
|
|
||||||
public FScrollPane(final Component c0) {
|
public FScrollPane(final Component c0) {
|
||||||
this(c0, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
this(c0, false, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||||
|
}
|
||||||
|
public FScrollPane(final Component c0, boolean useArrowButtons0) {
|
||||||
|
this(c0, useArrowButtons0, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A very basic extension of JScrollPane to centralize common styling changes.
|
|
||||||
*
|
|
||||||
* @param c0   Viewport component.
|
|
||||||
* @param vertical0   Vertical scroll bar policy
|
|
||||||
* @param horizontal0   Horizontal scroll bar policy
|
|
||||||
*/
|
|
||||||
public FScrollPane(final Component c0, final int vertical0, final int horizontal0) {
|
public FScrollPane(final Component c0, final int vertical0, final int horizontal0) {
|
||||||
|
this(c0, false, vertical0, horizontal0);
|
||||||
|
}
|
||||||
|
public FScrollPane(final Component c0, boolean useArrowButtons0, final int vertical0, final int horizontal0) {
|
||||||
super(c0, vertical0, horizontal0);
|
super(c0, vertical0, horizontal0);
|
||||||
|
|
||||||
getVerticalScrollBar().setUnitIncrement(16);
|
getVerticalScrollBar().setUnitIncrement(16);
|
||||||
getHorizontalScrollBar().setUnitIncrement(16);
|
getHorizontalScrollBar().setUnitIncrement(16);
|
||||||
getViewport().setOpaque(false);
|
getViewport().setOpaque(false);
|
||||||
this.setBorder(new FSkin.LineSkinBorder(FSkin.getColor(FSkin.Colors.CLR_BORDERS)));
|
|
||||||
setOpaque(false);
|
setOpaque(false);
|
||||||
|
setBorder((Border)null);
|
||||||
|
if (useArrowButtons0) {
|
||||||
|
//ensure scrollbar aren't shown
|
||||||
|
getHorizontalScrollBar().setPreferredSize(new Dimension(0, 0));
|
||||||
|
getVerticalScrollBar().setPreferredSize(new Dimension(0, 0));
|
||||||
|
arrowButtons = new ArrowButton[4];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
arrowButtons = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paint(Graphics g) {
|
||||||
|
super.paint(g);
|
||||||
|
if (arrowButtons == null) { return; }
|
||||||
|
|
||||||
|
//determine which buttons should be visible
|
||||||
|
boolean[] visible = new boolean[] { false, false, false, false };
|
||||||
|
final JScrollBar horzScrollBar = this.getHorizontalScrollBar();
|
||||||
|
if (horzScrollBar.isVisible()) { //NOTE: scrollbar wouldn't actually be visible since size set to 0 to hide it
|
||||||
|
visible[0] = horzScrollBar.getValue() > 0;
|
||||||
|
visible[1] = horzScrollBar.getValue() < horzScrollBar.getMaximum() - horzScrollBar.getModel().getExtent();
|
||||||
|
}
|
||||||
|
final JScrollBar vertScrollBar = this.getVerticalScrollBar();
|
||||||
|
if (vertScrollBar.isVisible()) {
|
||||||
|
visible[2] = vertScrollBar.getValue() > 0;
|
||||||
|
visible[3] = vertScrollBar.getValue() < vertScrollBar.getMaximum() - vertScrollBar.getModel().getExtent();
|
||||||
|
}
|
||||||
|
for (int dir = 0; dir < 4; dir++) {
|
||||||
|
updateArrowButton(dir, visible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateArrowButton(int dir, boolean[] visible) {
|
||||||
|
ArrowButton arrowButton = arrowButtons[dir];
|
||||||
|
if (!visible[dir]) {
|
||||||
|
if (arrowButton != null) {
|
||||||
|
arrowButton.setVisible(false);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//determine bounds of button
|
||||||
|
int x, y, w, h;
|
||||||
|
final int panelWidth = getWidth();
|
||||||
|
final int panelHeight = getHeight();
|
||||||
|
final int arrowButtonSize = 18;
|
||||||
|
final int cornerSize = arrowButtonSize - 1; //make borders line up
|
||||||
|
|
||||||
|
if (dir < 2) { //if button for horizontal scrolling
|
||||||
|
y = 0;
|
||||||
|
h = panelHeight;
|
||||||
|
if (visible[2]) {
|
||||||
|
y += cornerSize;
|
||||||
|
h -= cornerSize;
|
||||||
|
}
|
||||||
|
if (visible[3]) {
|
||||||
|
h -= cornerSize;
|
||||||
|
}
|
||||||
|
x = (dir == 0 ? 0 : panelWidth - arrowButtonSize);
|
||||||
|
w = arrowButtonSize;
|
||||||
|
}
|
||||||
|
else { //if button for vertical scrolling
|
||||||
|
x = 0;
|
||||||
|
w = panelWidth;
|
||||||
|
if (visible[0]) {
|
||||||
|
x += cornerSize;
|
||||||
|
w -= cornerSize;
|
||||||
|
}
|
||||||
|
if (visible[1]) {
|
||||||
|
w -= cornerSize;
|
||||||
|
}
|
||||||
|
y = (dir == 2 ? 0 : panelHeight - arrowButtonSize);
|
||||||
|
h = arrowButtonSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arrowButton == null) {
|
||||||
|
switch (dir) {
|
||||||
|
case 0:
|
||||||
|
arrowButton = new LeftArrowButton(getHorizontalScrollBar());
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
arrowButton = new RightArrowButton(getHorizontalScrollBar());
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
arrowButton = new TopArrowButton(getVerticalScrollBar());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
arrowButton = new BottomArrowButton(getVerticalScrollBar());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
arrowButtons[dir] = arrowButton;
|
||||||
|
}
|
||||||
|
//absolutely position button in front of scroll panel
|
||||||
|
arrowButton.setSize(w, h);
|
||||||
|
FAbsolutePositioner.SINGLETON_INSTANCE.show(arrowButton, this, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private abstract class ArrowButton extends FLabel {
|
||||||
|
protected final int arrowSize = 6;
|
||||||
|
private final JScrollBar scrollBar;
|
||||||
|
private final int incrementDirection;
|
||||||
|
|
||||||
|
protected ArrowButton(final JScrollBar scrollBar0, final int incrementDirection0) {
|
||||||
|
super(new FLabel.ButtonBuilder());
|
||||||
|
scrollBar = scrollBar0;
|
||||||
|
incrementDirection = incrementDirection0;
|
||||||
|
timer.setInitialDelay(500); //wait half a second after mouse down before starting timer
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setPressed(boolean pressed0) {
|
||||||
|
super.setPressed(pressed0);
|
||||||
|
if (pressed0) {
|
||||||
|
scrollBar.setValue(scrollBar.getValue() + scrollBar.getUnitIncrement() * incrementDirection);
|
||||||
|
timer.start();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
timer.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintContent(final Graphics2D g, int w, int h, final boolean paintPressedState) {
|
||||||
|
FSkin.setGraphicsColor(g, arrowColor);
|
||||||
|
drawArrow(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void drawArrow(final Graphics g);
|
||||||
|
|
||||||
|
//timer to continue scrollling while mouse remains down
|
||||||
|
final Timer timer = new Timer(50, new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (!isVisible()) {
|
||||||
|
//ensure timer stops if button hidden from scrolling to beginning/end (based on incrementDirection)
|
||||||
|
((Timer)e.getSource()).stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
scrollBar.setValue(scrollBar.getValue() + scrollBar.getUnitIncrement() * incrementDirection);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LeftArrowButton extends ArrowButton {
|
||||||
|
public LeftArrowButton(final JScrollBar horzScrollbar) {
|
||||||
|
super(horzScrollbar, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawArrow(final Graphics g) {
|
||||||
|
int x = (getWidth() - arrowSize) / 2;
|
||||||
|
int y2 = getHeight() / 2;
|
||||||
|
int y1 = y2 - 1;
|
||||||
|
for (int i = 0; i < arrowSize; i++) {
|
||||||
|
g.drawLine(x, y1, x, y2);
|
||||||
|
x++;
|
||||||
|
y1--;
|
||||||
|
y2++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RightArrowButton extends ArrowButton {
|
||||||
|
public RightArrowButton(final JScrollBar horzScrollbar) {
|
||||||
|
super(horzScrollbar, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawArrow(final Graphics g) {
|
||||||
|
int x = (getWidth() + arrowSize) / 2;
|
||||||
|
int y2 = getHeight() / 2;
|
||||||
|
int y1 = y2 - 1;
|
||||||
|
for (int i = 0; i < arrowSize; i++) {
|
||||||
|
g.drawLine(x, y1, x, y2);
|
||||||
|
x--;
|
||||||
|
y1--;
|
||||||
|
y2++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TopArrowButton extends ArrowButton {
|
||||||
|
public TopArrowButton(final JScrollBar vertScrollbar) {
|
||||||
|
super(vertScrollbar, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawArrow(final Graphics g) {
|
||||||
|
int x2 = getWidth() / 2;
|
||||||
|
int x1 = x2 - 1;
|
||||||
|
int y = (getHeight() - arrowSize) / 2;
|
||||||
|
for (int i = 0; i < arrowSize; i++) {
|
||||||
|
g.drawLine(x1, y, x2, y);
|
||||||
|
x1--;
|
||||||
|
x2++;
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BottomArrowButton extends ArrowButton {
|
||||||
|
public BottomArrowButton(final JScrollBar vertScrollbar) {
|
||||||
|
super(vertScrollbar, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawArrow(final Graphics g) {
|
||||||
|
int x2 = getWidth() / 2;
|
||||||
|
int x1 = x2 - 1;
|
||||||
|
int y = (getHeight() + arrowSize) / 2;
|
||||||
|
for (int i = 0; i < arrowSize; i++) {
|
||||||
|
g.drawLine(x1, y, x2, y);
|
||||||
|
x1--;
|
||||||
|
x2++;
|
||||||
|
y--;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,315 +18,34 @@
|
|||||||
package forge.gui.toolbox;
|
package forge.gui.toolbox;
|
||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Dimension;
|
|
||||||
import java.awt.Graphics;
|
|
||||||
import java.awt.Graphics2D;
|
|
||||||
import java.awt.LayoutManager;
|
import java.awt.LayoutManager;
|
||||||
import java.awt.PopupMenu;
|
import java.awt.PopupMenu;
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JScrollBar;
|
|
||||||
import javax.swing.ScrollPaneConstants;
|
import javax.swing.ScrollPaneConstants;
|
||||||
import javax.swing.Timer;
|
|
||||||
import javax.swing.border.Border;
|
|
||||||
|
|
||||||
import forge.gui.toolbox.FSkin.SkinColor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An extension of JScrollPane that can be used as a panel and supports using arrow buttons to scroll instead of scrollbars
|
* An extension of FScrollPane that can be used as a panel
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class FScrollPanel extends FScrollPane {
|
public class FScrollPanel extends FScrollPane {
|
||||||
private static final SkinColor arrowColor = FSkin.getColor(FSkin.Colors.CLR_TEXT);
|
|
||||||
private final boolean useArrowButtons;
|
|
||||||
private final ArrowButton[] arrowButtons = new ArrowButton[4];
|
|
||||||
private JPanel innerPanel;
|
private JPanel innerPanel;
|
||||||
|
|
||||||
/**
|
|
||||||
* An extension of JScrollPane that can be used as a panel and supports using arrow buttons to scroll instead of scrollbars
|
|
||||||
* This constructor assumes no layout, assumes using scrollbars to scroll, and "as needed" for horizontal and vertical scroll policies.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public FScrollPanel() {
|
public FScrollPanel() {
|
||||||
this(null);
|
this(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* An extension of JScrollPane that can be used as a panel and supports using arrow buttons to scroll instead of scrollbars
|
|
||||||
* This constructor assumes using scrollbars to scroll and "as needed" for horizontal and vertical scroll policies.
|
|
||||||
*
|
|
||||||
* @param layout   Layout for panel.
|
|
||||||
*/
|
|
||||||
public FScrollPanel(final LayoutManager layout) {
|
public FScrollPanel(final LayoutManager layout) {
|
||||||
this(layout, false);
|
this(layout, false);
|
||||||
}
|
}
|
||||||
|
public FScrollPanel(final LayoutManager layout, boolean useArrowButtons0) {
|
||||||
/**
|
this(layout, useArrowButtons0, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||||
* An extension of JScrollPane that can be used as a panel and supports using arrow buttons to scroll instead of scrollbars
|
|
||||||
* This constructor assumes "as needed" for horizontal and vertical scroll policies.
|
|
||||||
*
|
|
||||||
* @param layout   Layout for panel.
|
|
||||||
* @param useArrowButtons   True to use arrow buttons to scroll, false to use scrollbars
|
|
||||||
*/
|
|
||||||
public FScrollPanel(final LayoutManager layout, boolean useArrowButtons) {
|
|
||||||
this(layout, useArrowButtons, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* An extension of JScrollPane that can be used as a panel and supports using arrow buttons to scroll instead of scrollbars
|
|
||||||
*
|
|
||||||
* @param layout   Layout for panel.
|
|
||||||
* @param useArrowButtons0   True to use arrow buttons to scroll, false to use scrollbars
|
|
||||||
* @param vertical0   Vertical scroll bar policy
|
|
||||||
* @param horizontal0   Horizontal scroll bar policy
|
|
||||||
*/
|
|
||||||
public FScrollPanel(final LayoutManager layout, boolean useArrowButtons0, final int vertical0, final int horizontal0) {
|
public FScrollPanel(final LayoutManager layout, boolean useArrowButtons0, final int vertical0, final int horizontal0) {
|
||||||
this(new JPanel(layout), useArrowButtons0, vertical0, horizontal0);
|
super(new JPanel(layout), useArrowButtons0, vertical0, horizontal0);
|
||||||
innerPanel = (JPanel)getViewport().getView();
|
innerPanel = (JPanel)getViewport().getView();
|
||||||
innerPanel.setOpaque(false);
|
innerPanel.setOpaque(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* An extension of JScrollPane that can be used as a panel and supports using arrow buttons to scroll instead of scrollbars
|
|
||||||
*
|
|
||||||
* @param view   Scrollable view component.
|
|
||||||
* @param useArrowButtons0   True to use arrow buttons to scroll, false to use scrollbars
|
|
||||||
*/
|
|
||||||
public FScrollPanel(final Component view, boolean useArrowButtons0) {
|
|
||||||
this(view, useArrowButtons0, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An extension of JScrollPane that can be used as a panel and supports using arrow buttons to scroll instead of scrollbars
|
|
||||||
*
|
|
||||||
* @param view   Scrollable view component.
|
|
||||||
* @param useArrowButtons0   True to use arrow buttons to scroll, false to use scrollbars
|
|
||||||
* @param vertical0   Vertical scroll bar policy
|
|
||||||
* @param horizontal0   Horizontal scroll bar policy
|
|
||||||
*/
|
|
||||||
public FScrollPanel(final Component view, boolean useArrowButtons0, final int vertical0, final int horizontal0) {
|
|
||||||
super(view, vertical0, horizontal0);
|
|
||||||
|
|
||||||
useArrowButtons = useArrowButtons0;
|
|
||||||
setBorder((Border)null);
|
|
||||||
if (useArrowButtons) {
|
|
||||||
//ensure scrollbar aren't shown
|
|
||||||
getHorizontalScrollBar().setPreferredSize(new Dimension(0, 0));
|
|
||||||
getVerticalScrollBar().setPreferredSize(new Dimension(0, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void paint(Graphics g) {
|
|
||||||
super.paint(g);
|
|
||||||
if (useArrowButtons) {
|
|
||||||
//determine which buttons should be visible
|
|
||||||
boolean[] visible = new boolean[] { false, false, false, false };
|
|
||||||
final JScrollBar horzScrollBar = this.getHorizontalScrollBar();
|
|
||||||
if (horzScrollBar.isVisible()) { //NOTE: scrollbar wouldn't actually be visible since size set to 0 to hide it
|
|
||||||
visible[0] = horzScrollBar.getValue() > 0;
|
|
||||||
visible[1] = horzScrollBar.getValue() < horzScrollBar.getMaximum() - horzScrollBar.getModel().getExtent();
|
|
||||||
}
|
|
||||||
final JScrollBar vertScrollBar = this.getVerticalScrollBar();
|
|
||||||
if (vertScrollBar.isVisible()) {
|
|
||||||
visible[2] = vertScrollBar.getValue() > 0;
|
|
||||||
visible[3] = vertScrollBar.getValue() < vertScrollBar.getMaximum() - vertScrollBar.getModel().getExtent();
|
|
||||||
}
|
|
||||||
for (int dir = 0; dir < 4; dir++) {
|
|
||||||
updateArrowButton(dir, visible);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateArrowButton(int dir, boolean[] visible) {
|
|
||||||
ArrowButton arrowButton = arrowButtons[dir];
|
|
||||||
if (!visible[dir]) {
|
|
||||||
if (arrowButton != null) {
|
|
||||||
arrowButton.setVisible(false);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//determine bounds of button
|
|
||||||
int x, y, w, h;
|
|
||||||
final int panelWidth = getWidth();
|
|
||||||
final int panelHeight = getHeight();
|
|
||||||
final int arrowButtonSize = 18;
|
|
||||||
final int cornerSize = arrowButtonSize - 1; //make borders line up
|
|
||||||
|
|
||||||
if (dir < 2) { //if button for horizontal scrolling
|
|
||||||
y = 0;
|
|
||||||
h = panelHeight;
|
|
||||||
if (visible[2]) {
|
|
||||||
y += cornerSize;
|
|
||||||
h -= cornerSize;
|
|
||||||
}
|
|
||||||
if (visible[3]) {
|
|
||||||
h -= cornerSize;
|
|
||||||
}
|
|
||||||
x = (dir == 0 ? 0 : panelWidth - arrowButtonSize);
|
|
||||||
w = arrowButtonSize;
|
|
||||||
}
|
|
||||||
else { //if button for vertical scrolling
|
|
||||||
x = 0;
|
|
||||||
w = panelWidth;
|
|
||||||
if (visible[0]) {
|
|
||||||
x += cornerSize;
|
|
||||||
w -= cornerSize;
|
|
||||||
}
|
|
||||||
if (visible[1]) {
|
|
||||||
w -= cornerSize;
|
|
||||||
}
|
|
||||||
y = (dir == 2 ? 0 : panelHeight - arrowButtonSize);
|
|
||||||
h = arrowButtonSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arrowButton == null) {
|
|
||||||
switch (dir) {
|
|
||||||
case 0:
|
|
||||||
arrowButton = new LeftArrowButton(getHorizontalScrollBar());
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
arrowButton = new RightArrowButton(getHorizontalScrollBar());
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
arrowButton = new TopArrowButton(getVerticalScrollBar());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
arrowButton = new BottomArrowButton(getVerticalScrollBar());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
arrowButtons[dir] = arrowButton;
|
|
||||||
}
|
|
||||||
//absolutely position button in front of scroll panel
|
|
||||||
arrowButton.setSize(w, h);
|
|
||||||
FAbsolutePositioner.SINGLETON_INSTANCE.show(arrowButton, this, x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
private abstract class ArrowButton extends FLabel {
|
|
||||||
protected final int arrowSize = 6;
|
|
||||||
private final JScrollBar scrollBar;
|
|
||||||
private final int incrementDirection;
|
|
||||||
|
|
||||||
protected ArrowButton(final JScrollBar scrollBar0, final int incrementDirection0) {
|
|
||||||
super(new FLabel.ButtonBuilder());
|
|
||||||
scrollBar = scrollBar0;
|
|
||||||
incrementDirection = incrementDirection0;
|
|
||||||
timer.setInitialDelay(500); //wait half a second after mouse down before starting timer
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setPressed(boolean pressed0) {
|
|
||||||
super.setPressed(pressed0);
|
|
||||||
if (pressed0) {
|
|
||||||
scrollBar.setValue(scrollBar.getValue() + scrollBar.getUnitIncrement() * incrementDirection);
|
|
||||||
timer.start();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
timer.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void paintContent(final Graphics2D g, int w, int h, final boolean paintPressedState) {
|
|
||||||
FSkin.setGraphicsColor(g, arrowColor);
|
|
||||||
drawArrow(g);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void drawArrow(final Graphics g);
|
|
||||||
|
|
||||||
//timer to continue scrollling while mouse remains down
|
|
||||||
final Timer timer = new Timer(50, new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
if (!isVisible()) {
|
|
||||||
//ensure timer stops if button hidden from scrolling to beginning/end (based on incrementDirection)
|
|
||||||
((Timer)e.getSource()).stop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
scrollBar.setValue(scrollBar.getValue() + scrollBar.getUnitIncrement() * incrementDirection);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private class LeftArrowButton extends ArrowButton {
|
|
||||||
public LeftArrowButton(final JScrollBar horzScrollbar) {
|
|
||||||
super(horzScrollbar, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void drawArrow(final Graphics g) {
|
|
||||||
int x = (getWidth() - arrowSize) / 2;
|
|
||||||
int y2 = getHeight() / 2;
|
|
||||||
int y1 = y2 - 1;
|
|
||||||
for (int i = 0; i < arrowSize; i++) {
|
|
||||||
g.drawLine(x, y1, x, y2);
|
|
||||||
x++;
|
|
||||||
y1--;
|
|
||||||
y2++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class RightArrowButton extends ArrowButton {
|
|
||||||
public RightArrowButton(final JScrollBar horzScrollbar) {
|
|
||||||
super(horzScrollbar, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void drawArrow(final Graphics g) {
|
|
||||||
int x = (getWidth() + arrowSize) / 2;
|
|
||||||
int y2 = getHeight() / 2;
|
|
||||||
int y1 = y2 - 1;
|
|
||||||
for (int i = 0; i < arrowSize; i++) {
|
|
||||||
g.drawLine(x, y1, x, y2);
|
|
||||||
x--;
|
|
||||||
y1--;
|
|
||||||
y2++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class TopArrowButton extends ArrowButton {
|
|
||||||
public TopArrowButton(final JScrollBar vertScrollbar) {
|
|
||||||
super(vertScrollbar, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void drawArrow(final Graphics g) {
|
|
||||||
int x2 = getWidth() / 2;
|
|
||||||
int x1 = x2 - 1;
|
|
||||||
int y = (getHeight() - arrowSize) / 2;
|
|
||||||
for (int i = 0; i < arrowSize; i++) {
|
|
||||||
g.drawLine(x1, y, x2, y);
|
|
||||||
x1--;
|
|
||||||
x2++;
|
|
||||||
y++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class BottomArrowButton extends ArrowButton {
|
|
||||||
public BottomArrowButton(final JScrollBar vertScrollbar) {
|
|
||||||
super(vertScrollbar, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void drawArrow(final Graphics g) {
|
|
||||||
int x2 = getWidth() / 2;
|
|
||||||
int x1 = x2 - 1;
|
|
||||||
int y = (getHeight() + arrowSize) / 2;
|
|
||||||
for (int i = 0; i < arrowSize; i++) {
|
|
||||||
g.drawLine(x1, y, x2, y);
|
|
||||||
x1--;
|
|
||||||
x2++;
|
|
||||||
y--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//relay certain methods to the inner panel if it has been initialized
|
//relay certain methods to the inner panel if it has been initialized
|
||||||
@Override
|
@Override
|
||||||
public Component add(Component comp) {
|
public Component add(Component comp) {
|
||||||
|
|||||||
Reference in New Issue
Block a user