/******************************************************************************* * Copyright (c) 2008-2010 Sonatype, Inc. * 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: * Sonatype, Inc. - initial API and implementation *******************************************************************************/ package org.eclipse.m2e.editor.pom; import java.net.MalformedURLException; import java.net.URL; import java.util.Arrays; import java.util.Properties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CCombo; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseTrackAdapter; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.browser.IWebBrowser; import org.eclipse.ui.browser.IWorkbenchBrowserSupport; import org.eclipse.ui.forms.widgets.Form; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.Hyperlink; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.codehaus.plexus.interpolation.InterpolationException; import org.codehaus.plexus.interpolation.PrefixedObjectValueSource; import org.codehaus.plexus.interpolation.PropertiesBasedValueSource; import org.codehaus.plexus.interpolation.RegexBasedInterpolator; import org.apache.maven.project.MavenProject; import org.eclipse.m2e.core.ui.internal.dialogs.MavenMessageDialog; import org.eclipse.m2e.core.ui.internal.util.Util; import org.eclipse.m2e.editor.internal.Messages; import org.eclipse.m2e.editor.xml.internal.FormHoverProvider; /** * @author Eugene Kuleshov */ public abstract class FormUtils { private static final Logger log = LoggerFactory.getLogger(FormUtils.class); public static final int MAX_MSG_LENGTH = 80; /** * @deprecated use your own string.. this should not have been made ublic in the first place. */ public static final String MORE_DETAILS = ""; //$NON-NLS-1$ public static void decorateHeader(FormToolkit toolkit, Form form) { Util.proxy(toolkit, FormTooliktStub.class).decorateFormHeading(form); } /** * Stub interface for API added to FormToolikt in Eclipse 3.3 */ private interface FormTooliktStub { public void decorateFormHeading(Form form); } /** * @param form * @param message * @param severity * @return */ public static boolean setMessage(ScrolledForm form, String message, int severity) { if(message != null && (message.length() > MAX_MSG_LENGTH || message.contains("\n"))) { String truncMsg = message; String[] lines = message.split("\n"); //$NON-NLS-1$ if(lines.length > 0) { truncMsg = lines[0]; } else { truncMsg = message.substring(0, MAX_MSG_LENGTH); } setMessageAndTTip(form, NLS.bind(Messages.FormUtils_click_for_details, truncMsg), message, severity); return true; } else { setMessageAndTTip(form, message, message, severity); return false; } } public static void setMessageAndTTip(final ScrolledForm form, final String message, final String ttip, final int severity) { if(form.isDisposed()) { return; } form.getForm().setMessage(message, severity); addFormTitleListeners(createDefaultPerformer(form, message, ttip, severity), form); } /** * @param form * @param message * @param severity * @param runnable something that will be "run" once the user clicks the message area. */ static void setMessageWithPerformer(ScrolledForm form, String message, int severity, FormHoverProvider.Execute runnable) { form.getForm().setMessage(message, severity); addFormTitleListeners(runnable, form); } public static String nvl(String s) { return s == null ? "" : s; //$NON-NLS-1$ } public static String nvl(String s, String defaultValue) { return s == null ? defaultValue : s; } public static boolean isEmpty(String s) { return s == null || s.length() == 0; } public static boolean isEmpty(Text t) { return t == null || isEmpty(t.getText()); } public static void setText(Text control, String text) { if(control != null && !control.isDisposed() && !control.getText().equals(text)) { control.setText(nvl(text)); control.setSelection(nvl(text).length()); } } public static void setText(CCombo control, String text) { if(control != null && !control.isDisposed() && !control.getText().equals(text)) { control.setText(nvl(text)); } } public static void setButton(Button control, boolean selection) { if(control != null && !control.isDisposed() && control.getSelection() != selection) { control.setSelection(selection); } } public static void openHyperlink(String url) { if(!isEmpty(url) && (url.startsWith("http://") || url.startsWith("https://"))) { //$NON-NLS-1$ //$NON-NLS-2$ url = url.trim(); try { IWorkbenchBrowserSupport browserSupport = PlatformUI.getWorkbench().getBrowserSupport(); IWebBrowser browser = browserSupport.createBrowser(IWorkbenchBrowserSupport.NAVIGATION_BAR | IWorkbenchBrowserSupport.LOCATION_BAR, url, url, url); browser.openURL(new URL(url)); } catch(PartInitException ex) { log.error(ex.getMessage(), ex); } catch(MalformedURLException ex) { log.error("Malformed url " + url, ex); //$NON-NLS-1$ } } } public static void setEnabled(Composite composite, boolean enabled) { if(composite != null && !composite.isDisposed()) { composite.setEnabled(enabled); for(Control control : composite.getChildren()) { if(control instanceof Combo) { control.setEnabled(enabled); } else if(control instanceof CCombo) { control.setEnabled(enabled); } else if(control instanceof Hyperlink) { control.setEnabled(enabled); } else if(control instanceof Composite) { setEnabled((Composite) control, enabled); } else { control.setEnabled(enabled); } } } } /** * be very careful when using this method, see MNGECLIPSE-2674 ideally this would be replaced by a distributed system * where each component reacts to the readonly or not-readonly event and with the knowledge of the inner state decides * what gets enabled/disabled * * @param composite * @param readonly * @deprecated so that you think hard before using it. Using it for disabling all controls is probably fine. Enabling * all is NOT. */ public static void setReadonly(Composite composite, boolean readonly) { if(composite != null) { for(Control control : composite.getChildren()) { if(control instanceof Text) { ((Text) control).setEditable(!readonly); } else if(control instanceof Combo) { ((Combo) control).setEnabled(!readonly); } else if(control instanceof CCombo) { ((CCombo) control).setEnabled(!readonly); } else if(control instanceof Button) { ((Button) control).setEnabled(!readonly); } else if(control instanceof Composite) { setReadonly((Composite) control, readonly); } } } } private static void cleanupMouseListeners(Control kid, int event) { Listener[] listeners = kid.getListeners(event); if(listeners != null) { for(Listener list : listeners) { kid.removeListener(event, list); } } } private static FormHoverProvider.Execute createDefaultPerformer(final ScrolledForm form, final String message, final String ttip, final int severity) { if(ttip != null && ttip.length() > 0 && message != null) { return new FormHoverProvider.Execute() { public void run(Point point) { int dialogSev = IMessageProvider.ERROR == severity ? MessageDialog.ERROR : MessageDialog.WARNING; MavenMessageDialog.openWithSeverity(form.getShell(), Messages.FormUtils_error_info, Messages.FormUtils_pom_error, ttip, dialogSev); } }; } return null; } private static void addFormTitleListeners(final FormHoverProvider.Execute runnable, final ScrolledForm form) { if(runnable != null) { final Composite head = form.getForm().getHead(); Control[] kids = head.getChildren(); for(final Control kid : kids) { //want to get the title region only //Note: doing this instead of adding a head 'client' control because that gets put //on the second line of the title, and looks broken. instead, converting the title //into a url if(kid != form && kid instanceof Canvas) { cleanupMouseListeners(kid, SWT.MouseUp); cleanupMouseListeners(kid, SWT.MouseEnter); cleanupMouseListeners(kid, SWT.MouseExit); kid.addMouseListener(new MouseAdapter() { public void mouseUp(MouseEvent e) { runnable.run(kid.toDisplay(new Point(e.x, e.y))); } }); kid.addMouseTrackListener(new MouseTrackAdapter() { public void mouseEnter(MouseEvent e) { head.setCursor(Display.getDefault().getSystemCursor(SWT.CURSOR_HAND)); } public void mouseExit(MouseEvent e) { head.setCursor(null); } }); } } } else { //no ttip or message, make sure old listeners are cleaned up if errs are removed final Composite head = form.getForm().getHead(); Control[] kids = head.getChildren(); for(Control kid : kids) { //want to get the title region only //Note: doing this instead of adding a head 'client' control because that gets put //on the second line of the title, and looks broken. instead, converting the title //into a url if(kid != form && kid instanceof Canvas) { cleanupMouseListeners(kid, SWT.MouseUp); cleanupMouseListeners(kid, SWT.MouseEnter); cleanupMouseListeners(kid, SWT.MouseExit); } } } } /** * copy pas * * @param project * @param text * @return */ //TODO copy pasted from PomTemplateContext static String simpleInterpolate(MavenProject project, String text) { if(text != null && text.contains("${")) { //$NON-NLS-1$ //when expression is in the version but no project instance around // just give up. if(project == null) { return null; } Properties props = project.getProperties(); RegexBasedInterpolator inter = new RegexBasedInterpolator(); if(props != null) { inter.addValueSource(new PropertiesBasedValueSource(props)); } inter.addValueSource(new PrefixedObjectValueSource( Arrays.asList(new String[] {"pom.", "project."}), project.getModel(), false)); //$NON-NLS-1$ //$NON-NLS-2$ try { text = inter.interpolate(text); } catch(InterpolationException e) { text = null; } } return text; } }