/* GanttProject is an opensource project management tool. Copyright (C) 2005-2011 GanttProject team 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package net.sourceforge.ganttproject.gui; import biz.ganttproject.core.option.GPOptionGroup; import net.sourceforge.ganttproject.GPLogger; import net.sourceforge.ganttproject.IGanttProject; import net.sourceforge.ganttproject.action.CancelAction; import net.sourceforge.ganttproject.action.GPAction; import net.sourceforge.ganttproject.document.Document; import net.sourceforge.ganttproject.document.Document.DocumentException; import net.sourceforge.ganttproject.document.DocumentManager; import net.sourceforge.ganttproject.filter.GanttXMLFileFilter; import net.sourceforge.ganttproject.gui.projectwizard.NewProjectWizard; import net.sourceforge.ganttproject.language.GanttLanguage; import net.sourceforge.ganttproject.undo.GPUndoManager; import net.sourceforge.ganttproject.util.FileUtil; import org.eclipse.core.runtime.IStatus; import javax.swing.*; import javax.swing.filechooser.FileFilter; import java.awt.event.ActionEvent; import java.io.File; import java.io.IOException; import java.net.URI; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; public class ProjectUIFacadeImpl implements ProjectUIFacade { final UIFacade myWorkbenchFacade; private final GanttLanguage i18n = GanttLanguage.getInstance(); private final DocumentManager myDocumentManager; private final GPUndoManager myUndoManager; private final GPOptionGroup myConverterGroup = new GPOptionGroup("convert", ProjectOpenStrategy.getMilestonesOption()); public ProjectUIFacadeImpl(UIFacade workbenchFacade, DocumentManager documentManager, GPUndoManager undoManager) { myWorkbenchFacade = workbenchFacade; myDocumentManager = documentManager; myUndoManager = undoManager; } @Override public void saveProject(IGanttProject project) { if (project.getDocument() == null) { saveProjectAs(project); return; } Document document = project.getDocument(); saveProjectTryWrite(project, document); } private boolean saveProjectTryWrite(final IGanttProject project, final Document document) { IStatus canWrite = document.canWrite(); if (!canWrite.isOK()) { GPLogger.getLogger(Document.class).log(Level.INFO, canWrite.getMessage(), canWrite.getException()); String message = formatWriteStatusMessage(document, canWrite); List<Action> actions = new ArrayList<Action>(); actions.add(new GPAction("project.saveas") { @Override public void actionPerformed(ActionEvent e) { saveProjectAs(project); } }); if (canWrite.getCode() == Document.ErrorCode.LOST_UPDATE.ordinal()) { actions.add(new GPAction("document.overwrite") { @Override public void actionPerformed(ActionEvent e) { saveProjectTryLock(project, document); } }); } actions.add(CancelAction.EMPTY); myWorkbenchFacade.showOptionDialog(JOptionPane.ERROR_MESSAGE, message, actions.toArray(new Action[0])); return false; } return saveProjectTryLock(project, document); } private boolean saveProjectTryLock(IGanttProject project, Document document) { return saveProjectTrySave(project, document); } private boolean saveProjectTrySave(IGanttProject project, Document document) { try { saveProject(document); afterSaveProject(project); return true; } catch (Throwable e) { myWorkbenchFacade.showErrorDialog(e); return false; } } private String formatWriteStatusMessage(Document doc, IStatus canWrite) { assert canWrite.getCode() >= 0 && canWrite.getCode() < Document.ErrorCode.values().length; Document.ErrorCode errorCode = Document.ErrorCode.values()[canWrite.getCode()]; String key = "document.error.write." + errorCode.name().toLowerCase(); return MessageFormat.format(i18n.getText(key), doc.getPath(), canWrite.getMessage()); } private void afterSaveProject(IGanttProject project) { Document document = project.getDocument(); myDocumentManager.addToRecentDocuments(document); String title = i18n.getText("appliTitle") + " [" + document.getFileName() + "]"; myWorkbenchFacade.setWorkbenchTitle(title); if (document.isLocal()) { URI url = document.getURI(); if (url != null) { File file = new File(url); myDocumentManager.changeWorkingDirectory(file.getParentFile()); } } project.setModified(false); } private void saveProject(Document document) throws IOException { myWorkbenchFacade.setStatusText(GanttLanguage.getInstance().getText("saving") + " " + document.getPath()); document.write(); } @Override public void saveProjectAs(IGanttProject project) { /* * if (project.getDocument() instanceof AbstractURLDocument) { * saveProjectRemotely(project); return; } */ JFileChooser fc = new JFileChooser(myDocumentManager.getWorkingDirectory()); FileFilter ganttFilter = new GanttXMLFileFilter(); fc.addChoosableFileFilter(ganttFilter); // Remove the possibility to use a file filter for all files FileFilter[] filefilters = fc.getChoosableFileFilters(); for (int i = 0; i < filefilters.length; i++) { if (filefilters[i] != ganttFilter) { fc.removeChoosableFileFilter(filefilters[i]); } } try { for (;;) { int userChoice = fc.showSaveDialog(myWorkbenchFacade.getMainFrame()); if (userChoice != JFileChooser.APPROVE_OPTION) { break; } File projectfile = fc.getSelectedFile(); String extension = FileUtil.getExtension(projectfile).toLowerCase(); if (!"gan".equals(extension) && !"xml".equals(extension)) { projectfile = FileUtil.replaceExtension(projectfile, "gan"); } if (projectfile.exists()) { UIFacade.Choice overwritingChoice = myWorkbenchFacade.showConfirmationDialog( projectfile + "\n" + i18n.getText("msg18"), i18n.getText("warning")); if (overwritingChoice != UIFacade.Choice.YES) { continue; } } Document document = myDocumentManager.getDocument(projectfile.getAbsolutePath()); saveProject(document); project.setDocument(document); afterSaveProject(project); break; } } catch (Throwable e) { myWorkbenchFacade.showErrorDialog(e); } } /** * Check if the project has been modified, before creating or opening another * project * * @return true when the project is <b>not</b> modified or is allowed to be * discarded */ @Override public boolean ensureProjectSaved(IGanttProject project) { if (project.isModified()) { UIFacade.Choice saveChoice = myWorkbenchFacade.showConfirmationDialog(i18n.getText("msg1"), i18n.getText("warning")); if (UIFacade.Choice.CANCEL == saveChoice) { return false; } if (UIFacade.Choice.YES == saveChoice) { try { saveProject(project); // If all those complex save procedures complete successfully and project gets saved // then its modified state becomes false // Otherwise it remains true which means we have not saved and can't continue return !project.isModified(); } catch (Exception e) { myWorkbenchFacade.showErrorDialog(e); return false; } } } return true; } @Override public void openProject(final IGanttProject project) throws IOException, DocumentException { if (false == ensureProjectSaved(project)) { return; } JFileChooser fc = new JFileChooser(myDocumentManager.getWorkingDirectory()); FileFilter ganttFilter = new GanttXMLFileFilter(); // Remove the possibility to use a file filter for all files FileFilter[] filefilters = fc.getChoosableFileFilters(); for (int i = 0; i < filefilters.length; i++) { fc.removeChoosableFileFilter(filefilters[i]); } fc.addChoosableFileFilter(ganttFilter); int returnVal = fc.showOpenDialog(myWorkbenchFacade.getMainFrame()); if (returnVal == JFileChooser.APPROVE_OPTION) { Document document = getDocumentManager().getDocument(fc.getSelectedFile().getAbsolutePath()); openProject(document, project); } } @Override public void openProject(final Document document, final IGanttProject project) throws IOException, DocumentException { beforeClose(); project.close(); try (ProjectOpenStrategy strategy = new ProjectOpenStrategy(project, myWorkbenchFacade)) { strategy.openFileAsIs(document) .checkLegacyMilestones() .checkEarliestStartConstraints() .runUiTasks(); } catch (Exception e) { throw new DocumentException("Can't open document " + document, e); } } private void beforeClose() { myWorkbenchFacade.setWorkbenchTitle(i18n.getText("appliTitle")); getUndoManager().die(); } @Override public void createProject(final IGanttProject project) { if (false == ensureProjectSaved(project)) { return; } beforeClose(); project.close(); myWorkbenchFacade.setStatusText(i18n.getText("project.new.description")); showNewProjectWizard(project); } private void showNewProjectWizard(IGanttProject project) { NewProjectWizard wizard = new NewProjectWizard(); wizard.createNewProject(project, myWorkbenchFacade); } @Override public GPOptionGroup[] getOptionGroups() { return new GPOptionGroup[] { myConverterGroup }; } private GPUndoManager getUndoManager() { return myUndoManager; } private DocumentManager getDocumentManager() { return myDocumentManager; } }