From 1d672170cfad2853df71e8b77a42386456065c09 Mon Sep 17 00:00:00 2001 From: Doublestrike Date: Thu, 16 Feb 2012 10:42:44 +0000 Subject: [PATCH] Updated wrapping of avatars in settings submenu. --- .gitattributes | 1 + .../java/forge/view/home/ViewSettings.java | 16 +- .../java/forge/view/toolbox/WrapLayout.java | 189 ++++++++++++++++++ 3 files changed, 193 insertions(+), 13 deletions(-) create mode 100644 src/main/java/forge/view/toolbox/WrapLayout.java diff --git a/.gitattributes b/.gitattributes index 8b9417a4d0f..6edeb4c73e5 100644 --- a/.gitattributes +++ b/.gitattributes @@ -11371,6 +11371,7 @@ src/main/java/forge/view/toolbox/FSkin.java -text src/main/java/forge/view/toolbox/FTextArea.java -text src/main/java/forge/view/toolbox/FVerticalTabPanel.java -text src/main/java/forge/view/toolbox/SubTab.java -text +src/main/java/forge/view/toolbox/WrapLayout.java -text src/main/java/forge/view/toolbox/package-info.java svneol=native#text/plain src/main/java/net/slightlymagic/braids/LICENSE.txt svneol=native#text/plain src/main/java/net/slightlymagic/braids/util/ClumsyRunnable.java svneol=native#text/plain diff --git a/src/main/java/forge/view/home/ViewSettings.java b/src/main/java/forge/view/home/ViewSettings.java index 370b04d02c4..a14a6016310 100644 --- a/src/main/java/forge/view/home/ViewSettings.java +++ b/src/main/java/forge/view/home/ViewSettings.java @@ -43,6 +43,7 @@ import forge.view.toolbox.FList; import forge.view.toolbox.FScrollPane; import forge.view.toolbox.FSkin; import forge.view.toolbox.SubTab; +import forge.view.toolbox.WrapLayout; /** * Assembles swing components for "Settings" mode menu. @@ -231,24 +232,13 @@ public class ViewSettings extends JPanel { } // End populatePrefs() private void populateAvatars() { - final JLabel lblTitle = new SectionLabel("Avatar Selection"); - final JLabel lblNote1 = new NoteLabel("Click on an image to set that avatar for a player or AI."); - final JLabel lblNote2 = new NoteLabel("Click multiple times to cycle."); - - lblTitle.setHorizontalAlignment(SwingConstants.CENTER); - lblNote1.setHorizontalAlignment(SwingConstants.CENTER); - lblNote2.setHorizontalAlignment(SwingConstants.CENTER); - - pnlAvatars.setLayout(new MigLayout("insets 0, gap 0, align center, wrap 3")); - pnlAvatars.add(lblTitle, "w 330px!, span 3 1"); - pnlAvatars.add(lblNote1, "w 330px!, span 3 1"); - pnlAvatars.add(lblNote2, "w 330px!, span 3 1"); + pnlAvatars.setLayout(new WrapLayout()); lstAvatars = new ArrayList(); int counter = 0; for (final Image i : FSkin.getAvatars().values()) { lstAvatars.add(new AvatarLabel(i, counter++)); - pnlAvatars.add(lstAvatars.get(lstAvatars.size() - 1), "gap 5px 5px 5px 5px"); + pnlAvatars.add(lstAvatars.get(lstAvatars.size() - 1)); } final String[] indexes = Singletons.getModel().getPreferences().getPref(FPref.UI_AVATARS).split(","); diff --git a/src/main/java/forge/view/toolbox/WrapLayout.java b/src/main/java/forge/view/toolbox/WrapLayout.java new file mode 100644 index 00000000000..4d63d255f8d --- /dev/null +++ b/src/main/java/forge/view/toolbox/WrapLayout.java @@ -0,0 +1,189 @@ +package forge.view.toolbox; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Insets; + +import javax.swing.JScrollPane; +import javax.swing.SwingUtilities; + +/** + * FlowLayout subclass that fully supports wrapping of components. + */ +public class WrapLayout extends FlowLayout +{ + private Dimension preferredLayoutSize; + + /** + * Constructs a new WrapLayout with a left + * alignment and a default 5-unit horizontal and vertical gap. + */ + public WrapLayout() + { + super(); + } + + /** + * Constructs a new FlowLayout with the specified + * alignment and a default 5-unit horizontal and vertical gap. + * The value of the alignment argument must be one of + * WrapLayout, WrapLayout, + * or WrapLayout. + * @param align the alignment value + */ + public WrapLayout(int align) + { + super(align); + } + + /** + * Creates a new flow layout manager with the indicated alignment + * and the indicated horizontal and vertical gaps. + *

+ * The value of the alignment argument must be one of + * WrapLayout, WrapLayout, + * or WrapLayout. + * @param align the alignment value + * @param hgap the horizontal gap between components + * @param vgap the vertical gap between components + */ + public WrapLayout(int align, int hgap, int vgap) + { + super(align, hgap, vgap); + } + + /** + * Returns the preferred dimensions for this layout given the + * visible components in the specified target container. + * @param target the component which needs to be laid out + * @return the preferred dimensions to lay out the + * subcomponents of the specified container + */ + @Override + public Dimension preferredLayoutSize(Container target) + { + return layoutSize(target, true); + } + + /** + * Returns the minimum dimensions needed to layout the visible + * components contained in the specified target container. + * @param target the component which needs to be laid out + * @return the minimum dimensions to lay out the + * subcomponents of the specified container + */ + @Override + public Dimension minimumLayoutSize(Container target) + { + Dimension minimum = layoutSize(target, false); + minimum.width -= (getHgap() + 1); + return minimum; + } + + /** + * Returns the minimum or preferred dimension needed to layout the target + * container. + * + * @param target target to get layout size for + * @param preferred should preferred size be calculated + * @return the dimension to layout the target container + */ + private Dimension layoutSize(Container target, boolean preferred) + { + synchronized (target.getTreeLock()) + { + // Each row must fit with the width allocated to the containter. + // When the container width = 0, the preferred width of the container + // has not yet been calculated so lets ask for the maximum. + + int targetWidth = target.getSize().width; + + if (targetWidth == 0) + targetWidth = Integer.MAX_VALUE; + + int hgap = getHgap(); + int vgap = getVgap(); + Insets insets = target.getInsets(); + int horizontalInsetsAndGap = insets.left + insets.right + (hgap * 2); + int maxWidth = targetWidth - horizontalInsetsAndGap; + + // Fit components into the allowed width + + Dimension dim = new Dimension(0, 0); + int rowWidth = 0; + int rowHeight = 0; + + int nmembers = target.getComponentCount(); + + for (int i = 0; i < nmembers; i++) + { + Component m = target.getComponent(i); + + if (m.isVisible()) + { + Dimension d = preferred ? m.getPreferredSize() : m.getMinimumSize(); + + // Can't add the component to current row. Start a new row. + + if (rowWidth + d.width > maxWidth) + { + addRow(dim, rowWidth, rowHeight); + rowWidth = 0; + rowHeight = 0; + } + + // Add a horizontal gap for all components after the first + + if (rowWidth != 0) + { + rowWidth += hgap; + } + + rowWidth += d.width; + rowHeight = Math.max(rowHeight, d.height); + } + } + + addRow(dim, rowWidth, rowHeight); + + dim.width += horizontalInsetsAndGap; + dim.height += insets.top + insets.bottom + vgap * 2; + + // When using a scroll pane or the DecoratedLookAndFeel we need to + // make sure the preferred size is less than the size of the + // target containter so shrinking the container size works + // correctly. Removing the horizontal gap is an easy way to do this. + + Container scrollPane = SwingUtilities.getAncestorOfClass(JScrollPane.class, target); + + if (scrollPane != null) + { + dim.width -= (hgap + 1); + } + + return dim; + } + } + + /* + * A new row has been completed. Use the dimensions of this row + * to update the preferred size for the container. + * + * @param dim update the width and height when appropriate + * @param rowWidth the width of the row to add + * @param rowHeight the height of the row to add + */ + private void addRow(Dimension dim, int rowWidth, int rowHeight) + { + dim.width = Math.max(dim.width, rowWidth); + + if (dim.height > 0) + { + dim.height += getVgap(); + } + + dim.height += rowHeight; + } +}