/* * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ package mage.client.deck.generator; import javax.swing.*; import java.awt.*; import java.util.ArrayList; import java.util.List; /** * @author Simown */ public class RatioAdjustingSliderPanel extends JPanel { private JStorageSlider creatureSlider, nonCreatureSlider, landSlider; private final List<JLabel> textLabels = new ArrayList<>(); private AdjustingSliderGroup sg; private static class JStorageSlider extends JSlider { // Slider stores its initial value to revert to when reset private final int defaultValue; private int previousValue; public JStorageSlider(int min, int max, int value) { super(min, max, value); previousValue = value; defaultValue = value; setMinorTickSpacing(5); setMajorTickSpacing(10); setPaintTicks(true); setPaintLabels(true); setLabelTable(createStandardLabels(10)); } public int getPreviousValue() { return previousValue; } public void setPreviousValue(int value) { previousValue = value; } public void resetDefault() { this.setValue(defaultValue); previousValue = defaultValue; } } private static class AdjustingSliderGroup { private final ArrayList<JStorageSlider> storageSliders; private int sliderIndex = 0; AdjustingSliderGroup(JStorageSlider... sliders) { storageSliders = new ArrayList<>(); for(JStorageSlider slider: sliders) { storageSliders.add(slider); slider.addChangeListener(e -> fireSliderChangedEvent((JStorageSlider) e.getSource())); } } public void fireSliderChangedEvent(JStorageSlider source) { // We don't want to do anything if the value isn't changing if(!source.getValueIsAdjusting()) return; // Update the slider depending on how much it's changed relative to its previous position int change = (source.getValue() - source.getPreviousValue()); updateSliderPosition(change, source); } private void updateSliderPosition(int change, JStorageSlider source) { int remaining = change; while (remaining != 0) { // Get the currently indexed slider JStorageSlider slider = storageSliders.get(sliderIndex); // If it's not the slider that fired the event if (slider != source) { // Check we don't go over the upper and lower bounds if (remaining < 0 || (remaining > 0 && slider.getValue() > 0)) { // Adjust the currently selected slider by +/- 1 int adjustment = Integer.signum(remaining); slider.setValue(slider.getValue() - adjustment); remaining -= adjustment; } } // Select the next slider in the list of sliders sliderIndex = (sliderIndex + 1) % storageSliders.size(); } for (JStorageSlider slider : storageSliders) { slider.setPreviousValue(slider.getValue()); } } List<JStorageSlider> getSliders() { return storageSliders; } } public RatioAdjustingSliderPanel() { initPanel(); } private void initPanel() { // Create three sliders with default values creatureSlider = new JStorageSlider(0, 100, DeckGeneratorPool.DEFAULT_CREATURE_PERCENTAGE); nonCreatureSlider = new JStorageSlider(0, 100, DeckGeneratorPool.DEFAULT_NON_CREATURE_PERCENTAGE); landSlider = new JStorageSlider(0, 100, DeckGeneratorPool.DEFAULT_LAND_PERCENTAGE); sg = new AdjustingSliderGroup(creatureSlider, nonCreatureSlider, landSlider); this.setLayout(new GridLayout(3, 1)); this.add(createSliderPanel("Creatures ", creatureSlider)); this.add(createSliderPanel("Non-creatures ", nonCreatureSlider)); this.add(createSliderPanel("Lands ", landSlider)); setEnabled(true); } private JPanel createSliderPanel(String label, JStorageSlider slider) { JPanel sliderPanel = new JPanel(new BorderLayout()); // Title JLabel titleLabel = new JLabel(label); textLabels.add(titleLabel); sliderPanel.add(titleLabel, BorderLayout.WEST); // Slider slider.setToolTipText("Percentage of " + label.trim().toLowerCase() + " in the generated deck."); sliderPanel.add(slider, BorderLayout.CENTER); // Percentage JLabel percentageLabel = createChangingPercentageLabel(slider); textLabels.add(percentageLabel); sliderPanel.add(percentageLabel, BorderLayout.EAST); return sliderPanel; } private static JLabel createChangingPercentageLabel(final JSlider slider) { final JLabel label = new JLabel(" " + String.valueOf(slider.getValue()) + '%'); slider.addChangeListener(e -> { String value = String.valueOf(slider.getValue()); StringBuilder labelBuilder = new StringBuilder(); // Pad with spaces so all percentage labels are of equal size for(int i = 0; i < (5-value.length()); i++) { labelBuilder.append(" "); } labelBuilder.append(value); labelBuilder.append('%'); label.setText(labelBuilder.toString()); }); return label; } @Override public void setEnabled(boolean enabled) { for(JStorageSlider slider: sg.getSliders()) { slider.setEnabled(enabled); } for(JLabel label: textLabels) { label.setEnabled(enabled); } } public void resetValues() { for(JStorageSlider slider: sg.getSliders()) { slider.resetDefault(); } } public int getCreaturePercentage() { return creatureSlider.getValue(); } public int getNonCreaturePercentage() { return nonCreatureSlider.getValue(); } public int getLandPercentage() { return landSlider.getValue(); } public void setCreaturePercentage(int percentage) { creatureSlider.setValue(percentage); creatureSlider.previousValue = percentage; } public void setNonCreaturePercentage(int percentage) { nonCreatureSlider.setValue(percentage); nonCreatureSlider.previousValue = percentage; } public void setLandPercentage(int percentage) { landSlider.setValue(percentage); landSlider.previousValue = percentage; } }