model.objects.Project.java Source code

Java tutorial

Introduction

Here is the source code for model.objects.Project.java

Source

package model.objects;

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

//import declarations
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;

import model.objects.history.HistorySession;
import model.objects.painting.Picture;
import model.objects.painting.po.PaintObject;
import model.objects.painting.po.PaintObjectDrawImage;
import model.settings.State;
import model.util.DPoint;
import model.util.adt.list.SecureList;
import model.util.adt.list.SecureListSort;
import model.util.paint.Utils;
import model.util.pdf.PDFUtils;
import model.util.pdf.XDocument;

/**
 * Project class: the main model class which contains
 * pages and their history.
 * 
 * By now, it is only possible to have one page inside one Project.
 * That is going to be changed in the future.
 * 
 * @author Julius Huelsmann
 * @version %I%, %U%
 */
public class Project implements Serializable {

    /**
     * Serial version UID.
     */
    private static final long serialVersionUID = 1L;

    /**
     * The PDF document on which the current project is based.
     */
    private XDocument document;

    /**
     * The index of the displayed page.
     */
    private int currentlyDisplayedPage;

    /**
     * HistorySession of one Pictureclass.
     */
    private HistorySession[] history;

    /**
     * Picture class.
     */
    private Picture[] pictures;

    public int getAmountPages() {
        if (pictures == null) {
            return 0;
        }
        return pictures.length;
    }

    /**
     * If the document is saved, the path to the PDF file is saved in here.
     */
    private String pathToPDF;

    /**
     * Constructor of project: 
     * Initializes the sub-classes Picture and History.
     */
    public Project() {

        // create new instances of picture and history.
        pictures = new Picture[1];
        history = new HistorySession[1];

        // initialize picture and history
        pictures[0] = new Picture();
        history[0] = new HistorySession(pictures[0]);

        // set current display page
        this.currentlyDisplayedPage = 0;
    }

    /**
     * Constructor of project: 
     * Initializes the sub-classes Picture and History.
     */
    public void initialize(final String _pString) {

        try {
            this.document = new XDocument(_pString, this);
            this.pathToPDF = _pString;
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (document != null) {

            // create new instances of picture and history.
            final int amount = document.getNumberOfPages();
            pictures = new Picture[amount];
            history = new HistorySession[amount];

            // initialize picture and history
            for (int i = 0; i < history.length; i++) {
                pictures[i] = new Picture();
                history[i] = new HistorySession(pictures[0]);

            }

            initialize();
            Dimension d = document.initialize();

            State.setImageSize(d);
            State.setImageShowSize(d);

        } else {

            // create new instances of picture and history.
            pictures = new Picture[1];
            history = new HistorySession[1];

            // initialize picture and history
            pictures[0] = new Picture();
            history[0] = new HistorySession(pictures[0]);

            initialize();
        }

        // set current display page
        this.currentlyDisplayedPage = 0;

    }

    /**
     * load an image to the picture. and write it into bi_resized.
     * 
     * @param _wsLoc
     *            the location of the image
     * @return the size of the image
     */
    public DPoint load(final String _wsLoc) {

        if (_wsLoc.endsWith(".pdf")) {

            this.currentlyDisplayedPage = 0;
            initialize(_wsLoc);
            return null;
        } else {
            this.currentlyDisplayedPage = 0;
            return pictures[0].load(_wsLoc);

        }
    }

    /**
     * initialize the history of the picture.
     */
    public final void initialize() {

        //set the Picture into Status and set history to the picture.
        for (int i = 0; i < history.length; i++) {
            pictures[i].initialize(history[i]);

        }
    }

    /**
     * Set the project class serializable by removing the XDocument.
     * The path to the PDF file that has been edited is saved in the 
     * String pathToPDF.
     * 
     * For being able to restore the PDF file, it is necessary that
     * the original PDF file has not been removed.
     */
    public final void setSerializable() {

        document.setSerializable();
    }

    /**
     * Restore the XDocument file from the path which is saved in the
     * class-variable pathToPDF.
     * 
     * @see setSerializable()
     */
    public final void restoreFormSerializable() {
        document.restoreFormSerializable(pathToPDF);

        // get size of the first picture.
        BufferedImage bi = PDFUtils.pdf2image(document.getPDDocument(), 1);

        State.setImageSize(new Dimension(bi.getWidth(), bi.getHeight()));
        State.setImageShowSize(new Dimension(bi.getWidth(), bi.getHeight()));

        currentlyDisplayedPage = 0;
    }

    /**
     * Restore the XDocument file from the path which is saved in the
     * class-variable pathToPDF.
     * 
     * @see setSerializable()
     */
    public final void restoreFormSerializable(final PDDocument _xD) {
        if (!document.restoreFormSerializable(_xD)) {
            restoreFormSerializable();
        }

    }

    /**
     * 
     * @return the current page of the PDF document.
     */
    public final PDPage getCurrentPage() {
        if (document != null) {
            return document.getPage(currentlyDisplayedPage);
        }
        return null;
    }

    /**
     * @return the history
     */
    public final HistorySession getCurrentHistory() {

        if (currentlyDisplayedPage < history.length) {

            return history[currentlyDisplayedPage];
        }
        return null;
    }

    /**
     * @return the picture
     */
    public final Picture getCurrentPicture() {

        if (currentlyDisplayedPage < pictures.length) {

            return pictures[currentlyDisplayedPage];
        }
        return null;
    }

    public void resetCurrentPage() {
        currentlyDisplayedPage = 0;
    }

    public void increaseCurrentPage() {
        if (document != null && currentlyDisplayedPage < document.getNumberOfPages() - 1) {

            document.getPdfPages()[currentlyDisplayedPage].forget();

            currentlyDisplayedPage++;

            // fetch zoom factor
            double zW = 1.0 * State.getImageSize().getWidth() / State.getImageShowSize().getWidth();
            double zH = 1.0 * State.getImageSize().getHeight() / State.getImageShowSize().getHeight();

            document.getPdfPages()[currentlyDisplayedPage].remember();
            Rectangle r = document.getPdfPages()[currentlyDisplayedPage].getSnapshotBounds();

            State.setImageSize(r.getSize());
            State.setImageShowSize(new Dimension((int) (r.getWidth() / zW), (int) (r.getHeight() / zH)));

        }
    }

    public void decreaseCurrentPage() {

        if (document != null && currentlyDisplayedPage > 0) {

            document.getPdfPages()[currentlyDisplayedPage].forget();
            currentlyDisplayedPage--;

            // fetch zoom factor
            double zW = 1.0 * State.getImageSize().getWidth() / State.getImageShowSize().getWidth();
            double zH = 1.0 * State.getImageSize().getHeight() / State.getImageShowSize().getHeight();

            document.getPdfPages()[currentlyDisplayedPage].remember();
            Rectangle r = document.getPdfPages()[currentlyDisplayedPage].getSnapshotBounds();

            State.setImageSize(r.getSize());
            State.setImageShowSize(new Dimension((int) (r.getWidth() / zW), (int) (r.getHeight() / zH)));
        }
    }

    /**
     * @return the pictures
     */
    public Picture getPicture(int _pictureID) {
        return pictures[_pictureID];
    }

    /**
     * @return the currentlyDisplayedPage
     */
    public int getCurrentPageNumber() {
        return currentlyDisplayedPage;
    }

    /**
     * 
     * @param _doc
     * @param _bi
     * @param _pageindex       index of page to which the BufferedImage is 
     *                      inserted.
     *                      If it is equal to -1, new page is created.
     *                   
     */
    public void attatchToPDF(final PDDocument _doc, final BufferedImage _bi, final int _pageindex) {
        PDPage page = null;
        try {
            if (_pageindex == -1) {
                page = new PDPage(new PDRectangle(State.getImageSize().width, State.getImageSize().height));

                _doc.addPage(page);
            } else {
                page = _doc.getPage(_pageindex);
                //             page.setCropBox(new PDRectangle(State.getImageSize().width , 
                //                   State.getImageSize().height ));

            }

            int width = (int) page.getCropBox().getWidth();
            int height = (int) page.getCropBox().getHeight();

            PDImageXObject ximage = LosslessFactory.createFromImage(_doc,
                    //                 _bi);
                    Utils.resizeImage(width, height, _bi));

            PDPageContentStream content = new PDPageContentStream(_doc, page, true, true);

            // contentStream.drawImage(ximage, 20, 20 );
            // better method inspired by http://stackoverflow.com/a/22318681/535646
            // reduce this value if the image is too large
            float scale = 1f;
            content.drawImage(ximage, 20, 20, ximage.getWidth() * scale, ximage.getHeight() * scale);

            content.close();
            //  LosslessFactory.createFromImage(doc, bim)
            //              content.drawImage(ximage, 0, 0);
            //              content.close();
        } catch (IOException ie) {
            //handle exception
        }
    }

    public final void saveProject(final String _wsLoc) {
        try {
            FileOutputStream fos = new FileOutputStream(new File(_wsLoc));
            ObjectOutputStream oos = new ObjectOutputStream(fos);

            // store the content of the BufferedImages elsewhere and delete 
            // it afterwards because it is not serializable. After saving 
            // operation has been completed, the bufferedImages are 
            // automatically loaded.
            // pack images
            for (int i = 0; i < pictures.length; i++) {
                pictures[i].pack();
            }

            // pack project
            PDDocument temp = document.getPDDocument();
            this.setSerializable();

            oos.writeObject(this);

            this.restoreFormSerializable(temp);

            for (int i = 0; i < pictures.length; i++) {
                pictures[i].unpack();
            }
            oos.flush();
            oos.close();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void savePDF(final String firstPath) throws IOException {

        PDDocument doc = document.getPDDocument();
        System.out.println(doc);
        try {

            final boolean newlyCreated = (doc == null);

            if (newlyCreated) {

                // create new document and insert empty page to the document.
                doc = new PDDocument();
            } else {
                // reset wrong settings.
                State.setBorderBottomPercentExport(0);
                State.setBorderRightPercentExport(0);
                State.setBorderLeftPercentExport(0);
                State.setBorderTopPercentExport(0);
                State.setExportAlpha(true);
            }

            for (int i = 0; i < pictures.length; i++) {
                int index = i + 0;
                if (newlyCreated) {
                    index = -1;
                }

                attatchToPDF(doc, pictures[i].getBufferedImage(0, 0, false), index);
            }

            //save and close
            doc.save(firstPath);
        } finally {
            if (doc != null) {
                //                doc.close();
            }
        }
    }

    /**
     * @return the document
     */
    public XDocument getDocument() {
        return document;
    }

}