Java tutorial
// $codepro.audit.disable com.instantiations.assist.eclipse.analysis.audit.rule.effectivejava.alwaysOverridetoString.alwaysOverrideToString, com.instantiations.assist.eclipse.analysis.deserializeabilitySecurity, com.instantiations.assist.eclipse.analysis.disallowReturnMutable, com.instantiations.assist.eclipse.analysis.enforceCloneableUsageSecurity /******************************************************************************* * Copyright (c) 2012 Ericsson AB 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: * Ericsson AB - initial API and implementation *******************************************************************************/ package org.eclipse.mylyn.reviews.r4e.ui.internal.utils; import java.io.File; import java.lang.reflect.Field; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.StringTokenizer; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantLock; import org.eclipse.compare.ICompareNavigator; import org.eclipse.compare.contentmergeviewer.TextMergeViewer; import org.eclipse.compare.internal.CompareContentViewerSwitchingPane; import org.eclipse.compare.internal.CompareEditorInputNavigator; import org.eclipse.compare.internal.MergeSourceViewer; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceConverter; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.text.ITextOperationTarget; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.window.Window; import org.eclipse.mylyn.reviews.frame.ui.annotation.IReviewAnnotationSupport; import org.eclipse.mylyn.reviews.notifications.core.IMeetingData; import org.eclipse.mylyn.reviews.r4e.core.model.R4EAnomalyState; import org.eclipse.mylyn.reviews.r4e.core.model.R4EFileVersion; import org.eclipse.mylyn.reviews.r4e.core.model.R4EFormalReview; import org.eclipse.mylyn.reviews.r4e.core.model.R4EParticipant; import org.eclipse.mylyn.reviews.r4e.core.model.R4EReviewPhase; import org.eclipse.mylyn.reviews.r4e.core.model.drules.R4EDesignRuleClass; import org.eclipse.mylyn.reviews.r4e.core.model.drules.R4EDesignRuleRank; import org.eclipse.mylyn.reviews.r4e.core.model.serial.impl.CompatibilityException; import org.eclipse.mylyn.reviews.r4e.core.model.serial.impl.OutOfSyncException; import org.eclipse.mylyn.reviews.r4e.core.model.serial.impl.ResourceHandlingException; import org.eclipse.mylyn.reviews.r4e.core.rfs.spi.ReviewsFileStorageException; import org.eclipse.mylyn.reviews.r4e.ui.R4EUIPlugin; import org.eclipse.mylyn.reviews.r4e.ui.internal.annotation.control.R4ECompareAnnotationSupport; import org.eclipse.mylyn.reviews.r4e.ui.internal.annotation.control.R4ESingleAnnotationSupport; import org.eclipse.mylyn.reviews.r4e.ui.internal.commands.UIElementsProvider; import org.eclipse.mylyn.reviews.r4e.ui.internal.dialogs.IParticipantInputDialog; import org.eclipse.mylyn.reviews.r4e.ui.internal.dialogs.IParticipantUnassignDialog; import org.eclipse.mylyn.reviews.r4e.ui.internal.dialogs.R4EUIDialogFactory; import org.eclipse.mylyn.reviews.r4e.ui.internal.editors.EditorProxy; import org.eclipse.mylyn.reviews.r4e.ui.internal.editors.R4ECompareEditorInput; import org.eclipse.mylyn.reviews.r4e.ui.internal.model.IR4EUIModelElement; import org.eclipse.mylyn.reviews.r4e.ui.internal.model.IR4EUIPosition; import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIAnomalyBasic; import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIAnomalyExtended; import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIComment; import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIContent; import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIFileContext; import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIModelController; import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIPostponedAnomaly; import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIReviewBasic; import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIReviewExtended; import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUITextPosition; import org.eclipse.mylyn.reviews.userSearch.userInfo.IUserInfo; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.browser.IWebBrowser; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.services.ISourceProviderService; import org.eclipse.ui.texteditor.AnnotationPreference; import org.eclipse.ui.texteditor.ITextEditor; /** * This class provides general utility methods used in the UI implementation * * @author Sebastien Dubois * @version $Revision: 1.0 $ */ public class UIUtils { // ------------------------------------------------------------------------ // Constants // ------------------------------------------------------------------------ //NOTE: THese values are used in the hack to change cursor position in compare editor. /** * Field COMPARE_EDITOR_TEXT_CLASS_NAME. (value is ""org.eclipse.compare.contentmergeviewer.TextMergeViewer"") */ private static final String COMPARE_EDITOR_TEXT_CLASS_NAME = "org.eclipse.compare.contentmergeviewer.TextMergeViewer"; /** * Field COMPARE_EDITOR_TEXT_FIELD_LEFT. (value is ""fLeft"") */ private static final String COMPARE_EDITOR_TEXT_FIELD_LEFT = "fLeft"; /** * Field COMPARE_EDITOR_TEXT_FIELD_RIGHT. (value is ""fRight"") */ private static final String COMPARE_EDITOR_TEXT_FIELD_RIGHT = "fRight"; /** * Field DEFAULT_OBJECT_CLASS_NAME. (value is ""Object"") */ private static final String DEFAULT_OBJECT_CLASS_NAME = "Object"; /** * Field TEST_MODE. */ //This could be replaced by org.eclipse.mylyn.commons.core.CoreUtil#TEST_MODE, //however it's worth repeating as it's a small piece of code public static final boolean TEST_MODE; static { final String application = System.getProperty("eclipse.application", ""); //$NON-NLS-1$ //$NON-NLS-2$ if (application.length() > 0) { TEST_MODE = application.endsWith("testapplication") || application.endsWith("uitest"); //$NON-NLS-1$ //$NON-NLS-2$ } else { final String commands = System.getProperty("eclipse.commands", ""); //$NON-NLS-1$ //$NON-NLS-2$ TEST_MODE = commands.contains("testapplication\n"); //$NON-NLS-1$ } //Do not show Error Dialogs when doing automated testing if (TEST_MODE) { ErrorDialog.AUTOMATED_MODE = true; } else { ErrorDialog.AUTOMATED_MODE = false; } } /** * Field COMPATIBILITY_ERROR_MESSAGE. (value is ""Cannot use older version of R4E to open newer element version"") */ private static final String COMPATIBILITY_ERROR_MESSAGE = "Cannot use older version of R4E to open newer element version"; /** * Field COMPATIBILITY_WARNING_DIALOG_TITLE. (value is ""Version Mismatch Detected"") */ private static final String COMPATIBILITY_WARNING_DIALOG_TITLE = "Version Mismatch Detected"; /** * Field COMPATIBILITY_WARNING_MESSAGE. (value is ""You are trying to open an older version of the element than the * one currently handled by this version of R4E.\n You can open the element normally, which will upgrade its version * to the current one, or in Read-only mode, which will preserve its version.\n"") */ private static final String COMPATIBILITY_WARNING_MESSAGE = "You are trying to open an older version of the element than the one currently handled by this version of R4E." + R4EUIConstants.LINE_FEED + "You can open the element normally, which will convert its version to the current application meta-data, or in Read-only mode, which will preserve its version."; /** * Field COMPATIBILITY_WARNING_DIALOG_BUTTONS. */ private static final String[] COMPATIBILITY_WARNING_DIALOG_BUTTONS = { "Open (Convert Version)", "Open in Read-Only Mode (Preserve Version)", "Cancel" }; /** * Field MEETING_DATA_MISMATCH_DIALOG_TITLE. (value is ""Meeting Data Mismatch Detected"") */ private static final String MEETING_DATA_MISMATCH_DIALOG_TITLE = "Meeting Data Mismatch Detected"; /** * Field MEETING_DATA_MISMATCH_MESSAGE. (value is ""R4E Meeting Data is different than the Remote Mail Server * Meeting Data .\n Which one should we keep?"") */ private static final String MEETING_DATA_MISMATCH_MESSAGE = "R4E Meeting Data is different than the Remote Mail Server Meeting Data." + R4EUIConstants.LINE_FEED + "Which one should we keep?"; /** * Field MEETING_DATA_MISMATCH_DIALOG_BUTTONS. */ private static final String[] MEETING_DATA_MISMATCH_DIALOG_BUTTONS = { "Use Local data", "Use Remote Data", "Cancel" }; /** * Field DISABLED_FONT_COLOR. */ public static final Color DISABLED_FONT_COLOR = Display.getCurrent().getSystemColor(SWT.COLOR_DARK_GRAY); /** * Field ENABLED_FONT_COLOR. */ public static final Color ENABLED_FONT_COLOR = Display.getCurrent().getSystemColor(SWT.COLOR_BLACK); /** * Field SINGLE_KEY_ANNOTATION_SUPPORT. (value is ""singleEditorAnnotationSupport"") */ private static final String SINGLE_KEY_ANNOTATION_SUPPORT = "singleEditorAnnotationSupport"; /** * Field COMPARE_KEY_ANNOTATION_SUPPORT. (value is ""compareEditorAnnotationSupport"") */ private static final String COMPARE_KEY_ANNOTATION_SUPPORT = "compareEditorAnnotationSupport"; // ------------------------------------------------------------------------ // Members // ------------------------------------------------------------------------ /** * Field fLock. */ private final static ReentrantLock fLock = new ReentrantLock(); // ------------------------------------------------------------------------ // Methods // ------------------------------------------------------------------------ /** * Get the current image and add it to the image registry if necessary * * @param aUrl * - the location of the image to load * @return Image */ public static Image loadIcon(String aUrl) { final R4EUIPlugin plugin = R4EUIPlugin.getDefault(); //Need to lock since this can be called in multiple jobs for //the same icon. i.e. create multiple participants fLock.lock(); Image icon = plugin.getImageRegistry().get(aUrl); try { if (null == icon) { final URL imageURL = plugin.getBundle().getEntry(aUrl); final ImageDescriptor descriptor = ImageDescriptor.createFromURL(imageURL); icon = descriptor.createImage(); plugin.getImageRegistry().put(aUrl, icon); } } finally { fLock.unlock(); } return icon; } /** * Get a disabled version of the current image and add it to the image registry if necessary * * @param aUrl * - the location of the original image * @return Image */ public static Image loadDisabledIcon(final String aUrl) { final R4EUIPlugin plugin = R4EUIPlugin.getDefault(); fLock.lock(); Image icon = plugin.getImageRegistry().get(aUrl + "_disabled"); try { if (null == icon) { final URL imageURL = plugin.getBundle().getEntry(aUrl); final ImageDescriptor originalDescriptor = ImageDescriptor.createFromURL(imageURL); final ImageDescriptor disabledDescriptor = ImageDescriptor.createWithFlags(originalDescriptor, SWT.IMAGE_DISABLE); //NOTE: Here we block while creating the new Image because we need to return it from this method Display.getDefault().syncExec(new Runnable() { public void run() { final Image newIcon = disabledDescriptor.createImage(); plugin.getImageRegistry().put(aUrl + "_disabled", newIcon); } }); } } finally { fLock.unlock(); } return icon; } /** * Method displayResourceErrorDialog. * * @param e * ResourceHandlingException */ public static void displayResourceErrorDialog(ResourceHandlingException e) { R4EUIPlugin.Ftracer.traceError("Exception: " + e.toString() + " (" + e.getMessage() + ")"); R4EUIPlugin.getDefault().logError("Exception: " + e.toString(), e); final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_ERROR, "Resource Error Detected", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0, e.getMessage(), e), IStatus.ERROR); Display.getDefault().syncExec(new Runnable() { public void run() { dialog.open(); } }); } /** * Method displayCompatibilityErrorDialog. * * @param e * CompatibilityException */ public static void displayCompatibilityErrorDialog(CompatibilityException e) { R4EUIPlugin.Ftracer.traceError("Exception: " + e.toString() + " (" + e.getMessage() + ")"); R4EUIPlugin.getDefault().logError("Exception: " + e.toString(), e); final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_ERROR, "Compatibility problem Detected", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0, e.getMessage(), e), IStatus.ERROR); Display.getDefault().syncExec(new Runnable() { public void run() { dialog.open(); } }); } /** * Method displayCompatibilityErrorDialog. */ public static void displayCompatibilityErrorDialog() { R4EUIPlugin.Ftracer.traceError(COMPATIBILITY_ERROR_MESSAGE); final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_ERROR, "Compatibility problem Detected", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0, COMPATIBILITY_ERROR_MESSAGE, null), IStatus.ERROR); Display.getDefault().syncExec(new Runnable() { public void run() { dialog.open(); } }); } /** * Method displayCompatibilityWarningDialog. * * @param aDataVersion * String * @param aApplVersionl * String * @return int */ public static int displayCompatibilityWarningDialog(final String aDataVersion, final String aApplVersionl) { R4EUIPlugin.Ftracer.traceWarning(COMPATIBILITY_WARNING_MESSAGE); final int[] result = new int[1]; //We need this to be able to pass the result value outside. This is safe as we are using SyncExec Display.getDefault().syncExec(new Runnable() { public void run() { final MessageDialog dialog = new MessageDialog(null, COMPATIBILITY_WARNING_DIALOG_TITLE, null, COMPATIBILITY_WARNING_MESSAGE + R4EUIConstants.LINE_FEED + "Element meta-data Version: " + aDataVersion + R4EUIConstants.LINE_FEED + "Application meta-data Version: " + aApplVersionl, MessageDialog.QUESTION_WITH_CANCEL, COMPATIBILITY_WARNING_DIALOG_BUTTONS, 0); result[0] = dialog.open(); } }); return result[0]; } /** * Method displaySyncErrorDialog. * * @param e * OutOfSyncException */ public static void displaySyncErrorDialog(OutOfSyncException e) { R4EUIPlugin.Ftracer.traceWarning("Exception: " + e.toString() + " (" + e.getMessage() + ")"); final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_ERROR, "Synchronization Error Detected" + "Please refresh the review navigator view and try the command again", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0, e.getMessage(), e), IStatus.ERROR); Display.getDefault().syncExec(new Runnable() { public void run() { dialog.open(); } }); // TODO later we will want to do this automatically } /** * Method displayVersionErrorDialog. * * @param e */ public static void displayReviewsFileStorageErrorDialog(ReviewsFileStorageException e) { R4EUIPlugin.Ftracer.traceError("Exception: " + e.toString() + " (" + e.getMessage() + ")"); R4EUIPlugin.getDefault().logError("Exception: " + e.toString(), e); final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_ERROR, "Local Review Storage Error Detected", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0, e.getMessage(), e), IStatus.ERROR); Display.getDefault().syncExec(new Runnable() { public void run() { dialog.open(); } }); } /** * Method displayCoreErrorDialog. * * @param e * CoreException */ public static void displayCoreErrorDialog(CoreException e) { displayCoreErrorDialog(e, true); } /** * Method displayCoreErrorDialog. * * @param aEx * CoreException * @param aBol * Boolean : To log the error in the error log */ public static void displayCoreErrorDialog(CoreException aEx, Boolean aBol) { if (aBol) { R4EUIPlugin.Ftracer.traceError("Exception: " + aEx.toString() + " (" + aEx.getMessage() + ")"); //$NON-NLS-2$//$NON-NLS-3$ R4EUIPlugin.getDefault().logError("Exception: " + aEx.toString(), aEx); } final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_ERROR, "Eclipse Runtime Core Error Detected", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0, aEx.getMessage(), aEx), IStatus.ERROR); Display.getDefault().syncExec(new Runnable() { public void run() { dialog.open(); } }); } /** * Method displayFailedLoadDialog. * * @param aLoadErrors * List<String> */ public static void displayFailedLoadDialog(List<String> aLoadErrors) { final StringBuilder errorMsgs = new StringBuilder(); errorMsgs.append("The following errors were reported:" + R4EUIConstants.LINE_FEED); for (String msg : aLoadErrors) { errorMsgs.append(msg); } final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_ERROR, "Some elements failed to load", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0, errorMsgs.toString(), null), IStatus.ERROR); Display.getDefault().syncExec(new Runnable() { public void run() { dialog.open(); } }); } /** * Method displayMeetingDataMismatchDialog. * * @param aLocalData * IMeetingData * @param aRemoteData * IMeetingData * @return int */ public static int displayMeetingDataMismatchDialog(final IMeetingData aLocalData, final IMeetingData aRemoteData) { R4EUIPlugin.Ftracer.traceWarning(MEETING_DATA_MISMATCH_MESSAGE); final int[] result = new int[1]; //We need this to be able to pass the result value outside. This is safe as we are using SyncExec Display.getDefault().syncExec(new Runnable() { public void run() { final SimpleDateFormat dueDateFormat = new SimpleDateFormat( R4EUIConstants.SIMPLE_DATE_FORMAT_MINUTES); String localStartTime = dueDateFormat.format(new Date(aLocalData.getStartTime())); String remoteStartTime = ""; String remoteLocation = ""; String remoteDuration = ""; if (null != aRemoteData) { remoteStartTime = dueDateFormat.format(new Date(aRemoteData.getStartTime())); remoteLocation = aRemoteData.getLocation(); remoteDuration = aRemoteData.getDuration().toString(); } final MessageDialog dialog = new MessageDialog(null, MEETING_DATA_MISMATCH_DIALOG_TITLE, null, MEETING_DATA_MISMATCH_MESSAGE + R4EUIConstants.LINE_FEED + R4EUIConstants.LINE_FEED + "Local Data:" + R4EUIConstants.LINE_FEED + R4EUIConstants.TAB_FEED + "Start time = " + localStartTime + R4EUIConstants.LINE_FEED + R4EUIConstants.TAB_FEED + "Duration = " + aLocalData.getDuration() + R4EUIConstants.LINE_FEED + R4EUIConstants.TAB_FEED + "Location = " + aLocalData.getLocation() + R4EUIConstants.LINE_FEED + "Remote Data:" + R4EUIConstants.LINE_FEED + R4EUIConstants.TAB_FEED + "Start time = " + remoteStartTime + R4EUIConstants.LINE_FEED + R4EUIConstants.TAB_FEED + "Duration = " + remoteDuration + R4EUIConstants.LINE_FEED + R4EUIConstants.TAB_FEED + "Location = " + remoteLocation, MessageDialog.QUESTION_WITH_CANCEL, MEETING_DATA_MISMATCH_DIALOG_BUTTONS, 0); result[0] = dialog.open(); } }); return result[0]; } /** * Method displayPastDateError. * * @param aPastDate * Date * @param aPastDateStr * String * @return boolean */ public static void displayPastDateError(Date aPastDate, String aPastDateStr) { final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_ERROR, "Date Passed Error Detected", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0, "You cannot specify a date (" + aPastDateStr + ") that occured in the past", null), IStatus.ERROR); Display.getDefault().syncExec(new Runnable() { public void run() { dialog.open(); } }); } /** * Method isFilterPreferenceSet. * * @param aFilterSet * Object * @return boolean */ public static boolean isFilterPreferenceSet(Object aFilterSet) { if (null != aFilterSet && aFilterSet.toString().equals(R4EUIConstants.VALUE_TRUE_STR)) { return true; } return false; } /** * Method parseStringList. * * @param aStringList * String * @return List<String> */ public static List<String> parseStringList(String aStringList) { final List<String> stringArray = new ArrayList<String>(); if (null != aStringList) { final StringTokenizer st = new StringTokenizer(aStringList, File.pathSeparator + R4EUIConstants.LINE_FEED); while (st.hasMoreElements()) { stringArray.add((String) st.nextElement()); } } return stringArray; } /** * Method addTabbedPropertiesTextResizeListener. Resizes a Text widget in a ScrolledComposite to fit the text being * typed. It also adds scrollbars to the composite as needed * * @param aText * Text - The Text widget */ //TODO this only works for flatFormComposites and not vanilla ones. For now this is not a big deal, but we will want to review it later //A new auto-resizable text widget class should be created for this eventually public static void addTabbedPropertiesTextResizeListener(final Text aText) { aText.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { //compute new Text field size final Point newSize = aText.computeSize(SWT.DEFAULT, SWT.DEFAULT); final Point oldSize = aText.getSize(); final int heightDiff = newSize.y - oldSize.y; if (0 != heightDiff && 0 != oldSize.y) { aText.setSize(newSize); aText.getParent().layout(); //Set scrollable height so that scrollbar appear if needed Composite scrolledParent = aText.getParent(); while (!(scrolledParent instanceof ScrolledComposite)) { scrolledParent = scrolledParent.getParent(); if (null == scrolledParent) { return; } } ((ScrolledComposite) scrolledParent) .setMinSize(aText.getParent().computeSize(SWT.DEFAULT, SWT.DEFAULT)); //If the text falls outside of the display scroll down to reposition if ((aText.getLocation().y + aText.getCaretLocation().y + aText.getLineHeight()) > (scrolledParent.getClientArea().y + scrolledParent.getClientArea().height)) { final Point origin = ((ScrolledComposite) scrolledParent).getOrigin(); origin.y += heightDiff; ((ScrolledComposite) scrolledParent).setOrigin(origin); } } } }); } /** * Method mapParticipantToIndex. * * @param aParticipant * String * @return int */ public static int mapParticipantToIndex(String aParticipant) { if (null == R4EUIModelController.getActiveReview()) { return 0; } final List<R4EParticipant> participants = R4EUIModelController.getActiveReview().getParticipants(false); final int numParticipants = participants.size(); int index = 0; for (int i = 0; i < numParticipants; i++) { if (participants.get(i).isEnabled()) { if (participants.get(i).getId().equals(aParticipant)) { return index; } index++; } else { //Participant is disable, so do not consider the index since it does not show } } return R4EUIConstants.INVALID_VALUE; //Will happen for the disable participants } /** * Method getClassFromString. * * @param aClass * String * @return R4ECommentClass */ public static R4EDesignRuleClass getClassFromString(String aClass) { if (aClass.equals(R4EUIConstants.ANOMALY_CLASS_ERRONEOUS)) { return R4EDesignRuleClass.ERRONEOUS; } else if (aClass.equals(R4EUIConstants.ANOMALY_CLASS_SUPERFLUOUS)) { return R4EDesignRuleClass.SUPERFLUOUS; } else if (aClass.equals(R4EUIConstants.ANOMALY_CLASS_IMPROVEMENT)) { return R4EDesignRuleClass.IMPROVEMENT; } else if (aClass.equals(R4EUIConstants.ANOMALY_CLASS_COMMENT)) { return R4EDesignRuleClass.COMMENT; } else if (aClass.equals(R4EUIConstants.ANOMALY_CLASS_QUESTION)) { return R4EDesignRuleClass.QUESTION; } else if (aClass.equals(R4EUIConstants.ANOMALY_CLASS_MISSSING)) { return R4EDesignRuleClass.MISSING; } else { return null; //should never happen } } /** * Method getClassStr. * * @param aClass * R4EDesignRuleClass * @return String */ public static String getClassStr(R4EDesignRuleClass aClass) { if (aClass.equals(R4EDesignRuleClass.ERRONEOUS)) { return R4EUIConstants.ANOMALY_CLASS_ERRONEOUS; } else if (aClass.equals(R4EDesignRuleClass.SUPERFLUOUS)) { return R4EUIConstants.ANOMALY_CLASS_SUPERFLUOUS; } else if (aClass.equals(R4EDesignRuleClass.IMPROVEMENT)) { return R4EUIConstants.ANOMALY_CLASS_IMPROVEMENT; } else if (aClass.equals(R4EDesignRuleClass.QUESTION)) { return R4EUIConstants.ANOMALY_CLASS_QUESTION; } else if (aClass.equals(R4EDesignRuleClass.COMMENT)) { return R4EUIConstants.ANOMALY_CLASS_COMMENT; } else if (aClass.equals(R4EDesignRuleClass.MISSING)) { return R4EUIConstants.ANOMALY_CLASS_MISSSING; } else { return null; //should never happen } } /** * Method getRankFromString. * * @param aRank * String * @return R4EAnomalyRank */ public static R4EDesignRuleRank getRankFromString(String aRank) { if (aRank.equals(R4EUIConstants.ANOMALY_RANK_NONE)) { return R4EDesignRuleRank.NONE; } else if (aRank.equals(R4EUIConstants.ANOMALY_RANK_MINOR)) { return R4EDesignRuleRank.MINOR; } else if (aRank.equals(R4EUIConstants.ANOMALY_RANK_MAJOR)) { return R4EDesignRuleRank.MAJOR; } else { return null; //should never happen } } /** * Method getRankStr. * * @param aRank * R4EDesignRuleRank * @return String */ public static String getRankStr(R4EDesignRuleRank aRank) { if (aRank.equals(R4EDesignRuleRank.NONE)) { return R4EUIConstants.ANOMALY_RANK_NONE; } else if (aRank.equals(R4EDesignRuleRank.MINOR)) { return R4EUIConstants.ANOMALY_RANK_MINOR; } else if (aRank.equals(R4EDesignRuleRank.MAJOR)) { return R4EUIConstants.ANOMALY_RANK_MAJOR; } else if (aRank.equals(R4EDesignRuleRank.DEPRECATED)) { return R4EUIConstants.ANOMALY_RANK_MINOR; } else { return null; //should never happen } } /** * Method getClasses. * * @return String[] */ public static String[] getClasses() { return R4EUIConstants.CLASS_VALUES; } /** * Method getRanks. * * @return String[] */ public static String[] getRanks() { return R4EUIConstants.RANK_VALUES; } /** * Method buildUserDetailsString. * * @param aUserInfo * IUserInfo * @return String */ public static String buildUserDetailsString(IUserInfo aUserInfo) { final StringBuffer tempStr = new StringBuffer(100); final int numAttributeTypes = aUserInfo.getAttributeTypes().length; for (int i = 0; i < numAttributeTypes; i++) { tempStr.append(aUserInfo.getAttributeTypes()[i] + " = " + aUserInfo.getAttributeValues()[i] + R4EUIConstants.LINE_FEED); } return tempStr.toString(); } /** * Method selectElementInEditor. * * @param aInput * R4ECompareEditorInput * @return boolean */ public static boolean selectElementInEditor(R4ECompareEditorInput aInput) { //For now the Review Navigator View must be open to see the highlighted text in the compare editor if (null != R4EUIModelController.getNavigatorView()) { final ISelection selection = R4EUIModelController.getNavigatorView().getTreeViewer().getSelection(); final IR4EUIModelElement element = (IR4EUIModelElement) ((IStructuredSelection) selection) .getFirstElement(); IR4EUIPosition position = null; boolean isLeftPane = true; if (element instanceof R4EUIAnomalyBasic) { position = ((R4EUIAnomalyBasic) element).getPosition(); if (element instanceof R4EUIPostponedAnomaly) { isLeftPane = false; //Use right pane for postponed anomalies } } else if (element instanceof R4EUIComment) { position = ((R4EUIAnomalyBasic) element.getParent()).getPosition(); } else if (element instanceof R4EUIContent) { position = ((R4EUIContent) element).getPosition(); } if (null != position) { return selectElementInEditorPane(aInput.getNavigator(), position, isLeftPane); } } return true; } /** * Method selectElementInEditor. * * @param aInput * R4ECompareEditorInput * @return boolean */ public static boolean selectElementInEditorPane(ICompareNavigator aNavigator, IR4EUIPosition aPosition, boolean aIsLeftPane) { //Use free form to select position in file //NOTE: This is a dirty hack that involves accessing class and field we shouldn't, but that's // the only way to select the current position in the compare editor. Hopefully this code can // be removed later when the Eclipse compare editor allows this. if (aNavigator instanceof CompareEditorInputNavigator) { final Object[] panes = ((CompareEditorInputNavigator) aNavigator).getPanes(); for (Object pane : panes) { if (pane instanceof CompareContentViewerSwitchingPane) { Viewer viewer = ((CompareContentViewerSwitchingPane) pane).getViewer(); if (viewer instanceof TextMergeViewer) { TextMergeViewer textViewer = (TextMergeViewer) viewer; Class textViewerClass = textViewer.getClass(); if (!textViewerClass.getName().equals(COMPARE_EDITOR_TEXT_CLASS_NAME)) { do { textViewerClass = textViewerClass.getSuperclass(); if (textViewerClass.getName().equals(DEFAULT_OBJECT_CLASS_NAME)) { break; } } while (!textViewerClass.getName().equals(COMPARE_EDITOR_TEXT_CLASS_NAME)); } try { Field field; if (aIsLeftPane) { field = textViewerClass.getDeclaredField(COMPARE_EDITOR_TEXT_FIELD_LEFT); } else { field = textViewerClass.getDeclaredField(COMPARE_EDITOR_TEXT_FIELD_RIGHT); } field.setAccessible(true); MergeSourceViewer sourceViewer = (MergeSourceViewer) field.get(textViewer); //Now check if the element can be displayed completely in the current viewport. If so, do it. Otherwise, tell //the caller int visibleOffset = sourceViewer.getSourceViewer().getVisibleRegion().getOffset(); int visibleLength = sourceViewer.getSourceViewer().getVisibleRegion().getLength(); int elementOffset = ((R4EUITextPosition) aPosition).getOffset(); int elementLength = ((R4EUITextPosition) aPosition).getLength(); if (elementOffset < visibleOffset || (elementOffset + elementLength) > (visibleOffset + visibleLength)) { return false; //Element falls outside the visible region } else { ITextEditor adapter = (ITextEditor) sourceViewer.getAdapter(ITextEditor.class); adapter.selectAndReveal(((R4EUITextPosition) aPosition).getOffset(), ((R4EUITextPosition) aPosition).getLength()); } } catch (SecurityException e) { //just continue } catch (NoSuchFieldException e) { //just continue } catch (IllegalArgumentException e) { //just continue } catch (IllegalAccessException e) { //just continue } } } } } return true; } /** * Method openUrl Opens a default web browser * * @param aLocation * - String */ public static void openUrl(String aLocation) { URL url = null; if (null != aLocation) { try { url = new URL(aLocation); } catch (MalformedURLException e) { R4EUIPlugin.Ftracer.traceError("Exception: " + e.toString() + " (" + e.getMessage() + ")"); R4EUIPlugin.getDefault().logError("Exception: " + e.toString(), e); final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_ERROR, "Invalid location", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0, e.getMessage(), e), IStatus.ERROR); Display.getDefault().syncExec(new Runnable() { public void run() { dialog.open(); } }); } } final String generatedId = "org.eclipse.mylyn.web.browser-" + Calendar.getInstance().getTimeInMillis(); //$NON-NLS-1$ final IWebBrowser browser; try { browser = PlatformUI.getWorkbench().getBrowserSupport().createBrowser(generatedId); browser.openURL(url); } catch (PartInitException e) { R4EUIPlugin.Ftracer.traceError("Exception: " + e.toString() + " (" + e.getMessage() + ")"); R4EUIPlugin.getDefault().logError("Exception: " + e.toString(), e); final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_ERROR, "Error opening Browser", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0, e.getMessage(), e), IStatus.ERROR); Display.getDefault().syncExec(new Runnable() { public void run() { dialog.open(); } }); } } /** * Method changeReviewState Verifies and Changes Review Element phase to a new one * * @param aReview * - R4EUIModelElement * @param aNewPhase * - R4EReviewPhase */ public static void changeReviewPhase(IR4EUIModelElement aReview, R4EReviewPhase aNewPhase) { final AtomicReference<String> aResultMsg = new AtomicReference<String>(null); if (((R4EUIReviewBasic) aReview).validatePhaseChange(aNewPhase, aResultMsg)) { if (null != aResultMsg.get()) { final ErrorDialog dialog = new ErrorDialog(null, "Warning", aResultMsg.get(), new Status(IStatus.WARNING, R4EUIPlugin.PLUGIN_ID, 0, null, null), IStatus.WARNING); Display.getDefault().syncExec(new Runnable() { public void run() { dialog.open(); } }); } try { if (aReview instanceof R4EUIReviewExtended) { final R4EFormalReview review = ((R4EFormalReview) ((R4EUIReviewExtended) aReview).getReview()); if (aNewPhase.equals(R4EReviewPhase.PREPARATION) && null == review.getActiveMeeting()) { Display.getDefault().syncExec(new Runnable() { public void run() { try { MailServicesProxy.sendMeetingRequest(); } catch (ResourceHandlingException e) { displayResourceErrorDialog(e); } catch (OutOfSyncException e) { displaySyncErrorDialog(e); } } }); } //Prevent changing state to PREPARATION if no Meeting Request was sent out if (null != review.getActiveMeeting()) { ((R4EUIReviewExtended) aReview).updatePhase(aNewPhase); } else { final ErrorDialog dialog = new ErrorDialog(null, "Error", "No Meeting Data present", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0, "Please allow sending out a Meeting Request", null), IStatus.ERROR); Display.getDefault().syncExec(new Runnable() { public void run() { dialog.open(); } }); } } else { ((R4EUIReviewBasic) aReview).updatePhase(aNewPhase); } } catch (ResourceHandlingException e1) { UIUtils.displayResourceErrorDialog(e1); } catch (OutOfSyncException e1) { UIUtils.displaySyncErrorDialog(e1); } } else { final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.REVIEW_NOT_COMPLETED_ERROR, "Review phase cannot be changed", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0, aResultMsg.get(), null), IStatus.ERROR); Display.getDefault().syncExec(new Runnable() { public void run() { dialog.open(); } }); } } /** * Method changeAnomalyState Verifies and Changes Anomaly Element state to a new one * * @param aAnomaly * - IR4EUIModelElement * @param aNewState * - R4EAnomalyState */ public static void changeAnomalyState(final IR4EUIModelElement aAnomaly, R4EAnomalyState aNewState) { try { ((R4EUIAnomalyExtended) aAnomaly).updateState(aNewState); //If this is a postponed anomaly, update original one as well if (aAnomaly instanceof R4EUIPostponedAnomaly) { ((R4EUIPostponedAnomaly) aAnomaly).updateOriginalAnomaly(); } //Update inline markings (local anomalies only) if (aAnomaly.getParent().getParent() instanceof R4EUIFileContext) { Display.getDefault().syncExec(new Runnable() { public void run() { UIUtils.updateAnnotation(aAnomaly, (R4EUIFileContext) aAnomaly.getParent().getParent()); } }); } } catch (ResourceHandlingException e1) { UIUtils.displayResourceErrorDialog(e1); } catch (OutOfSyncException e1) { UIUtils.displaySyncErrorDialog(e1); } catch (CompatibilityException e) { UIUtils.displayCompatibilityErrorDialog(e); } } /** * Method setNavigatorViewFocus. Set focus to current view/element * * @param aElement * R4EUIModelElement * @param aExpandLevel * int */ public static void setNavigatorViewFocus(IR4EUIModelElement aElement, int aExpandLevel) { if (null != aElement) { R4EUIModelController.getNavigatorView().updateView(aElement, aExpandLevel, true); } } /** * Method formatAssignedParticipants. Concatenates assigned participants for UI display * * @param aParticipants * List<String> * @return String */ public static String formatAssignedParticipants(List<String> aParticipants) { if (aParticipants.size() > 0) { final StringBuffer buffer = new StringBuffer(); for (String participants : aParticipants) { buffer.append(participants + R4EUIConstants.LIST_SEPARATOR + " "); } return buffer.toString().substring(0, buffer.length() - 2); } else { return ""; } } /** * Display the dialog used by the user to enter the participant to use as filter criteria * * @return String */ public static String getParticipantFilterInputDialog() { final InputDialog dlg = R4EUIDialogFactory.getInstance().getParticipantFilterInputDialog(); if (dlg.open() == Window.OK) { return dlg.getValue(); } return ""; //$NON-NLS-1$ } /** * Display the dialog used by the user to enter the participant to assign * * @return String */ public static List<R4EParticipant> getAssignParticipants() { final IParticipantInputDialog dialog = R4EUIDialogFactory.getInstance().getParticipantInputDialog(false); final int[] result = new int[1]; //We need this to be able to pass the result value outside. This is safe as we are using SyncExec final List<R4EParticipant> resultParticipants = new ArrayList<R4EParticipant>(); Display.getDefault().syncExec(new Runnable() { public void run() { dialog.create(); result[0] = dialog.open(); for (R4EParticipant participant : dialog.getParticipants()) { resultParticipants.add(participant); } R4EUIDialogFactory.getInstance().removeParticipantInputDialog(); } }); if (result[0] == Window.OK) { return resultParticipants; } return new ArrayList<R4EParticipant>(0); //Cancelled, no participants to use } /** * Display the dialog used by the user to enter the participant unassign * * @param aElement * - IR4EUIModelElement * @return String */ public static List<R4EParticipant> getUnassignParticipants(final IR4EUIModelElement aElement) { final IParticipantUnassignDialog dialog = R4EUIDialogFactory.getInstance() .getParticipantUnassignDialog(aElement); final int[] result = new int[1]; //We need this to be able to pass the result value outside. This is safe as we are using SyncExec final List<R4EParticipant> resultParticipants = new ArrayList<R4EParticipant>(); Display.getDefault().syncExec(new Runnable() { public void run() { dialog.create(); result[0] = dialog.open(); for (R4EParticipant participant : dialog.getParticipants()) { resultParticipants.add(participant); } } }); if (result[0] == Window.OK) { return resultParticipants; } return new ArrayList<R4EParticipant>(0); //Cancelled, no participants to use } /** * Gets the project path for the given file version * * @param aFileVersion * - R4EFileVersion * @return String */ public static String getProjectPath(R4EFileVersion aFileVersion) { String path = ""; //$NON-NLS-1$ try { if (null != aFileVersion.getPlatformURI()) { final URI uri = new URI(aFileVersion.getPlatformURI()); final String uriPath = uri.getPath(); if (null != uriPath) { path = uriPath.substring(uriPath.indexOf(R4EUIConstants.SEPARATOR, 1) + 1); } } } catch (URISyntaxException e) { // Ignore } return path; } /** * Method formatNumChanges. formats the NumChanges value for UI display * * @param aNumChanges * int * @param aNumReviewedChanges * int * @return String */ public static String formatNumChanges(int aNumChanges, int aNumReviewedChanges) { return Integer.toString(aNumReviewedChanges) + R4EUIConstants.SEPARATOR + Integer.toString(aNumChanges); } //Inline commenting /** * Method refreshAnnotations * * @param aFile * - R4EUIFileContext */ public static void refreshAnnotations(R4EUIFileContext aFile) { //Add Annotation marker for inline commenting (if applicable) IReviewAnnotationSupport support = getAnnotationSupport(aFile); if (null != support) { support.refreshAnnotations(aFile); } } /** * Method addAnnotation * * @param aSource * - IR4EUIModelElement * @param aFile * - R4EUIFileContext */ public static void addAnnotation(final IR4EUIModelElement aSource, R4EUIFileContext aFile) { //Add Annotation marker for inline commenting (if applicable) IReviewAnnotationSupport support = getAnnotationSupport(aFile); if (null != support) { support.addAnnotation(aSource); } } /** * Method updateAnnotation * * @param aSource * - IR4EUIModelElement * @param aFile * - R4EUIFileContext */ public static void updateAnnotation(final IR4EUIModelElement aSource, R4EUIFileContext aFile) { //Add Annotation marker for inline commenting (if applicable) IReviewAnnotationSupport support = getAnnotationSupport(aFile); if (null != support) { support.updateAnnotation(aSource); } } /** * Method removeAnnotation * * @param aSource * - IR4EUIModelElement * @param aFile * - R4EUIFileContext */ public static void removeAnnotation(final IR4EUIModelElement aSource, R4EUIFileContext aFile) { //Add Annotation marker for inline commenting (if applicable) IReviewAnnotationSupport support = getAnnotationSupport(aFile); if (null != support) { support.removeAnnotation(aSource); } } /** * Method removeAnnotation * * @param aFile * - R4EUIFileContext * @return IReviewAnnotationSupport */ public static IReviewAnnotationSupport getAnnotationSupport(R4EUIFileContext aFile) { IReviewAnnotationSupport support = null; //First try to find Compare Editor IEditorPart editor = EditorProxy.findReusableCompareEditor( R4EUIModelController.getNavigatorView().getSite().getPage(), aFile.getBaseFileVersion(), aFile.getTargetFileVersion()); if (null != editor) { IEditorInput input = editor.getEditorInput(); Viewer viewer = ((R4ECompareEditorInput) input).getContentViewer(); if (null != viewer) { support = getCompareAnnotationSupport(viewer, aFile); } } else { //Try to find Single Editor editor = EditorProxy.findReusableEditor(R4EUIModelController.getNavigatorView().getSite().getPage(), aFile.getTargetFileVersion()); if (null != editor) { ITextOperationTarget target = (ITextOperationTarget) editor.getAdapter(ITextOperationTarget.class); if (target instanceof SourceViewer) { SourceViewer sourceViewer = (SourceViewer) target; support = getSingleAnnotationSupport(sourceViewer, aFile); } } } return support; } /** * Method getSingleAnnotationSupport. * * @param aSourceViewer * ISourceViewer * @param aFileContext * R4EUIFileContext * @return IReviewAnnotationSupport */ public static IReviewAnnotationSupport getSingleAnnotationSupport(SourceViewer aSourceViewer, Object aFileContext) { IReviewAnnotationSupport support = (IReviewAnnotationSupport) aSourceViewer .getData(SINGLE_KEY_ANNOTATION_SUPPORT); if (support == null) { support = new R4ESingleAnnotationSupport(aSourceViewer, aFileContext); aSourceViewer.setData(SINGLE_KEY_ANNOTATION_SUPPORT, support); } return support; } /** * Method getCompareAnnotationSupport. * * @param aSourceViewer * ISourceViewer * @param aFileContext * R4EUIFileContext * @return IReviewAnnotationSupport */ public static IReviewAnnotationSupport getCompareAnnotationSupport(Viewer aViewer, Object aFileContext) { IReviewAnnotationSupport support = (IReviewAnnotationSupport) aViewer .getData(COMPARE_KEY_ANNOTATION_SUPPORT); if (support == null) { support = new R4ECompareAnnotationSupport(aViewer, aFileContext); aViewer.setData(COMPARE_KEY_ANNOTATION_SUPPORT, support); } return support; } /** * Method removeAnnotation * * @param aPref * - AnnotationPreference * @param aStore * - IPreferenceStore * @return Color */ public static Color updateAnnotationColor(AnnotationPreference aPref, IPreferenceStore aStore) { if (aPref != null) { RGB rgb = getColorFromAnnotationPreference(aStore, aPref); return EditorsUI.getSharedTextColors().getColor(rgb); } return null; } /** * Method removeAnnotation * * @param aStore * - IPreferenceStore * @param aPref * - AnnotationPreference * @return RGB */ public static RGB getColorFromAnnotationPreference(IPreferenceStore aStore, AnnotationPreference aPref) { String key = aPref.getColorPreferenceKey(); RGB rgb = null; if (aStore.contains(key)) { if (aStore.isDefault(key)) { rgb = aPref.getColorPreferenceValue(); } else { rgb = PreferenceConverter.getColor(aStore, key); } } if (rgb == null) { rgb = aPref.getColorPreferenceValue(); } return rgb; } /** * Method getCommandUIElements * * @return List<IR4EUIModelElement> */ public static List<IR4EUIModelElement> getCommandUIElements() { UIElementsProvider uiElementProvider = getSourceProvider(); if (uiElementProvider != null) { return uiElementProvider.getSelectedElements(); } //Create an empty list List<IR4EUIModelElement> uiElements = new ArrayList<IR4EUIModelElement>(1); return uiElements; } /** * Method setCommandUIElements * * @param uiElements * - List<IR4EUIModelElement> */ public static void setCommandUIElements(List<IR4EUIModelElement> uiElements) { UIElementsProvider uiElementProvider = getSourceProvider(); if (uiElementProvider != null) { uiElementProvider.setSelectedElements(uiElements); } } /** * Method getCommandUIElements * * @return List<IR4EUIModelElement> */ public static void clearCommandUIElements() { UIElementsProvider uiElementProvider = getSourceProvider(); if (uiElementProvider != null) { uiElementProvider.setSelectedElements(null); } } /** * Method getSourceProvider. * * @return UIElementsProvider */ private static UIElementsProvider getSourceProvider() { IWorkbench workbench = PlatformUI.getWorkbench(); if (workbench != null) { IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); //Window can be null when exiting if (window != null) { ISourceProviderService service = (ISourceProviderService) window .getService(ISourceProviderService.class); return (UIElementsProvider) service.getSourceProvider(UIElementsProvider.SELECTED_ELEMENTS); } } return null; } }