/**
*
*/
package de.danielsenff.radds;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.Transferable;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Set;
import javax.imageio.ImageIO;
import javax.swing.ActionMap;
import javax.swing.JFileChooser;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.JSplitPane;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.filechooser.FileSystemView;
import model.TextureImage;
import org.jdesktop.application.Action;
import org.jdesktop.application.FrameView;
import org.jdesktop.application.ResourceMap;
import org.jdesktop.application.Task.BlockingScope;
import de.danielsenff.radds.models.ClipImage;
import de.danielsenff.radds.models.FilesListModel;
import de.danielsenff.radds.tasks.LoadImageTask;
import de.danielsenff.radds.util.OS;
import de.danielsenff.radds.view.FilesPanel;
import de.danielsenff.radds.view.InfoPanel;
import de.danielsenff.radds.view.canvas.BICanvas;
import de.danielsenff.radds.view.canvas.CanvasControlsPanel;
/**
* @author danielsenff
*
*/
public class RaddsView extends FrameView {
private FilesListModel openFilesModel;
private final FilesPanel filesPanel;
private File file;
private final CanvasControlsPanel canvasPanel;
private static JProgressBar progressBar;
private boolean opened = false;
private boolean modified = false;
private boolean paste = false;
private File chooserDirectory;
private TextureImage textureImage;
/**
* @param radds
*
*/
public RaddsView(final Radds radds) {
super(radds);
this.openFilesModel = new FilesListModel();
this.chooserDirectory = FileSystemView.getFileSystemView().getHomeDirectory();
// menu
initMenu();
// general layout
filesPanel = new FilesPanel();
canvasPanel = new CanvasControlsPanel(this);
final JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, filesPanel, canvasPanel);
splitPane.setDividerLocation(200);
splitPane.setContinuousLayout(true);
splitPane.setResizeWeight(0.0);
this.progressBar = new JProgressBar();
setComponent(splitPane);
}
private void initMenu() {
final JMenuBar menuBar = new JMenuBar();
final ResourceMap resourceMap = getResourceMap();
JMenu menuFile;
if(OS.isMacOS())
menuFile = new JMenu(resourceMap.getString("file.osx.menu"));
else
menuFile = new JMenu(resourceMap.getString("file.menu"));
menuFile.add(getAction("open"));
menuFile.add(getAction("export"));
menuBar.add(menuFile);
final JMenu menuEdit = new JMenu(resourceMap.getString("edit.menu"));
menuEdit.add(getAction("copy"));
menuBar.add(menuEdit);
JMenu menuHelp = new JMenu(getResourceString("help.menu"));
menuHelp.add(getAction("openAuthorURL"));
menuHelp.add(getAction("openWebsiteURL"));
menuHelp.add(getAction("openBugTrackerURL"));
menuBar.add(menuHelp);
setMenuBar(menuBar);
}
/**
* @return the progressbar
*/
public static JProgressBar getProgressbar() {
return progressBar;
}
/**
* Get the BufferedImage Canvas of this view.
* @return
*/
public BICanvas getCanvas() {
return this.canvasPanel.getCanvas();
}
/**
* Unused FileList of opened files. Currently only one opened file is supported.
* @return
*/
public FilesListModel getFilesListModel() {
return this.openFilesModel;
}
/**
* @return the progressBar
*/
public static synchronized final JProgressBar getProgressBar() {
return progressBar;
}
/**
* Set the bound file property and update the GUI.
* @param file
*/
public void setFile(final File file) {
File oldValue = this.file;
this.file = file;
String appId = getResourceString("Application.id");
getFrame().setTitle(file.getName() + " - " + appId);
firePropertyChange("file", oldValue, this.file);
}
/**
* True if the file value has been modified but not saved. The
* default value of this property is false.
* <p>
* This is a bound read-only property.
*
* @return the value of the modified property.
* @see #isModified
*/
public boolean isModified() {
return this.modified;
}
/**
* Sets the modified flag.
* @param modified
*/
public void setModified(final boolean modified) {
boolean oldValue = this.modified;
this.modified = modified;
// on program start, file may not be initialized
if(file != null){
String appId = getResourceString("Application.id");
String changed = modified ? "*" : "";
getFrame().setTitle(file.getName() + changed +" - " + appId);
}
firePropertyChange("modified", oldValue, this.modified);
}
/**
* @return the fileOpened
*/
public final boolean isOpened() {
return opened;
}
/**
* @param fileOpened the fileOpened to set
*/
public final void setOpened(boolean fileOpened) {
boolean oldvalue = this.opened;
this.opened = fileOpened;
firePropertyChange("opened", oldvalue, this.opened);
}
/**
* Returns the currently loaded image-file.
* @return
*/
public File getFile() {
return file;
}
/**
* Returns the currently opened {@link TextureImage}.
* @return
*/
public TextureImage getTextureImage() {
return this.textureImage;
}
/**
* Sets the image in the Canvas to the specified {@link TextureImage}.
* @param image
*/
public void setImage(final TextureImage image) {
TextureImage oldvalue = this.textureImage;
this.textureImage = image;
setOpened(true);
setFile(image.getFile());
getInfoPanel().setTextureFile(image);
this.canvasPanel.updateNumMipMaps();
firePropertyChange("textureImage", oldvalue, this.textureImage);
}
/**
* Sets the image in the Canvas to the specified {@link BufferedImage}.
* @param image
* @param file
*/
public void setImage(final BufferedImage image, final File file) {
getCanvas().setSourceBI(image);
setOpened(true);
setFile(file);
getInfoPanel().setTextureFile(image);
}
private InfoPanel getInfoPanel() {
return filesPanel.getInfoPanel();
}
private String getResourceString(final String key) {
return getResourceMap().getString(key);
}
/*
* Action definitions
*
*/
/**
* Convenience function for getting the {@link Action} by the given name.
* @param actionName
* @return
*/
public javax.swing.Action getAction(final String actionName) {
ActionMap actionMap = getContext().getActionMap(RaddsView.class, this);
return actionMap.get(actionName);
}
/**
* Copy the opened image
*/
@Action
(enabledProperty = "opened")
public void copy() {
/* Returns the currently loaded {@link BufferedImage} shown on the canvas.
* This may be different from the origin Image, as the canvas
* may be only displaying certain channels.
*/
BufferedImage bi = getCanvas().getCanvas();
Clipboard myClipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
ClipImage ci = new ClipImage(bi);
myClipboard.setContents(ci, new ClipboardOwner() {
public void lostOwnership(Clipboard clipboard, Transferable contents) { }
});
}
/**
* Export the opened image
*/
@Action
(enabledProperty = "opened")
public void export() {
String currentFileName = getFile().getName();
File defaultFileName = new File(currentFileName.substring(0, currentFileName.lastIndexOf('.')) + ".png");
final JFileChooser fc = new JFileChooser(chooserDirectory);
fc.setSelectedFile(defaultFileName);
fc.setFileFilter(new FileNameExtensionFilter("JPEG", "jpg"));
fc.setFileFilter(new FileNameExtensionFilter("PNG", "png"));
final int option = fc.showSaveDialog(getFrame());
if(option == JFileChooser.APPROVE_OPTION) {
try {
File file = fc.getSelectedFile();
chooserDirectory = file.getParentFile();
// TODO if(file.exists()= blabla
if(file.getName().toLowerCase().contains(".png")) {
//Get source image including alpha.
BufferedImage bi = getCanvas().getSource();
// TODO maybe option to say whether to save with or without alpha
// Save as PNG
ImageIO.write(bi, "png", file);
} else if(file.getName().toLowerCase().contains(".jpg") || file.getName().toLowerCase().contains(".jpeg")) {
//Get source image including alpha.
BufferedImage bi = getCanvas().getCanvas();
// TODO maybe option to say whether to save with or without alpha
// Save as jpg
ImageIO.write(bi, "jpg", file);
}
} catch (IOException e) {
final String msg = getResourceMap().getString("exportFailedMessage", getFile()) + e.getMessage();
final String title = getResourceMap().getString("exportFailedTitle");
final int type = JOptionPane.ERROR_MESSAGE;
RaddsView.getProgressBar().setIndeterminate(false);
RaddsView.getProgressBar().setVisible(false);
JOptionPane.showMessageDialog(getFrame(), msg, title, type);
}
}
}
/**
* Open a texture image file via FileChooser dialogue.
* @return
*/
@Action
(block = BlockingScope.APPLICATION)
public LoadImageTask open() {
/* unused so far, as radds doesn't modify
* if(isModified()) {
final int optionSave = showSaveConfirmation();
if(optionSave == JOptionPane.OK_OPTION) {
save().run();
}else if(optionSave == JOptionPane.CANCEL_OPTION) {
return null;
}
} */
final JFileChooser fc = new JFileChooser();
final String[] allExtensions = {"dds", "tga", "bmp", "gif", "jpg", "jpeg"};
fc.setFileFilter(new FileNameExtensionFilter("DirectDrawSurface texture", "dds"));
fc.setFileFilter(new FileNameExtensionFilter("GrandPrix4 TEX texture", "tex"));
fc.setFileFilter(new FileNameExtensionFilter("All supported images", allExtensions));
LoadImageTask task = null;
final int option = fc.showOpenDialog(null);
if (option == JFileChooser.APPROVE_OPTION) {
this.setModified(false);
task = new LoadImageTask(fc.getSelectedFile());
}
return task;
}
/**
* Opens the URL to the BugTracker.
*/
@Action
public void openBugTrackerURL() {
OS.openURLinDefaultBrowser(getResourceString("help.menu.bugtracker_url"));
}
/**
* Opens the URL to the BugTracker.
*/
@Action
public void openAuthorURL() {
OS.openURLinDefaultBrowser(getResourceString("help.menu.author_url"));
}
/**
* Opens the URL to the BugTracker.
*/
@Action
public void openWebsiteURL() {
OS.openURLinDefaultBrowser(getResourceString("help.menu.website_url"));
}
}