/*
* Copyright © 2010-2011 Rebecca G. Bettencourt / Kreative Software
* <p>
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* <a href="http://www.mozilla.org/MPL/">http://www.mozilla.org/MPL/</a>
* <p>
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
* <p>
* Alternatively, the contents of this file may be used under the terms
* of the GNU Lesser General Public License (the "LGPL License"), in which
* case the provisions of LGPL License are applicable instead of those
* above. If you wish to allow use of your version of this file only
* under the terms of the LGPL License and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the LGPL License. If you do not delete
* the provisions above, a recipient may use your version of this file
* under either the MPL or the LGPL License.
* @since PowerPaint 1.0
* @author Rebecca G. Bettencourt, Kreative Software
*/
package com.kreative.paint.ui;
import java.awt.Color;
import java.awt.FileDialog;
import java.awt.Frame;
import java.awt.Image;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import com.kreative.paint.Canvas;
import com.kreative.paint.CanvasController;
import com.kreative.paint.CanvasView;
import com.kreative.paint.Layer;
import com.kreative.paint.document.undo.History;
import com.kreative.paint.document.undo.HistoryEvent;
import com.kreative.paint.document.undo.HistoryListener;
import com.kreative.paint.filter.Filter;
import com.kreative.paint.filter.FilterUI;
import com.kreative.paint.format.Format;
import com.kreative.paint.format.FormatUI;
import com.kreative.paint.format.PowerPaintFormat;
import com.kreative.paint.io.MonitoredInputStream;
import com.kreative.paint.io.MonitoredOutputStream;
import com.kreative.paint.tool.ToolCommand;
import com.kreative.paint.ui.dialog.SaveChangesDialog;
import com.kreative.paint.ui.menu.CKPMenuBar;
import com.kreative.paint.ui.progress.IOProgressDialog;
import com.kreative.paint.util.ImageUtils;
public class CKPDocument {
private CKPApplication application;
private File documentFile;
private Format documentFormat;
private boolean changed;
private History history;
private Canvas canvas;
private CanvasView canvasView;
private JScrollPane canvasScrollPane;
private CanvasController canvasController;
private JFrame documentWindow;
private PageFormat pageSetup;
private Filter lastFilter;
public CKPDocument(CKPApplication app, File file, Format format, Canvas c) {
application = app;
documentFile = file;
documentFormat = format;
changed = false;
if (c.getHistory() == null) {
c.setHistory(history = new History());
} else {
history = c.getHistory();
}
canvas = c;
canvasView = new CanvasView(c);
canvasView.setOpaque(true);
canvasView.setBackground(Color.white);
canvasScrollPane = new JScrollPane(canvasView, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
canvasScrollPane.getViewport().setOpaque(true);
canvasScrollPane.getViewport().setBackground(Color.gray);
canvasScrollPane.setOpaque(true);
canvasScrollPane.setBackground(Color.gray);
JPanel p1 = new JPanel();
p1.setBackground(Color.white);
p1.setBorder(BorderFactory.createMatteBorder(1, 1, 0, 0, Color.white));
canvasScrollPane.setCorner(JScrollPane.LOWER_RIGHT_CORNER, p1);
canvasController = new CanvasController(canvas, canvasView, app.getToolContext(), app.getPaintContext());
documentWindow = new JFrame(file == null ? UIUtilities.messages.getString("defaultTitle") : file.getName());
documentWindow.setContentPane(canvasScrollPane);
documentWindow.setJMenuBar(new CKPMenuBar(app, this));
documentWindow.getRootPane().putClientProperty("Window.documentFile", file);
documentWindow.getRootPane().putClientProperty("Window.documentModified", false);
documentWindow.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
pageSetup = PrinterJob.getPrinterJob().defaultPage();
lastFilter = null;
history.addHistoryListener(new HistoryListener() {
public void transactionBegan(HistoryEvent e) {}
public void transactionCommitted(HistoryEvent e) {
changed = true;
documentWindow.getRootPane().putClientProperty("Window.documentModified", true);
}
public void transactionContinued(HistoryEvent e) {}
public void transactionLimitChanged(HistoryEvent e) {}
public void transactionRedone(HistoryEvent e) {
changed = true;
documentWindow.getRootPane().putClientProperty("Window.documentModified", true);
}
public void transactionRenamed(HistoryEvent e) {}
public void transactionRolledBack(HistoryEvent e) {}
public void transactionUndone(HistoryEvent e) {
changed = true;
documentWindow.getRootPane().putClientProperty("Window.documentModified", true);
}
});
documentWindow.addWindowListener(new WindowListener() {
public void windowActivated(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
public void windowClosing(WindowEvent e) { doClose(); }
public void windowDeactivated(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
});
}
public void show() {
documentWindow.pack();
documentWindow.setLocationRelativeTo(null);
documentWindow.setVisible(true);
}
public CKPApplication getApplication() {
return application;
}
public File getDocumentFile() {
return documentFile;
}
public Format getDocumentFormat() {
return documentFormat;
}
public boolean isChanged() {
return changed;
}
public History getHistory() {
return history;
}
public Canvas getCanvas() {
return canvas;
}
public CanvasView getCanvasView() {
return canvasView;
}
public JScrollPane getCanvasScrollPane() {
return canvasScrollPane;
}
public CanvasController getCanvasController() {
return canvasController;
}
public JFrame getDocumentWindow() {
return documentWindow;
}
public PageFormat getPageSetup() {
return pageSetup;
}
public Filter getLastFilter() {
return lastFilter;
}
public boolean doClose() {
if (changed) {
String document = (documentFile == null ? UIUtilities.messages.getString("defaultTitle") : documentFile.getName());
SaveChangesDialog.Action a = new SaveChangesDialog(documentWindow, document).showDialog();
switch (a) {
case DONT_SAVE:
documentWindow.dispose();
application.removeDocument(this);
return true;
case CANCEL:
return false;
case SAVE:
doSave();
documentWindow.dispose();
application.removeDocument(this);
return true;
default:
return false;
}
} else {
documentWindow.dispose();
application.removeDocument(this);
return true;
}
}
public void doMinimize() {
if (documentWindow.getState() == Frame.ICONIFIED)
documentWindow.setState(Frame.NORMAL);
else
documentWindow.setState(Frame.ICONIFIED);
}
public void doZoom() {
if (documentWindow.getExtendedState() == Frame.MAXIMIZED_BOTH)
documentWindow.setExtendedState(Frame.NORMAL);
else
documentWindow.setExtendedState(Frame.MAXIMIZED_BOTH);
}
public boolean enableSave() {
return changed;
}
public void doSave() {
doSaveAs(documentFile, documentFormat);
}
public void doSaveAs(File f, Format fmt) {
if (f == null) {
FileDialog fd = new FileDialog(
new Frame(),
UIUtilities.messages.getString("savedlg.title"),
FileDialog.SAVE
);
fd.setVisible(true);
if (fd.getDirectory() == null || fd.getFile() == null) return;
f = new File(fd.getDirectory(), fd.getFile());
}
if (fmt == null) {
fmt = application.getFormatManager().getFormatForFileName(f.getName(), true);
if (fmt == null) {
JOptionPane.showMessageDialog(
null,
UIUtilities.messages.getString("savedlg.unknown"),
UIUtilities.messages.getString("savedlg.title"),
JOptionPane.INFORMATION_MESSAGE
);
fmt = new PowerPaintFormat();
}
}
if (!fmt.usesWriteOptionForm() || new FormatUI(null, fmt, true).showOptions()) {
final File f2 = f;
final Format fmt2 = fmt;
final IOProgressDialog dlg = new IOProgressDialog((Frame)null, fmt, 0, fmt.approximateFileSize(canvas), true);
dlg.setVisible(true);
try {
FileOutputStream fos = new FileOutputStream(f2);
MonitoredOutputStream mos = new MonitoredOutputStream(dlg, fos, false);
BufferedOutputStream bos = new BufferedOutputStream(mos);
DataOutputStream dos = new DataOutputStream(bos);
fmt2.write(canvas, dos, dlg);
dos.flush();
bos.flush();
mos.flush();
fos.flush();
dos.close();
bos.close();
mos.close();
fos.close();
application.getFormatManager().postProcess(f2, fmt2);
documentFile = f2;
documentFormat = fmt2;
changed = false;
documentWindow.setTitle(f2.getName());
documentWindow.getRootPane().putClientProperty("Window.documentFile", f2);
documentWindow.getRootPane().putClientProperty("Window.documentModified", false);
} catch (Exception ex) {
ex.printStackTrace();
dlg.dispose();
JOptionPane.showMessageDialog(
null,
UIUtilities.messages.getString("savedlg.error").replace("$", fmt2.getName()),
UIUtilities.messages.getString("savedlg.title"),
JOptionPane.ERROR_MESSAGE
);
}
}
}
public boolean enableRevert() {
return (documentFile != null && documentFormat != null);
}
public void doRevert() {
if (documentFile != null && documentFormat != null) {
final IOProgressDialog dlg = new IOProgressDialog((Frame)null, documentFormat, 0, (int)documentFile.length(), false);
dlg.setVisible(true);
try {
FileInputStream fis = new FileInputStream(documentFile);
MonitoredInputStream mis = new MonitoredInputStream(dlg, fis, false);
BufferedInputStream bis = new BufferedInputStream(mis);
DataInputStream dis = new DataInputStream(bis);
Canvas c = documentFormat.read(dis, dlg);
dis.close();
bis.close();
mis.close();
fis.close();
history = new History();
canvas = c;
canvas.setHistory(history);
canvasView.setCanvas(canvas);
canvasController.setCanvas(canvas);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
canvasScrollPane.repaint();
canvasController.notifyCanvasControllerListeners();
}
});
history.addHistoryListener(new HistoryListener() {
public void transactionBegan(HistoryEvent e) {}
public void transactionCommitted(HistoryEvent e) {
changed = true;
documentWindow.getRootPane().putClientProperty("Window.documentModified", true);
}
public void transactionContinued(HistoryEvent e) {}
public void transactionLimitChanged(HistoryEvent e) {}
public void transactionRedone(HistoryEvent e) {
changed = true;
documentWindow.getRootPane().putClientProperty("Window.documentModified", true);
}
public void transactionRenamed(HistoryEvent e) {}
public void transactionRolledBack(HistoryEvent e) {}
public void transactionUndone(HistoryEvent e) {
changed = true;
documentWindow.getRootPane().putClientProperty("Window.documentModified", true);
}
});
changed = false;
documentWindow.getRootPane().putClientProperty("Window.documentModified", false);
} catch (Exception ex) {
ex.printStackTrace();
dlg.dispose();
JOptionPane.showMessageDialog(
null,
UIUtilities.messages.getString("opendlg.error").replace("$", documentFormat.getName()),
UIUtilities.messages.getString("opendlg.title"),
JOptionPane.ERROR_MESSAGE
);
}
}
}
public void doPageSetup() {
PrinterJob pj = PrinterJob.getPrinterJob();
pageSetup = pj.pageDialog(pageSetup == null ? pj.defaultPage() : pageSetup);
}
public void doPrint(boolean withDialog) {
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setPrintable(canvas, pageSetup == null ? pj.defaultPage() : pageSetup);
if (!withDialog || pj.printDialog()) {
try {
pj.print();
} catch (PrinterException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(
null,
UIUtilities.messages.getString("print.error"),
UIUtilities.messages.getString("print.title"),
JOptionPane.ERROR_MESSAGE
);
}
}
}
public String undoName() {
return history.canUndo() ? history.getUndoName() : "";
}
public boolean enableUndo() {
return history.canUndo();
}
public void doUndo() {
if (history.canUndo()) {
history.undo();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
canvasScrollPane.repaint();
canvasController.notifyCanvasControllerListeners();
}
});
}
}
public String redoName() {
return history.canRedo() ? history.getRedoName() : "";
}
public boolean enableRedo() {
return history.canRedo();
}
public void doRedo() {
if (history.canRedo()) {
history.redo();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
canvasScrollPane.repaint();
canvasController.notifyCanvasControllerListeners();
}
});
}
}
public boolean enableToolCommand(ToolCommand cmd) {
return canvasController.enableCommand(cmd);
}
public void doToolCommand(ToolCommand cmd) {
if (canvasController.enableCommand(cmd)) {
canvasController.doCommand(cmd);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
canvasScrollPane.repaint();
canvasController.notifyCanvasControllerListeners();
}
});
}
}
public void doActualSize() {
canvasView.setScale(1.0f);
canvasScrollPane.repaint();
}
public void doZoomIn() {
canvasView.setScale(canvasView.getScale()*2.0f);
canvasScrollPane.repaint();
}
public void doZoomOut() {
canvasView.setScale(canvasView.getScale()/2.0f);
canvasScrollPane.repaint();
}
public void doFilter(Filter f) {
history.begin(f.getName());
if (canvas.isPaintSelectionPopped()) {
Layer l = canvas.getPaintDrawLayer();
Image src = l.getPoppedImage();
if (!f.usesOptionForm() || new FilterUI(documentWindow, f, src).showOptions()) {
lastFilter = f;
Image dst = f.filter(src);
if (dst != null && dst != src) {
l.setPoppedImage(ImageUtils.toBufferedImage(dst, true), l.getPoppedImageTransform());
}
}
} else if (canvas.getPaintSelection() != null) {
canvas.popPaintSelection(false, false);
Layer l = canvas.getPaintDrawLayer();
Image src = l.getPoppedImage();
if (!f.usesOptionForm() || new FilterUI(documentWindow, f, src).showOptions()) {
lastFilter = f;
Image dst = f.filter(src);
if (dst != null && dst != src) {
l.setPoppedImage(ImageUtils.toBufferedImage(dst, true), l.getPoppedImageTransform());
}
}
canvas.pushPaintSelection();
} else {
int w = canvas.getWidth();
int h = canvas.getHeight();
BufferedImage src = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Layer l = canvas.getPaintDrawLayer();
int[] pixels = new int[w*h];
l.getRGB(-l.getX(), -l.getY(), w, h, pixels, 0, w);
src.setRGB(0, 0, w, h, pixels, 0, w);
if (!f.usesOptionForm() || new FilterUI(documentWindow, f, src).showOptions()) {
lastFilter = f;
Image dst = f.filter(src);
if (dst != null && dst != src) {
BufferedImage db = ImageUtils.toBufferedImage(dst, false);
db.getRGB(0, 0, w, h, pixels, 0, w);
l.setRGB(-l.getX(), -l.getY(), w, h, pixels, 0, w);
}
}
}
history.commit();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
canvasScrollPane.repaint();
canvasController.notifyCanvasControllerListeners();
}
});
}
public String lastFilterName() {
return (lastFilter == null) ? "" : lastFilter.getName();
}
public boolean enableLastFilter() {
return lastFilter != null;
}
public void doLastFilter() {
if (lastFilter == null) return;
history.begin(lastFilter.getName());
if (canvas.isPaintSelectionPopped()) {
Layer l = canvas.getPaintDrawLayer();
Image src = l.getPoppedImage();
Image dst = lastFilter.filter(src);
if (dst != null && dst != src) {
l.setPoppedImage(ImageUtils.toBufferedImage(dst, true), l.getPoppedImageTransform());
}
} else if (canvas.getPaintSelection() != null) {
canvas.popPaintSelection(false, false);
Layer l = canvas.getPaintDrawLayer();
Image src = l.getPoppedImage();
Image dst = lastFilter.filter(src);
if (dst != null && dst != src) {
l.setPoppedImage(ImageUtils.toBufferedImage(dst, true), l.getPoppedImageTransform());
}
canvas.pushPaintSelection();
} else {
int w = canvas.getWidth();
int h = canvas.getHeight();
BufferedImage src = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Layer l = canvas.getPaintDrawLayer();
int[] pixels = new int[w*h];
l.getRGB(-l.getX(), -l.getY(), w, h, pixels, 0, w);
src.setRGB(0, 0, w, h, pixels, 0, w);
Image dst = lastFilter.filter(src);
if (dst != null && dst != src) {
BufferedImage db = ImageUtils.toBufferedImage(dst, false);
db.getRGB(0, 0, w, h, pixels, 0, w);
l.setRGB(-l.getX(), -l.getY(), w, h, pixels, 0, w);
}
}
history.commit();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
canvasScrollPane.repaint();
canvasController.notifyCanvasControllerListeners();
}
});
}
}