/******************************************************************************* * Copyright (c) 2007 IBM Corporation and others. * 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: * IBM Corporation - initial API and implementation ******************************************************************************/ package org.eclipse.ui.internal.forms; import java.io.PrintWriter; import java.io.StringWriter; import java.util.*; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.widgets.*; import org.eclipse.ui.forms.*; import org.eclipse.ui.forms.widgets.Hyperlink; import org.eclipse.ui.forms.widgets.ScrolledForm; /** * @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 ScrolledForm 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 final String[] SINGLE_MESSAGE_SUMMARY_KEYS = { Messages.get().MessageManager_sMessageSummary, Messages.get().MessageManager_sMessageSummary, Messages.get().MessageManager_sWarningSummary, Messages.get().MessageManager_sErrorSummary }; private final String[] MULTIPLE_MESSAGE_SUMMARY_KEYS = { Messages.get().MessageManager_pMessageSummary, Messages.get().MessageManager_pMessageSummary, Messages.get().MessageManager_pWarningSummary, Messages.get().MessageManager_pErrorSummary }; static class Message implements IMessage { Control control; Object data; Object key; String message; int type; String prefix; Message(Object key, String message, int type, Object data) { this.key = key; this.message = message; this.type = type; this.data = 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#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.ui.forms.messages.IMessage#getPrefix() */ public String getPrefix() { return prefix; } } static class DefaultPrefixProvider implements IMessagePrefixProvider { public String getPrefix(Control c) { Composite parent = c.getParent(); 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--) { 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; } } class ControlDecorator { // private ControlDecoration decoration; private ArrayList controlMessages = new ArrayList(); private String prefix; ControlDecorator(Control control) { // this.decoration = new ControlDecoration(control, decorationPosition, scrolledForm.getBody()); } public boolean isDisposed() { // return decoration.getControl() == null; return false; } void updatePrefix() { prefix = null; } void updatePosition() { // Control control = decoration.getControl(); // decoration.dispose(); // this.decoration = new ControlDecoration(control, decorationPosition, scrolledForm.getBody()); update(); } String getPrefix() { if (prefix == null) createPrefix(); return prefix; } 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$ } void addAll(ArrayList target) { target.addAll(controlMessages); } void addMessage(Object key, String text, Object data, int type) { // Message message = MessageManager.this.addMessage(getPrefix(), key, // text, data, type, controlMessages); // message.control = decoration.getControl(); // if (isAutoUpdate()) // update(); } boolean removeMessage(Object key) { 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 { // ArrayList peers = createPeers(controlMessages); // int type = ((IMessage) peers.get(0)).getMessageType(); // String description = createDetails(createPeers(peers), true); // if (type == IMessageProvider.ERROR) // decoration.setImage(standardError.getImage()); // else if (type == IMessageProvider.WARNING) // decoration.setImage(standardWarning.getImage()); // decoration.setDescriptionText(description); // decoration.show(); // } } } /** * Creates a new instance of the message manager that will work with the * provided form. * * @param scrolledForm * the form to control */ public MessageManager(ScrolledForm scrolledForm) { this.scrolledForm = scrolledForm; } /* * (non-Javadoc) * * @see org.eclipse.ui.forms.IMessageManager#addMessage(java.lang.Object, * java.lang.String, int) */ public void addMessage(Object key, String messageText, Object data, 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(Object key, String messageText, Object data, int type, 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(); } /* * (non-Javadoc) * * @see org.eclipse.ui.forms.IMessageManager#removeMessage(java.lang.Object) */ public void removeMessage(Object key) { Message message = findMessage(key, messages); if (message != null) { messages.remove(message); 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#removeMessage(java.lang.Object, * org.eclipse.swt.widgets.Control) */ public void removeMessage(Object key, Control control) { 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(org.eclipse.swt.widgets.Control) */ public void removeMessages(Control control) { ControlDecorator dec = (ControlDecorator) decorators.get(control); if (dec != null) { if (dec.removeMessages()) { if (isAutoUpdate()) updateForm(); } } } /* * (non-Javadoc) * * @see org.eclipse.ui.forms.IMessageManager#removeAllMessages() */ public void removeAllMessages() { boolean needsUpdate = false; for (Enumeration enm = decorators.elements(); enm.hasMoreElements();) { ControlDecorator control = (ControlDecorator) enm.nextElement(); if (control.removeMessages()) needsUpdate = true; } if (!messages.isEmpty()) { messages.clear(); needsUpdate = true; } if (needsUpdate && isAutoUpdate()) updateForm(); } /* * Adds the message if it does not already exist in the provided list. */ private Message addMessage(String prefix, Object key, String messageText, Object data, int type, 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; } /* * Finds the message with the provided key in the provided list. */ private Message findMessage(Object key, ArrayList list) { for (int i = 0; i < list.size(); i++) { Message message = (Message) list.get(i); if (message.getKey().equals(key)) return message; } return null; } /* * (non-Javadoc) * * @see org.eclipse.ui.forms.IMessageManager#update() */ public void update() { // Update decorations for (Iterator iter = decorators.values().iterator(); iter.hasNext();) { ControlDecorator dec = (ControlDecorator) iter.next(); dec.update(); } // Update the form updateForm(); } /* * Updates the container by rolling the messages up from the controls. */ private void updateForm() { ArrayList mergedList = new ArrayList(); mergedList.addAll(messages); for (Enumeration enm = decorators.elements(); enm.hasMoreElements();) { ControlDecorator dec = (ControlDecorator) enm.nextElement(); dec.addAll(mergedList); } update(mergedList); } private void update(ArrayList mergedList) { pruneControlDecorators(); if (mergedList.isEmpty() || mergedList == null) { scrolledForm.setMessage(null, IMessageProvider.NONE); return; } ArrayList peers = createPeers(mergedList); int maxType = ((IMessage) peers.get(0)).getMessageType(); String messageText; IMessage[] array = (IMessage[]) peers .toArray(new IMessage[peers.size()]); if (peers.size() == 1 && ((Message) peers.get(0)).prefix == null) { // a single message 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 = NLS.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 static String getFullMessage(IMessage message) { if (message.getPrefix() == null) return message.getMessage(); return message.getPrefix() + message.getMessage(); } private ArrayList createPeers(ArrayList messages) { ArrayList peers = new ArrayList(); int maxType = 0; for (int i = 0; i < messages.size(); i++) { Message message = (Message) messages.get(i); if (message.type > maxType) { peers.clear(); maxType = message.type; } if (message.type == maxType) peers.add(message); } return peers; } private String createDetails(ArrayList messages, boolean excludePrefix) { StringWriter sw = new StringWriter(); PrintWriter out = new PrintWriter(sw); for (int i = 0; i < messages.size(); i++) { if (i > 0) out.println(); IMessage m = (IMessage) messages.get(i); out.print(excludePrefix ? m.getMessage() : getFullMessage(m)); } out.flush(); return sw.toString(); } public static String createDetails(IMessage[] messages) { if (messages == null || messages.length == 0) return null; StringWriter sw = new StringWriter(); 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(); } /* * (non-Javadoc) * * @see org.eclipse.ui.forms.IMessageManager#createSummary(org.eclipse.ui.forms.IMessage[]) */ public String createSummary(IMessage[] messages) { return createDetails(messages); } private void pruneControlDecorators() { for (Iterator iter = decorators.values().iterator(); iter.hasNext();) { ControlDecorator dec = (ControlDecorator) iter.next(); if (dec.isDisposed()) iter.remove(); } } /* * (non-Javadoc) * * @see org.eclipse.ui.forms.IMessageManager#getMessagePrefixProvider() */ public IMessagePrefixProvider getMessagePrefixProvider() { return prefixProvider; } /* * (non-Javadoc) * * @see org.eclipse.ui.forms.IMessageManager#setMessagePrefixProvider(org.eclipse.ui.forms.IMessagePrefixProvider) */ public void setMessagePrefixProvider(IMessagePrefixProvider provider) { this.prefixProvider = provider; for (Iterator iter = decorators.values().iterator(); iter.hasNext();) { ControlDecorator dec = (ControlDecorator) iter.next(); dec.updatePrefix(); } } /* * (non-Javadoc) * * @see org.eclipse.ui.forms.IMessageManager#getDecorationPosition() */ public int getDecorationPosition() { return decorationPosition; } /* * (non-Javadoc) * * @see org.eclipse.ui.forms.IMessageManager#setDecorationPosition(int) */ public void setDecorationPosition(int position) { this.decorationPosition = position; for (Iterator iter = decorators.values().iterator(); iter.hasNext();) { ControlDecorator dec = (ControlDecorator) iter.next(); dec.updatePosition(); } } /* * (non-Javadoc) * * @see org.eclipse.ui.forms.IMessageManager#isAutoUpdate() */ public boolean isAutoUpdate() { return autoUpdate; } /* * (non-Javadoc) * * @see org.eclipse.ui.forms.IMessageManager#setAutoUpdate(boolean) */ public void setAutoUpdate(boolean autoUpdate) { boolean needsUpdate = !this.autoUpdate && autoUpdate; this.autoUpdate = autoUpdate; if (needsUpdate) update(); } }