/*
* polycasso - Cubism Artwork generator
* Copyright 2009-2017 MeBigFatGuy.com
* Copyright 2009-2017 Dave Brosius
* Inspired by work by Roger Alsing
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*/
package com.mebigfatguy.polycasso;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.MessageFormat;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
/**
* the main window for showing the image as it is being improved on.
*/
public class PainterFrame extends JFrame implements ImageGeneratedListener {
private static final long serialVersionUID = 7729602294481171194L;
private PainterPanel panel;
private JMenuItem paintImage;
private JMenuItem copyImage;
private JMenuItem completeImage;
private JMenu saveAsMenu;
private JMenuItem saveAsPNGItem;
private JMenuItem saveAsSVGItem;
private JMenuItem saveAsJavaItem;
private JMenuItem quitItem;
private JMenuItem aboutItem;
private JMenuItem settingsItem;
private JMenuItem proxyItem;
private ImageGenerator generator;
private final Settings settings;
/**
* creates the main window, setups up menus and listeners
*/
public PainterFrame() {
setTitle(PolycassoBundle.getString(PolycassoBundle.Key.Title));
initComponents();
initMenus();
initListeners();
pack();
settings = loadSettings();
generator = null;
}
/**
* creates and lays out components for this frame
*/
private void initComponents() {
Container cp = getContentPane();
cp.setLayout(new BorderLayout(4, 4));
panel = new PainterPanel();
cp.add(panel, BorderLayout.CENTER);
}
/**
* initializes the menus
*/
private void initMenus() {
JMenuBar mb = new JMenuBar();
JMenu fileMenu = new JMenu(PolycassoBundle.getString(PolycassoBundle.Key.File));
paintImage = new JMenuItem(PolycassoBundle.getString(PolycassoBundle.Key.PaintImage));
fileMenu.add(paintImage);
copyImage = new JMenuItem(PolycassoBundle.getString(PolycassoBundle.Key.CopyImage));
fileMenu.add(copyImage);
completeImage = new JMenuItem(PolycassoBundle.getString(PolycassoBundle.Key.CompleteImage));
completeImage.setEnabled(false);
fileMenu.add(completeImage);
fileMenu.addSeparator();
saveAsMenu = new JMenu(PolycassoBundle.getString(PolycassoBundle.Key.SaveAs));
fileMenu.add(saveAsMenu);
saveAsPNGItem = new JMenuItem(PolycassoBundle.getString(PolycassoBundle.Key.PNG));
saveAsMenu.add(saveAsPNGItem);
saveAsSVGItem = new JMenuItem(PolycassoBundle.getString(PolycassoBundle.Key.SVG));
saveAsMenu.add(saveAsSVGItem);
saveAsJavaItem = new JMenuItem(PolycassoBundle.getString(PolycassoBundle.Key.JAVA));
saveAsMenu.add(saveAsJavaItem);
saveAsMenu.setEnabled(false);
fileMenu.addSeparator();
quitItem = new JMenuItem(PolycassoBundle.getString(PolycassoBundle.Key.Quit));
fileMenu.add(quitItem);
mb.add(fileMenu);
JMenu editMenu = new JMenu(PolycassoBundle.getString(PolycassoBundle.Key.Edit));
settingsItem = new JMenuItem(PolycassoBundle.getString(PolycassoBundle.Key.Settings));
editMenu.add(settingsItem);
proxyItem = new JMenuItem(PolycassoBundle.getString(PolycassoBundle.Key.Proxy));
editMenu.add(proxyItem);
mb.add(editMenu);
JMenu aboutMenu = new JMenu(PolycassoBundle.getString(PolycassoBundle.Key.About));
aboutItem = new JMenuItem(PolycassoBundle.getString(PolycassoBundle.Key.AboutPolycasso));
aboutMenu.add(aboutItem);
mb.add(aboutMenu);
setJMenuBar(mb);
}
/**
* initializes the listeners for the various components
*/
private void initListeners() {
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent we) {
dispose();
try {
saveSettings(settings);
} catch (IOException e) {
} finally {
System.exit(0);
}
}
});
paintImage.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
try {
Image targetImage = RandomImageFinder.findImage(settings);
beginGenerating(targetImage);
} catch (IOException ioe) {
JOptionPane.showMessageDialog(PainterFrame.this, ioe.getMessage());
}
}
});
copyImage.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
try {
String url = JOptionPane.showInputDialog(PainterFrame.this, PolycassoBundle.getString(PolycassoBundle.Key.EnterURL));
if (url != null) {
Image targetImage = new ImageIcon(URLFetcher.fetchURLData(url, settings.getProxyHost(), settings.getProxyPort())).getImage();
beginGenerating(targetImage);
}
} catch (IOException ioe) {
JOptionPane.showMessageDialog(PainterFrame.this, ioe.getMessage());
}
}
});
completeImage.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
if (generator != null) {
generator.complete();
}
completeImage.setEnabled(false);
}
});
saveAsPNGItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
saveImage(FileType.PNG);
}
});
saveAsSVGItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
saveImage(FileType.SVG);
}
});
saveAsJavaItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
saveImage(FileType.Java);
}
});
quitItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
if (generator != null) {
generator.stopGenerating();
}
dispose();
try {
saveSettings(settings);
} catch (IOException e) {
} finally {
System.exit(0);
}
}
});
settingsItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
SettingsDialog dialog = new SettingsDialog(settings);
dialog.setLocationRelativeTo(PainterFrame.this);
dialog.setModal(true);
dialog.setVisible(true);
if (dialog.isOK()) {
Settings dlgSettings = dialog.getSettings();
settings.setGenerationSize(dlgSettings.getGenerationSize());
settings.setEliteSize(dlgSettings.getEliteSize());
settings.setUseAnnealing(dlgSettings.isUseAnnealing());
settings.setStartTemperature(dlgSettings.getStartTemperature());
settings.setCoolingRate(dlgSettings.getCoolingRate());
settings.setMaxImageSize(dlgSettings.getMaxImageSize());
settings.setMaxPolygons(dlgSettings.getMaxPolygons());
settings.setMaxPoints(dlgSettings.getMaxPoints());
settings.setMaxPtMovement(dlgSettings.getMaxPtMovement());
}
}
});
proxyItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
ProxyDialog dialog = new ProxyDialog(settings);
dialog.setLocationRelativeTo(PainterFrame.this);
dialog.setModal(true);
dialog.setVisible(true);
if (dialog.isOK()) {
Settings dlgSettings = dialog.getSettings();
settings.setProxyHost(dlgSettings.getProxyHost());
settings.setProxyPort(dlgSettings.getProxyPort());
}
}
});
aboutItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
AboutDialog ad = new AboutDialog();
ad.setLocationRelativeTo(PainterFrame.this);
ad.setModal(true);
ad.setVisible(true);
}
});
}
/**
* implements the ImageGeneratedListener interface to redraw the new best image
*
* @param event
* the event describing the new best image
*/
@Override
public void imageGenerated(ImageGeneratedEvent event) {
panel.setImage(event.getImage());
}
/**
* save the image to what ever format was chosen
*
* @param type
* the chosen file type to save as
*/
public void saveImage(FileType type) {
try {
FileSelector selector = new FileSelector(type);
String fileName = selector.getFileName();
if (fileName != null) {
File f = new File(fileName);
if (f.exists()) {
String message = MessageFormat.format(PolycassoBundle.getString(PolycassoBundle.Key.OverwriteWarning), fileName);
int choice = JOptionPane.showConfirmDialog(PainterFrame.this, message, PolycassoBundle.getString(PolycassoBundle.Key.SaveAs),
JOptionPane.YES_NO_OPTION);
if (choice != JOptionPane.YES_OPTION) {
return;
}
}
type.getSaver().save(fileName, generator.getImageSize(), generator.getBestData());
}
} catch (IOException ioe) {
String message = MessageFormat.format(PolycassoBundle.getString(PolycassoBundle.Key.SaveFailure), ioe.getMessage());
JOptionPane.showMessageDialog(PainterFrame.this, message);
}
}
private void beginGenerating(Image targetImage) {
if (generator != null) {
generator.stopGenerating();
}
ImageSizer sizer = new ImageSizer(targetImage);
Dimension size = new Dimension(sizer.getWidth(), sizer.getHeight());
generator = new DefaultImageGenerator(settings, targetImage, size);
panel.setTarget(generator.getTargetImage());
size = generator.getImageSize();
Dimension wSize = new Dimension(size);
wSize.height += 2 * PainterFrame.this.getJMenuBar().getHeight();
if (Polycasso.DEBUG) {
wSize.height *= 2;
}
setSize(wSize);
generator = new DefaultImageGenerator(settings, targetImage, size);
generator.addImageGeneratedListener(PainterFrame.this);
generator.startGenerating();
completeImage.setEnabled(true);
saveAsMenu.setEnabled(true);
}
private Settings loadSettings() {
try {
Path polyPath = getSettingsDirectory();
try (ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(Files.newInputStream(polyPath.resolve("settings.ser"))))) {
return (Settings) ois.readObject();
}
} catch (Exception e) {
return new Settings();
}
}
private void saveSettings(Settings s) throws IOException {
Path polyPath = getSettingsDirectory();
try (ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(Files.newOutputStream(polyPath.resolve("settings.ser"))))) {
oos.writeObject(s);
} catch (Exception e) {
}
}
private Path getSettingsDirectory() throws IOException {
Path polyPath = Paths.get(System.getProperty("user.home"), ".polycasso");
Files.createDirectories(polyPath);
return polyPath;
}
}