net.tourbook.ui.MessageManager.java Source code

Java tutorial

Introduction

Here is the source code for net.tourbook.ui.MessageManager.java

Source

/*******************************************************************************
 * Copyright (C) 2005, 2009  Wolfgang Schramm and Contributors
 *   
 * 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 version 2 of the License.
 *  
 * 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 St, Fifth Floor, Boston, MA 02110, USA    
 *******************************************************************************/

package net.tourbook.ui;

/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 * 
 * this is a copy from MessageManager.java, this implementation is using a Form instead of a ScrolledForm
 * 
 * New Methods: getMessageCount()
 *  
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 */

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;

import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.fieldassist.FieldDecoration;
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.forms.IMessage;
import org.eclipse.ui.forms.IMessageManager;
import org.eclipse.ui.forms.IMessagePrefixProvider;
import org.eclipse.ui.forms.widgets.Form;
import org.eclipse.ui.forms.widgets.Hyperlink;

/**
 * @see IMessageManager
 */

public class MessageManager implements IMessageManager {

    private static final DefaultPrefixProvider DEFAULT_PREFIX_PROVIDER = new DefaultPrefixProvider();

    private ArrayList messages = new ArrayList();
    private Hashtable decorators = new Hashtable();
    private boolean autoUpdate = true;
    private Form scrolledForm;
    private IMessagePrefixProvider prefixProvider = DEFAULT_PREFIX_PROVIDER;
    private int decorationPosition = SWT.LEFT | SWT.BOTTOM;

    private static FieldDecoration standardError = FieldDecorationRegistry.getDefault()
            .getFieldDecoration(FieldDecorationRegistry.DEC_ERROR);
    private static FieldDecoration standardWarning = FieldDecorationRegistry.getDefault()
            .getFieldDecoration(FieldDecorationRegistry.DEC_WARNING);
    private static FieldDecoration standardInformation = FieldDecorationRegistry.getDefault()
            .getFieldDecoration(FieldDecorationRegistry.DEC_INFORMATION);

    private static final String[] SINGLE_MESSAGE_SUMMARY_KEYS = { Messages.message_manager_sMessageSummary,
            Messages.message_manager_sMessageSummary, Messages.message_manager_sWarningSummary,
            Messages.message_manager_sErrorSummary };

    private static final String[] MULTIPLE_MESSAGE_SUMMARY_KEYS = { Messages.message_manager_pMessageSummary,
            Messages.message_manager_pMessageSummary, Messages.message_manager_pWarningSummary,
            Messages.message_manager_pErrorSummary };

    class ControlDecorator {
        private ControlDecoration decoration;
        private ArrayList controlMessages = new ArrayList();
        private String prefix;

        ControlDecorator(final Control control) {
            this.decoration = new ControlDecoration(control, decorationPosition, scrolledForm.getBody());
        }

        void addAll(final ArrayList target) {
            target.addAll(controlMessages);
        }

        void addMessage(final Object key, final String text, final Object data, final int type) {
            final Message message = MessageManager.this.addMessage(getPrefix(), key, text, data, type,
                    controlMessages);
            message.control = decoration.getControl();
            if (isAutoUpdate())
                update();
        }

        private void createPrefix() {
            if (prefixProvider == null) {
                prefix = ""; //$NON-NLS-1$
                return;
            }
            prefix = prefixProvider.getPrefix(decoration.getControl());
            if (prefix == null)
                // make a prefix anyway
                prefix = ""; //$NON-NLS-1$
        }

        String getPrefix() {
            if (prefix == null)
                createPrefix();
            return prefix;
        }

        public boolean isDisposed() {
            return decoration.getControl() == null;
        }

        boolean removeMessage(final Object key) {
            final Message message = findMessage(key, controlMessages);
            if (message != null) {
                controlMessages.remove(message);
                if (isAutoUpdate())
                    update();
            }
            return message != null;
        }

        boolean removeMessages() {
            if (controlMessages.isEmpty())
                return false;
            controlMessages.clear();
            if (isAutoUpdate())
                update();
            return true;
        }

        public void update() {
            if (controlMessages.isEmpty()) {
                decoration.setDescriptionText(null);
                decoration.hide();
            } else {
                final ArrayList peers = createPeers(controlMessages);
                final int type = ((IMessage) peers.get(0)).getMessageType();
                final String description = createDetails(createPeers(peers), true);
                if (type == IMessageProvider.ERROR)
                    decoration.setImage(standardError.getImage());
                else if (type == IMessageProvider.WARNING)
                    decoration.setImage(standardWarning.getImage());
                else if (type == IMessageProvider.INFORMATION)
                    decoration.setImage(standardInformation.getImage());
                decoration.setDescriptionText(description);
                decoration.show();
            }
        }

        void updatePosition() {
            final Control control = decoration.getControl();
            decoration.dispose();
            this.decoration = new ControlDecoration(control, decorationPosition, scrolledForm.getBody());
            update();
        }

        void updatePrefix() {
            prefix = null;
        }
    }

    static class DefaultPrefixProvider implements IMessagePrefixProvider {

        public String getPrefix(final Control c) {
            final Composite parent = c.getParent();
            final Control[] siblings = parent.getChildren();
            for (int i = 0; i < siblings.length; i++) {
                if (siblings[i] == c) {
                    // this is us - go backward until you hit
                    // a label-like widget
                    for (int j = i - 1; j >= 0; j--) {
                        final Control label = siblings[j];
                        String ltext = null;
                        if (label instanceof Label) {
                            ltext = ((Label) label).getText();
                        } else if (label instanceof Hyperlink) {
                            ltext = ((Hyperlink) label).getText();
                        } else if (label instanceof CLabel) {
                            ltext = ((CLabel) label).getText();
                        }
                        if (ltext != null) {
                            if (!ltext.endsWith(":")) //$NON-NLS-1$
                                return ltext + ": "; //$NON-NLS-1$
                            return ltext + " "; //$NON-NLS-1$
                        }
                    }
                    break;
                }
            }
            return null;
        }
    }

    static class Message implements IMessage {
        Control control;
        Object data;
        Object key;
        String message;
        int type;
        String prefix;

        Message(final Object key, final String message, final int type, final Object data) {
            this.key = key;
            this.message = message;
            this.type = type;
            this.data = data;
        }

        /*
         * (non-Javadoc)
         * @see org.eclipse.ui.forms.messages.IMessage#getControl()
         */
        public Control getControl() {
            return control;
        }

        /*
         * (non-Javadoc)
         * @see org.eclipse.ui.forms.messages.IMessage#getData()
         */
        public Object getData() {
            return data;
        }

        /*
         * (non-Javadoc)
         * @see org.eclipse.jface.dialogs.IMessage#getKey()
         */
        public Object getKey() {
            return key;
        }

        /*
         * (non-Javadoc)
         * @see org.eclipse.jface.dialogs.IMessageProvider#getMessage()
         */
        public String getMessage() {
            return message;
        }

        /*
         * (non-Javadoc)
         * @see org.eclipse.jface.dialogs.IMessageProvider#getMessageType()
         */
        public int getMessageType() {
            return type;
        }

        /*
         * (non-Javadoc)
         * @see org.eclipse.ui.forms.messages.IMessage#getPrefix()
         */
        public String getPrefix() {
            return prefix;
        }
    }

    public static String createDetails(final IMessage[] messages) {
        if (messages == null || messages.length == 0)
            return null;
        final StringWriter sw = new StringWriter();
        final PrintWriter out = new PrintWriter(sw);

        for (int i = 0; i < messages.length; i++) {
            if (i > 0)
                out.println();
            out.print(getFullMessage(messages[i]));
        }
        out.flush();
        return sw.toString();
    }

    private static String getFullMessage(final IMessage message) {
        if (message.getPrefix() == null)
            return message.getMessage();
        return message.getPrefix() + message.getMessage();
    }

    /**
     * Creates a new instance of the message manager that will work with the provided form.
     * 
     * @param scrolledForm
     *            the form to control
     */
    public MessageManager(final Form scrolledForm) {
        this.scrolledForm = scrolledForm;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.forms.IMessageManager#addMessage(java.lang.Object, java.lang.String, int)
     */
    public void addMessage(final Object key, final String messageText, final Object data, final int type) {
        addMessage(null, key, messageText, data, type, messages);
        if (isAutoUpdate())
            updateForm();
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.forms.IMessageManager#addMessage(java.lang.Object, java.lang.String, int,
     * org.eclipse.swt.widgets.Control)
     */
    public void addMessage(final Object key, final String messageText, final Object data, final int type,
            final Control control) {
        ControlDecorator dec = (ControlDecorator) decorators.get(control);

        if (dec == null) {
            dec = new ControlDecorator(control);
            decorators.put(control, dec);
        }
        dec.addMessage(key, messageText, data, type);
        if (isAutoUpdate())
            updateForm();
    }

    private Message addMessage(final String prefix, final Object key, final String messageText, final Object data,
            final int type, final ArrayList list) {
        Message message = findMessage(key, list);
        if (message == null) {
            message = new Message(key, messageText, type, data);
            message.prefix = prefix;
            list.add(message);
        } else {
            message.message = messageText;
            message.type = type;
            message.data = data;
        }
        return message;
    }

    private String createDetails(final ArrayList messages, final boolean excludePrefix) {
        final StringWriter sw = new StringWriter();
        final PrintWriter out = new PrintWriter(sw);

        for (int i = 0; i < messages.size(); i++) {
            if (i > 0)
                out.println();
            final IMessage m = (IMessage) messages.get(i);
            out.print(excludePrefix ? m.getMessage() : getFullMessage(m));
        }
        out.flush();
        return sw.toString();
    }

    private ArrayList createPeers(final ArrayList messages) {
        final ArrayList peers = new ArrayList();
        int maxType = 0;
        for (int i = 0; i < messages.size(); i++) {
            final Message message = (Message) messages.get(i);
            if (message.type > maxType) {
                peers.clear();
                maxType = message.type;
            }
            if (message.type == maxType)
                peers.add(message);
        }
        return peers;
    }

    /*
     * Adds the message if it does not already exist in the provided list.
     */

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.forms.IMessageManager#createSummary(org.eclipse.ui.forms.IMessage[])
     */
    public String createSummary(final IMessage[] messages) {
        return createDetails(messages);
    }

    /*
     * Finds the message with the provided key in the provided list.
     */

    private Message findMessage(final Object key, final ArrayList list) {
        for (int i = 0; i < list.size(); i++) {
            final Message message = (Message) list.get(i);
            if (message.getKey().equals(key))
                return message;
        }
        return null;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.forms.IMessageManager#getDecorationPosition()
     */
    public int getDecorationPosition() {
        return decorationPosition;
    }

    /*
     * Updates the container by rolling the messages up from the controls.
     */

    /**
     * @return Returns the number of error messages
     */
    @SuppressWarnings("unchecked")
    public int getErrorMessageCount() {

        int errors = 0;

        for (final Enumeration<ControlDecorator> enm = decorators.elements(); enm.hasMoreElements();) {
            final ControlDecorator dec = enm.nextElement();
            final ArrayList<?> allMessages = dec.controlMessages;

            for (final Object object : allMessages) {
                if (object instanceof Message) {
                    final Message message = (Message) object;
                    if (message.getMessageType() == IMessageProvider.ERROR) {
                        errors++;
                    }
                }
            }
        }

        return errors;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.forms.IMessageManager#getMessagePrefixProvider()
     */
    public IMessagePrefixProvider getMessagePrefixProvider() {
        return prefixProvider;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.forms.IMessageManager#isAutoUpdate()
     */
    public boolean isAutoUpdate() {
        return autoUpdate;
    }

    private void pruneControlDecorators() {
        for (final Iterator iter = decorators.values().iterator(); iter.hasNext();) {
            final ControlDecorator dec = (ControlDecorator) iter.next();
            if (dec.isDisposed())
                iter.remove();
        }
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.forms.IMessageManager#removeAllMessages()
     */
    public void removeAllMessages() {
        boolean needsUpdate = false;
        for (final Enumeration enm = decorators.elements(); enm.hasMoreElements();) {
            final ControlDecorator control = (ControlDecorator) enm.nextElement();
            if (control.removeMessages())
                needsUpdate = true;
        }
        if (!messages.isEmpty()) {
            messages.clear();
            needsUpdate = true;
        }
        if (needsUpdate && isAutoUpdate())
            updateForm();
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.forms.IMessageManager#removeMessage(java.lang.Object)
     */
    public void removeMessage(final Object key) {
        final Message message = findMessage(key, messages);
        if (message != null) {
            messages.remove(message);
            if (isAutoUpdate())
                updateForm();
        }
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.forms.IMessageManager#removeMessage(java.lang.Object,
     * org.eclipse.swt.widgets.Control)
     */
    public void removeMessage(final Object key, final Control control) {
        final ControlDecorator dec = (ControlDecorator) decorators.get(control);
        if (dec == null)
            return;
        if (dec.removeMessage(key))
            if (isAutoUpdate())
                updateForm();
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.forms.IMessageManager#removeMessages()
     */
    public void removeMessages() {
        if (!messages.isEmpty()) {
            messages.clear();
            if (isAutoUpdate())
                updateForm();
        }
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.forms.IMessageManager#removeMessages(org.eclipse.swt.widgets.Control)
     */
    public void removeMessages(final Control control) {
        final ControlDecorator dec = (ControlDecorator) decorators.get(control);
        if (dec != null) {
            if (dec.removeMessages()) {
                if (isAutoUpdate())
                    updateForm();
            }
        }
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.forms.IMessageManager#setAutoUpdate(boolean)
     */
    public void setAutoUpdate(final boolean autoUpdate) {
        final boolean needsUpdate = !this.autoUpdate && autoUpdate;
        this.autoUpdate = autoUpdate;
        if (needsUpdate)
            update();
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.forms.IMessageManager#setDecorationPosition(int)
     */
    public void setDecorationPosition(final int position) {
        this.decorationPosition = position;
        for (final Iterator iter = decorators.values().iterator(); iter.hasNext();) {
            final ControlDecorator dec = (ControlDecorator) iter.next();
            dec.updatePosition();
        }
    }

    /*
     * (non-Javadoc)
     * @seeorg.eclipse.ui.forms.IMessageManager#setMessagePrefixProvider(org.eclipse.ui.forms.
     * IMessagePrefixProvider)
     */
    public void setMessagePrefixProvider(final IMessagePrefixProvider provider) {
        this.prefixProvider = provider;
        for (final Iterator iter = decorators.values().iterator(); iter.hasNext();) {
            final ControlDecorator dec = (ControlDecorator) iter.next();
            dec.updatePrefix();
        }
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.forms.IMessageManager#update()
     */
    public void update() {
        // Update decorations
        for (final Iterator iter = decorators.values().iterator(); iter.hasNext();) {
            final ControlDecorator dec = (ControlDecorator) iter.next();
            dec.update();
        }
        // Update the form
        updateForm();
    }

    private void update(final ArrayList mergedList) {
        pruneControlDecorators();
        if (scrolledForm.getHead().getBounds().height == 0 || mergedList.isEmpty() || mergedList == null) {
            scrolledForm.setMessage(null, IMessageProvider.NONE);
            return;
        }
        final ArrayList peers = createPeers(mergedList);
        final int maxType = ((IMessage) peers.get(0)).getMessageType();
        String messageText;
        final IMessage[] array = (IMessage[]) peers.toArray(new IMessage[peers.size()]);
        if (peers.size() == 1 && ((Message) peers.get(0)).prefix == null) {
            // a single message
            final IMessage message = (IMessage) peers.get(0);
            messageText = message.getMessage();
            scrolledForm.setMessage(messageText, maxType, array);
        } else {
            // show a summary message for the message
            // and list of errors for the details
            if (peers.size() > 1)
                messageText = Messages.bind(MULTIPLE_MESSAGE_SUMMARY_KEYS[maxType],
                        new String[] { peers.size() + "" }); //$NON-NLS-1$
            else
                messageText = SINGLE_MESSAGE_SUMMARY_KEYS[maxType];
            scrolledForm.setMessage(messageText, maxType, array);
        }
    }

    private void updateForm() {
        final ArrayList mergedList = new ArrayList();
        mergedList.addAll(messages);
        for (final Enumeration enm = decorators.elements(); enm.hasMoreElements();) {
            final ControlDecorator dec = (ControlDecorator) enm.nextElement();
            dec.addAll(mergedList);
        }
        update(mergedList);
    }
}