| /******************************************************************************* |
| * Copyright (c) 2007, 2016 Intel Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Intel Corporation - initial API and implementation |
| * Markus Schorn (Wind River Systems) |
| * James Blackburn (Broadcom Corp.) |
| * Serge Beauchamp (Freescale Semiconductor) - Bug 406545 |
| *******************************************************************************/ |
| package org.eclipse.cdt.ui.newui; |
| |
| import java.lang.reflect.Method; |
| |
| import org.eclipse.cdt.core.CCorePlugin; |
| import org.eclipse.cdt.core.cdtvariables.ICdtVariable; |
| import org.eclipse.cdt.core.cdtvariables.ICdtVariableManager; |
| import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; |
| import org.eclipse.cdt.core.settings.model.ICResourceDescription; |
| import org.eclipse.cdt.internal.core.resources.ResourceLookup; |
| import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; |
| import org.eclipse.cdt.internal.ui.newui.Messages; |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.CLabel; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.FontMetrics; |
| import org.eclipse.swt.graphics.GC; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.layout.FillLayout; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.DirectoryDialog; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.FileDialog; |
| import org.eclipse.swt.widgets.Group; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.Text; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.dialogs.ElementTreeSelectionDialog; |
| import org.eclipse.ui.dialogs.ISelectionStatusValidator; |
| import org.eclipse.ui.model.WorkbenchContentProvider; |
| import org.eclipse.ui.model.WorkbenchLabelProvider; |
| import org.eclipse.ui.part.PageBook; |
| import org.eclipse.ui.views.navigator.ResourceComparator; |
| |
| /** |
| * It is a parent for all standard property tabs |
| * in new CDT model. |
| * |
| * Although it's enough for new tabs to implement |
| * ICPropertyTab interface only, it would be better |
| * to extend them from this class. |
| * |
| * In this case, we'll able to use: |
| * - a lot of utility methods via "provider" link. |
| * In particular, it allows to get current project, |
| * configuration etc. See ICPropertyProvider interface. |
| * - a standard way to create buttons (ins/edit/del etc) |
| * and to handle their events (see buttonPressed(int)) |
| * - several utility methods to create widgets in the |
| * uniform manner (setupLabel(), setupText() etc). |
| * - means to handle control messages which are the main |
| * communication way for new CDT model pages and tabs. |
| */ |
| public abstract class AbstractCPropertyTab implements ICPropertyTab { |
| |
| public static final Method GRAY_METHOD = getGrayEnabled(); |
| public static final int BUTTON_WIDTH = 120; // used as hint for all push buttons |
| |
| // commonly used button names |
| public static final String EMPTY_STR = ""; //$NON-NLS-1$ |
| public static final String ADD_STR = Messages.FileListControl_add; |
| public static final String DEL_STR = Messages.FileListControl_delete; |
| public static final String EDIT_STR = Messages.FileListControl_edit; |
| public static final String MOVEUP_STR = Messages.FileListControl_moveup; |
| public static final String MOVEDOWN_STR = Messages.FileListControl_movedown; |
| /** @since 5.4 */ |
| public static final String PROJECTBUTTON_NAME = "Project..."; |
| public static final String WORKSPACEBUTTON_NAME = Messages.FileListControl_button_workspace; |
| public static final String FILESYSTEMBUTTON_NAME = Messages.FileListControl_button_fs; |
| public static final String VARIABLESBUTTON_NAME = Messages.AbstractCPropertyTab_1; |
| public static final String FILESYSTEM_DIR_DIALOG_MSG = Messages.BrowseEntryDialog_fs_dir_dlg_msg; |
| public static final String FILESYSTEM_FILE_DIALOG_TITLE = EMPTY_STR; |
| public static final String WORKSPACE_DIR_DIALOG_TITLE = Messages.BrowseEntryDialog_wsp_dir_dlg_title; |
| public static final String WORKSPACE_FILE_DIALOG_TITLE = Messages.BrowseEntryDialog_wsp_file_dlg_title; |
| public static final String WORKSPACE_DIR_DIALOG_MSG = Messages.BrowseEntryDialog_wsp_dir_dlg_msg; |
| public static final String WORKSPACE_FILE_DIALOG_MSG = Messages.BrowseEntryDialog_wsp_file_dlg_msg; |
| public static final String WORKSPACE_FILE_DIALOG_ERR = Messages.BrowseEntryDialog_wsp_file_dlg_err; |
| public static final String WORKSPACE_DIR_DIALOG_ERR = Messages.BrowseEntryDialog_wsp_dir_dlg_err; |
| public static final String BACKGROUND_TEXT_DEFAULT = Messages.AbstractCPropertyTab_2; |
| public static final Color BACKGROUND_FOR_USER_VAR = new Color(Display.getDefault(), 255, 255, 200); // light yellow |
| |
| private static final String PREFIX = "org.eclipse.cdt.ui."; //$NON-NLS-1$ |
| |
| public static final int TRI_UNKNOWN = 2; |
| public static final int TRI_YES = 1; |
| public static final int TRI_NO = 0; |
| |
| protected static final String ENUM = "enum"; //$NON-NLS-1$ |
| protected static final String SSET = "set"; //$NON-NLS-1$ |
| |
| private PageBook pageBook; // to select between background and usercomp. |
| private CLabel background; |
| private Composite userdata; |
| |
| protected Composite usercomp; // space where user can create widgets |
| protected Composite buttoncomp; // space for buttons on the right |
| private Button[] buttons; // buttons in buttoncomp |
| public ICPropertyProvider page; |
| protected Image icon = null; |
| private String helpId = EMPTY_STR; |
| |
| protected boolean visible; |
| |
| @Override |
| public void createControls(Composite _parent, ICPropertyProvider _provider) { |
| page = _provider; |
| createControls(_parent); |
| } |
| |
| /** |
| * Creates basic widgets for property tab. |
| * Descendants should, normally, override |
| * this method but call super.createControls(). |
| * |
| * @param parent |
| */ |
| protected void createControls(Composite parent) { |
| parent.setLayout(new FillLayout()); |
| pageBook = new PageBook(parent, SWT.NULL); |
| |
| background = new CLabel(pageBook, SWT.CENTER | SWT.SHADOW_NONE); |
| background.setText(EMPTY_STR); |
| |
| GridData gd; |
| userdata = new Composite(pageBook, SWT.NONE); |
| userdata.setLayout(new GridLayout(2, false)); |
| |
| usercomp = new Composite(userdata, SWT.NONE); |
| usercomp.setLayoutData(gd = new GridData(GridData.FILL_BOTH)); |
| gd.widthHint = 150; |
| |
| buttoncomp = new Composite(userdata, SWT.NONE); |
| buttoncomp.setLayoutData(gd = new GridData(GridData.END)); |
| // width hint must be set to one, otherwise subclasses that do not have buttons |
| // don't look pretty, bug 242408 |
| gd.widthHint = 1; |
| |
| pageBook.showPage(userdata); |
| |
| PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, helpId); |
| } |
| |
| /** |
| * The common way to create buttons cluster |
| * on the right of tab workspace. |
| * @param names : array of button names |
| * null instead of name means "skip place" |
| */ |
| protected void initButtons(String[] names) { |
| initButtons(buttoncomp, names, 80); |
| } |
| |
| protected void initButtons(String[] names, int width) { |
| initButtons(buttoncomp, names, width); |
| } |
| |
| /** |
| * Ability to create standard button on any composite. |
| * @param c |
| * @param names |
| */ |
| protected void initButtons(Composite c, String[] names) { |
| initButtons(c, names, 80); |
| } |
| |
| protected void initButtons(Composite c, String[] names, int width) { |
| if (names == null || names.length == 0) |
| return; |
| c.setLayoutData(new GridData(GridData.FILL_VERTICAL)); |
| c.setLayout(new GridLayout(1, false)); |
| buttons = new Button[names.length]; |
| for (int i = 0; i < names.length; i++) { |
| buttons[i] = new Button(c, SWT.PUSH); |
| GridData gdb = new GridData(GridData.VERTICAL_ALIGN_CENTER); |
| gdb.grabExcessHorizontalSpace = false; |
| gdb.horizontalAlignment = SWT.FILL; |
| gdb.minimumWidth = width; |
| |
| if (names[i] != null) |
| buttons[i].setText(names[i]); |
| else { // no button, but placeholder ! |
| buttons[i].setVisible(false); |
| buttons[i].setEnabled(false); |
| gdb.heightHint = 10; |
| } |
| |
| buttons[i].setLayoutData(gdb); |
| buttons[i].addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent event) { |
| buttonPressed(event); |
| } |
| }); |
| } |
| } |
| |
| /** |
| * Called when user changes |
| * @param cfg - selected configuration |
| */ |
| private void configChanged(ICResourceDescription cfg) { |
| if (visible) |
| updateData(cfg); |
| } |
| |
| /** |
| * Disposes the SWT resources allocated by this dialog page. |
| */ |
| public void dispose() { |
| } |
| |
| /** |
| * Sets the visibility of this property tab. |
| * |
| * @param _visible <code>true</code> to make this tab visible, |
| * and <code>false</code> to hide it |
| */ |
| public void setVisible(boolean _visible) { |
| visible = _visible; |
| if (visible) |
| updateData(page.getResDesc()); |
| } |
| |
| /** |
| * Descendant tabs should implement this method so |
| * that it copies it's data from one description |
| * to another. Only data affected by given tab |
| * should be copied. |
| * |
| * @param src |
| * @param dst |
| */ |
| protected abstract void performApply(ICResourceDescription src, ICResourceDescription dst); |
| |
| protected abstract void performDefaults(); |
| |
| protected abstract void updateData(ICResourceDescription cfg); |
| |
| protected abstract void updateButtons(); |
| |
| protected void performCancel() { |
| } |
| |
| protected void performOK() { |
| } |
| |
| /** |
| * @param e - event to be handled |
| */ |
| private void buttonPressed(SelectionEvent e) { |
| for (int i = 0; i < buttons.length; i++) { |
| if (buttons[i].equals(e.widget)) { |
| buttonPressed(i); |
| return; |
| } |
| } |
| } |
| |
| /** |
| * Method should be rewritten to handle button presses |
| * @param i : number of button pressed |
| * |
| * Does nothing by default. |
| * May (but not must) be overridden. |
| */ |
| protected void buttonPressed(int i) { |
| } |
| |
| /** |
| * Checks state of existing button. |
| * |
| * @param i - button index |
| * @return - true if button exists and enabled |
| */ |
| protected boolean buttonIsEnabled(int i) { |
| if (buttons == null || buttons.length <= i) |
| return false; |
| return buttons[i].isEnabled(); |
| } |
| |
| /** |
| * Changes state of existing button. |
| * Does nothing if index is invalid |
| * |
| * @param i - button index |
| * @param state - required state |
| */ |
| protected void buttonSetEnabled(int i, boolean state) { |
| if (buttons == null || buttons.length <= i) |
| return; |
| buttons[i].setEnabled(state); |
| } |
| |
| /** |
| * Changes text of existing button |
| * Does nothing if index is invalid |
| * |
| * @param i - button index |
| * @param text - text to display |
| */ |
| protected void buttonSetText(int i, String text) { |
| if (buttons == null || buttons.length <= i) |
| return; |
| buttons[i].setText(text); |
| Composite c = buttons[i].getParent(); |
| if (c != null) { |
| c.pack(); |
| c = c.getParent(); |
| if (c != null) |
| c.layout(true); |
| } |
| } |
| |
| /********************************************** |
| * Utility methods for unified widget creation |
| **********************************************/ |
| protected Label setupLabel(Composite c, String name, int span, int mode) { |
| Label l = new Label(c, SWT.NONE); |
| l.setText(name); |
| setupControl(l, span, mode); |
| return l; |
| } |
| |
| protected Button setupButton(Composite c, String name, int span, int mode) { |
| Button b = new Button(c, SWT.PUSH); |
| b.setText(name); |
| setupControl(b, span, mode); |
| GridData g = (GridData) b.getLayoutData(); |
| g.minimumWidth = BUTTON_WIDTH; |
| g.horizontalAlignment = SWT.RIGHT; |
| b.setLayoutData(g); |
| return b; |
| } |
| |
| protected Text setupText(Composite c, int span, int mode) { |
| Text t = new Text(c, SWT.SINGLE | SWT.BORDER); |
| setupControl(t, span, mode); |
| return t; |
| } |
| |
| protected Group setupGroup(Composite c, String name, int cols, int mode) { |
| Group g = new Group(c, SWT.NONE); |
| g.setText(name); |
| g.setLayout(new GridLayout(cols, false)); |
| setupControl(g, 1, mode); |
| return g; |
| } |
| |
| /** |
| * @since 7.2 |
| */ |
| protected Composite setupComposite(Composite c, int cols, int mode) { |
| Composite c1 = new Composite(c, SWT.NONE); |
| c1.setLayout(new GridLayout(cols, false)); |
| setupControl(c1, 1, mode); |
| return c1; |
| } |
| |
| protected Button setupCheck(Composite c, String name, int span, int mode) { |
| Button b = new Button(c, SWT.CHECK); |
| b.setText(name); |
| setupControl(b, span, mode); |
| b.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent event) { |
| ((Button) event.widget).setGrayed(false); |
| checkPressed(event); |
| } |
| }); |
| return b; |
| } |
| |
| /** |
| * @since 7.2 |
| */ |
| protected Button setupRadio(Composite c, String name, int span, int mode) { |
| Button b = new Button(c, SWT.RADIO); |
| b.setText(name); |
| setupControl(b, span, mode); |
| b.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent event) { |
| ((Button) event.widget).setGrayed(false); |
| checkPressed(event); |
| } |
| }); |
| return b; |
| } |
| |
| /** |
| * Selection handler for checkbox created |
| * by methods "setupCheck()" or "setupTri()" |
| * Descendants should override this method |
| * if they use "setupCheck". |
| * Usually the method body will look like: |
| * { |
| * Control b = (Control)e.widget; |
| * if (b.equals(myFirstCheckbox) { ... } |
| * else if (b.equals(mySecondCheckbox) { ... } |
| * ... } |
| */ |
| protected void checkPressed(SelectionEvent e) { |
| } |
| |
| protected void setupControl(Control c, int span, int mode) { |
| // although we use GridLayout usually, |
| // exceptions can occur: do nothing. |
| if (c != null) { |
| if (span != 0) { |
| GridData gd = new GridData(mode); |
| gd.horizontalSpan = span; |
| c.setLayoutData(gd); |
| } |
| Composite p = c.getParent(); |
| c.setFont(p.getFont()); |
| } |
| } |
| |
| /* |
| * A set of methods providing selection dialogs for files or dirs. |
| */ |
| |
| public static String getFileSystemDirDialog(Shell shell, String text) { |
| DirectoryDialog dialog = new DirectoryDialog(shell, SWT.OPEN | SWT.APPLICATION_MODAL); |
| if (text != null && text.trim().length() != 0) |
| dialog.setFilterPath(text); |
| dialog.setMessage(FILESYSTEM_DIR_DIALOG_MSG); |
| return dialog.open(); |
| } |
| |
| public static String getFileSystemFileDialog(Shell shell, String text) { |
| FileDialog dialog = new FileDialog(shell); |
| if (text != null && text.trim().length() != 0) |
| dialog.setFilterPath(text); |
| dialog.setText(FILESYSTEM_FILE_DIALOG_TITLE); |
| return dialog.open(); |
| } |
| |
| /** |
| * @since 5.3 |
| */ |
| public static String getFileSystemFileDialog(Shell shell, String text, String[] filter) { |
| FileDialog dialog = new FileDialog(shell); |
| if (text != null && text.trim().length() != 0) |
| dialog.setFilterPath(text); |
| dialog.setFilterExtensions(filter); |
| dialog.setText(FILESYSTEM_FILE_DIALOG_TITLE); |
| return dialog.open(); |
| } |
| |
| public static String getVariableDialog(Shell shell, ICConfigurationDescription cfgd) { |
| |
| ICdtVariableManager vm = CCorePlugin.getDefault().getCdtVariableManager(); |
| BuildVarListDialog dialog = new BuildVarListDialog(shell, vm.getVariables(cfgd)); |
| dialog.setTitle(Messages.AbstractCPropertyTab_0); |
| if (dialog.open() == Window.OK) { |
| Object[] selected = dialog.getResult(); |
| if (selected.length > 0) { |
| String s = ((ICdtVariable) selected[0]).getName(); |
| return "${" + s.trim() + "}"; //$NON-NLS-1$//$NON-NLS-2$ |
| } |
| } |
| return null; |
| } |
| |
| public static String getWorkspaceDirDialog(Shell shell, String text) { |
| return getWorkspaceDialog(shell, text, true, null); |
| } |
| |
| public static String getWorkspaceFileDialog(Shell shell, String text) { |
| return getWorkspaceDialog(shell, text, false, null); |
| } |
| |
| /** |
| * @since 5.4 |
| */ |
| public static String getProjectDirDialog(Shell shell, String text, IProject prj) { |
| return getWorkspaceDialog(shell, text, true, prj); |
| } |
| |
| /** |
| * @since 5.4 |
| */ |
| public static String getProjectFileDialog(Shell shell, String text, IProject prj) { |
| return getWorkspaceDialog(shell, text, false, prj); |
| } |
| |
| private static String getWorkspaceDialog(Shell shell, String text, boolean dir, IProject prj) { |
| String currentPathText; |
| IPath path; |
| currentPathText = text; |
| /* Remove double quotes */ |
| currentPathText = currentPathText.replaceAll("\"", ""); //$NON-NLS-1$ //$NON-NLS-2$ |
| path = new Path(currentPathText); |
| |
| ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(shell, new WorkbenchLabelProvider(), |
| new WorkbenchContentProvider()); |
| |
| if (prj == null) |
| dialog.setInput(ResourcesPlugin.getWorkspace().getRoot()); |
| else |
| dialog.setInput(prj); |
| dialog.setComparator(new ResourceComparator(ResourceComparator.NAME)); |
| |
| if (dir) { |
| IResource container = null; |
| if (path.isAbsolute()) { |
| IContainer cs[] = ResourcesPlugin.getWorkspace().getRoot().findContainersForLocation(path); |
| if (cs != null && cs.length > 0) |
| container = cs[0]; |
| } |
| dialog.setInitialSelection(container); |
| dialog.setValidator(new ISelectionStatusValidator() { |
| @Override |
| public IStatus validate(Object[] selection) { |
| if (selection != null) |
| if (selection.length > 0) |
| if ((selection[0] instanceof IFile)) |
| return new StatusInfo(IStatus.ERROR, WORKSPACE_DIR_DIALOG_ERR); |
| return new StatusInfo(); |
| } |
| }); |
| dialog.setTitle(WORKSPACE_DIR_DIALOG_TITLE); |
| dialog.setMessage(WORKSPACE_DIR_DIALOG_MSG); |
| } else { |
| IResource resource = null; |
| if (path.isAbsolute()) { |
| resource = ResourceLookup.selectFileForLocation(path, prj); |
| } |
| dialog.setInitialSelection(resource); |
| dialog.setValidator(new ISelectionStatusValidator() { |
| @Override |
| public IStatus validate(Object[] selection) { |
| if (selection != null) |
| if (selection.length > 0) |
| if (!(selection[0] instanceof IFile)) |
| return new StatusInfo(IStatus.ERROR, WORKSPACE_FILE_DIALOG_ERR); |
| return new StatusInfo(); |
| } |
| }); |
| dialog.setTitle(WORKSPACE_FILE_DIALOG_TITLE); |
| dialog.setMessage(WORKSPACE_FILE_DIALOG_MSG); |
| } |
| if (dialog.open() == Window.OK) { |
| IResource resource = (IResource) dialog.getFirstResult(); |
| if (resource != null) { |
| StringBuilder buf = new StringBuilder(); |
| return buf.append("${").append("workspace_loc:").append(resource.getFullPath()).append("}").toString(); //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ |
| } |
| } |
| return null; |
| } |
| |
| // shortcut to frequently-used method |
| public ICResourceDescription getResDesc() { |
| return page.getResDesc(); |
| } |
| |
| /** |
| * Common event handler: called by parent for each tab |
| */ |
| @Override |
| public void handleTabEvent(int kind, Object data) { |
| switch (kind) { |
| case ICPropertyTab.OK: |
| if (canBeVisible()) |
| performOK(); |
| break; |
| case ICPropertyTab.APPLY: |
| if (canBeVisible()) |
| performApply(getResDesc(), (ICResourceDescription) data); |
| break; |
| case ICPropertyTab.CANCEL: |
| if (canBeVisible()) |
| performCancel(); |
| break; |
| case ICPropertyTab.DEFAULTS: |
| if (canBeVisible() /*&& getResDesc() != null*/) { |
| updateData(getResDesc()); |
| performDefaults(); |
| } |
| break; |
| case ICPropertyTab.UPDATE: |
| if (canSupportMultiCfg() || !page.isMultiCfg()) { |
| if (canBeVisible()) { |
| setButtonVisible(true); |
| configChanged((ICResourceDescription) data); |
| } |
| } else |
| setAllVisible(false, null); |
| break; |
| case ICPropertyTab.DISPOSE: |
| dispose(); |
| break; |
| case ICPropertyTab.VISIBLE: |
| if (canSupportMultiCfg() || !page.isMultiCfg()) { |
| if (canBeVisible()) { |
| setVisible(data != null); |
| setButtonVisible(data != null); |
| } else |
| setVisible(false); |
| } else |
| setAllVisible(false, null); |
| break; |
| case ICPropertyTab.SET_ICON: |
| icon = (Image) data; |
| break; |
| default: |
| break; |
| } |
| } |
| |
| // By default, returns true (no visibility restriction) |
| // But several pages should rewrite this functionality. |
| @Override |
| public boolean canBeVisible() { |
| return true; |
| } |
| |
| /** |
| * Method to be implemented by inherited classes to indicate whether or not the tab supports displaying |
| * and editing settings for multiple configuration selection. |
| * |
| * Default implementation returns true. |
| * |
| * @return true if the tab supports multiple configurations, false otherwise |
| * @since 5.7 |
| */ |
| public boolean canSupportMultiCfg() { |
| return true; |
| } |
| |
| /** |
| * Returns true if this tab is the one currently selected in the UI. |
| * |
| * @return true if this tab is the one selected in the UI, false otherwise. |
| * @since 5.7 |
| */ |
| public boolean isTabSelected() { |
| if (page instanceof ICPropertyProvider2) |
| return ((ICPropertyProvider2) page).getSelectedTab() == this; |
| return false; |
| } |
| |
| /** |
| * Added to avoid usage PixelConverter class. |
| * @param control |
| * @return FontMetrics |
| */ |
| public static FontMetrics getFontMetrics(Control control) { |
| GC gc = new GC(control); |
| gc.setFont(control.getFont()); |
| FontMetrics fFontMetrics = gc.getFontMetrics(); |
| gc.dispose(); |
| return fFontMetrics; |
| } |
| |
| /** |
| * Sets checkbox to appropriate state: |
| * unchecked or checked |
| * @param b - checkbox to set |
| * @param state |
| */ |
| public static void setTriSelection(Button b, boolean state) { |
| setTriSelection(b, state ? TRI_YES : TRI_NO); |
| } |
| |
| /** |
| * Sets checkbox to appropriate state: |
| * unchecked, checked or unknown (grayed) |
| * @param b - checkbox to set |
| * @param state |
| */ |
| public static void setTriSelection(Button b, int state) { |
| switch (state) { |
| case TRI_NO: |
| b.setGrayed(false); |
| b.setSelection(false); |
| break; |
| case TRI_YES: |
| b.setGrayed(false); |
| b.setSelection(true); |
| break; |
| case TRI_UNKNOWN: |
| b.setGrayed(true); |
| b.setSelection(true); |
| break; |
| } |
| } |
| |
| /** |
| * This method will be simplified after M5 release, |
| * when Button.setGrayed() method will be accessible. |
| * In this case, reflection will not be required. |
| * |
| * @param b |
| * @param value |
| * @deprecated call {@link Button#setGrayed(boolean)} instead |
| */ |
| @Deprecated |
| public static void setGrayed(Button b, boolean value) { |
| b.setGrayed(value); |
| } |
| |
| /** |
| * This method will be removed after M5 release, |
| * when Button.setGrayed() will be officially accessible. |
| * |
| * @return reference to Button.setGrayed() method |
| */ |
| private static Method getGrayEnabled() { |
| try { |
| Class<?> cl = Class.forName("org.eclipse.swt.widgets.Button"); //$NON-NLS-1$ |
| return cl.getMethod("setGrayed", new Class[] { boolean.class }); //$NON-NLS-1$ |
| } catch (ClassNotFoundException e) { |
| return null; |
| } catch (NoSuchMethodException e) { |
| return null; |
| } |
| } |
| |
| /** |
| * Utility method to show/hide working panes |
| * When panes are hidden, message becomes visible |
| * |
| * @param visible - true or false |
| * @param msg - text to be shown instead of panes |
| */ |
| protected void setAllVisible(boolean visible, String msg) { |
| if (!visible) { |
| setBackgroundText(msg); |
| pageBook.showPage(background); |
| } else { |
| pageBook.showPage(userdata); |
| } |
| setButtonVisible(visible); |
| } |
| |
| /** |
| * Utility method to show/hide the 'Apply' and 'Restore Defaults' buttons |
| * @param visible - true or false |
| * @since 5.7 |
| */ |
| protected void setButtonVisible(boolean visible) { |
| if (page != null && isTabSelected()) { |
| Button b = page.getAButton(); |
| if (b != null) |
| b.setVisible(visible); |
| b = page.getDButton(); |
| if (b != null) |
| b.setVisible(visible); |
| } |
| } |
| |
| /** |
| * Allows changing message on background pane, |
| * which becomes visible after usercomp hidden |
| * |
| * @param s - text to display or null for default |
| */ |
| protected void setBackgroundText(String s) { |
| background.setText(s == null ? BACKGROUND_TEXT_DEFAULT : s); |
| } |
| |
| /** |
| * Used to display double-clickable buttons for multiple configurations |
| * string list mode (see Multiple Configurations Edit Preference page). |
| * |
| * @deprecated as of CDT 8.0. This functionality is presented as links |
| * to the preference page, see {@link AbstractLangsListTab#updateStringListModeControl()} |
| */ |
| @Deprecated |
| protected void updateLbs(Label lb1, Label lb2) { |
| if (page.isMultiCfg()) { |
| if (lb1 != null) { |
| lb1.setText(CDTPrefUtil.getDMode()); |
| lb1.setVisible(true); |
| } |
| if (lb2 != null) { |
| lb2.setText(CDTPrefUtil.getWMode()); |
| lb2.setVisible(true); |
| } |
| } else { |
| if (lb1 != null) |
| lb1.setVisible(false); |
| if (lb2 != null) |
| lb2.setVisible(false); |
| } |
| } |
| |
| /** |
| * The writing mode for multiple configurations edits (configuration drop-down list |
| * in project properties). This mode applies to lists of entries. |
| * See preference Multiple Configurations Edit, String List Write Mode. |
| * |
| * @return |
| * {@code true} if each list should be replaced as a whole with the |
| * list user is currently working with in UI<br/> |
| * {@code false} if changes apply only to individual entries and unaffected |
| * entries are preserved. |
| */ |
| protected boolean isWModifyMode() { |
| int wmode = CDTPrefUtil.getMultiCfgStringListWriteMode(); |
| return (wmode == CDTPrefUtil.WMODE_MODIFY); |
| } |
| |
| public String getHelpContextId() { |
| return helpId; |
| } |
| |
| public void setHelpContextId(String id) { |
| helpId = PREFIX + id; |
| } |
| |
| /** |
| * Allows subclasses to inform the container about changes relevant to the indexer. |
| * The tab will be asked before the apply is performed. As a consequence of returning |
| * <code>true</code> the user will be asked whether she wants to rebuild the index. |
| * @since 5.2 |
| */ |
| protected boolean isIndexerAffected() { |
| return false; |
| } |
| } |