package org.erikaredmark.monkeyshines.editor.dialog; import java.awt.Canvas; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import javax.swing.AbstractAction; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JColorChooser; import javax.swing.JDialog; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTabbedPane; import javax.swing.ScrollPaneConstants; import javax.swing.SpringLayout; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.erikaredmark.monkeyshines.background.Background; import org.erikaredmark.monkeyshines.background.FullBackground; import org.erikaredmark.monkeyshines.background.SingleColorBackground; import org.erikaredmark.monkeyshines.editor.resource.EditorResource; import org.erikaredmark.monkeyshines.resource.WorldResource; import org.erikaredmark.util.swing.layout.WrapLayout; public class SetBackgroundDialog extends JDialog { private static final long serialVersionUID = 1L; private final Canvas backgroundViewer; // The model for this dialog: The user's selected background choice. private Background selectedBackground; public SetBackgroundDialog(final WorldResource rsrc, final Background currentBackground) { this.selectedBackground = currentBackground; // Three tabs: One for full backgrounds, one for patterns, and finally one for // a colour picker. // Show a 'selected background' to the right so they know which of the three tabs // is active and which background was picked. setTitle("Background Picker"); final SpringLayout springLayout = new SpringLayout(); setLayout(springLayout); /* --------------------- Full background Panel --------------------- */ final JPanel fullBackgroundPanel = new JPanel(); createThumbnailSpan(fullBackgroundPanel, rsrc, true); final JScrollPane fullBackgroundScrollPane = new JScrollPane(fullBackgroundPanel); fullBackgroundScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); /* ------------------------- Pattern Panel ------------------------- */ final JPanel patternPanel = new JPanel(); createThumbnailSpan(patternPanel, rsrc, false); final JScrollPane patternScrollPane = new JScrollPane(patternPanel); patternScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); /* ----------------------------- Colour ---------------------------- */ // If the background is initially a color background, use that as first color. Otherwise default black Color initialColor = currentBackground instanceof SingleColorBackground ? ((SingleColorBackground)currentBackground).getColor() : Color.BLACK; final JColorChooser colorChooser = new JColorChooser(initialColor); colorChooser.getSelectionModel().addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent event) { Color newColor = colorChooser.getColor(); setSelectedBackground(new SingleColorBackground(newColor) ); } }); final JScrollPane singleColorPane = new JScrollPane(colorChooser); final JTabbedPane differentBackgroundsPane = new JTabbedPane(); differentBackgroundsPane.addTab("Full", fullBackgroundScrollPane); differentBackgroundsPane.addTab("Pattern", patternScrollPane); differentBackgroundsPane.addTab("Solid", singleColorPane); differentBackgroundsPane.setPreferredSize(new Dimension(720, 420) ); /* ---------------------------- Viewer ------------------------------ */ backgroundViewer = new Canvas() { private static final long serialVersionUID = 1L; @Override public void paint(Graphics g) { if (selectedBackground instanceof FullBackground) { BufferedImage thumbnail = EditorResource.generateThumbnailForBackground((FullBackground)selectedBackground); Graphics2D g2d = (Graphics2D) g; g2d.drawImage(thumbnail, 0, 0, 160, 100, 0, 0, 160, 100, null); } else { // Solid colour; technically this only draws a portion of it, but that doesn't matter. selectedBackground.draw((Graphics2D)g); } } }; backgroundViewer.setSize(160, 100); /* ------------------------ Okay and Cancel -------------------------- */ final JButton okay = new JButton(new AbstractAction("Okay") { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { setVisible(false); } }); final JButton cancel = new JButton(new AbstractAction("Cancel") { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { // reset selected to original selectedBackground = currentBackground; setVisible(false); } }); /* --------------- Layout Components -------------- */ add(differentBackgroundsPane); springLayout.putConstraint(SpringLayout.WEST, backgroundViewer, 0, SpringLayout.EAST, this); springLayout.putConstraint(SpringLayout.NORTH, backgroundViewer, 0, SpringLayout.SOUTH, differentBackgroundsPane); add(backgroundViewer); springLayout.putConstraint(SpringLayout.NORTH, okay, 2, SpringLayout.SOUTH, backgroundViewer); add(okay); springLayout.putConstraint(SpringLayout.WEST, cancel, 4, SpringLayout.EAST, okay); springLayout.putConstraint(SpringLayout.NORTH, cancel, 0, SpringLayout.NORTH, okay); add(cancel); setSize(730, 600); } /** * * Adds to the given panel buttons with thumbnails all generated from the given * list of backgrounds, along with having each one set the background to * the chosen one. * * @param fullOrPattern * {@code true} to create a span for full backgrounds, {@code false} for patterns * */ private void createThumbnailSpan(JPanel panel, WorldResource rsrc, boolean fullOrPattern) { panel.setLayout(new WrapLayout(FlowLayout.LEFT, 0, 0) ); int count = fullOrPattern ? rsrc.getBackgroundCount() : rsrc.getPatternCount(); for (int i = 0; i < count; i++) { final Background next = fullOrPattern ? rsrc.getBackground(i) : rsrc.getPattern(i); BufferedImage image = EditorResource.generateThumbnailForBackground((FullBackground)next); JButton button = new JButton(new ImageIcon(image) ); button.setMargin(new Insets(2, 2, 2, 2) ); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { setSelectedBackground(next); } }); panel.add(button); } // Height will be dynamically calculated panel.setSize(700, 1); } /** * * Sets the users selected background preference, updating the 'current background' * display * */ private void setSelectedBackground(Background background) { selectedBackground = background; backgroundViewer.repaint(); } /** * * Launches this dialog, allowing the user to choose a background. The user may choose an existing * full background, pattern, or solid color. If the user closes the dialog without choosing, this * will return {@code null}; null should signify 'no change'. * * @param rsrc * the world resource to grab the backgrounds from * * @param currentBackground * the current background for the world. If the user makes no changes, this will be returned * * @return * a background instance the user chose, or the current background if they canceled. Never {@code null} * */ public static Background launch(WorldResource rsrc, Background currentBackground) { SetBackgroundDialog dialog = new SetBackgroundDialog(rsrc, currentBackground); dialog.setModal(true); dialog.setLocationRelativeTo(null); dialog.setVisible(true); return dialog.selectedBackground; } }