/* GanttProject is an opensource project management tool. Copyright (C) 2016 BarD Software s.r.o This file is part of GanttProject. GanttProject 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. GanttProject 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 GanttProject. If not, see <http://www.gnu.org/licenses/>. */ package net.sourceforge.ganttproject.gui; import biz.ganttproject.core.time.CalendarFactory; import com.google.common.base.Joiner; import com.google.common.base.Objects; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import net.sourceforge.ganttproject.action.CancelAction; import net.sourceforge.ganttproject.language.GanttLanguage; import net.sourceforge.ganttproject.task.Task; import net.sourceforge.ganttproject.task.algorithm.AlgorithmBase; import net.sourceforge.ganttproject.util.collect.Pair; import javax.swing.*; import java.awt.*; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; /** * Diagnostic class collects information from the scheduler when user opens * a project. Should we have any changes in the task dates after the first scheduler * run, we report them to the user. * * @author dbarashev@ganttproject.biz (Dmitry Barashev) */ class ProjectOpenDiagnosticImpl implements AlgorithmBase.Diagnostic { interface ShowDialogCallback { void showDialog(JComponent contentPane); } private final UIFacade myUiFacade; List<String> myMessages = Lists.newArrayList(); LinkedHashMap<Task, Pair<Date, Date>> myModifiedTasks = new LinkedHashMap<>(); Map<Task, String> myReasons = Maps.newHashMap(); private boolean myHasOnlyEndDateChange = false; private GanttLanguage i18n = GanttLanguage.getInstance(); ProjectOpenDiagnosticImpl(UIFacade uiFacade) { myUiFacade = Preconditions.checkNotNull(uiFacade); } void info(String message) { myMessages.add(message); } @Override public void addModifiedTask(Task t, Date newStart, Date newEnd) { Pair<Date, Date> entry = myModifiedTasks.get(t); if (entry == null) { entry = Pair.create(null, null); } if (newStart != null) { entry = Pair.create(newStart, entry.second()); } if (newEnd != null) { entry = Pair.create(entry.first(), newEnd); } if (entry.first() == null && entry.second() != null) { myHasOnlyEndDateChange = true; } myModifiedTasks.put(t, entry); } void addReason(Task t, String reasonKey) { myReasons.put(t, reasonKey); } void showDialog() { myMessages.add(0, ""); String intro = Joiner.on("<li>").join(myMessages); String startDateChangeTable = buildStartDateChangeTable(); String endDateChangeTable = myHasOnlyEndDateChange ? buildEndDateChangeTable() : ""; //String reasonTable = buildReasonTable(); final String msg = String.format(i18n.getText("scheduler.warning.template"), i18n.getText("scheduler.warning.h1"), i18n.getText("scheduler.warning.intro1"), intro, i18n.getText("scheduler.warning.intro2"), i18n.getText("scheduler.warning.details.url"), i18n.getText("updateRss.question.2"), startDateChangeTable, endDateChangeTable ); final ShowDialogCallback showDialog = new ShowDialogCallback() { @Override public void showDialog(JComponent contentPane) { Dimension htmlSize = contentPane.getPreferredSize(); final JScrollPane scrollPane = new JScrollPane(contentPane); scrollPane.setAutoscrolls(false); scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); scrollPane.setPreferredSize(new Dimension(Math.min(600, htmlSize.width + 50), Math.min(400, htmlSize.height + 50))); scrollPane.setBorder(BorderFactory.createEmptyBorder(3, 3, 5, 3)); myUiFacade.createDialog(scrollPane, new Action[] {CancelAction.CLOSE}, "").show(); } }; try { Class.forName("javafx.beans.value.ChangeListener"); new ProjectOpenDiagnosticUiFx().run(msg, showDialog); } catch (ClassNotFoundException e) { new ProjectOpenDiagnosticUiSwing().run(msg, showDialog); } } private String buildStartDateChangeTable() { List<String> tableRows = Lists.newArrayList(); for (Entry<Task, Pair<Date, Date>> entry : myModifiedTasks.entrySet()) { Task t = entry.getKey(); Pair<Date,Date> changes = entry.getValue(); if (changes.first() != null) { String row = String.format(i18n.getText("scheduler.warning.table.row"), t.getName(), i18n.formatDate(CalendarFactory.createGanttCalendar(changes.first())), i18n.getText(Objects.firstNonNull( myReasons.get(t), "scheduler.warning.table.reason.other") + ".url"), i18n.getText(Objects.firstNonNull( myReasons.get(t), "scheduler.warning.table.reason.other") + ".label") ); tableRows.add(row); } } String rows = Joiner.on('\n').join(tableRows); String table = String.format(i18n.getText("scheduler.warning.table.template"), i18n.getText("scheduler.warning.section.startDate.title"), i18n.getText("scheduler.warning.section.startDate.desc"), i18n.getText("taskname"), i18n.getText("option.generic.startDate.label"), i18n.getText("scheduler.warning.table.reason"), rows); return table; } private String buildEndDateChangeTable() { List<String> tableRows = Lists.newArrayList(); for (Entry<Task, Pair<Date, Date>> entry : myModifiedTasks.entrySet()) { Task t = entry.getKey(); Pair<Date,Date> changes = entry.getValue(); if (changes.first() == null) { String row = String.format(i18n.getText("scheduler.warning.table.row"), t.getName(), i18n.formatDate(CalendarFactory.createGanttCalendar(changes.second())), i18n.getText(Objects.firstNonNull( myReasons.get(t), "scheduler.warning.table.reason.other") + ".url"), i18n.getText(Objects.firstNonNull( myReasons.get(t), "scheduler.warning.table.reason.other") + ".label") ); tableRows.add(row); } } String rows = Joiner.on('\n').join(tableRows); String table = String.format(i18n.getText("scheduler.warning.table.template"), i18n.getText("scheduler.warning.section.endDate.title"), i18n.getText("scheduler.warning.section.endDate.desc"), i18n.getText("taskname"), i18n.getText("option.generic.endDate.label"), i18n.getText("scheduler.warning.table.reason"), rows); return table; } }