/******************************************************************************* * Copyright (c) 2004, 2010 BREDEX GmbH. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * BREDEX GmbH - initial API and implementation and/or initial documentation *******************************************************************************/ package org.eclipse.jubula.client.ui.rcp.events; import java.util.HashSet; import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jubula.client.ui.constants.Constants; import org.eclipse.jubula.client.ui.rcp.Plugin; import org.eclipse.jubula.client.ui.rcp.editors.IJBEditor; import org.eclipse.jubula.client.ui.rcp.i18n.Messages; import org.eclipse.osgi.util.NLS; import org.eclipse.ui.PlatformUI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author BREDEX GmbH * @created Jun 7, 2010 */ public class GuiEventDispatcher { /** Multiplicator milliseconds to minutes. */ private static final int MS_TO_MIN_MULTIPLICATOR = 60000; /** to notify clients about change of the dirty state of an editor */ public interface IEditorDirtyStateListener { /** * callback method * @param editor The editor whose dirty state changed * @param isDirty The new dirty state */ public void handleEditorDirtyStateChanged(IJBEditor editor, boolean isDirty); } /** logger */ private static final Logger LOG = LoggerFactory.getLogger(GuiEventDispatcher.class); /** * <code>m_instance</code> singleton */ private static GuiEventDispatcher instance = null; /** * <code>m_editorDirtyStateListeners</code> listener for notification * about change of the dirty state of an editor */ private Set<IEditorDirtyStateListener> m_editorDirtyStateListeners = new HashSet<IEditorDirtyStateListener>(); /** * <code>m_editorDirtyStateListenersPost</code> listener for notification * about change of the dirty state of an editor * POST-Event for gui updates */ private Set<IEditorDirtyStateListener> m_editorDirtyStateListenersPost = new HashSet<IEditorDirtyStateListener>(); /** * */ private ScheduledExecutorService m_dirtyScheduler = Executors.newSingleThreadScheduledExecutor(); /** * The timestamp when the last save occurred. */ private volatile long m_dirtyTimestamp = System.currentTimeMillis(); /** * If the timer for the save reminder is activated. */ private volatile boolean m_dirtyTimer = false; /** * private constructor */ private GuiEventDispatcher() { m_dirtyScheduler = Executors.newSingleThreadScheduledExecutor(); m_dirtyScheduler.scheduleAtFixedRate(new Runnable() { @Override public void run() { long timer = m_dirtyTimestamp + (Plugin.getDefault().getPreferenceStore() .getInt(Constants.SAVE_REMINDER_INTERVAL_KEY) * MS_TO_MIN_MULTIPLICATOR); boolean enabled = Plugin.getDefault().getPreferenceStore() .getBoolean(Constants.SAVE_REMINDER_ENABLE_KEY); if (System.currentTimeMillis() > timer && enabled && m_dirtyTimer) { showSaveReminder(); updateDirtyTimer(false); } } }, 0, 1, TimeUnit.SECONDS); } /** * Shows the reminder pop-up. */ private void showSaveReminder() { final String message = NLS.bind(Messages.EditorSaveReminder, Plugin.getDefault().getPreferenceStore() .getInt(Constants.SAVE_REMINDER_INTERVAL_KEY)); Plugin.getDisplay().asyncExec(new Runnable() { @Override public void run() { MessageDialog .openWarning( PlatformUI.getWorkbench() .getActiveWorkbenchWindow().getShell(), "Warning", message); //$NON-NLS-1$ } }); } /** * @return the single instance */ public static synchronized GuiEventDispatcher getInstance() { if (instance == null) { instance = new GuiEventDispatcher(); } return instance; } /** * @param l The listener to add as new listener for notification * about change of the dirty state of an editor * @param guiMode * should this listener be called after the model listener */ public void addEditorDirtyStateListener( IEditorDirtyStateListener l, boolean guiMode) { if (guiMode) { m_editorDirtyStateListenersPost.add(l); } else { m_editorDirtyStateListeners.add(l); } } /** * @param l The listener to be deleted as listener for notification * about change of the dirty state of an editor */ public void removeEditorDirtyStateListener(IEditorDirtyStateListener l) { m_editorDirtyStateListeners.remove(l); m_editorDirtyStateListenersPost.remove(l); // scheduler update updateDirtyTimer(false); } /** * notify listener about change of the dirty state of an editor * @param editor The editor whose dirty state changed * @param isDirty The new dirty state */ public void fireEditorDirtyStateListener(IJBEditor editor, boolean isDirty) { // model updates final Set<IEditorDirtyStateListener> stableListeners = new HashSet<IEditorDirtyStateListener>(m_editorDirtyStateListeners); for (IEditorDirtyStateListener l : stableListeners) { try { l.handleEditorDirtyStateChanged(editor, isDirty); } catch (Throwable t) { LOG.error(Messages.UnhandledExceptionCallingListeners, t); } } // gui updates final Set<IEditorDirtyStateListener> stableListenersPost = new HashSet<IEditorDirtyStateListener>( m_editorDirtyStateListenersPost); for (IEditorDirtyStateListener l : stableListenersPost) { try { l.handleEditorDirtyStateChanged(editor, isDirty); } catch (Throwable t) { LOG.error(Messages.UnhandledExceptionCallingListeners, t); } } // scheduler update updateDirtyTimer(isDirty); } /** * * @param dirty * determines if new dirty editors exist */ private synchronized void updateDirtyTimer(boolean dirty) { if (dirty && !m_dirtyTimer) { this.m_dirtyTimestamp = System.currentTimeMillis(); } m_dirtyTimer = dirty; } }