/* * Freeplane - mind map editor * Copyright (C) 2008 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitry Polivaev * * This file author is Christian Foltin * It 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; import java.awt.Color; import java.awt.Component; import java.awt.EventQueue; import java.util.Timer; import java.util.TimerTask; import java.util.Vector; import javax.swing.SwingUtilities; import org.freeplane.core.extension.IExtension; import org.freeplane.core.undo.IActor; import org.freeplane.core.util.SysUtils; import org.freeplane.features.map.IMapChangeListener; import org.freeplane.features.map.IMapLifeCycleListener; import org.freeplane.features.map.INodeView; import org.freeplane.features.map.MapChangeEvent; import org.freeplane.features.map.MapController; import org.freeplane.features.map.MapModel; import org.freeplane.features.map.NodeModel; import org.freeplane.features.mode.Controller; import org.freeplane.features.mode.NodeHookDescriptor; import org.freeplane.features.mode.PersistentNodeHook; import org.freeplane.features.ui.INodeViewVisitor; import org.freeplane.n3.nanoxml.XMLElement; import org.freeplane.view.swing.map.NodeView; /** */ @NodeHookDescriptor(hookName = "accessories/plugins/BlinkingNodeHook.properties", onceForMap = false) public class BlinkingNodeHook extends PersistentNodeHook { protected class TimerColorChanger extends TimerTask implements IExtension, IMapChangeListener, IMapLifeCycleListener { final private NodeModel node; final private Timer timer; TimerColorChanger(final NodeModel node) { this.node = node; final MapController mapController = Controller.getCurrentModeController().getMapController(); mapController.addMapChangeListener(this); mapController.addMapLifeCycleListener(this); timer = SysUtils.createTimer(getClass().getSimpleName()); timer.schedule(this, 500, 500); BlinkingNodeHook.colors.clear(); BlinkingNodeHook.colors.add(Color.BLUE); BlinkingNodeHook.colors.add(Color.RED); BlinkingNodeHook.colors.add(Color.MAGENTA); BlinkingNodeHook.colors.add(Color.CYAN); } public NodeModel getNode() { return node; } public Timer getTimer() { return timer; } /** TimerTask method to enable the selection after a given time. */ @Override public void run() { SwingUtilities.invokeLater(new Runnable() { public void run() { if (getNode() == null || Controller.getCurrentModeController().isBlocked()) { return; } getNode().acceptViewVisitor(new INodeViewVisitor() { public void visit(final INodeView nodeView) { if(! (nodeView instanceof NodeView)){ return; } final Component container = ((NodeView)nodeView).getMainView(); if (container == null || !container.isVisible()) { return; } final Color col = container.getForeground(); int index = -1; if (col != null && BlinkingNodeHook.colors.contains(col)) { index = BlinkingNodeHook.colors.indexOf(col); } index++; if (index >= BlinkingNodeHook.colors.size()) { index = 0; } container.setForeground(BlinkingNodeHook.colors.get(index)); } }); } }); } public void mapChanged(final MapChangeEvent event) { } public void onNodeDeleted(final NodeModel parent, final NodeModel child, final int index) { if (Controller.getCurrentModeController().isUndoAction() || !(node.equals(child) || node.isDescendantOf(child))) { return; } final IActor actor = new IActor() { public void act() { EventQueue.invokeLater(new Runnable() { public void run() { remove(node, node.getExtension(TimerColorChanger.class)); } }); } public String getDescription() { return "BlinkingNodeHook.timer"; } public void undo() { node.addExtension(new TimerColorChanger(node)); } }; Controller.getCurrentModeController().execute(actor, node.getMap()); } public void onNodeInserted(final NodeModel parent, final NodeModel child, final int newIndex) { } public void onNodeMoved(final NodeModel oldParent, final int oldIndex, final NodeModel newParent, final NodeModel child, final int newIndex) { } public void onPreNodeDelete(final NodeModel oldParent, final NodeModel selectedNode, final int index) { } public void onPreNodeMoved(final NodeModel oldParent, final int oldIndex, final NodeModel newParent, final NodeModel child, final int newIndex) { } public void onCreate(final MapModel map) { } public void onRemove(final MapModel map) { if (node.getMap().equals(map)) { timer.cancel(); } } public void onSavedAs(MapModel map) { } public void onSaved(MapModel map) { } } static Vector<Color> colors = new Vector<Color>(); public BlinkingNodeHook() { super(); } @Override protected IExtension createExtension(final NodeModel node, final XMLElement element) { return new TimerColorChanger(node); } @Override protected Class<TimerColorChanger> getExtensionClass() { return TimerColorChanger.class; } /* * (non-Javadoc) * @see freeplane.extensions.MindMapHook#shutdownMapHook() */ @Override public void remove(final NodeModel node, final IExtension extension) { final TimerColorChanger timer = ((TimerColorChanger) extension); timer.getTimer().cancel(); final MapController mapController = Controller.getCurrentModeController().getMapController(); mapController.removeMapChangeListener(timer); mapController.removeMapLifeCycleListener(timer); super.remove(node, extension); } }