/*
* Freeplane - mind map editor
* Copyright (C) 2008 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitry Polivaev
*
* This file is modified by Dimitry Polivaev in 2008.
*
* 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 2 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, see <http://www.gnu.org/licenses/>.
*/
package org.freeplane.view.swing.features.time.mindmapmode;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.text.MessageFormat;
import java.util.Date;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import org.freeplane.core.extension.IExtension;
import org.freeplane.core.ui.AFreeplaneAction;
import org.freeplane.core.ui.EnabledAction;
import org.freeplane.core.ui.IMenuContributor;
import org.freeplane.core.ui.MenuBuilder;
import org.freeplane.core.ui.components.UITools;
import org.freeplane.core.util.TextUtils;
import org.freeplane.features.filter.FilterController;
import org.freeplane.features.icon.IStateIconProvider;
import org.freeplane.features.icon.IconController;
import org.freeplane.features.icon.IconStore;
import org.freeplane.features.icon.UIIcon;
import org.freeplane.features.icon.factory.IconStoreFactory;
import org.freeplane.features.map.INodeChangeListener;
import org.freeplane.features.map.INodeSelectionListener;
import org.freeplane.features.map.ITooltipProvider;
import org.freeplane.features.map.MapModel;
import org.freeplane.features.map.NodeChangeEvent;
import org.freeplane.features.map.NodeModel;
import org.freeplane.features.mode.Controller;
import org.freeplane.features.mode.ModeController;
import org.freeplane.features.mode.NodeHookDescriptor;
import org.freeplane.features.mode.PersistentNodeHook;
import org.freeplane.features.script.IScriptStarter;
import org.freeplane.n3.nanoxml.XMLElement;
import org.freeplane.view.swing.features.time.mindmapmode.TimeManagement.JTimePanel;
import org.freeplane.view.swing.map.attribute.AttributePanelManager;
/**
* @author foltin
*/
@NodeHookDescriptor(hookName = "plugins/TimeManagementReminder.xml", onceForMap = false)
public class ReminderHook extends PersistentNodeHook implements IExtension {
//******************************************
@EnabledAction(checkOnNodeChange = true)
private class ReminderHookAction extends HookAction {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
*
*/
public ReminderHookAction() {
super("ReminderHookAction");
}
@Override
public void setEnabled() {
setEnabled(isActiveForSelection());
}
}
static private class TimeListAction extends AFreeplaneAction {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
*
*/
private final NodeList timeList;
public TimeListAction() {
super("TimeListAction");
timeList = new NodeList(false, false);
}
public void actionPerformed(final ActionEvent e) {
timeList.startup();
}
}
static private class TimeManagementAction extends AFreeplaneAction {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
*
*/
private final TimeManagement timeManagement;
public TimeManagementAction( final ReminderHook reminderHook) {
super("TimeManagementAction");
timeManagement = new TimeManagement(reminderHook);
}
public void actionPerformed(final ActionEvent e) {
timeManagement.showDialog();
}
}
//******************************************
static final String PLUGIN_LABEL = "plugins/TimeManagementReminder.xml";
static final String REMINDUSERAT = "REMINDUSERAT";
static final String PERIOD = "PERIOD";
static final String UNIT = "UNIT";
static final String SCRIPT = "SCRIPT";
private static final Integer REMINDER_TOOLTIP = 12;
private ModeController modeController;
/**
*
*/
public ReminderHook(ModeController modeController){
super();
this.modeController = modeController;
modeController.addMenuContributor(new IMenuContributor() {
public void updateMenus(ModeController modeController, MenuBuilder builder) {
createTimePanel();
}
});
registerAction(new TimeManagementAction(this));
registerAction(new TimeListAction());
registerAction(new NodeListAction());
registerAction(new AllMapsNodeListAction());
registerTooltipProvider();
registerStateIconProvider();
FilterController.getCurrentFilterController().getConditionFactory().addConditionController(9,
new ReminderConditionController());
}
private static final IconStore STORE = IconStoreFactory.create();
private static UIIcon bellIcon;
private static UIIcon clockIcon;
private static UIIcon flagIcon;
void registerStateIconProvider(){
IconController.getController(modeController).addStateIconProvider(new IStateIconProvider() {
public UIIcon getStateIcon(NodeModel node) {
UIIcon icon = null;
ClockState stateAdded = node.getExtension(ClockState.class);
ReminderExtension reminder = node.getExtension(ReminderExtension.class);
if (stateAdded == ClockState.CLOCK_VISIBLE) {
icon = getClockIcon();
}
else if (stateAdded == ClockState.CLOCK_INVISIBLE) {
if (reminder != null && node == reminder.getNode()) {
icon = getBellIcon();
}
else {
icon = getFlagIcon();
}
}
if (stateAdded != null || reminder != null && node == reminder.getNode()
|| ReminderExtension.getExtension(node) == null) {
return icon;
}
return null;
}
});
}
private UIIcon getBellIcon() {
if (bellIcon == null) {
bellIcon = STORE.getUIIcon("bell.png");
}
return bellIcon;
}
private UIIcon getClockIcon() {
if (clockIcon == null) {
clockIcon = STORE.getUIIcon("clock.png");
}
return clockIcon;
}
private UIIcon getFlagIcon() {
if (flagIcon == null) {
flagIcon = STORE.getUIIcon("flag.png");
}
return flagIcon;
}
private void registerTooltipProvider() {
modeController.addToolTipProvider(REMINDER_TOOLTIP, new ITooltipProvider() {
public String getTooltip(ModeController modeController, NodeModel node, Component view) {
final ReminderExtension model = ReminderExtension.getExtension(node);
if(model == null)
return null;
final Date date = new Date(model.getRemindUserAt());
final Object[] messageArguments = { date };
final MessageFormat formatter = new MessageFormat(TextUtils
.getText("plugins/TimeManagement.xml_reminderNode_tooltip"));
final String message = formatter.format(messageArguments);
return message;
}
});
}
private void createTimePanel() {
final TimeManagement timeManagement = new TimeManagement(this);
final int axis = BoxLayout.Y_AXIS;
final JTimePanel timePanel = timeManagement.createTimePanel(null, false, 1);
modeController.getMapController().addNodeSelectionListener(new INodeSelectionListener() {
public void onSelect(NodeModel node) {
timePanel.update(node);
}
public void onDeselect(NodeModel node) {
}
});
modeController.getMapController().addNodeChangeListener(new INodeChangeListener() {
public void nodeChanged(NodeChangeEvent event) {
final NodeModel node = event.getNode();
if(event.getProperty().equals(getExtensionClass()) && node.equals(modeController.getMapController().getSelectedNode()))
timePanel.update(node);
}
});
timePanel.setBorder(BorderFactory.createTitledBorder(TextUtils.getText("calendar_panel")));
final JPanel tablePanel = new AttributePanelManager(modeController).getTablePanel();
tablePanel.setBorder(BorderFactory.createTitledBorder(TextUtils.getText("attributes_attribute")));
final Box panel = new Box(axis);
panel.add(timePanel);
panel.add(tablePanel);
System.out.println("REMINDERHOOK: "+modeController);
final JTabbedPane tabs = (JTabbedPane) modeController.getUserInputListenerFactory().getToolBar("/format").getComponent(1);
final JScrollPane timeScrollPane = new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
UITools.setScrollbarIncrement(timeScrollPane);
tabs.add(TextUtils.getText("calendar_attributes_panel"), timeScrollPane);
}
@Override
public void add(final NodeModel node, final IExtension extension) {
final ReminderExtension reminderExtension = (ReminderExtension) extension;
scheduleTimer(reminderExtension);
modeController.getMapController().addMapChangeListener(reminderExtension);
super.add(node, extension);
}
void blink(final ReminderExtension model, final boolean stateAdded) {
if (model.getNode().getMap() != Controller.getCurrentController().getMap()) {
return;
}
model.displayState((stateAdded) ? ClockState.CLOCK_VISIBLE : ClockState.CLOCK_INVISIBLE, model.getNode(), true);
}
@Override
protected IExtension createExtension(final NodeModel node, final XMLElement element) {
final ReminderExtension reminderExtension = new ReminderExtension(node);
final XMLElement parameters = element.getFirstChildNamed("Parameters");
final String time = parameters.getAttribute(REMINDUSERAT, "0");
final String unit = parameters.getAttribute(UNIT, "DAY");
final String period = parameters.getAttribute(PERIOD, "1");
reminderExtension.setRemindUserAt(Long.parseLong(time));
reminderExtension.setPeriodUnit(PeriodUnit.valueOf(unit));
reminderExtension.setPeriod(Integer.parseInt(period));
final String script = parameters.getAttribute(SCRIPT, null);
reminderExtension.setScript(script);
return reminderExtension;
}
@Override
protected HookAction createHookAction() {
return new ReminderHookAction();
}
@Override
protected Class<? extends IExtension> getExtensionClass() {
return ReminderExtension.class;
}
@Override
public void remove(final NodeModel node, final IExtension extension) {
final ReminderExtension reminderExtension = (ReminderExtension) extension;
reminderExtension.deactivateTimer();
reminderExtension.displayState(null, reminderExtension.getNode(), true);
modeController.getMapController().removeMapChangeListener(reminderExtension);
super.remove(node, extension);
}
@Override
protected void saveExtension(final IExtension extension, final XMLElement element) {
super.saveExtension(extension, element);
final ReminderExtension reminderExtension = (ReminderExtension) extension;
final XMLElement parameters = element.createElement("Parameters");
parameters.setAttribute(REMINDUSERAT, Long.toString(reminderExtension.getRemindUserAt()));
parameters.setAttribute(PERIOD, Integer.toString(reminderExtension.getPeriod()));
parameters.setAttribute(UNIT, reminderExtension.getPeriodUnit().toString());
final String script = reminderExtension.getScript();
if(script != null){
parameters.setAttribute(SCRIPT, script);
}
element.addChild(parameters);
}
private void scheduleTimer(final ReminderExtension model) {
final Date date = new Date(model.getRemindUserAt());
scheduleTimer(model, new TimerBlinkTask(this, model, false, System.currentTimeMillis() < date.getTime() + ReminderExtension.BLINKING_PERIOD));
model.displayState(ClockState.CLOCK_VISIBLE, model.getNode(), false);
}
private void scheduleTimer(final ReminderExtension model, final TimerBlinkTask task) {
final Date date = new Date(model.getRemindUserAt());
model.scheduleTimer(task, date);
}
ModeController getModeController() {
return modeController;
}
public void runScript(ReminderExtension reminderExtension) {
final String script = reminderExtension.getScript();
if(script == null || script.equals(""))
return;
final IScriptStarter starter = (IScriptStarter) modeController.getExtension(IScriptStarter.class);
if(starter == null)
return;
final NodeModel node = reminderExtension.getNode();
final MapModel map = node.getMap();
final Controller controller = modeController.getController();
if(! controller.getMapViewManager().getMaps(modeController.getModeName()).containsValue(map))
return;
starter.executeScript(node, script);
}
}