/** * @file EffectsFrame.java * @brief Class implementing an effect chooser for sprites and backgrounds. * * @section License * * Copyright (C) 2013-2014 Robert B. Colton * This file is a part of the LateralGM IDE. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. **/ package org.lateralgm.components; import java.awt.CardLayout; import java.awt.Component; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.Shape; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.image.BufferedImage; import java.util.List; import javax.swing.AbstractButton; import javax.swing.BorderFactory; import javax.swing.GroupLayout; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.ListCellRenderer; import javax.swing.GroupLayout.Alignment; import org.lateralgm.components.ImageEffects.EffectOptionListener; import org.lateralgm.components.ImageEffects.ImageEffect; import org.lateralgm.main.LGM; import org.lateralgm.main.Util; import org.lateralgm.messages.Messages; import static javax.swing.GroupLayout.PREFERRED_SIZE; public class EffectsFrame extends JFrame implements ActionListener, EffectOptionListener { /** * NOTE: Default UID generated, change if necessary. */ private static final long serialVersionUID = 4668913557919192011L; private static EffectsFrame INSTANCE = null; private static ImageEffect[] effects = null; private JComboBox<ImageEffect> effectsCombo = null; private List<BufferedImage> images = null; private AbstractButton applyButton; private AbstractButton closeButton; private EffectsFrameListener listener = null; private ImageEffectPreview beforePreview; private ImageEffectPreview afterPreview; public abstract interface EffectsFrameListener { public abstract void applyEffects(List<BufferedImage> imgs); } public void setEffectsListener(EffectsFrameListener ln) { listener = ln; } public static EffectsFrame getInstance(List<BufferedImage> imgs) { if (INSTANCE == null) INSTANCE = new EffectsFrame(); INSTANCE.setImages(imgs); return INSTANCE; } private class ImageEffectPreview extends JPanel { /** * NOTE: Default UID generated, change if necessary. */ private static final long serialVersionUID = -3708532748005061371L; BufferedImage image = null; public ImageEffectPreview() { JPanel jp = new JPanel() { /** * NOTE: Default UID generated, change if necessary. */ private static final long serialVersionUID = 1760158377097010861L; private BufferedImage transparentBackground; @Override public void paint(Graphics g) { if (image == null) return; Rectangle bounds = this.getBounds(); int swidth = image.getWidth(); int sheight = image.getHeight(); if (image.getWidth() > bounds.width) { float factor = (float) (bounds.getWidth() / image.getWidth()); swidth = bounds.width; sheight = (int) (factor * image.getHeight()); } if (sheight > bounds.height) { float factor = (float) (bounds.getHeight() / sheight); swidth = (int) (factor * swidth); sheight = bounds.height; } Graphics2D g2d = (Graphics2D) g; g2d.translate((bounds.width - swidth) / 2,(bounds.height - sheight) / 2); int width = (int)Math.ceil(swidth / 8f); int height = (int)Math.ceil(sheight / 8f); width = width < 1 ? 1 : width; height = height < 1 ? 1 : height; if (transparentBackground == null || transparentBackground.getWidth() != width || transparentBackground.getHeight() != height) { transparentBackground = Util.paintBackground(width, height); } Shape clip = g.getClip(); g.clipRect(0,0,swidth,sheight); g.drawImage(transparentBackground,0,0,transparentBackground.getWidth() * 8, transparentBackground.getHeight() * 8,null); g.drawImage(image,0,0,swidth,sheight,null); g.setClip(clip); } }; GroupLayout bl = new GroupLayout(this); bl.setHorizontalGroup(bl.createParallelGroup().addComponent(jp)); bl.setVerticalGroup(bl.createParallelGroup().addComponent(jp)); this.setLayout(bl); } public void setImage(BufferedImage img) { image = img; if (image != null) repaint(); } } public EffectsFrame() { setAlwaysOnTop(false); setDefaultCloseOperation(HIDE_ON_CLOSE); setSize(700,400); setLocationRelativeTo(LGM.frame); setTitle(Messages.getString("EffectsFrame.TITLE")); setIconImage(LGM.getIconForKey("EffectsFrame.ICON").getImage()); setResizable(true); beforePreview = new ImageEffectPreview(); beforePreview.setBorder(BorderFactory.createTitledBorder(Messages.getString("EffectsFrame.BEFORE"))); afterPreview = new ImageEffectPreview(); afterPreview.setBorder(BorderFactory.createTitledBorder(Messages.getString("EffectsFrame.AFTER"))); effects = new ImageEffect[12]; effects[0] = new ImageEffects.BlackAndWhiteEffect(); effects[1] = new ImageEffects.BlurEffect(); effects[2] = new ImageEffects.ColorizeEffect(); effects[3] = new ImageEffects.EdgeDetectEffect(); effects[4] = new ImageEffects.EmbossEffect(); effects[5] = new ImageEffects.FadeColorEffect(); effects[6] = new ImageEffects.InvertEffect(); effects[7] = new ImageEffects.IntensityEffect(); effects[8] = new ImageEffects.OpacityEffect(); effects[9] = new ImageEffects.RemoveColorEffect(); effects[10] = new ImageEffects.RemoveTransparencyEffect(); effects[11] = new ImageEffects.SharpenEffect(); final JPanel effectsOptions = new JPanel(new CardLayout()); for (ImageEffect effect : effects) { effect.addOptionUpdateListener(this); effectsOptions.add(effect.getOptionsPanel(),effect.getKey()); } effectsCombo = new JComboBox<ImageEffect>(effects); effectsCombo.setRenderer(new ListCellRenderer<ImageEffect>() { @Override public Component getListCellRendererComponent(JList<? extends ImageEffect> list, ImageEffect value, int index, boolean isSelected, boolean cellHasFocus) { return new JLabel(value.getName()); } }); effectsCombo.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent ie) { if (ie.getStateChange() != ItemEvent.SELECTED) return; ImageEffect effect = (ImageEffect) ie.getItem(); if (effect == null) return; CardLayout cl = (CardLayout)(effectsOptions.getLayout()); cl.show(effectsOptions, effect.getKey()); if (images == null || images.size() <= 0) return; BufferedImage img = images.get(0); if (img == null) return; afterPreview.setImage(effect.getAppliedImage(img)); } }); applyButton = new JButton(Messages.getString("EffectsFrame.APPLY")); applyButton.addActionListener(this); closeButton = new JButton(Messages.getString("EffectsFrame.CLOSE")); closeButton.addActionListener(this); GroupLayout gl = new GroupLayout(this.getContentPane()); gl.setAutoCreateContainerGaps(true); gl.setAutoCreateGaps(true); gl.setHorizontalGroup(gl.createParallelGroup() /**/.addGroup(gl.createSequentialGroup() /* */.addComponent(beforePreview) /* */.addComponent(afterPreview)) /**/.addGroup(gl.createSequentialGroup() /* */.addComponent(effectsCombo, PREFERRED_SIZE, PREFERRED_SIZE, PREFERRED_SIZE) /* */.addComponent(applyButton) /* */.addComponent(closeButton)) /**/.addComponent(effectsOptions)); gl.setVerticalGroup(gl.createSequentialGroup() /**/.addGroup(gl.createParallelGroup() /* */.addComponent(beforePreview) /* */.addComponent(afterPreview)) /**/.addGroup(gl.createParallelGroup(Alignment.BASELINE) /* */.addComponent(effectsCombo) /* */.addComponent(applyButton) /* */.addComponent(closeButton)) /**/.addComponent(effectsOptions, PREFERRED_SIZE, PREFERRED_SIZE, PREFERRED_SIZE)); this.setLayout(gl); } public void setImages(List<BufferedImage> imgs) { images = imgs; updatePreviews(); } @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == applyButton) { for (int i = 0; i < images.size(); i++){ ImageEffect effect = (ImageEffect) effectsCombo.getSelectedItem(); images.set(i,effect.getAppliedImage(images.get(i))); } if (listener != null) { listener.applyEffects(images); } updatePreviews(); } else if (e.getSource() == closeButton) { this.setVisible(false); listener = null; } } @Override public void optionsUpdated() { updatePreviews(); } public void updatePreviews() { ImageEffect effect = (ImageEffect) effectsCombo.getSelectedItem(); if (effect == null) return; if (images == null || images.size() <= 0) return; BufferedImage img = images.get(0); if (img == null) return; beforePreview.setImage(img); afterPreview.setImage(effect.getAppliedImage(img)); } }