From 2b5e3e6a20a411b4f000c0d9a4eb7a33813a628c Mon Sep 17 00:00:00 2001 From: Andrew Gvozdev Date: Tue, 1 May 2012 22:36:29 -0400 Subject: [PATCH] bug 328007: [sd90] Design user interface for new scanner discovery --- .../icons/obj16/search.gif | Bin 0 -> 347 bytes .../org.eclipse.cdt.make.ui/plugin.properties | 2 + build/org.eclipse.cdt.make.ui/plugin.xml | 8 + .../AbstractBuiltinSpecsDetector.java | 2 +- .../META-INF/MANIFEST.MF | 1 + .../icons/obj16/inspect_sys.gif | Bin 0 -> 553 bytes .../icons/obj16/log_obj.gif | Bin 0 -> 335 bytes .../icons/obj16/mbs.gif | Bin 0 -> 380 bytes .../plugin.xml | 39 +- .../managedbuilder/internal/ui/Messages.java | 11 + .../internal/ui/Messages.properties | 13 + .../BuiltinSpecsDetectorOptionPage.java | 155 ++ .../GCCBuildCommandParserOptionPage.java | 231 +++ .../providers/ScannerDiscoveryConsole.java | 39 + .../ScannerDiscoveryGlobalConsole.java | 117 ++ .../ui/preferences/PropertyPageDefsTab.java | 61 +- .../ScannerDiscoveryLegacySupport.java | 8 +- .../schema/LanguageSettingsProvider.exsd | 2 +- core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF | 2 + .../icons/obj16/filesyst.gif | Bin 310 -> 144 bytes .../icons/obj16/ls_entries.gif | Bin 0 -> 386 bytes .../icons/ovr16/edited_ovr.gif | Bin 0 -> 167 bytes .../icons/ovr16/person_ovr.gif | Bin 0 -> 165 bytes core/org.eclipse.cdt.ui/plugin.properties | 6 +- core/org.eclipse.cdt.ui/plugin.xml | 44 + .../LanguageSettingsProviderAssociation.exsd | 200 +++ .../eclipse/cdt/internal/ui/ImageCombo.java | 1471 +++++++++++++++++ .../providers/LanguageSettingEntryDialog.java | 615 +++++++ .../providers/LanguageSettingsEntriesTab.java | 1134 +++++++++++++ ...ageSettingsProviderAssociationManager.java | 361 ++++ .../LanguageSettingsProviderTab.java | 1171 +++++++++++++ ...anguageSettingsProvidersLabelProvider.java | 96 ++ .../LanguageSettingsProvidersPage.java | 104 ++ .../ui/newui/LanguageSettingsImages.java | 40 +- .../cdt/internal/ui/newui/Messages.java | 39 +- .../cdt/internal/ui/newui/Messages.properties | 39 +- .../viewsupport/ProblemsLabelDecorator.java | 37 +- .../org/eclipse/cdt/ui/CDTSharedImages.java | 8 + ...ractLanguageSettingProviderOptionPage.java | 79 + .../LanguageSettingsProvidersImages.java | 33 + .../cdt/ui/newui/AbstractCPropertyTab.java | 224 +-- .../cdt/ui/newui/AbstractLangsListTab.java | 8 +- .../eclipse/cdt/ui/newui/ErrorParsTab.java | 2 +- 43 files changed, 6249 insertions(+), 153 deletions(-) create mode 100644 build/org.eclipse.cdt.make.ui/icons/obj16/search.gif create mode 100644 build/org.eclipse.cdt.managedbuilder.ui/icons/obj16/inspect_sys.gif create mode 100644 build/org.eclipse.cdt.managedbuilder.ui/icons/obj16/log_obj.gif create mode 100644 build/org.eclipse.cdt.managedbuilder.ui/icons/obj16/mbs.gif create mode 100644 build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/BuiltinSpecsDetectorOptionPage.java create mode 100644 build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/GCCBuildCommandParserOptionPage.java create mode 100644 build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/ScannerDiscoveryConsole.java create mode 100644 build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/ScannerDiscoveryGlobalConsole.java create mode 100644 core/org.eclipse.cdt.ui/icons/obj16/ls_entries.gif create mode 100644 core/org.eclipse.cdt.ui/icons/ovr16/edited_ovr.gif create mode 100644 core/org.eclipse.cdt.ui/icons/ovr16/person_ovr.gif create mode 100644 core/org.eclipse.cdt.ui/schema/LanguageSettingsProviderAssociation.exsd create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ImageCombo.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingEntryDialog.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsEntriesTab.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProviderAssociationManager.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProviderTab.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProvidersLabelProvider.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProvidersPage.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/language/settings/providers/AbstractLanguageSettingProviderOptionPage.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/language/settings/providers/LanguageSettingsProvidersImages.java diff --git a/build/org.eclipse.cdt.make.ui/icons/obj16/search.gif b/build/org.eclipse.cdt.make.ui/icons/obj16/search.gif new file mode 100644 index 0000000000000000000000000000000000000000..d540a01f4d9eeb9d2951f30cee165c7370e9fc6a GIT binary patch literal 347 zcmZ?wbhEHb6krfwxXQq=Vd*RNf? z`oQk}`*!YKK6~ljZF_cZ+HvgAv6IJ69zSyY;J$;WPMkV&@Th0*!vFtI{{R2)-9{Q{xYzi!ojzd!Hm)rnuOPWpOf;{Cn#PZn9eTp#{=Q|#Kl_?H9)`m^Y_v_E|osjQ0xhPeU?V7 zFYefq7px@erW32aOhZI~o1e+F);Uj8NSKj>%P7ZHO;TK&kDY#h literal 0 HcmV?d00001 diff --git a/build/org.eclipse.cdt.make.ui/plugin.properties b/build/org.eclipse.cdt.make.ui/plugin.properties index 21b341f00ec..a931132ab90 100644 --- a/build/org.eclipse.cdt.make.ui/plugin.properties +++ b/build/org.eclipse.cdt.make.ui/plugin.properties @@ -43,6 +43,8 @@ LastTargetBuild.description=Rebuild the last make target for the selected contai PreferenceBuildSettings.name=Settings ErrorParsersTab.name=Error Parsers ErrorParsersTab.tooltip=Error Parsers scan build output and report errors in Problems view +LanguageSettingsProvidersTab.name=Discovery +LanguageSettingsProvidersTab.tooltip=Language settings providers PreferenceMakeProject.name=New Make Projects PreferenceMake.name=Make Targets diff --git a/build/org.eclipse.cdt.make.ui/plugin.xml b/build/org.eclipse.cdt.make.ui/plugin.xml index 002d57859e9..b93d372f944 100644 --- a/build/org.eclipse.cdt.make.ui/plugin.xml +++ b/build/org.eclipse.cdt.make.ui/plugin.xml @@ -470,6 +470,14 @@ tooltip="%ErrorParsersTab.tooltip" weight="020"> + + ga zv#4O{lBpY)mo8eddC{t^TUXa^TGP30P5qiR3)ZilyL#QqEt_Vo-?DfAj)_}$Y}vf? z;I=(ScJDv1fB&u{2iN}DXLIoIiDO5$A3ApO%!y4GPOZIo>D;9&*REbYclr9Qn>TO$ zxfgT)?uA?T9^AeE@X_NZ&z?Pd@#4k%cdtKv`t;??m+xObfByRQ&%Zg}zJLGo>&x%o zzyJOF_kR!r#h)yU3=H)QIt)MniW3L+wubtq=9bnbHCnQMuxbn?E#L3)ZDx;_@r#aum z$dP4>x0jP>o2@27^AWxvl)hmM=8bB*YIHYRDTl@iK87YGY** L`SDqVgTWdAt^i(L literal 0 HcmV?d00001 diff --git a/build/org.eclipse.cdt.managedbuilder.ui/icons/obj16/log_obj.gif b/build/org.eclipse.cdt.managedbuilder.ui/icons/obj16/log_obj.gif new file mode 100644 index 0000000000000000000000000000000000000000..aebeab820d82ab024a82b9e03c4b284b4e2f0a48 GIT binary patch literal 335 zcmZ?wbhEHb6krfwSgOR(F=0i+i~}=fOq?}q!o1nN9SaUDn%A{#Vf%_jZL1fztX7DfgJdj=f_AOQKvfi362{8SH}s5+07 zrH6COgguw2x~z?Io{*wEIZ}k_&Ibjny>aTEr_;~oSudJ+_LwvS!;`ib{Dm)n{})e5 z3(Lq1DJf$J70Ogl=qT%p%#@QWnL2|fP()_#ym{6OU;p2od-v(ryHCI0eg5_C^Y2eze}DS+``eE{|Nqbb z|Nr>^-yi;y3lx8{FfuUMGw3h?0mx4bY%>qcFYwTj>UV1w@+?_1@3g#9gNBhqgn+X| z04rDPLM7*Y3S1LzU07IPl0A11n=G3mo1k#K#M)^p%BpP4Dr)Q^Y!V_2{Pr@7HPkiO`uQ0o gjx#thaci<^7Tce=e9B3th+W3%^0B=>ZjKDr0Hf`~-v9sr literal 0 HcmV?d00001 diff --git a/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml b/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml index 9dd588b9397..f5c72d2b4ae 100644 --- a/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml +++ b/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml @@ -671,5 +671,42 @@ projectType="org.eclipse.cdt.build.makefile.projectType"> - + + + + + + + + + + + + + + + + + diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/Messages.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/Messages.java index 82299423e16..5986337af0e 100644 --- a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/Messages.java +++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/Messages.java @@ -61,6 +61,10 @@ public class Messages extends NLS { public static String BuildToolSettingsPage_tool_advancedSettings; public static String BuildToolSettingsPage_tool_command; public static String BuildToolSettingsPage_tool_commandLinePattern; + public static String BuiltinSpecsDetectorOptionPage_AllocateConsole; + public static String BuiltinSpecsDetectorOptionPage_Browse; + public static String BuiltinSpecsDetectorOptionPage_ChooseFile; + public static String BuiltinSpecsDetectorOptionPage_CompilerSpecsCommand; public static String CConfigWizardPage_0; public static String CConfigWizardPage_1; public static String CConfigWizardPage_10; @@ -105,6 +109,12 @@ public class Messages extends NLS { public static String DiscoveryTab_ErrorClearingEntries; public static String EnvironmentTab_15; public static String EnvironmentTab_23; + public static String GCCBuildCommandParserOptionPage_CompilerPattern; + public static String GCCBuildCommandParserOptionPage_ContainerForDiscoveredEntries; + public static String GCCBuildCommandParserOptionPage_File; + public static String GCCBuildCommandParserOptionPage_Folder; + public static String GCCBuildCommandParserOptionPage_Project; + public static String GCCBuildCommandParserOptionPage_ResolvePaths; public static String MacrosBlock_label_delete_all_confirm_message; public static String MacrosBlock_label_delete_all_confirm_title; public static String MacrosBlock_label_delete_confirm_message; @@ -212,6 +222,7 @@ public class Messages extends NLS { public static String PropertyPageDefsTab_8; public static String PropertyPageDefsTab_9; public static String PropertyPageDefsTab_showIncludeFileTab; + public static String PropertyPageDefsTab_showProvidersTab; public static String RefreshPolicyExceptionDialog_addDialogLabel; public static String RefreshPolicyExceptionDialog_AddExceptionInfoDialog_message; public static String RefreshPolicyExceptionDialog_AddExceptionInfoDialog_title; diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/Messages.properties b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/Messages.properties index 652c6679364..a39e5245364 100644 --- a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/Messages.properties +++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/Messages.properties @@ -274,6 +274,7 @@ PropertyPageDefsTab_7=Show disc. page names if they are unique. Else show profil PropertyPageDefsTab_8=Always show names + profile IDs PropertyPageDefsTab_9=Always show profile IDs only PropertyPageDefsTab_showIncludeFileTab=Display "Include Files" tab +PropertyPageDefsTab_showProvidersTab=Display "Preprocessor Include Paths" tabs ProjectConvert_convertersList=Converters List AbstractPrefPage_0=\ Preference settings will be applied to new projects \n only when there were no toolchains selected. @@ -303,3 +304,15 @@ NewCfgDialog_5=Import predefined ToolChainSelectionPage_Description=Select the initial toolchain for this project. ToolChainSelectionPage_Title=Select Tool Chain + +# Language Settings Providers +BuiltinSpecsDetectorOptionPage_AllocateConsole=Allocate console in the Console View +BuiltinSpecsDetectorOptionPage_Browse=Browse... +BuiltinSpecsDetectorOptionPage_ChooseFile=Choose file +BuiltinSpecsDetectorOptionPage_CompilerSpecsCommand=Command to get compiler specs: +GCCBuildCommandParserOptionPage_CompilerPattern=Compiler command pattern: +GCCBuildCommandParserOptionPage_ContainerForDiscoveredEntries=Container to keep discovered entries +GCCBuildCommandParserOptionPage_File=File (use when settings vary for different files) +GCCBuildCommandParserOptionPage_Folder=Folder (use when settings are the same for all files in each folder) +GCCBuildCommandParserOptionPage_Project=Project (use when settings are the same for all files in the project) +GCCBuildCommandParserOptionPage_ResolvePaths=Use heuristics to resolve paths diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/BuiltinSpecsDetectorOptionPage.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/BuiltinSpecsDetectorOptionPage.java new file mode 100644 index 00000000000..9888493ed5e --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/BuiltinSpecsDetectorOptionPage.java @@ -0,0 +1,155 @@ +/******************************************************************************* + * Copyright (c) 2009, 2012 Andrew Gvozdev 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: + * Andrew Gvozdev - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.managedbuilder.internal.ui.language.settings.providers; + +import org.eclipse.cdt.managedbuilder.internal.ui.Messages; +import org.eclipse.cdt.managedbuilder.language.settings.providers.AbstractBuiltinSpecsDetector; +import org.eclipse.cdt.ui.language.settings.providers.AbstractLanguageSettingProviderOptionPage; +import org.eclipse.cdt.utils.ui.controls.ControlFactory; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +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.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +/** + * Options page for {@link AbstractBuiltinSpecsDetector}. + */ +public final class BuiltinSpecsDetectorOptionPage extends AbstractLanguageSettingProviderOptionPage { + private boolean fEditable; + private Text inputCommand; + private Button allocateConsoleCheckBox; + + @Override + public void createControl(Composite parent) { + fEditable = parent.isEnabled(); + AbstractBuiltinSpecsDetector provider = (AbstractBuiltinSpecsDetector) getProvider(); + + Composite composite = createCompositeForPageArea(parent); + createCompilerCommandInputControl(composite, provider); + createBrowseButton(composite); + createConsoleCheckbox(composite, provider); + + setControl(composite); + } + + /** + * Create composite for the page. + */ + private Composite createCompositeForPageArea(Composite parent) { + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + layout.marginWidth = 1; + layout.marginHeight = 1; + layout.marginRight = 1; + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_BOTH)); + Dialog.applyDialogFont(composite); + + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 2; + composite.setLayoutData(gd); + return composite; + } + + /** + * Create input control for compiler command. + */ + private void createCompilerCommandInputControl(Composite composite, AbstractBuiltinSpecsDetector provider) { + Label label = ControlFactory.createLabel(composite, Messages.BuiltinSpecsDetectorOptionPage_CompilerSpecsCommand); + GridData gd = new GridData(); + gd.horizontalSpan = 2; + label.setLayoutData(gd); + label.setEnabled(fEditable); + + inputCommand = ControlFactory.createTextField(composite, SWT.SINGLE | SWT.BORDER); + String command = provider.getCommand(); + inputCommand.setText(command!=null ? command : ""); //$NON-NLS-1$ + inputCommand.setEnabled(fEditable); + inputCommand.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + String text = inputCommand.getText(); + AbstractBuiltinSpecsDetector provider = (AbstractBuiltinSpecsDetector) getProvider(); + if (!text.equals(provider.getCommand())) { + AbstractBuiltinSpecsDetector selectedProvider = (AbstractBuiltinSpecsDetector) getProviderWorkingCopy(); + selectedProvider.setCommand(text); + refreshItem(selectedProvider); + } + } + }); + } + + /** + * Create "Browse" button. + */ + private void createBrowseButton(Composite composite) { + Button button = ControlFactory.createPushButton(composite, Messages.BuiltinSpecsDetectorOptionPage_Browse); + button.setEnabled(fEditable); + button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent evt) { + FileDialog dialog = new FileDialog(getShell(), SWT.NONE); + dialog.setText(Messages.BuiltinSpecsDetectorOptionPage_ChooseFile); + String fileName = inputCommand.getText(); + // taking chance that the first word is a compiler path + int space = fileName.indexOf(' '); + if (space > 0) { + fileName = fileName.substring(0, space); + } + IPath folder = new Path(fileName).removeLastSegments(1); + dialog.setFilterPath(folder.toOSString()); + String chosenFile = dialog.open(); + if (chosenFile != null) { + inputCommand.insert(chosenFile); + } + } + }); + } + + /** + * Create check-box for console. + */ + private void createConsoleCheckbox(Composite composite, AbstractBuiltinSpecsDetector provider) { + allocateConsoleCheckBox = new Button(composite, SWT.CHECK); + allocateConsoleCheckBox.setText(Messages.BuiltinSpecsDetectorOptionPage_AllocateConsole); + allocateConsoleCheckBox.setSelection(provider.isConsoleEnabled()); + allocateConsoleCheckBox.setEnabled(fEditable); + allocateConsoleCheckBox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + boolean enabled = allocateConsoleCheckBox.getSelection(); + AbstractBuiltinSpecsDetector provider = (AbstractBuiltinSpecsDetector) getProvider(); + if (enabled != provider.isConsoleEnabled()) { + AbstractBuiltinSpecsDetector selectedProvider = (AbstractBuiltinSpecsDetector) getProviderWorkingCopy(); + selectedProvider.setConsoleEnabled(enabled); + refreshItem(selectedProvider); + } + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + } + }); + } + +} diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/GCCBuildCommandParserOptionPage.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/GCCBuildCommandParserOptionPage.java new file mode 100644 index 00000000000..9f999d8d7a6 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/GCCBuildCommandParserOptionPage.java @@ -0,0 +1,231 @@ +/******************************************************************************* + * Copyright (c) 2009, 2012 Andrew Gvozdev 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: + * Andrew Gvozdev - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.managedbuilder.internal.ui.language.settings.providers; + +import org.eclipse.cdt.managedbuilder.internal.ui.Messages; +import org.eclipse.cdt.managedbuilder.language.settings.providers.AbstractBuildCommandParser; +import org.eclipse.cdt.ui.language.settings.providers.AbstractLanguageSettingProviderOptionPage; +import org.eclipse.cdt.utils.ui.controls.ControlFactory; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +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.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +/** + * Options page for {@link AbstractBuildCommandParser}. + * + */ +public final class GCCBuildCommandParserOptionPage extends AbstractLanguageSettingProviderOptionPage { + private boolean fEditable; + + private Text inputCommand; + private Button expandRelativePathCheckBox; + + private Button scopeProjectRadioButton; + private Button scopeFolderRadioButton; + private Button scopeFileRadioButton; + + @Override + public void createControl(Composite parent) { + fEditable = parent.isEnabled(); + AbstractBuildCommandParser provider = (AbstractBuildCommandParser) getProvider(); + + Composite composite = new Composite(parent, SWT.NONE); + createCompositeForPageArea(composite); + createCompilerPatternInputControl(provider, composite); + createResourceScopeGroup(provider, composite); + createResolvePathsCheckbox(composite, provider); + + setControl(composite); + } + + /** + * Create composite for the page. + */ + private void createCompositeForPageArea(final Composite composite) { + { + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + layout.marginWidth = 1; + layout.marginHeight = 1; + layout.marginRight = 1; + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_BOTH)); + Dialog.applyDialogFont(composite); + + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 2; + composite.setLayoutData(gd); + } + } + + /** + * Create input control for compiler pattern. + */ + private void createCompilerPatternInputControl(AbstractBuildCommandParser provider, Composite composite) { + Label label = ControlFactory.createLabel(composite, Messages.GCCBuildCommandParserOptionPage_CompilerPattern); + GridData gd = new GridData(); + gd.horizontalSpan = 1; + label.setLayoutData(gd); + label.setEnabled(fEditable); + + inputCommand = ControlFactory.createTextField(composite, SWT.SINGLE | SWT.BORDER); + String compilerPattern = provider.getCompilerPattern(); + inputCommand.setText(compilerPattern!=null ? compilerPattern : ""); //$NON-NLS-1$ + + gd = new GridData(); + gd.horizontalSpan = 1; + gd.grabExcessHorizontalSpace = true; + gd.horizontalAlignment = SWT.FILL; + inputCommand.setLayoutData(gd); + inputCommand.setEnabled(fEditable); + + inputCommand.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + String text = inputCommand.getText(); + AbstractBuildCommandParser provider = (AbstractBuildCommandParser) getProvider(); + if (!text.equals(provider.getCompilerPattern())) { + AbstractBuildCommandParser selectedProvider = (AbstractBuildCommandParser) getProviderWorkingCopy(); + selectedProvider.setCompilerPattern(text); + refreshItem(selectedProvider); + } + } + }); + } + + /** + * Create check-box for resolving paths. + */ + private void createResolvePathsCheckbox(Composite composite, AbstractBuildCommandParser provider) { + expandRelativePathCheckBox = new Button(composite, SWT.CHECK); + expandRelativePathCheckBox.setText(Messages.GCCBuildCommandParserOptionPage_ResolvePaths); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 2; + expandRelativePathCheckBox.setLayoutData(gd); + + expandRelativePathCheckBox.setSelection(provider.isResolvingPaths()); + expandRelativePathCheckBox.setEnabled(fEditable); + expandRelativePathCheckBox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + boolean enabled = expandRelativePathCheckBox.getSelection(); + AbstractBuildCommandParser provider = (AbstractBuildCommandParser) getProvider(); + if (enabled != provider.isResolvingPaths()) { + AbstractBuildCommandParser selectedProvider = (AbstractBuildCommandParser) getProviderWorkingCopy(); + selectedProvider.setResolvingPaths(enabled); + refreshItem(selectedProvider); + } + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + } + }); + } + + /** + * Create group and radio buttons for container to keep discovered entries. + */ + private void createResourceScopeGroup(AbstractBuildCommandParser provider, Composite composite) { + Group resourceScopeGroup = new Group(composite, SWT.NONE); + resourceScopeGroup.setText(Messages.GCCBuildCommandParserOptionPage_ContainerForDiscoveredEntries); + resourceScopeGroup.setLayout(new GridLayout(2, false)); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 2; + resourceScopeGroup.setLayoutData(gd); + + scopeFileRadioButton = new Button(resourceScopeGroup, SWT.RADIO); + scopeFileRadioButton.setText(Messages.GCCBuildCommandParserOptionPage_File); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 2; + scopeFileRadioButton.setLayoutData(gd); + + scopeFileRadioButton.setSelection(provider.getResourceScope() == AbstractBuildCommandParser.ResourceScope.FILE); + scopeFileRadioButton.setEnabled(fEditable); + scopeFileRadioButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + boolean enabled = scopeFileRadioButton.getSelection(); + AbstractBuildCommandParser provider = (AbstractBuildCommandParser) getProvider(); + if (enabled != (provider.getResourceScope() == AbstractBuildCommandParser.ResourceScope.FILE)) { + AbstractBuildCommandParser selectedProvider = (AbstractBuildCommandParser) getProviderWorkingCopy(); + selectedProvider.setResourceScope(AbstractBuildCommandParser.ResourceScope.FILE); + refreshItem(selectedProvider); + } + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + } + }); + + scopeFolderRadioButton = new Button(resourceScopeGroup, SWT.RADIO); + scopeFolderRadioButton.setText(Messages.GCCBuildCommandParserOptionPage_Folder); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 2; + scopeFolderRadioButton.setLayoutData(gd); + + scopeFolderRadioButton.setSelection(provider.getResourceScope() == AbstractBuildCommandParser.ResourceScope.FOLDER); + scopeFolderRadioButton.setEnabled(fEditable); + scopeFolderRadioButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + boolean enabled = scopeFolderRadioButton.getSelection(); + AbstractBuildCommandParser provider = (AbstractBuildCommandParser) getProvider(); + if (enabled != (provider.getResourceScope() == AbstractBuildCommandParser.ResourceScope.FOLDER)) { + AbstractBuildCommandParser selectedProvider = (AbstractBuildCommandParser) getProviderWorkingCopy(); + selectedProvider.setResourceScope(AbstractBuildCommandParser.ResourceScope.FOLDER); + refreshItem(selectedProvider); + } + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + } + }); + + scopeProjectRadioButton = new Button(resourceScopeGroup, SWT.RADIO); + scopeProjectRadioButton.setText(Messages.GCCBuildCommandParserOptionPage_Project); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 2; + scopeProjectRadioButton.setLayoutData(gd); + + scopeProjectRadioButton.setSelection(provider.getResourceScope() == AbstractBuildCommandParser.ResourceScope.PROJECT); + scopeProjectRadioButton.setEnabled(fEditable); + scopeProjectRadioButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + boolean enabled = scopeProjectRadioButton.getSelection(); + AbstractBuildCommandParser provider = (AbstractBuildCommandParser) getProvider(); + if (enabled != (provider.getResourceScope() == AbstractBuildCommandParser.ResourceScope.PROJECT)) { + AbstractBuildCommandParser selectedProvider = (AbstractBuildCommandParser) getProviderWorkingCopy(); + selectedProvider.setResourceScope(AbstractBuildCommandParser.ResourceScope.PROJECT); + refreshItem(selectedProvider); + } + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + } + }); + } + +} diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/ScannerDiscoveryConsole.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/ScannerDiscoveryConsole.java new file mode 100644 index 00000000000..b12bf1c19c3 --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/ScannerDiscoveryConsole.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2010, 2012 Andrew Gvozdev 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: + * Andrew Gvozdev - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.managedbuilder.internal.ui.language.settings.providers; + +import java.net.URL; + +import org.eclipse.cdt.internal.ui.buildconsole.CBuildConsole; +import org.eclipse.cdt.managedbuilder.language.settings.providers.AbstractBuiltinSpecsDetector; +import org.eclipse.cdt.ui.language.settings.providers.LanguageSettingsProvidersImages; + +/** + * Console adapter for {@link AbstractBuiltinSpecsDetector}. + */ +public class ScannerDiscoveryConsole extends CBuildConsole { + /** + * {@inheritDoc} + * @param consoleId - a console ID is expected here which then is used as menu context ID. + * @param defaultIconUrl - if {@code LanguageSettingsProviderAssociation} extension point + * defines URL by provider id, {@code defaultIconUrl} will be ignored and the URL from the extension + * point will be used. If not, supplied {@code defaultIconUrl} will be used. + */ + @Override + public void init(String consoleId, String name, URL defaultIconUrl) { + URL iconUrl = LanguageSettingsProvidersImages.getImageUrl(consoleId); + if (iconUrl == null) { + iconUrl = defaultIconUrl; + } + + super.init(consoleId, name, iconUrl); + } +} diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/ScannerDiscoveryGlobalConsole.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/ScannerDiscoveryGlobalConsole.java new file mode 100644 index 00000000000..0eed304893e --- /dev/null +++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/language/settings/providers/ScannerDiscoveryGlobalConsole.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 Andrew Gvozdev 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: + * Andrew Gvozdev - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.managedbuilder.internal.ui.language.settings.providers; + +import java.io.IOException; +import java.net.URL; + +import org.eclipse.cdt.core.ConsoleOutputStream; +import org.eclipse.cdt.internal.core.ICConsole; +import org.eclipse.cdt.managedbuilder.language.settings.providers.AbstractBuiltinSpecsDetector; +import org.eclipse.cdt.ui.CDTSharedImages; +import org.eclipse.cdt.ui.language.settings.providers.LanguageSettingsProvidersImages; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.console.ConsolePlugin; +import org.eclipse.ui.console.IConsole; +import org.eclipse.ui.console.IConsoleManager; +import org.eclipse.ui.console.MessageConsole; +import org.eclipse.ui.console.MessageConsoleStream; + +/** + * Console adapter for global {@link AbstractBuiltinSpecsDetector}. + * + * Note that this console is not colored. + */ +public class ScannerDiscoveryGlobalConsole implements ICConsole { + private MessageConsole console; + + private class ConsoleOutputStreamAdapter extends ConsoleOutputStream { + private MessageConsoleStream fConsoleStream; + public ConsoleOutputStreamAdapter(MessageConsoleStream stream) { + fConsoleStream = stream; + } + @Override + public void write(int arg0) throws IOException { + fConsoleStream.write(arg0); + } + @Override + public synchronized void write(byte[] b, int off, int len) throws IOException { + fConsoleStream.write(b, off, len); + } + + @Override + public void flush() throws IOException { + fConsoleStream.flush(); + } + + @Override + public void close() throws IOException { + fConsoleStream.close(); + } + } + + @Override + public void start(IProject project) { + Assert.isTrue(project == null); + } + + @Override + public ConsoleOutputStream getOutputStream() throws CoreException { + return new ConsoleOutputStreamAdapter(console.newMessageStream()); + } + + @Override + public ConsoleOutputStream getInfoStream() throws CoreException { + return new ConsoleOutputStreamAdapter(console.newMessageStream()); + } + + @Override + public ConsoleOutputStream getErrorStream() throws CoreException { + return new ConsoleOutputStreamAdapter(console.newMessageStream()); + } + + @Override + public void init(String consoleId, String name, URL defaultIconUrl) { + console = null; + + IConsoleManager consoleManager = ConsolePlugin.getDefault().getConsoleManager(); + IConsole[] allConsoles = consoleManager.getConsoles(); + for (IConsole con : allConsoles) { + if (name.equals(con.getName()) && con instanceof MessageConsole) { + console = (MessageConsole) con; + console.clearConsole(); + break; + } + } + + if (console==null) { + URL iconUrl = LanguageSettingsProvidersImages.getImageUrl(consoleId); + if (iconUrl == null) { + iconUrl = defaultIconUrl; + } + + ImageDescriptor imageDescriptor; + if (iconUrl != null) { + imageDescriptor = CDTSharedImages.getImageDescriptor(iconUrl.toString()); + } else { + imageDescriptor = ImageDescriptor.getMissingImageDescriptor(); + } + + console = new MessageConsole(name, imageDescriptor); + console.activate(); + consoleManager.addConsoles(new IConsole[]{ console }); + } + } + +} diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/preferences/PropertyPageDefsTab.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/preferences/PropertyPageDefsTab.java index 458f7e517a1..9c6bb0af7ee 100644 --- a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/preferences/PropertyPageDefsTab.java +++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/ui/preferences/PropertyPageDefsTab.java @@ -12,9 +12,10 @@ package org.eclipse.cdt.managedbuilder.ui.preferences; import org.eclipse.cdt.core.settings.model.ICResourceDescription; +import org.eclipse.cdt.internal.ui.language.settings.providers.LanguageSettingsProvidersPage; +import org.eclipse.cdt.managedbuilder.internal.ui.Messages; import org.eclipse.cdt.ui.newui.AbstractCPropertyTab; import org.eclipse.cdt.ui.newui.CDTPrefUtil; -import org.eclipse.cdt.managedbuilder.internal.ui.Messages; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; @@ -25,19 +26,20 @@ import org.eclipse.swt.widgets.Group; /** * @since 5.1 - * + * * @noextend This class is not intended to be subclassed by clients. * @noinstantiate This class is not intended to be instantiated by clients. */ public class PropertyPageDefsTab extends AbstractCPropertyTab { private static final int SPACING = 5; // for radio buttons layout - + private Button show_tree; private Button show_inc_files; private Button show_mng; private Button show_tool; private Button show_exp; + private Button show_providers_tab; // temporary checkbox for scanner discovery Providers tab private Button show_tipbox; private Button b_0; @@ -48,77 +50,82 @@ public class PropertyPageDefsTab extends AbstractCPropertyTab { private Button s_0; private Button s_1; private Button s_2; - + @Override public void createControls(Composite parent) { super.createControls(parent); usercomp.setLayout(new GridLayout(1, false)); show_mng = new Button(usercomp, SWT.CHECK); - show_mng.setText(Messages.PropertyPageDefsTab_0); + show_mng.setText(Messages.PropertyPageDefsTab_0); show_mng.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); show_inc_files = new Button(usercomp, SWT.CHECK); - show_inc_files.setText(Messages.PropertyPageDefsTab_showIncludeFileTab); + show_inc_files.setText(Messages.PropertyPageDefsTab_showIncludeFileTab); show_inc_files.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); show_tree = new Button(usercomp, SWT.CHECK); - show_tree.setText(Messages.PropertyPageDefsTab_1); + show_tree.setText(Messages.PropertyPageDefsTab_1); show_tree.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); show_tool = new Button(usercomp, SWT.CHECK); - show_tool.setText(Messages.PropertyPageDefsTab_4); + show_tool.setText(Messages.PropertyPageDefsTab_4); show_tool.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); show_exp = new Button(usercomp, SWT.CHECK); - show_exp.setText(Messages.PropertyPageDefsTab_10); + show_exp.setText(Messages.PropertyPageDefsTab_10); show_exp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - + + show_providers_tab = new Button(usercomp, SWT.CHECK); + show_providers_tab.setText(Messages.PropertyPageDefsTab_showProvidersTab); + show_providers_tab.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + show_tipbox = new Button(usercomp, SWT.CHECK); - show_tipbox.setText(Messages.PropertyPageDefsTab_16); + show_tipbox.setText(Messages.PropertyPageDefsTab_16); show_tipbox.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); Group saveGrp = new Group(usercomp, SWT.NONE); - saveGrp.setText(Messages.PropertyPageDefsTab_11); + saveGrp.setText(Messages.PropertyPageDefsTab_11); saveGrp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); FillLayout fl = new FillLayout(SWT.VERTICAL); fl.spacing = SPACING; fl.marginHeight = SPACING; fl.marginWidth = SPACING; saveGrp.setLayout(fl); - + s_0 = new Button(saveGrp, SWT.RADIO); - s_0.setText(Messages.PropertyPageDefsTab_13); + s_0.setText(Messages.PropertyPageDefsTab_13); s_1 = new Button(saveGrp, SWT.RADIO); - s_1.setText(Messages.PropertyPageDefsTab_12); + s_1.setText(Messages.PropertyPageDefsTab_12); s_2 = new Button(saveGrp, SWT.RADIO); - s_2.setText(Messages.PropertyPageDefsTab_14); - + s_2.setText(Messages.PropertyPageDefsTab_14); + Group discGrp = new Group(usercomp, SWT.NONE); - discGrp.setText(Messages.PropertyPageDefsTab_5); + discGrp.setText(Messages.PropertyPageDefsTab_5); discGrp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); fl = new FillLayout(SWT.VERTICAL); fl.spacing = SPACING; fl.marginHeight = SPACING; fl.marginWidth = SPACING; discGrp.setLayout(fl); - + b_0 = new Button(discGrp, SWT.RADIO); - b_0.setText(Messages.PropertyPageDefsTab_6); + b_0.setText(Messages.PropertyPageDefsTab_6); b_1 = new Button(discGrp, SWT.RADIO); - b_1.setText(Messages.PropertyPageDefsTab_7); + b_1.setText(Messages.PropertyPageDefsTab_7); b_2 = new Button(discGrp, SWT.RADIO); - b_2.setText(Messages.PropertyPageDefsTab_8); + b_2.setText(Messages.PropertyPageDefsTab_8); b_3 = new Button(discGrp, SWT.RADIO); - b_3.setText(Messages.PropertyPageDefsTab_9); - + b_3.setText(Messages.PropertyPageDefsTab_9); + show_inc_files.setSelection(CDTPrefUtil.getBool(CDTPrefUtil.KEY_SHOW_INC_FILES)); show_tree.setSelection(CDTPrefUtil.getBool(CDTPrefUtil.KEY_DTREE)); show_mng.setSelection(!CDTPrefUtil.getBool(CDTPrefUtil.KEY_NOMNG)); show_tool.setSelection(!CDTPrefUtil.getBool(CDTPrefUtil.KEY_NOTOOLM)); show_exp.setSelection(CDTPrefUtil.getBool(CDTPrefUtil.KEY_EXPORT)); + show_providers_tab.setSelection(!CDTPrefUtil.getBool(LanguageSettingsProvidersPage.KEY_NO_SHOW_PROVIDERS)); show_tipbox.setSelection(CDTPrefUtil.getBool(CDTPrefUtil.KEY_TIPBOX)); - + switch (CDTPrefUtil.getInt(CDTPrefUtil.KEY_DISC_NAMES)) { case CDTPrefUtil.DISC_NAMING_UNIQUE_OR_BOTH: b_0.setSelection(true); break; case CDTPrefUtil.DISC_NAMING_UNIQUE_OR_IDS: b_1.setSelection(true); break; @@ -140,6 +147,7 @@ public class PropertyPageDefsTab extends AbstractCPropertyTab { CDTPrefUtil.setBool(CDTPrefUtil.KEY_NOMNG, !show_mng.getSelection()); CDTPrefUtil.setBool(CDTPrefUtil.KEY_NOTOOLM, !show_tool.getSelection()); CDTPrefUtil.setBool(CDTPrefUtil.KEY_EXPORT, show_exp.getSelection()); + CDTPrefUtil.setBool(LanguageSettingsProvidersPage.KEY_NO_SHOW_PROVIDERS, !show_providers_tab.getSelection()); CDTPrefUtil.setBool(CDTPrefUtil.KEY_TIPBOX, show_tipbox.getSelection()); int x = 0; if (b_1.getSelection()) x = 1; @@ -152,7 +160,7 @@ public class PropertyPageDefsTab extends AbstractCPropertyTab { else if (s_2.getSelection()) x = CDTPrefUtil.POSITION_SAVE_NONE; CDTPrefUtil.setInt(CDTPrefUtil.KEY_POSSAVE, x); } - + @Override protected void performDefaults() { show_tree.setSelection(false); @@ -160,6 +168,7 @@ public class PropertyPageDefsTab extends AbstractCPropertyTab { show_mng.setSelection(true); show_tool.setSelection(true); show_exp.setSelection(false); + show_providers_tab.setSelection(false); show_tipbox.setSelection(false); b_0.setSelection(true); b_1.setSelection(false); diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/ScannerDiscoveryLegacySupport.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/ScannerDiscoveryLegacySupport.java index 53f77ee6fc3..212d31465a5 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/ScannerDiscoveryLegacySupport.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/ScannerDiscoveryLegacySupport.java @@ -47,11 +47,15 @@ public class ScannerDiscoveryLegacySupport { private static final String PREFERENCES_QUALIFIER = CCorePlugin.PLUGIN_ID; private static final String LANGUAGE_SETTINGS_PROVIDERS_NODE = "languageSettingsProviders"; //$NON-NLS-1$ + /** + * Get preferences node for org.eclipse.cdt.core. + */ private static Preferences getPreferences(IProject project) { - if (project == null) + if (project == null) { return InstanceScope.INSTANCE.getNode(PREFERENCES_QUALIFIER).node(LANGUAGE_SETTINGS_PROVIDERS_NODE); - else + } else { return new LocalProjectScope(project).getNode(PREFERENCES_QUALIFIER).node(LANGUAGE_SETTINGS_PROVIDERS_NODE); + } } /** diff --git a/core/org.eclipse.cdt.core/schema/LanguageSettingsProvider.exsd b/core/org.eclipse.cdt.core/schema/LanguageSettingsProvider.exsd index 9cfae19859f..8c5e164a99d 100644 --- a/core/org.eclipse.cdt.core/schema/LanguageSettingsProvider.exsd +++ b/core/org.eclipse.cdt.core/schema/LanguageSettingsProvider.exsd @@ -226,7 +226,7 @@ The value "true" of this attribute is meaningful only for providers ca - CDT 9.0 + CDT 8.1 diff --git a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF index ed8dab488a6..b90b6aa0a12 100644 --- a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF @@ -29,6 +29,7 @@ Export-Package: org.eclipse.cdt.internal.corext;x-internal:=true, org.eclipse.cdt.internal.ui.includebrowser;x-internal:=true, org.eclipse.cdt.internal.ui.indexview;x-internal:=true, org.eclipse.cdt.internal.ui.language;x-internal:=true, + org.eclipse.cdt.internal.ui.language.settings.providers;x-internal:=true, org.eclipse.cdt.internal.ui.navigator;x-internal:=true, org.eclipse.cdt.internal.ui.newui;x-internal:=true, org.eclipse.cdt.internal.ui.preferences;x-internal:=true, @@ -75,6 +76,7 @@ Export-Package: org.eclipse.cdt.internal.corext;x-internal:=true, org.eclipse.cdt.ui.browser.typeinfo, org.eclipse.cdt.ui.dialogs, org.eclipse.cdt.ui.internal.templateengine.wizard;x-internal:=true, + org.eclipse.cdt.ui.language.settings.providers, org.eclipse.cdt.ui.newui, org.eclipse.cdt.ui.refactoring, org.eclipse.cdt.ui.refactoring.actions, diff --git a/core/org.eclipse.cdt.ui/icons/obj16/filesyst.gif b/core/org.eclipse.cdt.ui/icons/obj16/filesyst.gif index 13ce11b1490b0691db9fc3b2a7a2a2055a5cf965..4b98a62c6eed7401e6fc5d44a2b319fdf56097de 100644 GIT binary patch literal 144 zcmZ?wbhEHb6krfw*v!BnlDS$SwCmuD|Ns9V|Nn8t|I3v-n!S$n`mZQ;UQyyaC(8~f z!GHu5f3h$#FmN;IfW$y%FtFGbob+71_gjX~`5)5h0xF3*POJPp9*Uh5I`d`89Sd{T mDpsFa%+I%fXlM~*P%zM%8#eWtcG&6%MSItj?e1V;um%8#wKpgL literal 310 zcmZ?wbhEHb6krfwxXQp_5i-F#Vya!t47-?VZYlHA>(@?NeB3%}s%zRpx3q<>Df3;^ z=DVfM_sd_oXx)M9kKaz+bz2NL8_aH3$V%m-ttg1k{!KHJAIgSNSZjV$qwL z&{OL*vEJigk^S^0x4EsZi#nV)b#g85a$3{lu)UvWL%-dY3ASak_xyiUfAGcsJI}x0 zfBEC#s~?Zve1G!h=d*V|pTGa{>ch`JACA8L^y|ad-=Dtz{`%wh_n*Ii{`&KuGNAaA zg^_{5o15rEb(&zAA)EYfpgZl2uvGVX>2@ zUU4}*ZwbSP5LHh{-FM|v;`}|m{NyDY<<(nTg**k-BpG`p)l#I@1U&^*^J|3Jh1PA|dq&N(!Z@HZp>ApQj9uH0 z-*(HJ)4%@g@&h-XzWws!_us$&{{8>|pMf}__>+Z^fkB8t2c#TiCj+a>0u`@7OE;d! j9f6w-IBz!Z6#d0YIyfF^6zUE+}|O5WTND;=`zP> z$)A|3bZU{>=_Tst*BahB7WDK%)4Q+RKK(iS>Cc7#gn;5t7Dg@xc?KN@AOP9Pz^e4% oduWR4Bp%1UfEI_esSYOu!aFvE34UcTY + @@ -3368,6 +3369,17 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + This extension point defines appearance and behavior of UI controls for Language Settings Providers defined with extension point <samp>org.eclipse.cdt.core.LanguageSettingsProvider</samp>. + + + + + + + + + + This extension point is used to define appearance and behavior of Language Settings Providers in user interface. + + + + + + + + + + + + + + + + + + ID of the extension point, not used + + + + + + + Name of the extension point, not used + + + + + + + + + + + + + The definition of UI elements associated with ID of language settings provider. + + + + + + + ID of language settings provider for which appearance is being defined. + + + + + + + The path to the provider icon in the defining plugin, for example icons/obj16/picture.gif. + + + + + + + + + + Options page for the provider to appear in preferences in Providers tab. + + + + + + + + + + Defines if user is allowed to edit provider's entries in UI. + + + + + + + Defines if user is allowed to clear provider's entries in UI. For some providers like compiler specs detectors that may trigger automatic rerun. + + + + + + + + + + The definition of UI elements associated with type of language settings provider. Providers subclassed from this type will inherit characteristics from closest super-type (unless exact ID association is defined). + + + + + + + Class of language settings provider for which appearance is being defined. + + + + + + + + + + The path to the provider icon in the defining plugin, for example icons/obj16/picture.gif. + + + + + + + + + + Options page for the provider to appear in preferences in Providers tab. + + + + + + + + + + Defines if user is allowed to edit provider's entries in UI. + + + + + + + Defines if user is allowed to clear provider's entries in UI. For some providers like compiler specs detectors that may trigger automatic rerun. + + + + + + + + + + + + CDT 8.1 + + + + + + + + + For an example see definition for org.eclipse.cdt.ui.UserLanguageSettingsProvider. + + + + + + + + + [Enter API information here.] + + + + + + + + + + Copyright (c) 2010, 2012 Andrew Gvozdev 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 + + + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ImageCombo.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ImageCombo.java new file mode 100644 index 00000000000..8b71742590a --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ImageCombo.java @@ -0,0 +1,1471 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 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 + * Tom Seidel - enhancements for image-handling + *******************************************************************************/ +package org.eclipse.cdt.internal.ui; + +import java.util.Arrays; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.accessibility.ACC; +import org.eclipse.swt.accessibility.AccessibleAdapter; +import org.eclipse.swt.accessibility.AccessibleControlAdapter; +import org.eclipse.swt.accessibility.AccessibleControlEvent; +import org.eclipse.swt.accessibility.AccessibleEvent; +import org.eclipse.swt.accessibility.AccessibleTextAdapter; +import org.eclipse.swt.accessibility.AccessibleTextEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Layout; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.TypedListener; +import org.eclipse.swt.widgets.Widget; + +/** + * The ImageCombo class represents a selectable user interface object + * that combines a text field and a table and issues notification + * when an item is selected from the table. + *

+ * Note that although this class is a subclass of Composite, + * it does not make sense to add children to it, or set a layout on it. + *

+ *
+ *
Styles: + *
BORDER, READ_ONLY, FLAT
+ *
Events: + *
Selection
+ *
+ */ +public final class ImageCombo extends Composite { + + Text text; + Table table; + int visibleItemCount = 5; + Shell popup; + Button arrow; + boolean hasFocus; + Listener listener, filter; + Color foreground, background; + Font font; + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + *

+ * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

+ * + * @param parent a widget which will be the parent of the new instance (cannot be null) + * @param style the style of widget to construct + * + * @exception IllegalArgumentException
    + *
  • ERROR_NULL_ARGUMENT - if the parent is null
  • + *
+ * @exception SWTException
    + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
  • + *
+ * + * @see SWT#BORDER + * @see SWT#READ_ONLY + * @see SWT#FLAT + * @see Widget#getStyle() + */ +public ImageCombo (Composite parent, int style) { + super (parent, style = checkStyle (style)); + + int textStyle = SWT.SINGLE; + if ((style & SWT.READ_ONLY) != 0) textStyle |= SWT.READ_ONLY; + if ((style & SWT.FLAT) != 0) textStyle |= SWT.FLAT; + text = new Text (this, SWT.NONE); + int arrowStyle = SWT.ARROW | SWT.DOWN; + if ((style & SWT.FLAT) != 0) arrowStyle |= SWT.FLAT; + arrow = new Button (this, arrowStyle); + + listener = new Listener () { + public void handleEvent (Event event) { + if (popup == event.widget) { + popupEvent (event); + return; + } + if (text == event.widget) { + textEvent (event); + return; + } + if (table == event.widget) { + listEvent (event); + return; + } + if (arrow == event.widget) { + arrowEvent (event); + return; + } + if (ImageCombo.this == event.widget) { + comboEvent (event); + return; + } + if (getShell () == event.widget) { + handleFocus (SWT.FocusOut); + } + } + }; + filter = new Listener() { + public void handleEvent(Event event) { + Shell shell = ((Control)event.widget).getShell (); + if (shell == ImageCombo.this.getShell ()) { + handleFocus (SWT.FocusOut); + } + } + }; + + int [] comboEvents = {SWT.Dispose, SWT.Move, SWT.Resize}; + for (int i=0; i + *
  • ERROR_NULL_ARGUMENT - if the string is null
  • + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #add(String,int) + */ +public void add (String string, Image image) { + checkWidget(); + if (string == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + TableItem newItem = new TableItem(this.table,SWT.NONE); + newItem.setText(string); + if (image != null) newItem.setImage(image); +} +/** + * Adds the argument to the receiver's list at the given + * zero-relative index. + *

    + * Note: To add an item at the end of the list, use the + * result of calling getItemCount() as the + * index or use add(String). + *

    + * + * @param string the new item + * @param index the index for the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #add(String) + */ +public void add (String string,Image image, int index) { + checkWidget(); + if (string == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + TableItem newItem = new TableItem(this.table,SWT.NONE,index); + if (image != null) newItem.setImage(image); +} +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver's text is modified, by sending + * it one of the messages defined in the ModifyListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ModifyListener + * @see #removeModifyListener + */ +public void addModifyListener (ModifyListener listener) { + checkWidget(); + if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Modify, typedListener); +} +/** + * Adds the listener to the collection of listeners who will + * be notified when the receiver's selection changes, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * widgetSelected is called when the combo's list selection changes. + * widgetDefaultSelected is typically called when ENTER is pressed the combo's text area. + *

    + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener(SelectionListener listener) { + checkWidget(); + if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Selection,typedListener); + addListener (SWT.DefaultSelection,typedListener); +} +void arrowEvent (Event event) { + switch (event.type) { + case SWT.FocusIn: { + handleFocus (SWT.FocusIn); + break; + } + case SWT.Selection: { + dropDown (!isDropped ()); + break; + } + } +} +/** + * Sets the selection in the receiver's text field to an empty + * selection starting just before the first character. If the + * text field is editable, this has the effect of placing the + * i-beam at the start of the text. + *

    + * Note: To clear the selected items in the receiver's list, + * use deselectAll(). + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #deselectAll + */ +public void clearSelection () { + checkWidget (); + text.clearSelection (); + table.deselectAll (); +} +void comboEvent (Event event) { + switch (event.type) { + case SWT.Dispose: + if (popup != null && !popup.isDisposed ()) { + table.removeListener (SWT.Dispose, listener); + popup.dispose (); + } + Shell shell = getShell (); + shell.removeListener (SWT.Deactivate, listener); + Display display = getDisplay (); + display.removeFilter (SWT.FocusIn, filter); + popup = null; + text = null; + table = null; + arrow = null; + break; + case SWT.Move: + dropDown (false); + break; + case SWT.Resize: + internalLayout (false); + break; + } +} + +public Point computeSize (int wHint, int hHint, boolean changed) { + checkWidget (); + int width = 0, height = 0; + String[] items = getStringsFromTable(); + int textWidth = 0; + GC gc = new GC (text); + int spacer = gc.stringExtent (" ").x; //$NON-NLS-1$ + for (int i = 0; i < items.length; i++) { + textWidth = Math.max (gc.stringExtent (items[i]).x, textWidth); + } + gc.dispose(); + Point textSize = text.computeSize (SWT.DEFAULT, SWT.DEFAULT, changed); + Point arrowSize = arrow.computeSize (SWT.DEFAULT, SWT.DEFAULT, changed); + Point listSize = table.computeSize (wHint, SWT.DEFAULT, changed); + int borderWidth = getBorderWidth (); + + height = Math.max (hHint, Math.max (textSize.y, arrowSize.y) + 2*borderWidth); + width = Math.max (wHint, Math.max (textWidth + 2*spacer + arrowSize.x + 2*borderWidth, listSize.x)); + return new Point (width, height); +} +void createPopup(int selectionIndex) { + // create shell and list + popup = new Shell (getShell (), SWT.NO_TRIM | SWT.ON_TOP); + int style = getStyle (); + int listStyle = SWT.SINGLE | SWT.V_SCROLL; + if ((style & SWT.FLAT) != 0) listStyle |= SWT.FLAT; + if ((style & SWT.RIGHT_TO_LEFT) != 0) listStyle |= SWT.RIGHT_TO_LEFT; + if ((style & SWT.LEFT_TO_RIGHT) != 0) listStyle |= SWT.LEFT_TO_RIGHT; + // create a table instead of a list. + table = new Table (popup, listStyle); + if (font != null) table.setFont (font); + if (foreground != null) table.setForeground (foreground); + if (background != null) table.setBackground (background); + + int [] popupEvents = {SWT.Close, SWT.Paint, SWT.Deactivate}; + for (int i=0; i + *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • + * + */ +public void deselect (int index) { + checkWidget (); + table.deselect (index); +} +/** + * Deselects all selected items in the receiver's list. + *

    + * Note: To clear the selection in the receiver's text field, + * use clearSelection(). + *

    + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #clearSelection + */ +public void deselectAll () { + checkWidget (); + table.deselectAll (); +} +void dropDown (boolean drop) { + if (drop == isDropped ()) return; + if (!drop) { + popup.setVisible (false); + if (!isDisposed ()&& arrow.isFocusControl()) { + text.setFocus(); + } + return; + } + + if (getShell() != popup.getParent ()) { + TableItem[] items = table.getItems (); + int selectionIndex = table.getSelectionIndex (); + table.removeListener (SWT.Dispose, listener); + popup.dispose(); + popup = null; + table = null; + createPopup (selectionIndex); + } + + Point size = getSize (); + int itemCount = table.getItemCount (); + itemCount = (itemCount == 0) ? visibleItemCount : Math.min(visibleItemCount, itemCount); + int itemHeight = table.getItemHeight () * itemCount; + Point listSize = table.computeSize (SWT.DEFAULT, itemHeight, false); + table.setBounds (1, 1, Math.max (size.x - 2, listSize.x), listSize.y); + + int index = table.getSelectionIndex (); + if (index != -1) table.setTopIndex (index); + Display display = getDisplay (); + Rectangle listRect = table.getBounds (); + Rectangle parentRect = display.map (getParent (), null, getBounds ()); + Point comboSize = getSize (); + Rectangle displayRect = getMonitor ().getClientArea (); + int width = Math.max (comboSize.x, listRect.width + 2); + int height = listRect.height + 2; + int x = parentRect.x; + int y = parentRect.y + comboSize.y; + if (y + height > displayRect.y + displayRect.height) y = parentRect.y - height; + popup.setBounds (x, y, width, height); + popup.setVisible (true); + table.setFocus (); +} +/* + * Return the Label immediately preceding the receiver in the z-order, + * or null if none. + */ +Label getAssociatedLabel () { + Control[] siblings = getParent ().getChildren (); + for (int i = 0; i < siblings.length; i++) { + if (siblings [i] == ImageCombo.this) { + if (i > 0 && siblings [i-1] instanceof Label) { + return (Label) siblings [i-1]; + } + } + } + return null; +} +public Control [] getChildren () { + checkWidget(); + return new Control [0]; +} +/** + * Gets the editable state. + * + * @return whether or not the reciever is editable + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + */ +public boolean getEditable () { + checkWidget (); + return text.getEditable(); +} +/** + * Returns the item at the given, zero-relative index in the + * receiver's list. Throws an exception if the index is out + * of range. + * + * @param index the index of the item to return + * @return the item at the given index + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public TableItem getItem (int index) { + checkWidget(); + return this.table.getItem (index); +} +/** + * Returns the number of items contained in the receiver's list. + * + * @return the number of items + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getItemCount () { + checkWidget (); + return table.getItemCount (); +} +/** + * Returns the height of the area which would be used to + * display one of the items in the receiver's list. + * + * @return the height of one item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getItemHeight () { + checkWidget (); + return table.getItemHeight (); +} +/** + * Returns an array of Strings which are the items + * in the receiver's list. + *

    + * Note: This is not the actual structure used by the receiver + * to maintain its list of items, so modifying the array will + * not affect the receiver. + *

    + * + * @return the items in the receiver's list + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public TableItem [] getItems () { + checkWidget (); + return table.getItems (); +} +char getMnemonic (String string) { + int index = 0; + int length = string.length (); + do { + while ((index < length) && (string.charAt (index) != '&')) index++; + if (++index >= length) return '\0'; + if (string.charAt (index) != '&') return string.charAt (index); + index++; + } while (index < length); + return '\0'; +} + +String [] getStringsFromTable() +{ + String[] items = new String[this.table.getItems().length]; + for (int i = 0, n = items.length; i < n; i++) { + items[i]=this.table.getItem(i).getText(); + } + return items; +} +/** + * Returns a Point whose x coordinate is the start + * of the selection in the receiver's text field, and whose y + * coordinate is the end of the selection. The returned values + * are zero-relative. An "empty" selection as indicated by + * the the x and y coordinates having the same value. + * + * @return a point representing the selection start and end + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Point getSelection () { + checkWidget (); + return text.getSelection (); +} +/** + * Returns the zero-relative index of the item which is currently + * selected in the receiver's list, or -1 if no item is selected. + * + * @return the index of the selected item + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getSelectionIndex () { + checkWidget (); + return table.getSelectionIndex (); +} +public int getStyle () { + int style = super.getStyle (); + style &= ~SWT.READ_ONLY; + if (!text.getEditable()) style |= SWT.READ_ONLY; + return style; +} +/** + * Returns a string containing a copy of the contents of the + * receiver's text field. + * + * @return the receiver's text + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public String getText () { + checkWidget (); + return text.getText (); +} +/** + * Returns the height of the receivers's text field. + * + * @return the text height + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getTextHeight () { + checkWidget (); + return text.getLineHeight (); +} +/** + * Returns the maximum number of characters that the receiver's + * text field is capable of holding. If this has not been changed + * by setTextLimit(), it will be the constant + * Combo.LIMIT. + * + * @return the text limit + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getTextLimit () { + checkWidget (); + return text.getTextLimit (); +} +/** + * Gets the number of items that are visible in the drop + * down portion of the receiver's list. + * + * @return the number of items that are visible + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + */ +public int getVisibleItemCount () { + checkWidget (); + return visibleItemCount; +} +void handleFocus (int type) { + if (isDisposed ()) return; + switch (type) { + case SWT.FocusIn: { + if (hasFocus) return; + if (getEditable ()) text.selectAll (); + hasFocus = true; + Shell shell = getShell (); + shell.removeListener (SWT.Deactivate, listener); + shell.addListener (SWT.Deactivate, listener); + Display display = getDisplay (); + display.removeFilter (SWT.FocusIn, filter); + display.addFilter (SWT.FocusIn, filter); + Event e = new Event (); + notifyListeners (SWT.FocusIn, e); + break; + } + case SWT.FocusOut: { + if (!hasFocus) return; + Control focusControl = getDisplay ().getFocusControl (); + if (focusControl == arrow || focusControl == table || focusControl == text) return; + hasFocus = false; + Shell shell = getShell (); + shell.removeListener(SWT.Deactivate, listener); + Display display = getDisplay (); + display.removeFilter (SWT.FocusIn, filter); + Event e = new Event (); + notifyListeners (SWT.FocusOut, e); + break; + } + } +} +/** + * Searches the receiver's list starting at the first item + * (index 0) until an item is found that is equal to the + * argument, and returns the index of that item. If no item + * is found, returns -1. + * + * @param string the search item + * @return the index of the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int indexOf (String string) { + checkWidget (); + if (string == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + return Arrays.asList(getStringsFromTable()).indexOf (string); +} + + +void initAccessible() { + AccessibleAdapter accessibleAdapter = new AccessibleAdapter () { + public void getName (AccessibleEvent e) { + String name = null; + Label label = getAssociatedLabel (); + if (label != null) { + name = stripMnemonic (label.getText()); + } + e.result = name; + } + public void getKeyboardShortcut(AccessibleEvent e) { + String shortcut = null; + Label label = getAssociatedLabel (); + if (label != null) { + String text = label.getText (); + if (text != null) { + char mnemonic = getMnemonic (text); + if (mnemonic != '\0') { + shortcut = "Alt+"+mnemonic; //$NON-NLS-1$ + } + } + } + e.result = shortcut; + } + public void getHelp (AccessibleEvent e) { + e.result = getToolTipText (); + } + }; + getAccessible ().addAccessibleListener (accessibleAdapter); + text.getAccessible ().addAccessibleListener (accessibleAdapter); + table.getAccessible ().addAccessibleListener (accessibleAdapter); + + arrow.getAccessible ().addAccessibleListener (new AccessibleAdapter() { + public void getName (AccessibleEvent e) { + e.result = isDropped () ? SWT.getMessage ("SWT_Close") : SWT.getMessage ("SWT_Open"); //$NON-NLS-1$ //$NON-NLS-2$ + } + public void getKeyboardShortcut (AccessibleEvent e) { + e.result = "Alt+Down Arrow"; //$NON-NLS-1$ + } + public void getHelp (AccessibleEvent e) { + e.result = getToolTipText (); + } + }); + + getAccessible().addAccessibleTextListener (new AccessibleTextAdapter() { + public void getCaretOffset (AccessibleTextEvent e) { + e.offset = text.getCaretPosition (); + } + }); + + getAccessible().addAccessibleControlListener (new AccessibleControlAdapter() { + public void getChildAtPoint (AccessibleControlEvent e) { + Point testPoint = toControl (e.x, e.y); + if (getBounds ().contains (testPoint)) { + e.childID = ACC.CHILDID_SELF; + } + } + + public void getLocation (AccessibleControlEvent e) { + Rectangle location = getBounds (); + Point pt = toDisplay (location.x, location.y); + e.x = pt.x; + e.y = pt.y; + e.width = location.width; + e.height = location.height; + } + + public void getChildCount (AccessibleControlEvent e) { + e.detail = 0; + } + + public void getRole (AccessibleControlEvent e) { + e.detail = ACC.ROLE_COMBOBOX; + } + + public void getState (AccessibleControlEvent e) { + e.detail = ACC.STATE_NORMAL; + } + + public void getValue (AccessibleControlEvent e) { + e.result = getText (); + } + }); + + text.getAccessible ().addAccessibleControlListener (new AccessibleControlAdapter () { + public void getRole (AccessibleControlEvent e) { + e.detail = text.getEditable () ? ACC.ROLE_TEXT : ACC.ROLE_LABEL; + } + }); + + arrow.getAccessible ().addAccessibleControlListener (new AccessibleControlAdapter() { + public void getDefaultAction (AccessibleControlEvent e) { + e.result = isDropped () ? SWT.getMessage ("SWT_Close") : SWT.getMessage ("SWT_Open"); //$NON-NLS-1$ //$NON-NLS-2$ + } + }); +} +boolean isDropped () { + return popup.getVisible (); +} +public boolean isFocusControl () { + checkWidget(); + if (text.isFocusControl () || arrow.isFocusControl () || table.isFocusControl () || popup.isFocusControl ()) { + return true; + } + return super.isFocusControl (); +} +void internalLayout (boolean changed) { + if (isDropped ()) dropDown (false); + Rectangle rect = getClientArea (); + int width = rect.width; + int height = rect.height; + Point arrowSize = arrow.computeSize (SWT.DEFAULT, height, changed); + text.setBounds (0, 0, width - arrowSize.x, height); + arrow.setBounds (width - arrowSize.x, 0, arrowSize.x, arrowSize.y); +} +void listEvent (Event event) { + switch (event.type) { + case SWT.Dispose: + if (getShell () != popup.getParent ()) { + TableItem[] items = table.getItems (); + int selectionIndex = table.getSelectionIndex (); + popup = null; + table = null; + createPopup (selectionIndex); + } + break; + case SWT.FocusIn: { + handleFocus (SWT.FocusIn); + break; + } + case SWT.MouseUp: { + if (event.button != 1) return; + dropDown (false); + break; + } + case SWT.Selection: { + int index = table.getSelectionIndex (); + if (index == -1) return; + text.setText (table.getItem (index).getText()); + text.selectAll (); + table.setSelection (index); + Event e = new Event (); + e.time = event.time; + e.stateMask = event.stateMask; + e.doit = event.doit; + notifyListeners (SWT.Selection, e); + event.doit = e.doit; + break; + } + case SWT.Traverse: { + switch (event.detail) { + case SWT.TRAVERSE_RETURN: + case SWT.TRAVERSE_ESCAPE: + case SWT.TRAVERSE_ARROW_PREVIOUS: + case SWT.TRAVERSE_ARROW_NEXT: + event.doit = false; + break; + } + Event e = new Event (); + e.time = event.time; + e.detail = event.detail; + e.doit = event.doit; + e.character = event.character; + e.keyCode = event.keyCode; + notifyListeners (SWT.Traverse, e); + event.doit = e.doit; + event.detail = e.detail; + break; + } + case SWT.KeyUp: { + Event e = new Event (); + e.time = event.time; + e.character = event.character; + e.keyCode = event.keyCode; + e.stateMask = event.stateMask; + notifyListeners (SWT.KeyUp, e); + break; + } + case SWT.KeyDown: { + if (event.character == SWT.ESC) { + // Escape key cancels popup list + dropDown (false); + } + if ((event.stateMask & SWT.ALT) != 0 && (event.keyCode == SWT.ARROW_UP || event.keyCode == SWT.ARROW_DOWN)) { + dropDown (false); + } + if (event.character == SWT.CR) { + // Enter causes default selection + dropDown (false); + Event e = new Event (); + e.time = event.time; + e.stateMask = event.stateMask; + notifyListeners (SWT.DefaultSelection, e); + } + // At this point the widget may have been disposed. + // If so, do not continue. + if (isDisposed ()) break; + Event e = new Event(); + e.time = event.time; + e.character = event.character; + e.keyCode = event.keyCode; + e.stateMask = event.stateMask; + notifyListeners(SWT.KeyDown, e); + break; + + } + } +} + +void popupEvent(Event event) { + switch (event.type) { + case SWT.Paint: + // draw black rectangle around list + Rectangle listRect = table.getBounds(); + Color black = getDisplay().getSystemColor(SWT.COLOR_BLACK); + event.gc.setForeground(black); + event.gc.drawRectangle(0, 0, listRect.width + 1, listRect.height + 1); + break; + case SWT.Close: + event.doit = false; + dropDown (false); + break; + case SWT.Deactivate: + dropDown (false); + break; + } +} +public void redraw () { + super.redraw(); + text.redraw(); + arrow.redraw(); + if (popup.isVisible()) table.redraw(); +} +public void redraw (int x, int y, int width, int height, boolean all) { + super.redraw(x, y, width, height, true); +} + +/** + * Removes the item from the receiver's list at the given + * zero-relative index. + * + * @param index the index for the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void remove (int index) { + checkWidget(); + table.remove (index); +} +/** + * Removes the items from the receiver's list which are + * between the given zero-relative start and end + * indices (inclusive). + * + * @param start the start of the range + * @param end the end of the range + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void remove (int start, int end) { + checkWidget(); + table.remove (start, end); +} +/** + * Searches the receiver's list starting at the first item + * until an item is found that is equal to the argument, + * and removes that item from the list. + * + * @param string the item to remove + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the string is not found in the list
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void remove (String string) { + checkWidget(); + if (string == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + int index = -1; + for (int i = 0, n = table.getItemCount(); i < n; i++) { + if (table.getItem(i).getText().equals(string)) { + index = i; + break; + } + } + remove(index); +} +/** + * Removes all of the items from the receiver's list and clear the + * contents of receiver's text field. + *

    + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void removeAll () { + checkWidget(); + text.setText (""); //$NON-NLS-1$ + table.removeAll (); +} +/** + * Removes the listener from the collection of listeners who will + * be notified when the receiver's text is modified. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ModifyListener + * @see #addModifyListener + */ +public void removeModifyListener (ModifyListener listener) { + checkWidget(); + if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + removeListener(SWT.Modify, listener); +} +/** + * Removes the listener from the collection of listeners who will + * be notified when the receiver's selection changes. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener (SelectionListener listener) { + checkWidget(); + if (listener == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + removeListener(SWT.Selection, listener); + removeListener(SWT.DefaultSelection,listener); +} +/** + * Selects the item at the given zero-relative index in the receiver's + * list. If the item at the index was already selected, it remains + * selected. Indices that are out of range are ignored. + * + * @param index the index of the item to select + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void select (int index) { + checkWidget(); + if (index == -1) { + table.deselectAll (); + text.setText (""); //$NON-NLS-1$ + return; + } + if (0 <= index && index < table.getItemCount()) { + if (index != getSelectionIndex()) { + text.setText (table.getItem (index).getText()); + text.selectAll (); + table.select (index); + table.showSelection (); + } + } +} +public void setBackground (Color color) { + super.setBackground(color); + background = color; + if (text != null) text.setBackground(color); + if (table != null) table.setBackground(color); + if (arrow != null) arrow.setBackground(color); +} +/** + * Sets the editable state. + * + * @param editable the new editable state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + */ +public void setEditable (boolean editable) { + checkWidget (); + text.setEditable(editable); +} +public void setEnabled (boolean enabled) { + super.setEnabled(enabled); + if (popup != null) popup.setVisible (false); + if (text != null) text.setEnabled(enabled); + if (arrow != null) arrow.setEnabled(enabled); +} +public boolean setFocus () { + checkWidget(); + return text.setFocus (); +} +public void setFont (Font font) { + super.setFont (font); + this.font = font; + text.setFont (font); + table.setFont (font); + internalLayout (true); +} +public void setForeground (Color color) { + super.setForeground(color); + foreground = color; + if (text != null) text.setForeground(color); + if (table != null) table.setForeground(color); + if (arrow != null) arrow.setForeground(color); +} +/** + * Sets the text of the item in the receiver's list at the given + * zero-relative index to the string argument. This is equivalent + * to remove'ing the old item at the index, and then + * add'ing the new item at that index. + * + * @param index the index for the item + * @param string the new text for the item + * + * @exception IllegalArgumentException
      + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
    • + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setItem (int index, String string, Image image) { + checkWidget(); + remove(index); + add(string,image,index); +} +/** + * Sets the receiver's list to be the given array of items. + * + * @param items the array of items + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the items array is null
    • + *
    • ERROR_INVALID_ARGUMENT - if an item in the items array is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setItems (String [] items) { + checkWidget (); + this.table.removeAll(); + for (int i = 0, n = items.length; i < n; i++) { + add(items[i],null); + } + if (!text.getEditable ()) text.setText (""); //$NON-NLS-1$ +} + +/** + * Sets the layout which is associated with the receiver to be + * the argument which may be null. + *

    + * Note : No Layout can be set on this Control because it already + * manages the size and position of its children. + *

    + * + * @param layout the receiver's new layout or null + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setLayout (Layout layout) { + checkWidget (); + return; +} +/** + * Sets the selection in the receiver's text field to the + * range specified by the argument whose x coordinate is the + * start of the selection and whose y coordinate is the end + * of the selection. + * + * @param selection a point representing the new selection start and end + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the point is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSelection (Point selection) { + checkWidget(); + if (selection == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + text.setSelection (selection.x, selection.y); +} + +/** + * Sets the contents of the receiver's text field to the + * given string. + *

    + * Note: The text field in a Combo is typically + * only capable of displaying a single line of text. Thus, + * setting the text to a string containing line breaks or + * other special characters will probably cause it to + * display incorrectly. + *

    + * + * @param string the new text + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the string is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setText (String string) { + checkWidget(); + if (string == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + int index = -1; + for (int i = 0, n = table.getItemCount(); i < n; i++) { + if (table.getItem(i).getText().equals(string)) { + index = i; + break; + } + } + if (index == -1) { + table.deselectAll (); + text.setText (string); + return; + } + text.setText (string); + text.selectAll (); + table.setSelection (index); + table.showSelection (); +} +/** + * Sets the maximum number of characters that the receiver's + * text field is capable of holding to be the argument. + * + * @param limit new text limit + * + * @exception IllegalArgumentException
      + *
    • ERROR_CANNOT_BE_ZERO - if the limit is zero
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setTextLimit (int limit) { + checkWidget(); + text.setTextLimit (limit); +} + +public void setToolTipText (String string) { + checkWidget(); + super.setToolTipText(string); + arrow.setToolTipText (string); + text.setToolTipText (string); +} + +public void setVisible (boolean visible) { + super.setVisible(visible); + if (!visible) popup.setVisible(false); +} +/** + * Sets the number of items that are visible in the drop + * down portion of the receiver's list. + * + * @param count the new number of items to be visible + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.0 + */ +public void setVisibleItemCount (int count) { + checkWidget (); + if (count < 0) return; + visibleItemCount = count; +} +String stripMnemonic (String string) { + int index = 0; + int length = string.length (); + do { + while ((index < length) && (string.charAt (index) != '&')) index++; + if (++index >= length) return string; + if (string.charAt (index) != '&') { + return string.substring(0, index-1) + string.substring(index, length); + } + index++; + } while (index < length); + return string; +} +void textEvent (Event event) { + switch (event.type) { + case SWT.FocusIn: { + handleFocus (SWT.FocusIn); + break; + } + case SWT.KeyDown: { + if (event.character == SWT.CR) { + dropDown (false); + Event e = new Event (); + e.time = event.time; + e.stateMask = event.stateMask; + notifyListeners (SWT.DefaultSelection, e); + } + //At this point the widget may have been disposed. + // If so, do not continue. + if (isDisposed ()) break; + + if (event.keyCode == SWT.ARROW_UP || event.keyCode == SWT.ARROW_DOWN) { + event.doit = false; + if ((event.stateMask & SWT.ALT) != 0) { + boolean dropped = isDropped (); + text.selectAll (); + if (!dropped) setFocus (); + dropDown (!dropped); + break; + } + + int oldIndex = getSelectionIndex (); + if (event.keyCode == SWT.ARROW_UP) { + select (Math.max (oldIndex - 1, 0)); + } else { + select (Math.min (oldIndex + 1, getItemCount () - 1)); + } + if (oldIndex != getSelectionIndex ()) { + Event e = new Event(); + e.time = event.time; + e.stateMask = event.stateMask; + notifyListeners (SWT.Selection, e); + } + //At this point the widget may have been disposed. + // If so, do not continue. + if (isDisposed ()) break; + } + + // Further work : Need to add support for incremental search in + // pop up list as characters typed in text widget + + Event e = new Event (); + e.time = event.time; + e.character = event.character; + e.keyCode = event.keyCode; + e.stateMask = event.stateMask; + notifyListeners (SWT.KeyDown, e); + break; + } + case SWT.KeyUp: { + Event e = new Event (); + e.time = event.time; + e.character = event.character; + e.keyCode = event.keyCode; + e.stateMask = event.stateMask; + notifyListeners (SWT.KeyUp, e); + break; + } + case SWT.Modify: { + table.deselectAll (); + Event e = new Event (); + e.time = event.time; + notifyListeners (SWT.Modify, e); + break; + } + case SWT.MouseDown: { + if (event.button != 1) return; + if (text.getEditable ()) return; + boolean dropped = isDropped (); + text.selectAll (); + if (!dropped) setFocus (); + dropDown (!dropped); + break; + } + case SWT.MouseUp: { + if (event.button != 1) return; + if (text.getEditable ()) return; + text.selectAll (); + break; + } + case SWT.Traverse: { + switch (event.detail) { + case SWT.TRAVERSE_RETURN: + case SWT.TRAVERSE_ARROW_PREVIOUS: + case SWT.TRAVERSE_ARROW_NEXT: + // The enter causes default selection and + // the arrow keys are used to manipulate the list contents so + // do not use them for traversal. + event.doit = false; + break; + } + + Event e = new Event (); + e.time = event.time; + e.detail = event.detail; + e.doit = event.doit; + e.character = event.character; + e.keyCode = event.keyCode; + notifyListeners (SWT.Traverse, e); + event.doit = e.doit; + event.detail = e.detail; + break; + } + } +} +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingEntryDialog.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingEntryDialog.java new file mode 100644 index 00000000000..277cd15bd40 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingEntryDialog.java @@ -0,0 +1,615 @@ +/******************************************************************************* + * Copyright (c) 2010, 2012 Andrew Gvozdev 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: + * Andrew Gvozdev - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.language.settings.providers; + +import org.eclipse.core.resources.IProject; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Image; +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.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; +import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; +import org.eclipse.cdt.core.settings.model.ICSettingEntry; +import org.eclipse.cdt.core.settings.model.util.CDataUtil; +import org.eclipse.cdt.ui.CDTSharedImages; +import org.eclipse.cdt.ui.newui.AbstractCPropertyTab; +import org.eclipse.cdt.ui.newui.AbstractPropertyDialog; + +import org.eclipse.cdt.internal.ui.ImageCombo; +import org.eclipse.cdt.internal.ui.newui.LanguageSettingsImages; +import org.eclipse.cdt.internal.ui.newui.Messages; + +/** + * @noextend This class is not intended to be subclassed by clients. + */ +public class LanguageSettingEntryDialog extends AbstractPropertyDialog { + private static final String SLASH = "/"; //$NON-NLS-1$ + + private ICConfigurationDescription cfgDescription; + private IProject project; + private ICLanguageSettingEntry entry; + private boolean clearValue; + private int kind; + + private Composite compositeArea; + private Label iconComboKind; + private ImageCombo comboKind; + private ImageCombo comboPathCategory; + private Label labelInput; + public Text inputName; + private Label checkBoxValue; + public Text inputValue; + private Button buttonBrowse; + private Button buttonVars; + private Button checkBoxBuiltIn; + private Button checkBoxFramework; + + private Button buttonOk; + private Button buttonCancel; + + private static final int COMBO_INDEX_INCLUDE_PATH = 0; + private static final int COMBO_INDEX_MACRO = 1; + private static final int COMBO_INDEX_INCLUDE_FILE = 2; + private static final int COMBO_INDEX_MACRO_FILE = 3; + private static final int COMBO_INDEX_LIBRARY_PATH = 4; + private static final int COMBO_INDEX_LIBRARY_FILE = 5; + + final private String [] comboKindItems = { + Messages.LanguageSettingEntryDialog_IncludeDirectory, + Messages.LanguageSettingEntryDialog_PreporocessorMacro, + Messages.LanguageSettingEntryDialog_IncludeFile, + Messages.LanguageSettingEntryDialog_PreprocessorMacroFile, + Messages.LanguageSettingEntryDialog_LibraryPath, + Messages.LanguageSettingEntryDialog_Library, + }; + final private Image[] comboKindImages = { + CDTSharedImages.getImage(CDTSharedImages.IMG_OBJS_INCLUDES_FOLDER), + CDTSharedImages.getImage(CDTSharedImages.IMG_OBJS_MACRO), + CDTSharedImages.getImage(CDTSharedImages.IMG_OBJS_TUNIT_HEADER), + CDTSharedImages.getImage(CDTSharedImages.IMG_OBJS_MACROS_FILE), + CDTSharedImages.getImage(CDTSharedImages.IMG_OBJS_LIBRARY_FOLDER), + CDTSharedImages.getImage(CDTSharedImages.IMG_OBJS_LIBRARY), + }; + + private static final int COMBO_PATH_INDEX_PROJECT = 0; + private static final int COMBO_PATH_INDEX_WORKSPACE = 1; + private static final int COMBO_PATH_INDEX_FILESYSTEM = 2; + + final private String [] pathCategories = { + Messages.LanguageSettingEntryDialog_ProjectPath, + Messages.LanguageSettingEntryDialog_WorkspacePath, + Messages.LanguageSettingEntryDialog_Filesystem, + }; + final private Image[] pathCategoryImages = { + CDTSharedImages.getImage(CDTSharedImages.IMG_ETOOL_PROJECT), + CDTSharedImages.getImage(CDTSharedImages.IMG_OBJS_WORKSPACE), + CDTSharedImages.getImage(CDTSharedImages.IMG_OBJS_FILESYSTEM), + }; + + private ICLanguageSettingEntry[] entries; + + + public LanguageSettingEntryDialog(Shell parent, ICConfigurationDescription cfgDescription, int kind) { + super(parent, ""); //$NON-NLS-1$ + this.cfgDescription = cfgDescription; + this.project = cfgDescription.getProjectDescription().getProject(); + this.entry = null; + this.clearValue = true; + this.kind = kind; + } + + /** + * This constructor is intended to be used with {@code clearValue=true} for "Add" dialogs + * where provided entry is used as a template. + */ + public LanguageSettingEntryDialog(Shell parent, ICConfigurationDescription cfgDescription, ICLanguageSettingEntry entry, boolean clearValue) { + super(parent, ""); //$NON-NLS-1$ + this.cfgDescription = cfgDescription; + this.project = cfgDescription.getProjectDescription().getProject(); + this.entry = entry; + this.kind = entry!=null ? entry.getKind() : ICSettingEntry.INCLUDE_PATH; + this.clearValue = clearValue; + } + + /** + * This constructor is used for "Edit" dialogs to edit provided entry + */ + public LanguageSettingEntryDialog(Shell parent, ICConfigurationDescription cfgDescription, ICLanguageSettingEntry entry) { + this(parent, cfgDescription, entry, false); + } + + private int comboIndexToKind(int index) { + int kind=0; + switch (index) { + case COMBO_INDEX_INCLUDE_PATH: + kind = ICSettingEntry.INCLUDE_PATH; + break; + case COMBO_INDEX_MACRO: + kind = ICSettingEntry.MACRO; + break; + case COMBO_INDEX_INCLUDE_FILE: + kind = ICSettingEntry.INCLUDE_FILE; + break; + case COMBO_INDEX_MACRO_FILE: + kind = ICSettingEntry.MACRO_FILE; + break; + case COMBO_INDEX_LIBRARY_PATH: + kind = ICSettingEntry.LIBRARY_PATH; + break; + case COMBO_INDEX_LIBRARY_FILE: + kind = ICSettingEntry.LIBRARY_FILE; + break; + } + return kind; + } + + private int kindToComboIndex(int kind) { + int index=0; + switch (kind) { + case ICSettingEntry.INCLUDE_PATH: + index = COMBO_INDEX_INCLUDE_PATH; + break; + case ICSettingEntry.MACRO: + index = COMBO_INDEX_MACRO; + break; + case ICSettingEntry.INCLUDE_FILE: + index = COMBO_INDEX_INCLUDE_FILE; + break; + case ICSettingEntry.MACRO_FILE: + index = COMBO_INDEX_MACRO_FILE; + break; + case ICSettingEntry.LIBRARY_PATH: + index = COMBO_INDEX_LIBRARY_PATH; + break; + case ICSettingEntry.LIBRARY_FILE: + index = COMBO_INDEX_LIBRARY_FILE; + break; + } + return index; + } + + @Override + protected Control createDialogArea(Composite parent) { + parent.setLayout(new GridLayout(4, false)); + GridData gd; + + // Composite for the dialog area + compositeArea = new Composite (parent, SWT.NONE); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.verticalAlignment = SWT.TOP; + gd.horizontalSpan = 7; + compositeArea.setLayoutData(gd); + compositeArea.setLayout(new GridLayout(7, false)); + + // Icon for kind + iconComboKind = new Label (compositeArea, SWT.NONE); + gd = new GridData(); + gd.verticalAlignment = SWT.TOP; + gd.horizontalAlignment = SWT.RIGHT; + iconComboKind.setLayoutData(gd); + iconComboKind.setText(Messages.LanguageSettingEntryDialog_SelectKind); + int kindToComboIndex = kindToComboIndex(kind); + iconComboKind.setImage(comboKindImages[kindToComboIndex]); + + // Combo for the setting entry kind + comboKind = new ImageCombo(compositeArea, SWT.DROP_DOWN | SWT.READ_ONLY | SWT.BORDER); + for (int i = 0; i < comboKindItems.length; i++) { + comboKind.add(comboKindItems[i], comboKindImages[i]); + } + comboKind.setText(comboKindItems[kindToComboIndex]); + + comboKind.addSelectionListener(new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent e) { + updateImages(); + setButtons(); + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + + } + }); + comboKind.setEnabled(clearValue); + + // Icon for path category + final Label comboPathCategoryIcon = new Label (compositeArea, SWT.NONE); + gd = new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_END); + gd.verticalAlignment = SWT.TOP; + gd.widthHint = 15; + comboPathCategoryIcon.setLayoutData(gd); + comboPathCategoryIcon.setText(""); //$NON-NLS-1$ + + // Combo for path category + comboPathCategory = new ImageCombo(compositeArea, SWT.DROP_DOWN | SWT.READ_ONLY | SWT.BORDER); + for (int i = 0; i < pathCategories.length; i++) { + comboPathCategory.add(pathCategories[i], pathCategoryImages[i]); + } + int pcindex = COMBO_PATH_INDEX_PROJECT; + if (entry != null) { + if ((entry.getFlags() & ICSettingEntry.VALUE_WORKSPACE_PATH) == 0) { + pcindex = COMBO_PATH_INDEX_FILESYSTEM; + } else { + if (entry.getName().startsWith(SLASH)) { + pcindex = COMBO_PATH_INDEX_WORKSPACE; + } else { + pcindex = COMBO_PATH_INDEX_PROJECT; + } + } + + } + comboPathCategory.setText(pathCategories[pcindex]); + gd = new GridData(SWT.FILL, SWT.NONE, false, false); + gd.verticalAlignment = SWT.TOP; + gd.horizontalSpan = 4; + comboPathCategory.setLayoutData(gd); + + comboPathCategory.addSelectionListener(new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent e) { + updateImages(); + setButtons(); + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + + } + }); + + // Dir/File/Name label + labelInput = new Label(compositeArea, SWT.NONE); + labelInput.setText(Messages.LanguageSettingEntryDialog_Directory); + gd = new GridData(); + labelInput.setLayoutData(gd); + + // Dir/File/Name input + inputName = new Text(compositeArea, SWT.SINGLE | SWT.BORDER); + if (entry!=null && !clearValue) { + inputName.setText(entry.getName()); + } + gd = new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL); + gd.horizontalSpan = 2; + gd.widthHint = 200; + inputName.setLayoutData(gd); + inputName.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + setButtons(); + }}); + + inputName.setFocus(); + inputName.setSelection(0, inputName.getText().length()); + + // Value label + checkBoxValue = new Label(compositeArea, SWT.NONE); + checkBoxValue.setText(Messages.LanguageSettingEntryDialog_Value); + gd = new GridData(); + checkBoxValue.setLayoutData(gd); + + // Path button + buttonBrowse = new Button(compositeArea, SWT.PUSH); + buttonBrowse.setText("..."); //$NON-NLS-1$ + buttonBrowse.setImage(pathCategoryImages[0]); + buttonBrowse.setLayoutData(new GridData()); + buttonBrowse.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + buttonPressed(event); + } + }); + + // Variables button + buttonVars = new Button(compositeArea, SWT.PUSH); + buttonVars.setText(AbstractCPropertyTab.VARIABLESBUTTON_NAME); + buttonVars.setLayoutData(new GridData()); + buttonVars.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + buttonPressed(event); + } + }); + + // Value input. Located after the other controls to get sufficient width + int comboPathWidth = comboPathCategory.computeSize(SWT.DEFAULT, SWT.NONE).x; + inputValue = new Text(compositeArea, SWT.SINGLE | SWT.BORDER); + if (entry != null && !clearValue) { + inputValue.setText(entry.getValue()); + } + gd = new GridData(SWT.FILL, SWT.NONE, false, false); + gd.widthHint = comboPathWidth; + inputValue.setLayoutData(gd); + + if (entry != null && kind == ICSettingEntry.MACRO && !clearValue) { + inputValue.setFocus(); + inputValue.setSelection(0, inputValue.getText().length()); + } + + // Checkboxes + Composite compCheckboxes = new Composite (parent, SWT.NONE); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.verticalAlignment = SWT.TOP; + gd.horizontalSpan = 4; + compCheckboxes.setLayoutData(gd); + compCheckboxes.setLayout(new GridLayout(1, false)); + + // Checkbox "Built-In" + checkBoxBuiltIn = new Button(compCheckboxes, SWT.CHECK); + checkBoxBuiltIn.setText(Messages.LanguageSettingEntryDialog_BuiltInFlag); + checkBoxBuiltIn.setSelection(entry!=null && (entry.getFlags()&ICSettingEntry.BUILTIN)!=0); + gd = new GridData(GridData.FILL_HORIZONTAL); + checkBoxBuiltIn.setLayoutData(gd); + checkBoxBuiltIn.addSelectionListener(new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent e) { + updateImages(); + setButtons(); + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + } + }); + + // Checkbox "Framework" + checkBoxFramework = new Button(compCheckboxes, SWT.CHECK); + checkBoxFramework.setText(Messages.LanguageSettingEntryDialog_FrameworkFolder); + checkBoxFramework.setSelection(entry!=null && (entry.getFlags()&ICSettingEntry.FRAMEWORKS_MAC)!=0); + gd = new GridData(GridData.FILL_HORIZONTAL); + checkBoxFramework.setLayoutData(gd); + checkBoxFramework.addSelectionListener(new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent e) { + updateImages(); + setButtons(); + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + } + }); + + // Buttons + Composite compButtons = new Composite (parent, SWT.FILL); + gd = new GridData(SWT.RIGHT, SWT.BOTTOM, false, false); + gd.horizontalSpan = 4; + gd.grabExcessVerticalSpace = true; + compButtons.setLayoutData(gd); + compButtons.setLayout(new GridLayout(4, false)); + + // placeholder + Label placeholder = new Label(compButtons, 0); + placeholder.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL)); + + // Button OK + buttonOk = new Button(compButtons, SWT.PUSH); + buttonOk.setText(IDialogConstants.OK_LABEL); + gd = new GridData(); + gd.widthHint = buttonVars.computeSize(SWT.DEFAULT,SWT.NONE).x; + buttonOk.setLayoutData(gd); + buttonOk.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + buttonPressed(event); + } + }); + + // Button Cancel + buttonCancel = new Button(compButtons, SWT.PUSH); + buttonCancel.setText(IDialogConstants.CANCEL_LABEL); + gd = new GridData(); + gd.widthHint = buttonVars.computeSize(SWT.DEFAULT, SWT.NONE).x; + buttonCancel.setLayoutData(gd); + buttonCancel.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + buttonPressed(event); + } + }); + + parent.getShell().setDefaultButton(buttonOk); + parent.pack(); + + updateImages(); + setButtons(); + return parent; + } + + private void setButtons() { + int kindSelectionIndex = comboKind.getSelectionIndex(); + boolean isMacroSelected = (kindSelectionIndex == COMBO_INDEX_MACRO); + comboPathCategory.setVisible(!isMacroSelected); + buttonBrowse.setVisible(!isMacroSelected); + buttonVars.setVisible(!isMacroSelected); + checkBoxValue.setVisible(isMacroSelected); + inputValue.setVisible(isMacroSelected); + + ((GridData)checkBoxValue.getLayoutData()).exclude = !isMacroSelected; + ((GridData)inputValue.getLayoutData()).exclude = !isMacroSelected; + + ((GridData)buttonBrowse.getLayoutData()).exclude = isMacroSelected; + ((GridData)buttonVars.getLayoutData()).exclude = isMacroSelected; + + switch (kindSelectionIndex) { + case COMBO_INDEX_INCLUDE_PATH: + case COMBO_INDEX_LIBRARY_PATH: + labelInput.setText(Messages.LanguageSettingEntryDialog_Path); + break; + case COMBO_INDEX_INCLUDE_FILE: + case COMBO_INDEX_MACRO_FILE: + case COMBO_INDEX_LIBRARY_FILE: + labelInput.setText(Messages.LanguageSettingEntryDialog_File); + break; + case COMBO_INDEX_MACRO: + default: + labelInput.setText(Messages.LanguageSettingEntryDialog_Name); + } + + inputValue.setEnabled(isMacroSelected); + + int indexPathKind = comboPathCategory.getSelectionIndex(); + boolean isProjectSelected = (indexPathKind == COMBO_PATH_INDEX_PROJECT); + boolean isWorkspaceSelected = (indexPathKind == COMBO_PATH_INDEX_WORKSPACE); + boolean isFilesystemSelected = (indexPathKind == COMBO_PATH_INDEX_FILESYSTEM); + + String path = inputName.getText(); + if (path.trim().length() == 0) { + buttonOk.setEnabled(false); + } else { + buttonOk.setEnabled((isProjectSelected && !path.startsWith(SLASH)) || + (isWorkspaceSelected && path.startsWith(SLASH)) || isFilesystemSelected); + } + + buttonVars.setEnabled(isFilesystemSelected); + + compositeArea.layout(true); + } + + @Override + public void buttonPressed(SelectionEvent e) { + String str = null; + if (e.widget.equals(buttonOk)) { + String name = inputName.getText(); + text1 = name; + String value = inputValue.getText(); + result = true; + + int flagBuiltIn = checkBoxBuiltIn.getSelection() ? ICSettingEntry.BUILTIN : 0; + int flagFramework = checkBoxFramework.getSelection() ? ICSettingEntry.FRAMEWORKS_MAC : 0; + int indexPathKind = comboPathCategory.getSelectionIndex(); + int kind = comboKind.getSelectionIndex(); + boolean isProjectPath = indexPathKind==COMBO_PATH_INDEX_PROJECT; + boolean isWorkspacePath = (kind!=COMBO_INDEX_MACRO) && (isProjectPath || indexPathKind==COMBO_PATH_INDEX_WORKSPACE); + int flagWorkspace = isWorkspacePath ? ICSettingEntry.VALUE_WORKSPACE_PATH | ICSettingEntry.RESOLVED : 0; + int flags = flagBuiltIn | flagWorkspace | flagFramework; + + ICLanguageSettingEntry entry=null; + switch (comboKind.getSelectionIndex()) { + case COMBO_INDEX_INCLUDE_PATH: + entry = CDataUtil.createCIncludePathEntry(name, flags); + break; + case COMBO_INDEX_MACRO: + // note that value=null is not supported by CMacroEntry + entry = CDataUtil.createCMacroEntry(name, value, flags); + break; + case COMBO_INDEX_INCLUDE_FILE: + entry = CDataUtil.createCIncludeFileEntry(name, flags); + break; + case COMBO_INDEX_MACRO_FILE: + entry = CDataUtil.createCMacroFileEntry(name, flags); + break; + case COMBO_INDEX_LIBRARY_PATH: + entry = CDataUtil.createCLibraryPathEntry(name, flags); + break; + case COMBO_INDEX_LIBRARY_FILE: + entry = CDataUtil.createCLibraryFileEntry(name, flags); + break; + default: + result = false; + } + + entries = new ICLanguageSettingEntry[] {entry}; + shell.dispose(); + } else if (e.widget.equals(buttonCancel)) { + shell.dispose(); + } else if (e.widget.equals(buttonBrowse)) { + boolean isDirectory = false; + boolean isFile = false; + switch (comboKind.getSelectionIndex()) { + case COMBO_INDEX_INCLUDE_PATH: + case COMBO_INDEX_LIBRARY_PATH: + isDirectory = true; + break; + case COMBO_INDEX_INCLUDE_FILE: + case COMBO_INDEX_MACRO_FILE: + case COMBO_INDEX_LIBRARY_FILE: + isFile = true; + break; + case COMBO_INDEX_MACRO: + break; + } + + if (isDirectory) { + switch (comboPathCategory.getSelectionIndex()) { + case COMBO_PATH_INDEX_WORKSPACE: + str = AbstractCPropertyTab.getWorkspaceDirDialog(shell, inputName.getText()); + break; + case COMBO_PATH_INDEX_PROJECT: + str = AbstractCPropertyTab.getProjectDirDialog(shell, inputName.getText(), project); + break; + case COMBO_PATH_INDEX_FILESYSTEM: + str = AbstractCPropertyTab.getFileSystemDirDialog(shell, inputName.getText()); + break; + } + } else if (isFile) { + switch (comboPathCategory.getSelectionIndex()) { + case COMBO_PATH_INDEX_WORKSPACE: + str = AbstractCPropertyTab.getWorkspaceFileDialog(shell, inputName.getText()); + break; + case COMBO_PATH_INDEX_PROJECT: + str = AbstractCPropertyTab.getProjectFileDialog(shell, inputName.getText(), project); + break; + case COMBO_PATH_INDEX_FILESYSTEM: + str = AbstractCPropertyTab.getFileSystemFileDialog(shell, inputName.getText()); + break; + } + } + + if (str != null) { + str = strip_wsp(str); + if (comboPathCategory.getSelectionIndex()==COMBO_PATH_INDEX_PROJECT && str.startsWith(SLASH+project.getName()+SLASH)) { + str=str.substring(project.getName().length()+2); + } + inputName.setText(str); + } + } else if (e.widget.equals(buttonVars)) { + str = AbstractCPropertyTab.getVariableDialog(shell, cfgDescription); + if (str != null) inputName.insert(str); + } + } + + public ICLanguageSettingEntry[] getEntries() { + return entries; + } + + private void updateImages() { + int indexEntryKind = comboKind.getSelectionIndex(); + int indexPathKind = comboPathCategory.getSelectionIndex(); + shell.setText(Messages.LanguageSettingEntryDialog_Add + comboKindItems[indexEntryKind]); + + int kind = comboIndexToKind(indexEntryKind); + int flagBuiltin = checkBoxBuiltIn.getSelection() ? ICSettingEntry.BUILTIN : 0; + int flagFramework = checkBoxFramework.getSelection() ? ICSettingEntry.FRAMEWORKS_MAC : 0; + boolean isWorkspacePath = indexPathKind==COMBO_PATH_INDEX_PROJECT || indexPathKind==COMBO_PATH_INDEX_WORKSPACE; + int flagWorkspace = isWorkspacePath ? ICSettingEntry.VALUE_WORKSPACE_PATH | ICSettingEntry.RESOLVED : 0; + int flags = flagBuiltin | flagWorkspace | flagFramework; + Image image = LanguageSettingsImages.getImage(kind, flags, indexPathKind==COMBO_PATH_INDEX_PROJECT); + + iconComboKind.setImage(image); + shell.setImage(image); + + buttonBrowse.setImage(pathCategoryImages[indexPathKind]); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsEntriesTab.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsEntriesTab.java new file mode 100644 index 00000000000..f708569a2bb --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsEntriesTab.java @@ -0,0 +1,1134 @@ +/******************************************************************************* + * Copyright (c) 2010, 2012 Andrew Gvozdev 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: + * Andrew Gvozdev - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.language.settings.providers; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.viewers.IDecoration; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +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.Tree; +import org.eclipse.swt.widgets.TreeColumn; +import org.eclipse.swt.widgets.TreeItem; + +import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsBroadcastingProvider; +import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsEditableProvider; +import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider; +import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvidersKeeper; +import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsBaseProvider; +import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager; +import org.eclipse.cdt.core.model.ILanguage; +import org.eclipse.cdt.core.model.LanguageManager; +import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; +import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; +import org.eclipse.cdt.core.settings.model.ICResourceDescription; +import org.eclipse.cdt.core.settings.model.ICSettingEntry; +import org.eclipse.cdt.ui.CDTSharedImages; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.newui.AbstractCPropertyTab; +import org.eclipse.cdt.ui.newui.CDTPrefUtil; + +import org.eclipse.cdt.internal.ui.newui.LanguageSettingsImages; +import org.eclipse.cdt.internal.ui.newui.Messages; +import org.eclipse.cdt.internal.ui.newui.StatusMessageLine; + +/** + * This tab presents language settings entries categorized by language + * settings providers. + * + * @noinstantiate This class is not intended to be instantiated by clients. + * @noextend This class is not intended to be subclassed by clients. + */ +public class LanguageSettingsEntriesTab extends AbstractCPropertyTab { + private static final int[] DEFAULT_ENTRIES_SASH_WEIGHTS = new int[] { 10, 30 }; + + private SashForm sashFormEntries; + private Tree treeLanguages; + private Tree treeEntries; + private TreeViewer treeEntriesViewer; + private String currentLanguageId = null; + private static String currentLanguageIdGlobal = null; + + private Button builtInCheckBox; + private Button enableProvidersCheckBox; + private StatusMessageLine fStatusLine; + + private LanguageSettingsProvidersPage masterPropertyPage = null; + + private static final int BUTTON_ADD = 0; + private static final int BUTTON_EDIT = 1; + private static final int BUTTON_DELETE = 2; + // there is a separator instead of button #3 + private static final int BUTTON_MOVE_UP = 4; + private static final int BUTTON_MOVE_DOWN = 5; + + private static final String[] BUTTON_LABELS = new String[6]; + { + BUTTON_LABELS[BUTTON_ADD] = ADD_STR; + BUTTON_LABELS[BUTTON_EDIT] = EDIT_STR; + BUTTON_LABELS[BUTTON_DELETE] = DEL_STR; + BUTTON_LABELS[BUTTON_MOVE_UP] = MOVEUP_STR; + BUTTON_LABELS[BUTTON_MOVE_DOWN] = MOVEDOWN_STR; + } + + private static final String CLEAR_STR = Messages.LanguageSettingsProviderTab_Clear; + + private Map> initialProvidersMap = new HashMap>(); + + /** + * Label provider for language settings providers displayed by this tab. + */ + private class EntriesTreeLabelProvider extends LanguageSettingsProvidersLabelProvider { + @Override + protected String[] getOverlayKeys(ILanguageSettingsProvider provider) { + String[] overlayKeys = super.getOverlayKeys(provider); + + if (currentLanguageId != null) { + IResource rc = getResource(); + List entries = getSettingEntries(provider); + if (entries == null && !(rc instanceof IProject)) { + List entriesParent = getSettingEntriesUpResourceTree(provider); + if (entriesParent != null) { + overlayKeys[IDecoration.TOP_RIGHT] = CDTSharedImages.IMG_OVR_PARENT; + } + } else if (provider instanceof ILanguageSettingsBroadcastingProvider && (page.isForFile() || page.isForFolder())) { + // Assuming that the default entries for a resource are always null. + // Using that for performance reasons. See note in performDefaults(). + List entriesParent = provider.getSettingEntries(null, null, currentLanguageId); + if (entries != null && !entries.equals(entriesParent)) { + overlayKeys[IDecoration.TOP_RIGHT] = CDTSharedImages.IMG_OVR_SETTING; + } + } + } + + ICConfigurationDescription cfgDescription = getConfigurationDescription(); + List initialProviders = initialProvidersMap.get(cfgDescription.getId()); + if (initialProviders != null && !initialProviders.contains(provider)) { + overlayKeys[IDecoration.TOP_RIGHT] = CDTSharedImages.IMG_OVR_EDITED; + } + return overlayKeys; + } + + @Override + public Image getImage(Object element) { + if (element instanceof ICLanguageSettingEntry) { + ICConfigurationDescription cfgDescription = getConfigurationDescription(); + return LanguageSettingsImages.getImage((ICLanguageSettingEntry) element, cfgDescription); + } + + return super.getImage(element); + } + + @Override + public String getText(Object element) { + if (element instanceof ICLanguageSettingEntry) { + ICLanguageSettingEntry entry = (ICLanguageSettingEntry) element; + String s = entry.getName(); + if ((entry.getKind() == ICSettingEntry.MACRO) && (entry.getFlags()&ICSettingEntry.UNDEFINED) == 0) { + s = s + '=' + entry.getValue(); + } + return s; + } + + return super.getText(element); + } + } + + /** + * Content provider for setting entries tree. + */ + private class EntriesTreeContentProvider implements ITreeContentProvider { + @Override + public Object[] getElements(Object inputElement) { + return getChildren(inputElement); + } + + @Override + public Object[] getChildren(Object parentElement) { + if (parentElement instanceof Object[]) + return (Object[]) parentElement; + + if (parentElement instanceof ILanguageSettingsProvider) { + ILanguageSettingsProvider lsProvider = (ILanguageSettingsProvider)parentElement; + List entriesList = getSettingEntriesUpResourceTree(lsProvider); + if (entriesList == null) { + return null; + } + + // convert to modifiable list + entriesList = new ArrayList(entriesList); + + if (builtInCheckBox.getSelection() == false) { + for (Iterator iter = entriesList.iterator(); iter.hasNext();) { + ICLanguageSettingEntry entry = iter.next(); + if (entry.isBuiltIn()) { + iter.remove(); + } + } + } + return entriesList.toArray(); + } + + return null; + } + + @Override + public Object getParent(Object element) { + return null; + } + + @Override + public boolean hasChildren(Object element) { + Object[] children = getChildren(element); + return children!=null && children.length>0; + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + @Override + public void dispose() { + } + + } + + /** + * Shortcut for getting the current resource for the property page. + */ + private IResource getResource() { + return (IResource)page.getElement(); + } + + /** + * Shortcut for getting the current configuration description. + */ + private ICConfigurationDescription getConfigurationDescription() { + return getResDesc().getConfiguration(); + } + + /** + * Shortcut for getting the currently selected provider. + */ + private ILanguageSettingsProvider getSelectedProvider() { + ILanguageSettingsProvider provider = null; + + TreeItem[] items = treeEntries.getSelection(); + if (items.length == 1) { + TreeItem item = items[0]; + Object itemData = item.getData(); + if (itemData instanceof ICLanguageSettingEntry) { + item = item.getParentItem(); + if (item != null) { + itemData = item.getData(); + } + } + if (itemData instanceof ILanguageSettingsProvider) { + provider = (ILanguageSettingsProvider)itemData; + } + } + + return provider; + } + + /** + * Shortcut for getting the currently selected setting entry. + */ + private ICLanguageSettingEntry getSelectedEntry() { + ICLanguageSettingEntry entry = null; + + TreeItem[] items = treeEntries.getSelection(); + if (items.length == 1) { + TreeItem item = items[0]; + Object itemData = item.getData(); + if (itemData instanceof ICLanguageSettingEntry) { + entry = (ICLanguageSettingEntry)itemData; + } + } + + return entry; + } + + /** + * Shortcut for getting setting entries for current context. {@link LanguageSettingsManager} + * will be checking parent resources if no settings defined for current resource. + * + * @return list of setting entries for the current context. + */ + private List getSettingEntriesUpResourceTree(ILanguageSettingsProvider provider) { + if (currentLanguageId == null) + return null; + + ICConfigurationDescription cfgDescription = getConfigurationDescription(); + IResource rc = getResource(); + List entries = LanguageSettingsManager.getSettingEntriesUpResourceTree(provider, cfgDescription, rc, currentLanguageId); + return entries; + } + + /** + * Shortcut for getting setting entries for current context without checking the parent resource. + * @return list of setting entries for the current context. + */ + private List getSettingEntries(ILanguageSettingsProvider provider) { + if (currentLanguageId==null) + return null; + + ICConfigurationDescription cfgDescription = getConfigurationDescription(); + IResource rc = getResource(); + return provider.getSettingEntries(cfgDescription, rc, currentLanguageId); + } + + /** + * Store original providers to be able to tell whether they were changed by user. + */ + private void trackInitialSettings() { + if (!page.isForPrefs()) { + ICConfigurationDescription[] cfgDescriptions = page.getCfgsEditable(); + for (ICConfigurationDescription cfgDescription : cfgDescriptions) { + if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) { + String cfgId = cfgDescription.getId(); + List initialProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders(); + initialProvidersMap.put(cfgId, initialProviders); + } + } + } + } + + /** + * Create UI control for languages. + */ + private void createTreeForLanguages(Composite parent) { + treeLanguages = new Tree(parent, SWT.BORDER | SWT.SINGLE | SWT.H_SCROLL); + treeLanguages.setLayoutData(new GridData(GridData.FILL_VERTICAL)); + treeLanguages.setHeaderVisible(true); + + treeLanguages.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + TreeItem[] items = treeLanguages.getSelection(); + if (items.length > 0) { + currentLanguageId = (String) items[0].getData(); + currentLanguageIdGlobal = currentLanguageId; + updateTreeForEntries(); + } + } + }); + + final TreeColumn columnLanguages = new TreeColumn(treeLanguages, SWT.NONE); + columnLanguages.setText(Messages.AbstractLangsListTab_Languages); + columnLanguages.setWidth(200); + columnLanguages.setResizable(false); + columnLanguages.setToolTipText(Messages.AbstractLangsListTab_Languages); + + treeLanguages.addPaintListener(new PaintListener() { + @Override + public void paintControl(PaintEvent e) { + int x = treeLanguages.getBounds().width - 5; + if (columnLanguages.getWidth() != x) { + columnLanguages.setWidth(x); + } + } + }); + } + + /** + * Create tree for providers and their entries. + */ + private void createTreeForEntries(Composite parent) { + treeEntries = new Tree(parent, SWT.BORDER | SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL); + treeEntries.setLayoutData(new GridData(GridData.FILL_VERTICAL)); + treeEntries.setHeaderVisible(true); + treeEntries.setLinesVisible(true); + + final TreeColumn treeCol = new TreeColumn(treeEntries, SWT.NONE); + treeEntries.addPaintListener(new PaintListener() { + @Override + public void paintControl(PaintEvent e) { + int x = treeEntries.getClientArea().width; + if (treeCol.getWidth() != x) + treeCol.setWidth(x); + } + }); + + treeCol.setText(Messages.LanguageSettingsProviderTab_SettingEntries); + treeCol.setWidth(200); + treeCol.setResizable(false); + treeCol.setToolTipText(Messages.LanguageSettingsProviderTab_SettingEntriesTooltip); + + treeEntriesViewer = new TreeViewer(treeEntries); + treeEntriesViewer.setContentProvider(new EntriesTreeContentProvider()); + treeEntriesViewer.setLabelProvider(new EntriesTreeLabelProvider()); + + treeEntriesViewer.setUseHashlookup(true); + + treeEntries.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + if (treeLanguages.getSelectionCount() == 0) { + selectLanguage(currentLanguageId); + } + updateStatusLine(); + updateButtons(); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + if (buttonIsEnabled(BUTTON_EDIT) && treeEntries.getSelection().length>0) + buttonPressed(BUTTON_EDIT); + } + }); + + } + + /** + * Create sash form. + */ + private void createSashForm() { + sashFormEntries = new SashForm(usercomp,SWT.HORIZONTAL); + + GridData gd = new GridData(GridData.FILL_BOTH); + gd.horizontalSpan = 2; + gd.grabExcessVerticalSpace = true; + sashFormEntries.setLayoutData(gd); + + GridLayout layout = new GridLayout(); + sashFormEntries.setLayout(layout); + + createTreeForLanguages(sashFormEntries); + createTreeForEntries(sashFormEntries); + + sashFormEntries.setWeights(DEFAULT_ENTRIES_SASH_WEIGHTS); + } + + /** + * Create check-box to control whether to show built-in entries or not. + */ + private void createBuiltInsCheckBox() { + builtInCheckBox = setupCheck(usercomp, Messages.AbstractLangsListTab_ShowBuiltin, 1, GridData.FILL_HORIZONTAL); + builtInCheckBox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + updateTreeForEntries(); + } + }); + builtInCheckBox.setSelection(true); + builtInCheckBox.setEnabled(true); + } + + /** + * Create check-box to allow disable/enable language settings providers functionality. + */ + private void createEnableProvidersCheckBox() { + // take the flag from master page if available (normally for resource properties) + if (masterPropertyPage != null) { + enableProvidersCheckBox = setupCheck(usercomp, Messages.LanguageSettingsProviders_EnableForProject, 2, GridData.FILL_HORIZONTAL); + enableProvidersCheckBox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + boolean enabled = enableProvidersCheckBox.getSelection(); + masterPropertyPage.setLanguageSettingsProvidersEnabled(enabled); + enableTabControls(enabled); + updateStatusLine(); + } + }); + + enableProvidersCheckBox.setSelection(masterPropertyPage.isLanguageSettingsProvidersEnabled()); + + // display but disable the checkbox for file/folder resource + enableProvidersCheckBox.setEnabled(page.isForProject()); + enableTabControls(enableProvidersCheckBox.getSelection()); + } + } + + @Override + public void createControls(Composite parent) { + super.createControls(parent); + currentLanguageId = null; + + usercomp.setLayout(new GridLayout()); + GridData gd = (GridData) usercomp.getLayoutData(); + // Discourage settings entry table from trying to show all its items at once, see bug 264330 + gd.heightHint =1; + + if (page instanceof LanguageSettingsProvidersPage) { + masterPropertyPage = (LanguageSettingsProvidersPage) page; + } + + trackInitialSettings(); + + createSashForm(); + fStatusLine = new StatusMessageLine(usercomp, SWT.LEFT, 2); + createBuiltInsCheckBox(); + // "I want to try new scanner discovery" temporary checkbox + createEnableProvidersCheckBox(); + + initButtons(BUTTON_LABELS); + updateData(getResDesc()); + } + + /** + * Gray out or restore all controls except enabling check-box. + */ + private void enableTabControls(boolean enable) { + sashFormEntries.setEnabled(enable); + treeLanguages.setEnabled(enable); + treeEntries.setEnabled(enable); + builtInCheckBox.setEnabled(enable); + + buttoncomp.setEnabled(enable); + + if (enable) { + updateTreeForEntries(); + } else { + buttonSetEnabled(BUTTON_ADD, false); + buttonSetEnabled(BUTTON_EDIT, false); + buttonSetEnabled(BUTTON_DELETE, false); + buttonSetEnabled(BUTTON_MOVE_UP, false); + buttonSetEnabled(BUTTON_MOVE_DOWN, false); + } + } + + /** + * Updates state for all buttons. Called when table selection changes. + */ + @Override + protected void updateButtons() { + ILanguageSettingsProvider provider = getSelectedProvider(); + ICLanguageSettingEntry entry = getSelectedEntry(); + List entries = getSettingEntriesUpResourceTree(provider); + + boolean isEntrySelected = (entry != null); + boolean isProviderSelected = !isEntrySelected && (provider != null); + + boolean isAllowedToEdit = provider instanceof ILanguageSettingsEditableProvider + && LanguageSettingsProviderAssociationManager.isAllowedToEditEntries(provider); + + boolean isAllowedToClear = provider instanceof ILanguageSettingsEditableProvider + && LanguageSettingsProviderAssociationManager.isAllowedToClear(provider); + + boolean canAdd = isAllowedToEdit; + boolean canEdit = isAllowedToEdit && isEntrySelected; + boolean canDelete = isAllowedToEdit && isEntrySelected; + boolean canClear = isAllowedToClear && isProviderSelected && entries != null && entries.size() > 0; + + boolean canMoveUp = false; + boolean canMoveDown = false; + if (isAllowedToEdit && isEntrySelected && entries != null) { + int last = entries.size() - 1; + int pos = getExactIndex(entries, entry); + + if (pos >= 0 && pos <= last) { + canMoveUp = (pos != 0); + canMoveDown = (pos != last); + } + } + + buttonSetText(BUTTON_DELETE, isProviderSelected ? CLEAR_STR : DEL_STR); + + buttonSetEnabled(BUTTON_ADD, canAdd); + buttonSetEnabled(BUTTON_EDIT, canEdit); + buttonSetEnabled(BUTTON_DELETE, canDelete || canClear); + + buttonSetEnabled(BUTTON_MOVE_UP, canMoveUp); + buttonSetEnabled(BUTTON_MOVE_DOWN, canMoveDown); + } + + /** + * Displays warning message - if any - for selected language settings entry. + */ + private void updateStatusLine() { + IStatus status=null; + if (enableProvidersCheckBox.getSelection() == true) { + ICConfigurationDescription cfgDescription = getConfigurationDescription(); + status = LanguageSettingsImages.getStatus(getSelectedEntry(), cfgDescription); + } + if (status == null || status == Status.OK_STATUS) { + ILanguageSettingsProvider provider = getSelectedProvider(); + boolean isAllowedEditing = provider instanceof ILanguageSettingsEditableProvider + && LanguageSettingsProviderAssociationManager.isAllowedToEditEntries(provider); + if (provider != null && !isAllowedEditing) { + status = new Status(IStatus.INFO, CUIPlugin.PLUGIN_ID, Messages.LanguageSettingsEntriesTab_Entries_Not_Editable); + } + } + if (status == null || status == Status.OK_STATUS) { + if (treeLanguages.getItemCount() <= 0) { + status = new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, Messages.LanguageSettingsEntriesTab_Cannot_Determine_Languages); + } + } + fStatusLine.setErrorStatus(status); + } + + /** + * Handle buttons + */ + @Override + public void buttonPressed(int buttonIndex) { + ILanguageSettingsProvider selectedProvider = getSelectedProvider(); + ICLanguageSettingEntry selectedEntry = getSelectedEntry(); + + switch (buttonIndex) { + case BUTTON_ADD: + performAdd(selectedProvider); + break; + case BUTTON_EDIT: + performEdit(selectedProvider, selectedEntry); + break; + case BUTTON_DELETE: + performDelete(selectedProvider, selectedEntry); + break; + case BUTTON_MOVE_UP: + performMoveUp(selectedProvider, selectedEntry); + break; + case BUTTON_MOVE_DOWN: + performMoveDown(selectedProvider, selectedEntry); + break; + default: + } + treeEntries.setFocus(); + } + + /** + * That method returns exact position of an element in the list. + * Note that {@link List#indexOf(Object)} returns position of the first element + * equals to the given one, not exact element. + * + * @param entries + * @param entry + * @return exact position of the element or -1 of not found. + */ + private int getExactIndex(List entries, ICLanguageSettingEntry entry) { + if (entries != null) { + for (int i = 0; i < entries.size(); i++) { + if (entries.get(i) == entry) + return i; + } + } + return -1; + } + + /** + * Find TreeItem associated with a provider. + */ + private TreeItem findProviderItem(String id) { + TreeItem[] providerItems = treeEntries.getItems(); + for (TreeItem providerItem : providerItems) { + Object providerItemData = providerItem.getData(); + if (providerItemData instanceof ILanguageSettingsProvider) { + ILanguageSettingsProvider provider = (ILanguageSettingsProvider)providerItemData; + if (provider.getId().equals(id)) { + return providerItem; + } + } + } + return null; + } + + /** + * Find TreeItem associated with a provider's entry. + */ + private TreeItem findEntryItem(String providerId, ICLanguageSettingEntry entry) { + TreeItem[] providerItems = treeEntries.getItems(); + for (TreeItem providerItem : providerItems) { + Object providerItemData = providerItem.getData(); + if (providerItemData instanceof ILanguageSettingsProvider) { + ILanguageSettingsProvider provider = (ILanguageSettingsProvider)providerItemData; + if (provider.getId().equals(providerId)) { + TreeItem[] entryItems = providerItem.getItems(); + for (TreeItem entryItem : entryItems) { + Object entryItemData = entryItem.getData(); + if (entryItemData==entry) + return entryItem; + } + } + } + } + return null; + } + + /** + * Select language settings entry item in the tree. + */ + private void selectItem(String providerId, ICLanguageSettingEntry entry) { + TreeItem providerItem = findProviderItem(providerId); + if (providerItem != null) { + treeEntries.select(providerItem); + if (providerItem.getItems().length > 0) { + treeEntries.showItem(providerItem.getItems()[0]); + } + TreeItem entryItem = findEntryItem(providerId, entry); + if (entryItem != null) { + treeEntries.showItem(entryItem); + treeEntries.select(entryItem); + } + updateStatusLine(); + } + } + + /** + * Add language settings entry. + */ + private void addEntry(ILanguageSettingsProvider provider, ICLanguageSettingEntry entry) { + if (provider != null && entry != null) { + String providerId = provider.getId(); + + List entries = getEntriesShownToUser(provider); + ICLanguageSettingEntry selectedEntry = getSelectedEntry(); + int pos = getExactIndex(entries, selectedEntry); + entries.add(pos+1, entry); + saveEntries(provider, entries); + + updateTreeForEntries(); + selectItem(providerId, entry); + updateButtons(); + } + } + + /** + * Save entries into provider considering resource parent. + */ + private void saveEntries(ILanguageSettingsProvider provider, List entries) { + if (provider instanceof ILanguageSettingsEditableProvider) { + ICConfigurationDescription cfgDescription = getConfigurationDescription(); + IResource rc = getResource(); + if (entries != null && rc != null) { + List parentEntries = null; + if (rc instanceof IProject) { + parentEntries = new ArrayList(); + } else { + parentEntries = LanguageSettingsManager.getSettingEntriesUpResourceTree(provider, cfgDescription, rc.getParent(), currentLanguageId); + } + if (entries.equals(parentEntries)) { + // to use parent entries instead + entries = null; + } + } + ((ILanguageSettingsEditableProvider)provider).setSettingEntries(cfgDescription, rc, currentLanguageId, entries); + } + } + + /** + * Get list of setting entries shown to user. If current resource has no entries assigned the parent + * resource is inspected. + */ + private List getEntriesShownToUser(ILanguageSettingsProvider provider) { + ICConfigurationDescription cfgDescription = getConfigurationDescription(); + IResource rc = getResource(); + List entries = provider.getSettingEntries(cfgDescription, rc, currentLanguageId); + if (entries == null) { + entries = getSettingEntriesUpResourceTree(provider); + } + entries = new ArrayList(entries); + return entries; + } + + /** + * Call dialog to add settings entry. + */ + private void performAdd(ILanguageSettingsProvider selectedProvider) { + if (selectedProvider instanceof ILanguageSettingsEditableProvider) { + ICConfigurationDescription cfgDescription = getConfigurationDescription(); + ICLanguageSettingEntry selectedEntry = getSelectedEntry(); + LanguageSettingEntryDialog addDialog = new LanguageSettingEntryDialog(usercomp.getShell(), cfgDescription, selectedEntry, true); + if (addDialog.open()) { + ICLanguageSettingEntry settingEntry = addDialog.getEntries()[0]; + if (settingEntry != null) { + selectedProvider = getWorkingCopy((ILanguageSettingsEditableProvider)selectedProvider); + addEntry(selectedProvider, settingEntry); + } + } + } + } + + /** + * Return working copy of the provider to edit in current session. If the supplied provider is already + * the working copy return it. If not, create a copy to be edited. + */ + private ILanguageSettingsEditableProvider getWorkingCopy(ILanguageSettingsEditableProvider provider) { + ICConfigurationDescription cfgDescription = getConfigurationDescription(); + List initialProviders = initialProvidersMap.get(cfgDescription.getId()); + if (initialProviders.contains(provider)) { + List providers = new ArrayList(((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders()); + int pos = providers.indexOf(provider); + if (pos >= 0) { + try { + provider = provider.clone(); + providers.set(pos, provider); + ((ILanguageSettingsProvidersKeeper) cfgDescription).setLanguageSettingProviders(providers); + } catch (CloneNotSupportedException e) { + CUIPlugin.log("Internal Error: cannot clone provider "+provider.getId(), e); //$NON-NLS-1$ + } + } else { + CUIPlugin.log("Internal Error: cannot find provider "+provider.getId(), new Exception()); //$NON-NLS-1$ + } + } + return provider; + } + + /** + * Call dialog to edit settings entry. + */ + private void performEdit(ILanguageSettingsProvider selectedProvider, ICLanguageSettingEntry selectedEntry) { + if (selectedProvider instanceof ILanguageSettingsEditableProvider && selectedEntry != null) { + ICConfigurationDescription cfgDecsription = getConfigurationDescription(); + LanguageSettingEntryDialog editDialog = new LanguageSettingEntryDialog(usercomp.getShell(), cfgDecsription, selectedEntry); + if (editDialog.open()) { + ICLanguageSettingEntry newEntry = editDialog.getEntries()[0]; + if (newEntry != null) { + selectedProvider = getWorkingCopy((ILanguageSettingsEditableProvider)selectedProvider); + replaceEntry(selectedProvider, selectedEntry, newEntry); + } + } + + } + } + + /** + * Delete provider's entry and update UI. + */ + private void deleteEntry(ILanguageSettingsProvider provider, ICLanguageSettingEntry entry) { + if (provider != null && entry != null) { + String providerId = provider.getId(); + + List entries = getEntriesShownToUser(provider); + int pos = getExactIndex(entries, entry); + entries.remove(entry); + saveEntries(provider, entries); + + if (pos >= entries.size()) { + pos = entries.size() - 1; + } + ICLanguageSettingEntry entryToSelect = (pos >= 0) ? entries.get(pos) : null; + + updateTreeForEntries(); + selectItem(providerId, entryToSelect); + updateButtons(); + } + } + + /** + * Replace provider's entry and update UI. + */ + private void replaceEntry(ILanguageSettingsProvider provider, ICLanguageSettingEntry oldEntry, ICLanguageSettingEntry newEntry) { + if (provider != null && oldEntry != null && newEntry != null) { + String providerId = provider.getId(); + + List entries = getEntriesShownToUser(provider); + int pos = getExactIndex(entries, oldEntry); + entries.set(pos, newEntry); + saveEntries(provider, entries); + + updateTreeForEntries(); + selectItem(providerId, newEntry); + updateButtons(); + } + } + + /** + * Clear all provider's entries for the given resource and update UI. + */ + private void clearProvider(ILanguageSettingsProvider provider) { + if (provider != null) { + String providerId = provider.getId(); + List empty = new ArrayList(); + saveEntries(provider, empty); + + updateTreeForEntries(); + selectItem(providerId, null); + updateButtons(); + } + } + + /** + * Clear provider's entries for the given resource or remove one entry depending on selection. + */ + private void performDelete(ILanguageSettingsProvider selectedProvider, ICLanguageSettingEntry selectedEntry) { + if (selectedProvider instanceof ILanguageSettingsEditableProvider) { + selectedProvider = getWorkingCopy((ILanguageSettingsEditableProvider)selectedProvider); + if (selectedEntry != null) { + deleteEntry(selectedProvider, selectedEntry); + } else { + clearProvider(selectedProvider); + } + } + } + + /** + * Move provider's entry up or down. + */ + private void moveEntry(ILanguageSettingsProvider provider, ICLanguageSettingEntry entry, boolean up) { + if (provider != null && entry != null) { + String providerId = provider.getId(); + + List entries = getEntriesShownToUser(provider); + int pos = getExactIndex(entries, entry); + int newPos = up ? pos-1 : pos+1; + Collections.swap(entries, pos, newPos); + saveEntries(provider, entries); + + updateTreeForEntries(); + selectItem(providerId, entry); + updateButtons(); + } + } + + /** + * Move provider's entry up. + */ + private void performMoveUp(ILanguageSettingsProvider selectedProvider, ICLanguageSettingEntry selectedEntry) { + if (selectedEntry != null && (selectedProvider instanceof ILanguageSettingsEditableProvider)) { + selectedProvider = getWorkingCopy((ILanguageSettingsEditableProvider)selectedProvider); + moveEntry(selectedProvider, selectedEntry, true); + } + } + + /** + * Move provider's entry down. + */ + private void performMoveDown(ILanguageSettingsProvider selectedProvider, ICLanguageSettingEntry selectedEntry) { + if (selectedEntry != null && (selectedProvider instanceof ILanguageSettingsEditableProvider)) { + selectedProvider = getWorkingCopy((ILanguageSettingsEditableProvider)selectedProvider); + moveEntry(selectedProvider, selectedEntry, false); + } + } + + /** + * Get list of providers to display in the settings entry tree. + */ + private List getProviders(String languageSettingId) { + List itemsList = new LinkedList(); + if (currentLanguageId != null) { + IResource rc = getResource(); + ICConfigurationDescription cfgDescription = getConfigurationDescription(); + if (rc != null && cfgDescription instanceof ILanguageSettingsProvidersKeeper) { + List cfgProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders(); + for (ILanguageSettingsProvider cfgProvider : cfgProviders) { + ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(cfgProvider); + if (rawProvider instanceof LanguageSettingsBaseProvider) { + // filter out providers incapable of providing entries for this language + List languageIds = ((LanguageSettingsBaseProvider)rawProvider).getLanguageScope(); + if (languageIds != null && !languageIds.contains(currentLanguageId)) { + continue; + } + } + itemsList.add(cfgProvider); + } + } + } + return itemsList; + } + + /** + * Re-reads and refreshes the entries tree. + */ + private void updateTreeForEntries() { + List tableItems = getProviders(currentLanguageId); + treeEntriesViewer.setInput(tableItems.toArray(new Object[tableItems.size()])); + updateStatusLine(); + updateButtons(); + } + + /** + * Re-reads and refreshes the languages tree. + */ + private void updateTreeForLanguages(ICResourceDescription rcDes) { + treeLanguages.removeAll(); + currentLanguageId = null; + + List languageIds = LanguageSettingsManager.getLanguages(rcDes); + Collections.sort(languageIds); + for (String langId : languageIds) { + ILanguage language = LanguageManager.getInstance().getLanguage(langId); + if (language == null) + continue; + + String langName = language.getName(); + if (langName == null || langName.length() == 0) + continue; + + TreeItem t = new TreeItem(treeLanguages, SWT.NONE); + t.setText(0, langName); + t.setData(langId); + if (currentLanguageIdGlobal != null && currentLanguageIdGlobal.equals(langId)) { + currentLanguageId = currentLanguageIdGlobal; + treeLanguages.setSelection(t); + } else if (currentLanguageId == null) { + // this selects first language on first round + // do not select the tree item and global language selection here, only on actual click + currentLanguageId = langId; + } + } + + } + + /** + * Change selection of language. + */ + private void selectLanguage(String langId) { + currentLanguageId = langId; + currentLanguageIdGlobal = currentLanguageId; + + for (TreeItem t : treeLanguages.getItems()) { + if (t.getData().equals(langId)) { + treeLanguages.setSelection(t); + break; + } + } + } + + /** + * Update the tab. Called when configuration changes. + */ + @Override + public void updateData(ICResourceDescription rcDes) { + if (!canBeVisible()) + return; + + if (rcDes != null) { + if (page.isMultiCfg()) { + setAllVisible(false, null); + return; + } else { + setAllVisible(true, null); + } + + updateTreeForLanguages(rcDes); + updateTreeForEntries(); + + if (masterPropertyPage != null) { + boolean enabled = masterPropertyPage.isLanguageSettingsProvidersEnabled(); + enableProvidersCheckBox.setSelection(enabled); + enableTabControls(enabled); + } + } + updateButtons(); + } + + @Override + protected void performDefaults() { + // This page restores defaults for file/folder only. + // Project and Preferences page are restored by LanguageSettingsProviderTab. + if (page.isForFile() || page.isForFolder()) { + // The logic below is not exactly correct as the default for a resource could be different than null. + // It is supposed to match the one taken from extension for the same resource which in theory can be non-null. + // However for the performance reasons for resource decorators where the same logic is used + // we use null for resetting file/folder resource which should be correct in most cases. + // Count that as a feature. + ICConfigurationDescription cfgDescription = getConfigurationDescription(); + if (!(cfgDescription instanceof ILanguageSettingsProvidersKeeper)) { + return; + } + + boolean changed = false; + IResource rc = getResource(); + List oldProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders(); + List newProviders = new ArrayList(oldProviders.size()); + + // clear entries for a given resource for all languages where applicable +providers: for (ILanguageSettingsProvider provider : oldProviders) { + ILanguageSettingsEditableProvider providerCopy = null; + if (provider instanceof ILanguageSettingsEditableProvider) { + for (TreeItem langItems : treeLanguages.getItems()) { + String langId = (String)langItems.getData(); + if (langId != null) { + if (provider.getSettingEntries(cfgDescription, rc, langId) != null) { + if (providerCopy == null) { + // copy providers to be able to "Cancel" in UI + providerCopy = LanguageSettingsManager.getProviderCopy((ILanguageSettingsEditableProvider) provider, true); + if (providerCopy == null) { + continue providers; + } + } + providerCopy.setSettingEntries(cfgDescription, rc, langId, null); + changed = true; + } + } + } + } + if (providerCopy != null) { + newProviders.add(providerCopy); + } else { + newProviders.add(provider); + } + } + if (changed) { + ((ILanguageSettingsProvidersKeeper) cfgDescription).setLanguageSettingProviders(newProviders); + updateTreeForEntries(); + } + } + } + + @Override + protected void performApply(ICResourceDescription srcRcDescription, ICResourceDescription destRcDescription) { + if (!page.isForPrefs()) { + ICConfigurationDescription sd = srcRcDescription.getConfiguration(); + ICConfigurationDescription dd = destRcDescription.getConfiguration(); + if (sd instanceof ILanguageSettingsProvidersKeeper && dd instanceof ILanguageSettingsProvidersKeeper) { + List newProviders = ((ILanguageSettingsProvidersKeeper) sd).getLanguageSettingProviders(); + ((ILanguageSettingsProvidersKeeper) dd).setLanguageSettingProviders(newProviders); + } + } + + performOK(); + + trackInitialSettings(); + updateData(getResDesc()); + } + + @Override + protected void performOK() { + if (masterPropertyPage != null && enableProvidersCheckBox.getEnabled()) { + masterPropertyPage.applyLanguageSettingsProvidersEnabled(); + } + } + + @Override + public boolean canBeVisible() { + if (CDTPrefUtil.getBool(LanguageSettingsProvidersPage.KEY_NO_SHOW_PROVIDERS)) { + return false; + } + + // filter out files not associated with any languages such as *.o + if (page.isForFile()) { + List languageIds = LanguageSettingsManager.getLanguages(getResDesc()); + for (String langId : languageIds) { + ILanguage language = LanguageManager.getInstance().getLanguage(langId); + if (language != null) + return true; + } + return false; + } + + return true; + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProviderAssociationManager.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProviderAssociationManager.java new file mode 100644 index 00000000000..7cb5c087873 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProviderAssociationManager.java @@ -0,0 +1,361 @@ +/******************************************************************************* + * Copyright (c) 2010, 2012 Andrew Gvozdev 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: + * Andrew Gvozdev - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.language.settings.providers; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.Platform; + +import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider; +import org.eclipse.cdt.ui.CDTSharedImages; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.dialogs.ICOptionPage; + +/** + * This class manages extensions of extension point org.eclipse.cdt.core.LanguageSettingsProvider + * which defines appearance and behavior of UI controls for Language Settings Providers. + * + * @noextend This class is not intended to be subclassed by clients. + * @noinstantiate This class is not intended to be instantiated by clients. + */ +public class LanguageSettingsProviderAssociationManager { + /** Name of the extension point for contributing language settings provider associations */ + private static final String PROVIDER_ASSOCIATION_EXTENSION_POINT_SIMPLE_ID = "LanguageSettingsProviderAssociation"; //$NON-NLS-1$ + + private static final String ELEM_ID_ASSOCIATION = "id-association"; //$NON-NLS-1$ + private static final String ELEM_CLASS_ASSOCIATION = "class-association"; //$NON-NLS-1$ + private static final String ATTR_ID = "id"; //$NON-NLS-1$ + private static final String ATTR_CLASS = "class"; //$NON-NLS-1$ + private static final String ATTR_ICON = "icon"; //$NON-NLS-1$ + private static final String ATTR_PAGE = "page"; //$NON-NLS-1$ + private static final String ATTR_UI_CLEAR_ENTRIES = "ui-clear-entries"; //$NON-NLS-1$ + private static final String ATTR_UI_EDIT_ENTRIES = "ui-edit-entries"; //$NON-NLS-1$ + + private static boolean isLoaded = false; + private static List loadedIcons = new ArrayList(); + private static Map fImagesUrlById = new HashMap(); + private static Map fImagesUrlByClass = new HashMap(); + private static List fRegirestedIds = new ArrayList(); + private static List fRegisteredClasses = new ArrayList(); + + private static Map> fAssociationsById = new HashMap>(); + private static Map> fAssociationsByClass = new HashMap>(); + + /** + * Load extensions into memory maps. + */ + private static void loadExtensions() { + if (isLoaded) { + return; + } + isLoaded = true; + + IExtensionRegistry registry = Platform.getExtensionRegistry(); + IExtensionPoint extension = registry.getExtensionPoint(CUIPlugin.PLUGIN_ID, PROVIDER_ASSOCIATION_EXTENSION_POINT_SIMPLE_ID); + if (extension != null) { + IExtension[] extensions = extension.getExtensions(); + for (IExtension ext : extensions) { + @SuppressWarnings("unused") + String extensionID = ext.getUniqueIdentifier(); + for (IConfigurationElement cfgEl : ext.getConfigurationElements()) { + if (cfgEl.getName().equals(ELEM_ID_ASSOCIATION)) { + String id = cfgEl.getAttribute(ATTR_ID); + URL url = getIconUrl(cfgEl); + fImagesUrlById.put(id, url); + fRegirestedIds.add(id); + + Map properties = new HashMap(); + putNotEmpty(properties, ATTR_PAGE, cfgEl.getAttribute(ATTR_PAGE)); + putNotEmpty(properties, ATTR_UI_CLEAR_ENTRIES, cfgEl.getAttribute(ATTR_UI_CLEAR_ENTRIES)); + putNotEmpty(properties, ATTR_UI_EDIT_ENTRIES, cfgEl.getAttribute(ATTR_UI_EDIT_ENTRIES)); + fAssociationsById.put(id, properties); + } else if (cfgEl.getName().equals(ELEM_CLASS_ASSOCIATION)) { + String className = cfgEl.getAttribute(ATTR_CLASS); + URL url = getIconUrl(cfgEl); + fImagesUrlByClass.put(className, url); + String pageClass = cfgEl.getAttribute(ATTR_PAGE); + if (pageClass != null && pageClass.length() > 0) { + fRegisteredClasses.add(className); + } + + Map properties = new HashMap(); + putNotEmpty(properties, ATTR_PAGE, cfgEl.getAttribute(ATTR_PAGE)); + putNotEmpty(properties, ATTR_UI_CLEAR_ENTRIES, cfgEl.getAttribute(ATTR_UI_CLEAR_ENTRIES)); + putNotEmpty(properties, ATTR_UI_EDIT_ENTRIES, cfgEl.getAttribute(ATTR_UI_EDIT_ENTRIES)); + fAssociationsByClass.put(className, properties); + } + } + } + } + + } + + /** + * Put value into properties ignoring nulls. + */ + private static void putNotEmpty(Map properties, String key, String value) { + if (value != null) + properties.put(key, value); + } + + /** + * Find icon URL in its bundle. + */ + private static URL getIconUrl(IConfigurationElement config) { + URL url = null; + try { + String iconName = config.getAttribute(ATTR_ICON); + if (iconName != null) { + URL pluginInstallUrl = Platform.getBundle(config.getDeclaringExtension().getContributor().getName()).getEntry("/"); //$NON-NLS-1$ + url = new URL(pluginInstallUrl, iconName); + if (loadedIcons.contains(url)) { + return url; + } + } + } catch (MalformedURLException e) { + CUIPlugin.log(e); + } + + loadedIcons.add(url); + if (url != null) { + CDTSharedImages.register(url); + } + + return url; + } + + /** + * Get image URL for language settings provider with the given ID. + * + * @param providerId - ID of language settings provider. + * @return image URL or {@code null}. + */ + public static URL getImageUrl(String providerId) { + loadExtensions(); + return fImagesUrlById.get(providerId); + } + + /** + * Create an Options page for language settings provider with given ID. + */ + private static ICOptionPage createOptionsPageById(String providerId) { + loadExtensions(); + + if (fRegirestedIds.contains(providerId)) { + IExtensionRegistry registry = Platform.getExtensionRegistry(); + IExtensionPoint extension = registry.getExtensionPoint(CUIPlugin.PLUGIN_ID, PROVIDER_ASSOCIATION_EXTENSION_POINT_SIMPLE_ID); + if (extension != null) { + IExtension[] extensions = extension.getExtensions(); + for (IExtension ext : extensions) { + try { + @SuppressWarnings("unused") + String extensionID = ext.getUniqueIdentifier(); + for (IConfigurationElement cfgEl : ext.getConfigurationElements()) { + if (cfgEl.getName().equals(ELEM_ID_ASSOCIATION)) { + String id = cfgEl.getAttribute(ATTR_ID); + if (providerId.equals(id)) { + String pageClass = cfgEl.getAttribute(ATTR_PAGE); + if (pageClass != null && pageClass.trim().length() > 0) { + ICOptionPage page = (ICOptionPage) cfgEl.createExecutableExtension(ATTR_PAGE); + return page; + } + } + } + } + } catch (Exception e) { + CUIPlugin.log("Cannot load LanguageSettingsProviderAssociation extension " + ext.getUniqueIdentifier(), e); //$NON-NLS-1$ + } + } + } + } + return null; + } + + /** + * Create an Options page for language settings provider class by its name. + */ + private static ICOptionPage createOptionsPageByClass(String providerClassName) { + loadExtensions(); + + if (fRegisteredClasses.contains(providerClassName)) { + IExtensionRegistry registry = Platform.getExtensionRegistry(); + IExtensionPoint extension = registry.getExtensionPoint(CUIPlugin.PLUGIN_ID, PROVIDER_ASSOCIATION_EXTENSION_POINT_SIMPLE_ID); + if (extension != null) { + IExtension[] extensions = extension.getExtensions(); + for (IExtension ext : extensions) { + try { + @SuppressWarnings("unused") + String extensionID = ext.getUniqueIdentifier(); + for (IConfigurationElement cfgEl : ext.getConfigurationElements()) { + if (cfgEl.getName().equals(ELEM_CLASS_ASSOCIATION)) { + String className = cfgEl.getAttribute(ATTR_CLASS); + if (providerClassName.equals(className)) { + String pageClass = cfgEl.getAttribute(ATTR_PAGE); + if (pageClass!=null && pageClass.trim().length()>0) { + ICOptionPage page = (ICOptionPage) cfgEl.createExecutableExtension(ATTR_PAGE); + return page; + } + } + } + } + } catch (Exception e) { + CUIPlugin.log("Cannot load LanguageSettingsProviderAssociation extension " + ext.getUniqueIdentifier(), e); //$NON-NLS-1$ + } + } + } + } + return null; + } + + /** + * Returns Language Settings Provider image registered for closest superclass + * or interface. + * + * @param providerClass - class to find Language Settings Provider image. + * @return image or {@code null} + */ + public static URL getImage(Class providerClass) { + URL url = null; + + outer: for (Class c = providerClass; c != null; c = c.getSuperclass()) { + url = getImageURL(c); + if (url != null) { + break; + } + + // this does not check for super-interfaces, feel free to implement as needed + for (Class i : c.getInterfaces()) { + url = getImageURL(i); + if (url != null) { + break outer; + } + } + } + return url; + } + + /** + * Return image URL registered for the given class. + */ + private static URL getImageURL(Class clazz) { + String className = clazz.getCanonicalName(); + for (Entry entry : fImagesUrlByClass.entrySet()) { + if (entry.getKey().equals(className)) { + return entry.getValue(); + } + } + return null; + } + + /** + * Returns language settings provider Options page registered for closest superclass. + * + * @param provider - instance of provider to create Options page for. + * @return image or {@code null}. + */ + public static ICOptionPage createOptionsPage(ILanguageSettingsProvider provider) { + String id = provider.getId(); + ICOptionPage optionsPage = createOptionsPageById(id); + if (optionsPage != null) { + return optionsPage; + } + + Class clazz = provider.getClass(); + outer: for (Class c = clazz ;c != null; c = c.getSuperclass()) { + optionsPage = createOptionsPageByClass(c); + if (optionsPage != null) { + break; + } + + // this does not check for super-interfaces, feel free to implement as needed + for (Class i : c.getInterfaces()) { + optionsPage = createOptionsPageByClass(i); + if (optionsPage != null) { + break outer; + } + } + } + return optionsPage; + } + + /** + * Create an Options page for language settings provider class. + */ + private static ICOptionPage createOptionsPageByClass(Class clazz) { + ICOptionPage optionsPage = null; + String className = clazz.getCanonicalName(); + if (fRegisteredClasses.contains(className)) { + optionsPage = createOptionsPageByClass(className); + } + return optionsPage; + } + + /** + * Returns value of the attribute of the provider by id or closest superclass. + */ + private static boolean getBooleanAttribute(ILanguageSettingsProvider provider, String attr) { + loadExtensions(); + + String id = provider.getId(); + + Map properties = fAssociationsById.get(id); + if (properties != null) { + return Boolean.parseBoolean(properties.get(attr)); + } + + for (Class c = provider.getClass();c != null; c = c.getSuperclass()) { + String className = c.getCanonicalName(); + properties = fAssociationsByClass.get(className); + if (properties != null) { + return Boolean.parseBoolean(properties.get(attr)); + } + + // this does not check for superinterfaces, feel free to implement as needed + for (Class i : c.getInterfaces()) { + String interfaceName = i.getCanonicalName(); + properties = fAssociationsByClass.get(interfaceName); + if (properties != null) { + return Boolean.parseBoolean(properties.get(attr)); + } + } + } + return false; + } + + /** + * Check if the user is allowed to edit language settings provider entries in UI. + * @param provider - language settings provider. + * @return {@code true} if editing is allowed or {@code false} if not. + */ + public static boolean isAllowedToEditEntries(ILanguageSettingsProvider provider) { + return getBooleanAttribute(provider, ATTR_UI_EDIT_ENTRIES); + } + + /** + * Check if the user is allowed to clear language settings provider entries in UI. + * @param provider - language settings provider. + * @return {@code true} if clearing is allowed or {@code false} if not. + */ + public static boolean isAllowedToClear(ILanguageSettingsProvider provider) { + return getBooleanAttribute(provider, ATTR_UI_CLEAR_ENTRIES); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProviderTab.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProviderTab.java new file mode 100644 index 00000000000..0e81a9b7663 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProviderTab.java @@ -0,0 +1,1171 @@ +/******************************************************************************* + * Copyright (c) 2010, 2011 Andrew Gvozdev 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: + * Andrew Gvozdev - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.language.settings.providers; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.CheckStateChangedEvent; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ICheckStateListener; +import org.eclipse.jface.viewers.IDecoration; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +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.Event; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Link; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Table; +import org.eclipse.ui.dialogs.PreferencesUtil; + +import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsEditableProvider; +import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider; +import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvidersKeeper; +import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager; +import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsSerializableProvider; +import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; +import org.eclipse.cdt.core.settings.model.ICResourceDescription; +import org.eclipse.cdt.ui.CDTSharedImages; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.dialogs.ICOptionPage; +import org.eclipse.cdt.ui.language.settings.providers.AbstractLanguageSettingProviderOptionPage; +import org.eclipse.cdt.ui.newui.AbstractCPropertyTab; +import org.eclipse.cdt.ui.newui.CDTPrefUtil; +import org.eclipse.cdt.utils.ui.controls.TabFolderLayout; + +import org.eclipse.cdt.internal.ui.newui.Messages; +import org.eclipse.cdt.internal.ui.newui.StatusMessageLine; + +/** + * This tab presents language settings entries categorized by language + * settings providers. + * + *@noinstantiate This class is not intended to be instantiated by clients. + *@noextend This class is not intended to be subclassed by clients. + */ +public class LanguageSettingsProviderTab extends AbstractCPropertyTab { + private static final String WORKSPACE_PREFERENCE_PAGE = "org.eclipse.cdt.ui.preferences.BuildSettingProperties"; //$NON-NLS-1$ + private static final String TEST_PLUGIN_ID_PATTERN = "org.eclipse.cdt.*.tests.*"; //$NON-NLS-1$ + + private static final String CLEAR_STR = Messages.LanguageSettingsProviderTab_Clear; + private static final String RESET_STR = Messages.LanguageSettingsProviderTab_Reset; + + private static final int BUTTON_CLEAR = 0; + private static final int BUTTON_RESET = 1; + // there is a separator instead of button #2 + private static final int BUTTON_MOVE_UP = 3; + private static final int BUTTON_MOVE_DOWN = 4; + + private static final int[] DEFAULT_CONFIGURE_SASH_WEIGHTS = new int[] { 50, 50 }; + private SashForm sashFormProviders; + + private Table tableProviders; + private CheckboxTableViewer tableProvidersViewer; + private Group groupOptionsPage; + private ICOptionPage currentOptionsPage = null; + private Composite compositeOptionsPage; + + private Button enableProvidersCheckBox; + private StatusMessageLine fStatusLine; + + private Button sharedProviderCheckBox = null; + private Link linkToWorkspacePreferences = null; + private Button projectStorageCheckBox = null; + + private LanguageSettingsProvidersPage masterPropertyPage = null; + + /** + * List of providers presented to the user. + * For global providers included in a configuration this contains references + * not raw providers. + */ + private List presentedProviders = null; + private final Map optionsPageMap = new HashMap(); + private Map> initialProvidersByCfg = new HashMap>(); + + /** + * Label provider for language settings providers displayed by this tab. + */ + private class ProvidersTableLabelProvider extends LanguageSettingsProvidersLabelProvider { + @Override + protected String[] getOverlayKeys(ILanguageSettingsProvider provider) { + if (provider.getName() == null) { + String[] overlayKeys = new String[5]; + overlayKeys[IDecoration.TOP_RIGHT] = CDTSharedImages.IMG_OVR_ERROR; + return overlayKeys; + } + + String[] overlayKeys = super.getOverlayKeys(provider); + + if (page.isForProject()) { + if (isEditedForProject(provider)) { + overlayKeys[IDecoration.TOP_RIGHT] = CDTSharedImages.IMG_OVR_EDITED; + } else if (!LanguageSettingsManager.getExtensionProviderIds().contains(provider.getId())) { + overlayKeys[IDecoration.TOP_RIGHT] = CDTSharedImages.IMG_OVR_USER; + } else if (isReconfiguredForProject(provider)) { + overlayKeys[IDecoration.TOP_RIGHT] = CDTSharedImages.IMG_OVR_SETTING; + } + } else if (page.isForPrefs()) { + if (isWorkingCopy(provider) && !provider.equals(LanguageSettingsManager.getRawProvider(LanguageSettingsManager.getWorkspaceProvider(provider.getId())))) { + overlayKeys[IDecoration.TOP_RIGHT] = CDTSharedImages.IMG_OVR_EDITED; + } else if (!LanguageSettingsManager.getExtensionProviderIds().contains(provider.getId())) { + overlayKeys[IDecoration.TOP_RIGHT] = CDTSharedImages.IMG_OVR_USER; + } else { + ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(provider); + if (rawProvider instanceof ILanguageSettingsEditableProvider && !LanguageSettingsManager.isEqualExtensionProvider(rawProvider, false)) { + overlayKeys[IDecoration.TOP_RIGHT] = CDTSharedImages.IMG_OVR_SETTING; + } + } + } + + return overlayKeys; + } + + @Override + public String getText(Object element) { + if (element instanceof ILanguageSettingsProvider) { + ILanguageSettingsProvider provider = (ILanguageSettingsProvider) element; + String name = provider.getName(); + if (name != null && (page.isForPrefs() || isPresentedAsShared(provider))) { + return name + Messages.LanguageSettingsProvidersLabelProvider_TextDecorator_Shared; + } + } + return super.getText(element); + } + } + + /** + * Returns the provider which is being presented to the user in UI. + * Used by option pages when there is a need. + * Warning: Do not cache the result as the provider can be replaced at any time. + * @param id - id of the provider. + * + * @return the provider. + */ + public ILanguageSettingsProvider getProvider(String id) { + return findProvider(id, presentedProviders); + } + + /** + * Check if the provider is a working copy and can be modified. + */ + private boolean isWorkingCopy(ILanguageSettingsProvider provider) { + boolean isWorkingCopy = false; + if (page.isForPrefs()) { + isWorkingCopy = ! LanguageSettingsManager.isWorkspaceProvider(provider); + } else { + if (!LanguageSettingsManager.isWorkspaceProvider(provider)) { + ICConfigurationDescription cfgDescription = getConfigurationDescription(); + List initialProviders = initialProvidersByCfg.get(cfgDescription.getId()); + isWorkingCopy = ! initialProviders.contains(provider); + } + + } + return isWorkingCopy; + } + + /** + * Returns current working copy of the provider. Creates one if it has not been created yet. + * A working copy will be discarded if user pushes [Cancel] or it will replace original + * provider on [Apply] or [OK]. + * + * This method is used also by option pages when there is a need to modify the provider. + * Warning: Do not cache the result as the provider can be replaced at any time. + * + * @param id - id of the provider. + * @return working copy of the provider. + */ + public ILanguageSettingsProvider getWorkingCopy(String id) { + ILanguageSettingsProvider provider = findProvider(id, presentedProviders); + if (isWorkingCopy(provider)) { + return provider; + } + + ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(provider); + ILanguageSettingsEditableProvider newProvider = LanguageSettingsManager.getProviderCopy((ILanguageSettingsEditableProvider)rawProvider, true); + if (newProvider != null) { + replaceSelectedProvider(newProvider); + // Warning: Do not initializeOptionsPage() here as the method can be called from an existing page + } + + return newProvider; + } + + /** + * Refresh provider item in the table and update buttons. + * This method is intended for use by an Options Page of the provider. + * + * @param provider - provider item in the table to refresh. + */ + public void refreshItem(ILanguageSettingsProvider provider) { + tableProvidersViewer.refresh(provider); + updateButtons(); + } + + /** + * Check if provider should get "reconfigured" overlay in UI. + */ + private boolean isReconfiguredForProject(ILanguageSettingsProvider provider) { + String id = provider.getId(); + + ICConfigurationDescription cfgDescription = getConfigurationDescription(); + String[] defaultIds = ((ILanguageSettingsProvidersKeeper) cfgDescription).getDefaultLanguageSettingsProvidersIds(); + List providers = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders(); + + // check for the provider mismatch in configuration list vs. default list from the tool-chain + if (defaultIds != null && (Arrays.asList(defaultIds).contains(id) != providers.contains(provider))) { + return true; + } + + // check if provider belongs to configuration (i.e. checked in the table) + if (!providers.contains(provider)) { + return false; + } + + // check if "shared" flag matches default shared preference from extension point definition + if (LanguageSettingsManager.isPreferShared(id) != LanguageSettingsManager.isWorkspaceProvider(provider)) { + return true; + } + + // check if configuration provider equals to the default one from extension point + if (!LanguageSettingsManager.isWorkspaceProvider(provider) && !LanguageSettingsManager.isEqualExtensionProvider(provider, false)) { + return true; + } + + return false; + } + + /** + * Check if provider should get "edited" overlay in UI. + */ + private boolean isEditedForProject(ILanguageSettingsProvider provider) { + String id = provider.getId(); + ICConfigurationDescription cfgDescription = getConfigurationDescription(); + List initialProviders = initialProvidersByCfg.get(cfgDescription.getId()); + List providers = getCheckedProviders(); + + // check for the provider mismatch in configuration list vs. initial list + ILanguageSettingsProvider initialProvider = findProvider(id, initialProviders); + if ((initialProvider != null) != providers.contains(provider)) { + return true; + } + + // check if "shared" flag matches that of initial provider + if (providers.contains(provider) && LanguageSettingsManager.isWorkspaceProvider(initialProvider) != LanguageSettingsManager.isWorkspaceProvider(provider)) { + return true; + } + + // check if configuration provider equals to the initial one + if (!LanguageSettingsManager.isWorkspaceProvider(provider) && !provider.equals(initialProvider)) { + return true; + } + + return false; + } + + /** + * Checks if the provider should be presented as shared. Unchecked providers are shown as non-shared + * if they are defined as non-shared in extension point even if in fact shared instance is used to display + * the options page. + */ + private boolean isPresentedAsShared(ILanguageSettingsProvider provider) { + ICConfigurationDescription cfgDescription = getConfigurationDescription(); + List providers = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders(); + return LanguageSettingsManager.isWorkspaceProvider(provider) && + ( providers.contains(provider) || LanguageSettingsManager.isPreferShared(provider.getId()) ); + } + + /** + * Find provider with a given ID in the list or {@code null}. + */ + private ILanguageSettingsProvider findProvider(String id, List providers) { + for (ILanguageSettingsProvider provider : providers) { + if (provider.getId().equals(id)) { + return provider; + } + } + return null; + } + + /** + * Shortcut for getting the currently selected provider. + * Do not use if you need to change provider's settings or entries, use {@link #getWorkingCopy(String)}. + */ + private ILanguageSettingsProvider getSelectedProvider() { + ILanguageSettingsProvider provider = null; + + int pos = tableProviders.getSelectionIndex(); + if (pos >= 0 && pos < tableProviders.getItemCount()) { + provider = (ILanguageSettingsProvider)tableProvidersViewer.getElementAt(pos); + } + return provider; + } + + /** + * Shortcut for getting the current configuration description. + */ + private ICConfigurationDescription getConfigurationDescription() { + if (page.isForPrefs()) { + return null; + } + + return getResDesc().getConfiguration(); + } + + /** + * Get the list of providers checked in the table in UI. + * @return + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + private List getCheckedProviders() { + return (List)Arrays.asList(tableProvidersViewer.getCheckedElements()); + } + + /** + * Replace the selected provider in UI and in configuration. + */ + private void replaceSelectedProvider(ILanguageSettingsProvider newProvider) { + int pos = tableProviders.getSelectionIndex(); + boolean isChecked = tableProvidersViewer.getChecked(tableProvidersViewer.getElementAt(pos)); + + presentedProviders.set(pos, newProvider); + tableProvidersViewer.refresh(); + tableProvidersViewer.setChecked(newProvider, isChecked); + tableProviders.setSelection(pos); + tableProvidersViewer.refresh(newProvider); + + saveCheckedProviders(); + } + + /** + * Save checked providers from UI table into configuration. + */ + private void saveCheckedProviders() { + ICConfigurationDescription cfgDescription = getConfigurationDescription(); + if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) { + ((ILanguageSettingsProvidersKeeper) cfgDescription).setLanguageSettingProviders(getCheckedProviders()); + } + } + + /** + * Store original providers to be able to tell whether they were changed by user. + */ + private void trackInitialSettings() { + if (!page.isForPrefs()) { + ICConfigurationDescription[] cfgDescriptions = page.getCfgsEditable(); + for (ICConfigurationDescription cfgDescription : cfgDescriptions) { + if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) { + String cfgId = cfgDescription.getId(); + List initialProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders(); + initialProvidersByCfg.put(cfgId, initialProviders); + } + } + } + } + + /** + * Create table to display providers. + */ + private void createProvidersPane(Composite parent) { + Composite composite = new Composite(parent, SWT.BORDER | SWT.SINGLE); + composite.setLayout(new GridLayout()); + + // items checkboxes only for project properties page + tableProviders = new Table(composite, page.isForPrefs() ? SWT.NONE : SWT.CHECK); + tableProviders.setLayoutData(new GridData(GridData.FILL_BOTH)); + tableProviders.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + displaySelectedOptionPage(); + updateButtons(); + } + }); + tableProvidersViewer = new CheckboxTableViewer(tableProviders); + tableProvidersViewer.setContentProvider(new ArrayContentProvider()); + tableProvidersViewer.setLabelProvider(new ProvidersTableLabelProvider()); + + tableProvidersViewer.addCheckStateListener(new ICheckStateListener() { + @Override + public void checkStateChanged(CheckStateChangedEvent event) { + ILanguageSettingsProvider checkedProvider = (ILanguageSettingsProvider) event.getElement(); + String id = checkedProvider.getId(); + ILanguageSettingsProvider newProvider = null; + + if (event.getChecked()) { + if (LanguageSettingsManager.isWorkspaceProvider(checkedProvider) && !LanguageSettingsManager.isPreferShared(id)) { + ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(checkedProvider); + if (rawProvider instanceof ILanguageSettingsEditableProvider) { + newProvider = LanguageSettingsManager.getProviderCopy((ILanguageSettingsEditableProvider) rawProvider, false); + } + } + } else { + if (!LanguageSettingsManager.isWorkspaceProvider(checkedProvider)) { + newProvider = LanguageSettingsManager.getWorkspaceProvider(id); + } + } + + int pos = presentedProviders.indexOf(checkedProvider); + tableProviders.setSelection(pos); + + if (newProvider != null) { + replaceSelectedProvider(newProvider); // will refresh and save checked providers + createOptionsPage(newProvider); + } else { + tableProvidersViewer.refresh(checkedProvider); + saveCheckedProviders(); + // option page is reused + } + + displaySelectedOptionPage(); + updateButtons(); + } + }); + } + + /** + * Change "globality" of a provider. + */ + private ILanguageSettingsProvider toggleGlobalProvider(ILanguageSettingsProvider provider, boolean toGlobal) { + ILanguageSettingsProvider newProvider = null; + + String id = provider.getId(); + if (toGlobal) { + newProvider = LanguageSettingsManager.getWorkspaceProvider(id); + } else { + // Toggle to configuration-owned provider + try { + ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(provider); + if (rawProvider instanceof ILanguageSettingsEditableProvider) { + newProvider = ((ILanguageSettingsEditableProvider) rawProvider).cloneShallow(); + } + } catch (CloneNotSupportedException e) { + CUIPlugin.log("Error cloning provider " + id, e); //$NON-NLS-1$ + } + } + if (newProvider != null) { + replaceSelectedProvider(newProvider); + createOptionsPage(newProvider); + displaySelectedOptionPage(); + updateButtons(); + } else { + newProvider = provider; + } + + return newProvider; + } + + /** + * Create a check-box for "shared" or "global" property of a provider. + */ + private void createSharedProviderCheckBox(Composite parent) { + sharedProviderCheckBox = new Button(parent, SWT.CHECK); + sharedProviderCheckBox.setText(Messages.LanguageSettingsProviderTab_ShareProviders); + sharedProviderCheckBox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + boolean isGlobal = sharedProviderCheckBox.getSelection(); + ILanguageSettingsProvider provider = getSelectedProvider(); + if (isGlobal != LanguageSettingsManager.isWorkspaceProvider(provider)) { + // globality changed + provider = toggleGlobalProvider(provider, isGlobal); + } + projectStorageCheckBox.setSelection(provider instanceof LanguageSettingsSerializableProvider + && LanguageSettingsManager.isStoringEntriesInProjectArea((LanguageSettingsSerializableProvider) provider)); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + } + }); + } + + /** + * Create a check-box defining where to store entries of a provider. + */ + private void createProjectStorageCheckBox(Composite parent) { + projectStorageCheckBox = new Button(parent, SWT.CHECK); + projectStorageCheckBox.setText(Messages.LanguageSettingsProviderTab_StoreEntriesInsideProject); + projectStorageCheckBox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + boolean inProjectArea = projectStorageCheckBox.getSelection(); + ILanguageSettingsProvider newProvider = getWorkingCopy(getSelectedProvider().getId()); + LanguageSettingsManager.setStoringEntriesInProjectArea((LanguageSettingsSerializableProvider) newProvider, inProjectArea); + replaceSelectedProvider(newProvider); + createOptionsPage(newProvider); + displaySelectedOptionPage(); + updateButtons(); + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + } + }); + } + + /** + * Create a link to Preferences page. + */ + private void createLinkToPreferences(final Composite parent, int span) { + linkToWorkspacePreferences = new Link(parent, SWT.NONE); + String href = NLS.bind("{0}", Messages.LanguageSettingsProviderTab_WorkspaceSettings); //$NON-NLS-1$ + linkToWorkspacePreferences.setText(NLS.bind(Messages.LanguageSettingsProviderTab_OptionsCanBeChangedInPreferencesDiscoveryTab, href)); + GridData gd = new GridData(); + gd.horizontalSpan = span; + linkToWorkspacePreferences.setLayoutData(gd); + + linkToWorkspacePreferences.addListener(SWT.Selection, new Listener() { + @Override + public void handleEvent(Event event) { + // Use event.text to tell which link was used + PreferencesUtil.createPreferenceDialogOn(parent.getShell(), WORKSPACE_PREFERENCE_PAGE, null, null).open(); + } + }); + } + + /** + * Create Options pane. + */ + private void createOptionsPane(Composite parent) { + groupOptionsPage = new Group(parent, SWT.SHADOW_ETCHED_IN); + groupOptionsPage.setText(Messages.LanguageSettingsProviderTab_LanguageSettingsProvidersOptions); + groupOptionsPage.setLayout(new GridLayout(2, false)); + + if (!page.isForPrefs()) { + createSharedProviderCheckBox(groupOptionsPage); + createProjectStorageCheckBox(groupOptionsPage); + createLinkToPreferences(groupOptionsPage, 2); + } + + compositeOptionsPage = new Composite(groupOptionsPage, SWT.NONE); + compositeOptionsPage.setLayout(new TabFolderLayout()); + } + + /** + * Create sash form. + */ + private void createSashForm() { + sashFormProviders = new SashForm(usercomp, SWT.VERTICAL); + GridLayout layout = new GridLayout(); + sashFormProviders.setLayout(layout); + GridData gd = new GridData(GridData.FILL_BOTH); + gd.horizontalSpan = 2; + sashFormProviders.setLayoutData(gd); + + createProvidersPane(sashFormProviders); + createOptionsPane(sashFormProviders); + + sashFormProviders.setWeights(DEFAULT_CONFIGURE_SASH_WEIGHTS); + } + + /** + * Gray out or restore all controls except enabling check-box. + */ + private void enableTabControls(boolean enable) { + sashFormProviders.setEnabled(enable); + tableProviders.setEnabled(enable); + compositeOptionsPage.setEnabled(enable); + + buttoncomp.setEnabled(enable); + + if (enable) { + displaySelectedOptionPage(); + } else { + if (currentOptionsPage != null) { + currentOptionsPage.setVisible(false); + } + + buttonSetEnabled(BUTTON_CLEAR, false); + buttonSetEnabled(BUTTON_RESET, false); + buttonSetEnabled(BUTTON_MOVE_UP, false); + buttonSetEnabled(BUTTON_MOVE_DOWN, false); + } + } + + /** + * Create check-box to allow disable/enable language settings providers functionality. + */ + private void createEnableProvidersCheckBox() { + // take the flag from master page if available (normally for resource properties) + if (masterPropertyPage != null) { + enableProvidersCheckBox = setupCheck(usercomp, Messages.LanguageSettingsProviders_EnableForProject, 2, GridData.FILL_HORIZONTAL); + enableProvidersCheckBox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + boolean enabled = enableProvidersCheckBox.getSelection(); + masterPropertyPage.setLanguageSettingsProvidersEnabled(enabled); + enableTabControls(enabled); + } + }); + + enableProvidersCheckBox.setSelection(masterPropertyPage.isLanguageSettingsProvidersEnabled()); + + // display but disable the checkbox for file/folder resource + enableProvidersCheckBox.setEnabled(page.isForProject()); + enableTabControls(enableProvidersCheckBox.getSelection()); + } + } + + @Override + public void createControls(Composite parent) { + super.createControls(parent); + + usercomp.setLayout(new GridLayout()); + GridData gd = (GridData) usercomp.getLayoutData(); + // Discourage settings entry table from trying to show all its items at once, see bug 264330 + gd.heightHint = 1; + + if (page instanceof LanguageSettingsProvidersPage) { + masterPropertyPage = (LanguageSettingsProvidersPage) page; + } + + trackInitialSettings(); + + createSashForm(); + + fStatusLine = new StatusMessageLine(usercomp, SWT.LEFT, 2); + if (!page.isForPrefs()) { + createEnableProvidersCheckBox(); + } + + String[] buttonLabels; + if (page.isForPrefs()) { + buttonLabels = new String[2]; + buttonLabels[BUTTON_CLEAR] = CLEAR_STR; + buttonLabels[BUTTON_RESET] = RESET_STR; + } else { + buttonLabels = new String[5]; + buttonLabels[BUTTON_CLEAR] = CLEAR_STR; + buttonLabels[BUTTON_RESET] = RESET_STR; + buttonLabels[BUTTON_MOVE_UP] = MOVEUP_STR; + buttonLabels[BUTTON_MOVE_DOWN] = MOVEDOWN_STR; + } + initButtons(buttonLabels); + + updateData(getResDesc()); + } + + /** + * Clear entries of the selected provider. + */ + private void performClear(ILanguageSettingsProvider selectedProvider) { + if (isWorkingCopy(selectedProvider)) { + if (selectedProvider instanceof LanguageSettingsSerializableProvider) { + LanguageSettingsSerializableProvider editableProvider = (LanguageSettingsSerializableProvider) selectedProvider; + editableProvider.clear(); + tableProvidersViewer.update(selectedProvider, null); + } + } else { + ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(selectedProvider); + if (rawProvider instanceof ILanguageSettingsEditableProvider) { + ILanguageSettingsEditableProvider newProvider = LanguageSettingsManager.getProviderCopy((ILanguageSettingsEditableProvider) rawProvider, false); + if (newProvider != null) { + replaceSelectedProvider(newProvider); + createOptionsPage(newProvider); + displaySelectedOptionPage(); + } + } + } + updateButtons(); + } + + /** + * Reset settings of the selected provider. + */ + private void performReset(ILanguageSettingsProvider selectedProvider) { + String id = selectedProvider.getId(); + + ILanguageSettingsProvider newProvider = null; + if (page.isForPrefs()) { + newProvider = LanguageSettingsManager.getExtensionProviderCopy(id, true); + if (newProvider == null) { + Status status = new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, IStatus.ERROR, Messages.GeneralMessages_InternalError_ReportLogToCdtTeam, + new Exception("Internal Error getting copy of provider id="+id)); //$NON-NLS-1$ + fStatusLine.setErrorStatus(status); + CUIPlugin.log(status); + } + } else { + ICConfigurationDescription cfgDescription = getConfigurationDescription(); + String[] defaultIds = ((ILanguageSettingsProvidersKeeper) cfgDescription).getDefaultLanguageSettingsProvidersIds(); + boolean isDefault = Arrays.asList(defaultIds).contains(id); + if (isDefault && !LanguageSettingsManager.isPreferShared(id)) { + newProvider = LanguageSettingsManager.getExtensionProviderCopy(id, true); + if (newProvider == null) { + Status status = new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, IStatus.ERROR, Messages.GeneralMessages_InternalError_ReportLogToCdtTeam, + new Exception("Internal Error getting copy of provider id="+id)); //$NON-NLS-1$ + fStatusLine.setErrorStatus(status); + CUIPlugin.log(status); + } + } else { + newProvider = LanguageSettingsManager.getWorkspaceProvider(id); + } + tableProvidersViewer.setChecked(selectedProvider, isDefault); + } + + if (newProvider != null) { + replaceSelectedProvider(newProvider); + createOptionsPage(newProvider); + displaySelectedOptionPage(); + updateButtons(); + } + } + + /** + * Move selected provider in the table. + */ + private void moveProvider(int oldPos, int newPos) { + Collections.swap(presentedProviders, oldPos, newPos); + tableProvidersViewer.refresh(); + tableProviders.showSelection(); + + saveCheckedProviders(); + updateButtons(); + } + + /** + * Move selected provider up. + */ + private void performMoveUp(ILanguageSettingsProvider selectedProvider) { + int pos = presentedProviders.indexOf(selectedProvider); + if (pos > 0) { + moveProvider(pos, pos-1); + } + } + + /** + * Move selected provider down. + */ + private void performMoveDown(ILanguageSettingsProvider selectedProvider) { + int pos = presentedProviders.indexOf(selectedProvider); + int last = presentedProviders.size() - 1; + if (pos >= 0 && pos < last) { + moveProvider(pos, pos+1); + } + } + + /** + * Handle pressed buttons. + */ + @Override + public void buttonPressed(int buttonIndex) { + ILanguageSettingsProvider selectedProvider = getSelectedProvider(); + + switch (buttonIndex) { + case BUTTON_CLEAR: + performClear(selectedProvider); + break; + case BUTTON_RESET: + performReset(selectedProvider); + break; + case BUTTON_MOVE_UP: + performMoveUp(selectedProvider); + break; + case BUTTON_MOVE_DOWN: + performMoveDown(selectedProvider); + break; + default: + } + } + + /** + * Updates state for all buttons. + */ + @Override + protected void updateButtons() { + ILanguageSettingsProvider provider = getSelectedProvider(); + boolean isProviderSelected = provider != null; + boolean canForWorkspace = isProviderSelected && page.isForPrefs(); + boolean canForProject = isProviderSelected && page.isForProject(); + + int pos = tableProviders.getSelectionIndex(); + int count = tableProviders.getItemCount(); + int last = count - 1; + boolean isRangeOk = (pos >= 0 && pos <= last); + + ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(provider); + boolean isAllowedClearing = rawProvider instanceof ILanguageSettingsEditableProvider && rawProvider instanceof LanguageSettingsSerializableProvider + && LanguageSettingsProviderAssociationManager.isAllowedToClear(rawProvider); + + boolean canClear = isAllowedClearing && (canForWorkspace || (canForProject && !LanguageSettingsManager.isWorkspaceProvider(provider))); + if (rawProvider instanceof LanguageSettingsSerializableProvider) { + canClear = canClear && !((LanguageSettingsSerializableProvider)rawProvider).isEmpty(); + } + + boolean canResetForProject = canForProject && isReconfiguredForProject(provider); + boolean canResetForWorkspace = canForWorkspace && + (rawProvider instanceof ILanguageSettingsEditableProvider + && !LanguageSettingsManager.isEqualExtensionProvider(rawProvider, false)) + && ( LanguageSettingsManager.getExtensionProviderIds().contains(rawProvider.getId()) ); + boolean canReset = canResetForProject || canResetForWorkspace; + + boolean canMoveUp = canForProject && isRangeOk && pos != 0; + boolean canMoveDown = canForProject && isRangeOk && pos != last; + + buttonSetEnabled(BUTTON_CLEAR, canClear); + buttonSetEnabled(BUTTON_RESET, canReset); + buttonSetEnabled(BUTTON_MOVE_UP, canMoveUp); + buttonSetEnabled(BUTTON_MOVE_DOWN, canMoveDown); + } + + /** + * Sort providers displayed in UI. Sorting is by name except test providers are shown + * on bottom. + */ + private void sortByName(List providers) { + // ensure sorting by name all unchecked providers + Collections.sort(providers, new Comparator() { + @Override + public int compare(ILanguageSettingsProvider prov1, ILanguageSettingsProvider prov2) { + Boolean isTest1 = prov1.getId().matches(TEST_PLUGIN_ID_PATTERN); + Boolean isTest2 = prov2.getId().matches(TEST_PLUGIN_ID_PATTERN); + int result = isTest1.compareTo(isTest2); + if (result == 0) { + String name1 = prov1.getName(); + String name2 = prov2.getName(); + if (name1 != null && name2 != null) { + result = name1.compareTo(name2); + } + } + return result; + } + }); + } + + /** + * Initialize providers list. + */ + private void initializeProviders() { + // The providers list is formed to consist of configuration providers (checked elements on top of the table) + // and after that other providers which could be possible added (unchecked) sorted by name. + + List idsList = new ArrayList(); + + List providers; + ICConfigurationDescription cfgDescription = getConfigurationDescription(); + if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) { + providers = new ArrayList(((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders()); + for (ILanguageSettingsProvider provider : providers) { + idsList.add(provider.getId()); + } + } else { + providers = new ArrayList(); + } + + List allAvailableProvidersSet = LanguageSettingsManager.getWorkspaceProviders(); + sortByName(allAvailableProvidersSet); + + for (ILanguageSettingsProvider provider : allAvailableProvidersSet) { + String id = provider.getId(); + if (!idsList.contains(id)) { + providers.add(provider); + idsList.add(id); + } + } + + // renders better when using temporary + presentedProviders = providers; + + ILanguageSettingsProvider selectedProvider = getSelectedProvider(); + String selectedId = selectedProvider!=null ? selectedProvider.getId() : null; + + tableProvidersViewer.setInput(presentedProviders); + if (selectedId!=null) { + for (int i=0; i cfgProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders(); + tableProvidersViewer.setCheckedElements(cfgProviders.toArray(new ILanguageSettingsProvider[0])); + } + + if (selectedId != null) { + for (int i = 0; i < presentedProviders.size(); i++) { + if (selectedId.equals(presentedProviders.get(i).getId())) { + tableProviders.setSelection(i); + break; + } + } + } + tableProvidersViewer.refresh(); + + optionsPageMap.clear(); + for (ILanguageSettingsProvider provider : presentedProviders) { + createOptionsPage(provider); + } + + displaySelectedOptionPage(); + } + + /** + * Update the tab. Called when configuration changes. + */ + @Override + public void updateData(ICResourceDescription rcDes) { + if (!canBeVisible()) + return; + + if (rcDes!=null) { + if (page.isMultiCfg()) { + setAllVisible(false, null); + return; + } else { + setAllVisible(true, null); + } + + if (masterPropertyPage != null) { + boolean enabled = masterPropertyPage.isLanguageSettingsProvidersEnabled(); + enableProvidersCheckBox.setSelection(enabled); + enableTabControls(enabled); + } + } + + // for Preference page initialize providers list just once as no configuration here to change + // and re-initializing could overwrite modified providers in case of switching tabs or pages + if (!page.isForPrefs() || presentedProviders == null) { + initializeProviders(); + } + updateProvidersTable(); + updateButtons(); + } + + @Override + protected void performDefaults() { + if (page.isForProject() && (enableProvidersCheckBox==null || enableProvidersCheckBox.getSelection() == false)) + return; + + if (page.isForPrefs() || page.isForProject()) { + if (MessageDialog.openQuestion(usercomp.getShell(), + Messages.LanguageSettingsProviderTab_TitleResetProviders, + Messages.LanguageSettingsProviderTab_AreYouSureToResetProviders)) { + + if (page.isForProject()) { + ICConfigurationDescription cfgDescription = getConfigurationDescription(); + if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) { + List cfgProviders = new ArrayList(((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders()); + String[] defaultIds = ((ILanguageSettingsProvidersKeeper) cfgDescription).getDefaultLanguageSettingsProvidersIds(); + + List newProviders = new ArrayList(defaultIds.length); + for (String id : defaultIds) { + boolean preferShared = LanguageSettingsManager.isPreferShared(id); + ILanguageSettingsProvider newProvider = null; + if (!preferShared) { + newProvider = LanguageSettingsManager.getExtensionProviderCopy(id, true); + } + if (newProvider == null) { + newProvider = LanguageSettingsManager.getWorkspaceProvider(id); + } + newProviders.add(newProvider); + } + + if (!cfgProviders.equals(newProviders)) { + ((ILanguageSettingsProvidersKeeper) cfgDescription).setLanguageSettingProviders(newProviders); + } + } + + } else if (page.isForPrefs()) { + presentedProviders = new ArrayList(); + for (ILanguageSettingsProvider provider : LanguageSettingsManager.getWorkspaceProviders()) { + if (!LanguageSettingsManager.isEqualExtensionProvider(provider, true)) { + ILanguageSettingsProvider extProvider = LanguageSettingsManager.getExtensionProviderCopy(provider.getId(), true); + if (extProvider != null) { + provider = extProvider; + } + } + presentedProviders.add(provider); + } + sortByName(presentedProviders); + } + } + + ICResourceDescription rcDescription = getResDesc(); + + updateData(rcDescription); + // update other tabs + masterPropertyPage.informAll(UPDATE, rcDescription); + } + } + + @Override + protected void performApply(ICResourceDescription srcRcDescription, ICResourceDescription destRcDescription) { + if (!page.isForPrefs()) { + ICConfigurationDescription sd = srcRcDescription.getConfiguration(); + ICConfigurationDescription dd = destRcDescription.getConfiguration(); + if (sd instanceof ILanguageSettingsProvidersKeeper && dd instanceof ILanguageSettingsProvidersKeeper) { + List newProviders = ((ILanguageSettingsProvidersKeeper) sd).getLanguageSettingProviders(); + ((ILanguageSettingsProvidersKeeper) dd).setLanguageSettingProviders(newProviders); + } + } + + performOK(); + + trackInitialSettings(); + updateData(getResDesc()); + } + + @Override + protected void performOK() { + // Build Settings page + if (page.isForPrefs()) { + try { + LanguageSettingsManager.setWorkspaceProviders(presentedProviders); + } catch (CoreException e) { + CUIPlugin.log("Error setting user defined providers", e); //$NON-NLS-1$ + } + initializeProviders(); + } + + if (masterPropertyPage != null && enableProvidersCheckBox.getEnabled()) { + masterPropertyPage.applyLanguageSettingsProvidersEnabled(); + } + + Collection optionPages = optionsPageMap.values(); + for (ICOptionPage op : optionPages) { + try { + op.performApply(null); + } catch (CoreException e) { + CUIPlugin.log("Error applying options page", e); //$NON-NLS-1$ + } + } + } + + @Override + public boolean canBeVisible() { + if (CDTPrefUtil.getBool(LanguageSettingsProvidersPage.KEY_NO_SHOW_PROVIDERS)) { + return false; + } + + return page.isForPrefs() || page.isForProject(); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProvidersLabelProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProvidersLabelProvider.java new file mode 100644 index 00000000000..e93bae0f8d3 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProvidersLabelProvider.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2010, 2012 Andrew Gvozdev 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: + * Andrew Gvozdev - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.language.settings.providers; + +import java.net.URL; + +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.graphics.Image; + +import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider; +import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager; +import org.eclipse.cdt.ui.CDTSharedImages; + +import org.eclipse.cdt.internal.ui.newui.Messages; + +/** + * Label provider for language settings providers. + * + */ +public class LanguageSettingsProvidersLabelProvider extends LabelProvider { + private static final String TEST_PLUGIN_ID_PATTERN = "org.eclipse.cdt.*.tests.*"; //$NON-NLS-1$ + private static final String OOPS = "OOPS"; //$NON-NLS-1$ + + /** + * Returns base image key (for image without overlay). + */ + protected String getBaseKey(ILanguageSettingsProvider provider) { + String imageKey = null; + // try id-association + String id = provider.getId(); + URL url = LanguageSettingsProviderAssociationManager.getImageUrl(id); + // try class-association + if (url == null) { + ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(provider); + if (rawProvider != null) { + url = LanguageSettingsProviderAssociationManager.getImage(rawProvider.getClass()); + } + } + if (url != null) { + imageKey = url.toString(); + } + + if (imageKey == null) { + if (id.matches(TEST_PLUGIN_ID_PATTERN)) { + imageKey = CDTSharedImages.IMG_OBJS_CDT_TESTING; + } else { + imageKey = CDTSharedImages.IMG_OBJS_EXTENSION; + } + } + return imageKey; + } + + /** + * Returns keys for image overlays. Returning {@code null} is not allowed. + */ + protected String[] getOverlayKeys(ILanguageSettingsProvider provider) { + return new String[5]; + } + + @Override + public Image getImage(Object element) { + if (element instanceof ILanguageSettingsProvider) { + ILanguageSettingsProvider provider = (ILanguageSettingsProvider)element; + String imageKey = getBaseKey(provider); + String[] overlayKeys = getOverlayKeys(provider); + return CDTSharedImages.getImageOverlaid(imageKey, overlayKeys); + } + return null; + } + + @Override + public String getText(Object element) { + if (element instanceof ILanguageSettingsProvider) { + ILanguageSettingsProvider provider = (ILanguageSettingsProvider) element; + String name = provider.getName(); + if (name != null) { + if (LanguageSettingsManager.isWorkspaceProvider(provider)) { + name = name + Messages.LanguageSettingsProvidersLabelProvider_TextDecorator_Shared; + } + return name; + } + return NLS.bind(Messages.GeneralMessages_NonAccessibleID, provider.getId()); + } + return OOPS; + } + +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProvidersPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProvidersPage.java new file mode 100644 index 00000000000..84f5d735386 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProvidersPage.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2010, 2012 Andrew Gvozdev 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: + * Andrew Gvozdev - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.language.settings.providers; + +import org.eclipse.core.resources.IProject; + +import org.eclipse.cdt.core.language.settings.providers.ScannerDiscoveryLegacySupport; +import org.eclipse.cdt.ui.newui.AbstractPage; +import org.eclipse.cdt.ui.newui.ICPropertyTab; + +/** + * Property page for language settings providers tabs. + * The handling of isLanguageSettingsProvidersEnabled is temporary, this control is to be removed. + * + * @noextend This class is not intended to be subclassed by clients. + * @noinstantiate This class is not intended to be instantiated by clients. + */ +public class LanguageSettingsProvidersPage extends AbstractPage { + /** @since 5.4 */ // temporary key, subject to removal + public static final String KEY_NO_SHOW_PROVIDERS = "properties.providers.tab.disable"; //$NON-NLS-1$ + /** @since 5.4 */ // temporary key, subject to removal + public static final String KEY_NEWSD = "wizard.try.new.sd.enable"; //$NON-NLS-1$ + + private static boolean isLanguageSettingsProvidersEnabled = false; + private static IProject project = null; + + @Override + protected boolean isSingle() { + return false; + } + + /** + * Check if language settings providers functionality is enabled for the project. + * Need this method as another page could be inquiring before this page gets initialized. + * + * @noreference This method is temporary and not intended to be referenced by clients. + */ + public static boolean isLanguageSettingsProvidersEnabled(IProject prj) { + if (prj != null) { + if (prj.equals(project)) { + return isLanguageSettingsProvidersEnabled; + } else { + return ScannerDiscoveryLegacySupport.isLanguageSettingsProvidersFunctionalityEnabled(project); + } + } + return false; + } + + /** + * Check if language settings providers functionality is enabled for the current project. + * + * @noreference This method is temporary and not intended to be referenced by clients. + */ + public boolean isLanguageSettingsProvidersEnabled() { + IProject prj = getProject(); + if (prj != null) { + if (!prj.equals(project)) { + project = prj; + isLanguageSettingsProvidersEnabled = ScannerDiscoveryLegacySupport.isLanguageSettingsProvidersFunctionalityEnabled(project); + } + return isLanguageSettingsProvidersEnabled; + } + return false; + } + + /** + * Enable or disable language settings providers functionality for the current project. + * Triggers update of all the property pages. + * + * Note that this method only sets property for the current editing session. + * Use {@link #applyLanguageSettingsProvidersEnabled()} to apply to the project. + * + * @noreference This method is temporary and not intended to be referenced by clients. + */ + public void setLanguageSettingsProvidersEnabled(boolean enable) { + isLanguageSettingsProvidersEnabled = enable; + project = getProject(); + forEach(ICPropertyTab.UPDATE,getResDesc()); + } + + /** + * Apply enablement of language settings providers functionality to the current project. + * + * @noreference This method is temporary and not intended to be referenced by clients. + */ + public void applyLanguageSettingsProvidersEnabled() { + ScannerDiscoveryLegacySupport.setLanguageSettingsProvidersFunctionalityEnabled(getProject(), isLanguageSettingsProvidersEnabled); + } + + @Override + public void dispose() { + isLanguageSettingsProvidersEnabled = false; + project = null; + super.dispose(); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/newui/LanguageSettingsImages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/newui/LanguageSettingsImages.java index 2f96922703a..7e26e3a295c 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/newui/LanguageSettingsImages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/newui/LanguageSettingsImages.java @@ -11,6 +11,7 @@ package org.eclipse.cdt.internal.ui.newui; +import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; @@ -23,6 +24,7 @@ import org.eclipse.swt.graphics.Image; import org.eclipse.cdt.core.settings.model.ACPathEntry; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; +import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.core.settings.model.ICSettingEntry; import org.eclipse.cdt.core.settings.model.util.CDataUtil; import org.eclipse.cdt.ui.CDTSharedImages; @@ -32,16 +34,48 @@ import org.eclipse.cdt.ui.CUIPlugin; * Helper class to provide unified images for {@link ICLanguageSettingEntry}. */ public class LanguageSettingsImages { + public static Image getImage(int kind, int flags, boolean isProjectRelative) { + String imageKey = getImageKey(kind, flags, isProjectRelative); + if (imageKey != null) { + return CDTSharedImages.getImage(imageKey); + } + return null; + } + + /** + * Returns image for the given entry from internally managed repository including + * necessary overlays for given configuration description. + * + * @param entry - language settings entry to get an image for. + * @param cfgDescription - configuration description of the entry. + * @return the image for the entry with appropriate overlays. + */ + public static Image getImage(ICLanguageSettingEntry entry, ICConfigurationDescription cfgDescription) { + String projectName = null; + + if (cfgDescription != null) { + ICProjectDescription prjDescription = cfgDescription.getProjectDescription(); + if (prjDescription != null) { + IProject project = prjDescription.getProject(); + if (project != null) { + projectName = project.getName(); + } + } + } + + return getImage(entry, projectName, cfgDescription); + } + /** * @return the base key for the image. */ public static String getImageKey(int kind, int flag, boolean isProjectRelative) { String imageKey = null; - + boolean isWorkspacePath = (flag & ICSettingEntry.VALUE_WORKSPACE_PATH) != 0; boolean isBuiltin = (flag & ICSettingEntry.BUILTIN) != 0; boolean isFramework = (flag & ICSettingEntry.FRAMEWORKS_MAC) != 0; - + switch (kind) { case ICSettingEntry.INCLUDE_PATH: if (isWorkspacePath) { @@ -89,7 +123,7 @@ public class LanguageSettingsImages { * @param cfgDescription - configuration description of the entry. * @return the image for the entry with appropriate overlays. */ - public static Image getImage(ICLanguageSettingEntry entry, String projectName, ICConfigurationDescription cfgDescription) { + private static Image getImage(ICLanguageSettingEntry entry, String projectName, ICConfigurationDescription cfgDescription) { int kind = entry.getKind(); int flags = entry.getFlags(); boolean isWorkspacePath = (flags & ICSettingEntry.VALUE_WORKSPACE_PATH) != 0; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/newui/Messages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/newui/Messages.java index c6f86743b89..d0ad9a79ce5 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/newui/Messages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/newui/Messages.java @@ -4,7 +4,7 @@ * 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: * Andrew Gvozdev - Initial API and implementation * IBM Corporation @@ -138,7 +138,6 @@ public class Messages extends NLS { public static String EnvironmentTab_8; public static String EnvironmentTab_9; public static String ErrorParsTab_error_IllegalCharacter; - public static String ErrorParsTab_error_NonAccessibleID; public static String ErrorParsTab_error_NonEmptyName; public static String ErrorParsTab_error_NonUniqueID; public static String ErrorParsTab_error_OnApplyingSettings; @@ -174,6 +173,8 @@ public class Messages extends NLS { public static String FileListControl_editdialog_title; public static String FileListControl_movedown; public static String FileListControl_moveup; + public static String GeneralMessages_InternalError_ReportLogToCdtTeam; + public static String GeneralMessages_NonAccessibleID; public static String IncludeDialog_0; public static String IncludeDialog_1; public static String IncludeDialog_2; @@ -186,9 +187,43 @@ public class Messages extends NLS { public static String IncludeTab_2; public static String IncludeTab_export; public static String IncludeTab_import; + public static String LanguageSettingEntryDialog_Add; + public static String LanguageSettingEntryDialog_BuiltInFlag; + public static String LanguageSettingEntryDialog_Directory; + public static String LanguageSettingEntryDialog_File; + public static String LanguageSettingEntryDialog_Filesystem; + public static String LanguageSettingEntryDialog_FrameworkFolder; + public static String LanguageSettingEntryDialog_IncludeDirectory; + public static String LanguageSettingEntryDialog_IncludeFile; + public static String LanguageSettingEntryDialog_Library; + public static String LanguageSettingEntryDialog_LibraryPath; + public static String LanguageSettingEntryDialog_Name; + public static String LanguageSettingEntryDialog_Path; + public static String LanguageSettingEntryDialog_PreporocessorMacro; + public static String LanguageSettingEntryDialog_PreprocessorMacroFile; + public static String LanguageSettingEntryDialog_ProjectPath; + public static String LanguageSettingEntryDialog_SelectKind; + public static String LanguageSettingEntryDialog_Value; + public static String LanguageSettingEntryDialog_WorkspacePath; + public static String LanguageSettingsEntriesTab_Cannot_Determine_Languages; + public static String LanguageSettingsEntriesTab_Entries_Not_Editable; public static String LanguageSettingsImages_FileDoesNotExist; public static String LanguageSettingsImages_FolderDoesNotExist; public static String LanguageSettingsImages_UsingRelativePathsNotRecommended; + public static String LanguageSettingsProviders_EnableForProject; + public static String LanguageSettingsProvidersLabelProvider_TextDecorator_Shared; + public static String LanguageSettingsProviderTab_AreYouSureToResetProviders; + public static String LanguageSettingsProviderTab_Clear; + public static String LanguageSettingsProviderTab_LanguageSettingsProvidersOptions; + public static String LanguageSettingsProviderTab_OptionsCanBeChangedInPreferencesDiscoveryTab; + public static String LanguageSettingsProviderTab_ProviderOptions; + public static String LanguageSettingsProviderTab_Reset; + public static String LanguageSettingsProviderTab_SettingEntries; + public static String LanguageSettingsProviderTab_SettingEntriesTooltip; + public static String LanguageSettingsProviderTab_ShareProviders; + public static String LanguageSettingsProviderTab_StoreEntriesInsideProject; + public static String LanguageSettingsProviderTab_TitleResetProviders; + public static String LanguageSettingsProviderTab_WorkspaceSettings; public static String LanguagesTab_0; public static String LanguagesTab_1; public static String LibraryPathTab_1; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/newui/Messages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/newui/Messages.properties index 8da3b3582fc..06cc6138bdb 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/newui/Messages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/newui/Messages.properties @@ -166,9 +166,45 @@ IncludeDialog_0=Directory: IncludeDialog_1=File: IncludeDialog_2=Add to all configurations IncludeDialog_3=Add to all languages +LanguageSettingEntryDialog_Add=Add +LanguageSettingEntryDialog_BuiltInFlag=Treat as built-in +LanguageSettingEntryDialog_Directory=Dir: +LanguageSettingEntryDialog_File=File: +LanguageSettingEntryDialog_Filesystem=Filesystem +LanguageSettingEntryDialog_FrameworkFolder=Framework folder (Mac only) +LanguageSettingEntryDialog_IncludeDirectory=Include Directory +LanguageSettingEntryDialog_IncludeFile=Include File +LanguageSettingEntryDialog_Library=Library +LanguageSettingEntryDialog_LibraryPath=Library Path +LanguageSettingEntryDialog_Name=Name: +LanguageSettingEntryDialog_Path=Path: +LanguageSettingEntryDialog_PreporocessorMacro=Preprocessor Macro +LanguageSettingEntryDialog_PreprocessorMacroFile=Preprocessor Macros File +LanguageSettingEntryDialog_ProjectPath=Project Path +LanguageSettingEntryDialog_SelectKind=Select Kind: +LanguageSettingEntryDialog_Value=Value: +LanguageSettingEntryDialog_WorkspacePath=Workspace Path +LanguageSettingsEntriesTab_Cannot_Determine_Languages=Cannot determine toolchain languages. +LanguageSettingsEntriesTab_Entries_Not_Editable=Setting entries for this provider are supplied by the system and are not editable. LanguageSettingsImages_FileDoesNotExist=The selected file does not exist or not accessible. LanguageSettingsImages_FolderDoesNotExist=The selected folder does not exist or not accessible. LanguageSettingsImages_UsingRelativePathsNotRecommended=Using relative paths is ambiguous and not recommended. It can cause unexpected effects. + +LanguageSettingsProviders_EnableForProject=Enable language settings providers for this project +LanguageSettingsProvidersLabelProvider_TextDecorator_Shared=\ \ \ [ Shared ] +LanguageSettingsProviderTab_AreYouSureToResetProviders=Are you sure you want to reset all customized language settings providers?\nPlease note that providers may regain entries on their own schedule. +LanguageSettingsProviderTab_Clear=Clear Entries +LanguageSettingsProviderTab_LanguageSettingsProvidersOptions=Language Settings Provider Options +LanguageSettingsProviderTab_OptionsCanBeChangedInPreferencesDiscoveryTab=Options of global providers below can be changed in {0}, Discovery Tab. +LanguageSettingsProviderTab_Reset=Reset +LanguageSettingsProviderTab_ProviderOptions=Language Settings Provider Options +LanguageSettingsProviderTab_SettingEntries=Setting Entries +LanguageSettingsProviderTab_SettingEntriesTooltip=Setting Entries +LanguageSettingsProviderTab_ShareProviders=Share setting entries between projects (global provider) +LanguageSettingsProviderTab_StoreEntriesInsideProject=Store entries in project settings folder (easing project miration) +LanguageSettingsProviderTab_TitleResetProviders=Reset Language Settings Providers +LanguageSettingsProviderTab_WorkspaceSettings=Workspace Settings + LanguagesTab_0=Content type LanguagesTab_1=Language LibraryPathTab_1=Add... @@ -207,7 +243,6 @@ ErrorParsTab_error_NonEmptyName=Specify non empty name ErrorParsTab_error_NonUniqueID=Error parser ID is not unique, specify different name ErrorParsTab_error_OnApplyingSettings=Error applying Error Parser Tab settings ErrorParsTab_error_OnRestoring=Error restoring default Error Parser Tab settings -ErrorParsTab_error_NonAccessibleID=[ Not accessible id={0} ] ErrorParsTab_error_IllegalCharacter=Special character ''{0}'' is not allowed ErrorParsTab_label_EnterName=Enter name of new error parser: ErrorParsTab_label_DefaultRegexErrorParserName=Regex Error Parser @@ -274,6 +309,8 @@ CDTMainWizardPage_0=Project name cannot contain '\#' symbol CDTMainWizardPage_1=Project category is selected. Expand the category and select a concrete project type. CProjectWizard_0=Add C Project Nature CCProjectWizard_0=Add CC Project Nature +GeneralMessages_InternalError_ReportLogToCdtTeam=Internal error happened, report application log to CDT team. +GeneralMessages_NonAccessibleID=[ Not accessible id={0} ] WorkingSetConfigAction_21=Building project WorkingSetConfigAction_22=Build error IncludeTab_export=Export Settings... diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/ProblemsLabelDecorator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/ProblemsLabelDecorator.java index 4176c89f54e..21ec525f43c 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/ProblemsLabelDecorator.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/ProblemsLabelDecorator.java @@ -10,12 +10,13 @@ *******************************************************************************/ package org.eclipse.cdt.internal.ui.viewsupport; +import java.util.List; + import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceStatus; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.ListenerList; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.IBaseLabelProvider; @@ -29,6 +30,10 @@ import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.ui.texteditor.MarkerUtilities; +import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider; +import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvidersKeeper; +import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager; +import org.eclipse.cdt.core.language.settings.providers.ScannerDiscoveryLegacySupport; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICElement; @@ -36,6 +41,7 @@ import org.eclipse.cdt.core.model.ISourceRange; import org.eclipse.cdt.core.model.ISourceReference; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; +import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.core.settings.model.ICResourceDescription; import org.eclipse.cdt.ui.CElementImageDescriptor; @@ -379,6 +385,31 @@ public class ProblemsLabelDecorator implements ILabelDecorator, ILightweightLabe } } + private static boolean isCustomizedResource(ICConfigurationDescription cfgDescription, IResource rc) { + if (rc instanceof IProject) + return false; + + if (!ScannerDiscoveryLegacySupport.isLanguageSettingsProvidersFunctionalityEnabled(rc.getProject())) { + ICResourceDescription rcDescription = cfgDescription.getResourceDescription(rc.getProjectRelativePath(), true); + return rcDescription != null; + } + + if (cfgDescription instanceof ILanguageSettingsProvidersKeeper) { + for (ILanguageSettingsProvider provider: ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders()) { + for (String languageId : LanguageSettingsManager.getLanguages(rc, cfgDescription)) { + List list = provider.getSettingEntries(cfgDescription, rc, languageId); + if (list != null) { + List listDefault = provider.getSettingEntries(cfgDescription, rc.getParent(), languageId); + // != is OK here due as the equal lists will have the same reference in WeakHashSet + if (list != listDefault) + return true; + } + } + } + } + return false; + } + /** * @param rc - resource to check * @return flags {@link TICK_CONFIGURATION} if the resource has custom settings and possibly needs @@ -393,9 +424,7 @@ public class ProblemsLabelDecorator implements ILabelDecorator, ILightweightLabe if (prjDescription != null) { ICConfigurationDescription cfgDescription = prjDescription.getDefaultSettingConfiguration(); if (cfgDescription != null) { - IPath path = rc.getProjectRelativePath(); - ICResourceDescription rcDescription = cfgDescription.getResourceDescription(path, true); - if (rcDescription != null) + if (isCustomizedResource(cfgDescription, rc)) result |= TICK_CONFIGURATION; } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CDTSharedImages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CDTSharedImages.java index adf97abc88d..e812341ba42 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CDTSharedImages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CDTSharedImages.java @@ -172,6 +172,8 @@ public class CDTSharedImages { public static final String IMG_OBJS_CORRECTION_RENAME = "icons/obj16/correction_rename.gif"; //$NON-NLS-1$ public static final String IMG_OBJS_CORRECTION_LINKED_RENAME = "icons/obj16/correction_linked_rename.gif"; //$NON-NLS-1$ + /** @since 5.4 */ + public static final String IMG_ETOOL_PROJECT = "icons/etool16/prj_obj.gif"; //$NON-NLS-1$ public static final String IMG_VIEW_BUILD_CONSOLE = "icons/view16/buildconsole.gif"; //$NON-NLS-1$ // Images for file list control @@ -186,6 +188,12 @@ public class CDTSharedImages { public static final String IMG_OVR_ERROR = "icons/ovr16/error_co.gif"; //$NON-NLS-1$ public static final String IMG_OVR_SETTING = "icons/ovr16/setting_nav.gif"; //$NON-NLS-1$ public static final String IMG_OVR_INACTIVE = "icons/ovr16/inactive_co.gif"; //$NON-NLS-1$ + /** @since 5.4 */ + public static final String IMG_OVR_PARENT = "icons/ovr16/path_inherit_co.gif"; //$NON-NLS-1$ + /** @since 5.4 */ + public static final String IMG_OVR_EDITED = "icons/ovr16/edited_ovr.gif"; //$NON-NLS-1$ + /** @since 5.4 */ + public static final String IMG_OVR_USER = "icons/ovr16/person_ovr.gif"; //$NON-NLS-1$ // Pin & Clone public static final String IMG_THREAD_SUSPENDED_R_PINNED = "icons/obj16/threads_obj_r.gif"; //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/language/settings/providers/AbstractLanguageSettingProviderOptionPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/language/settings/providers/AbstractLanguageSettingProviderOptionPage.java new file mode 100644 index 00000000000..13871ccfa8c --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/language/settings/providers/AbstractLanguageSettingProviderOptionPage.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2010, 2012 Andrew Gvozdev 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: + * Andrew Gvozdev - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.ui.language.settings.providers; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; + +import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider; +import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager; +import org.eclipse.cdt.ui.dialogs.AbstractCOptionPage; +import org.eclipse.cdt.ui.newui.AbstractCPropertyTab; + +import org.eclipse.cdt.internal.ui.language.settings.providers.LanguageSettingsProviderTab; + +/** + * Abstract class to implement language settings providers Options page. + * + * @since 5.4 + */ +public abstract class AbstractLanguageSettingProviderOptionPage extends AbstractCOptionPage { + private LanguageSettingsProviderTab providerTab; + private String providerId; + + /** + * Initialize the options page with the owning tab and provider ID. + * + * @param providerTab - provider tab which owns the options page. + * @param providerId - ID of the provider the options page is for. + */ + public void init(AbstractCPropertyTab providerTab, String providerId) { + this.providerTab = (LanguageSettingsProviderTab) providerTab; + this.providerId = providerId; + } + + /** + * Get provider being displayed on this Options Page. + * @return provider. + */ + public ILanguageSettingsProvider getProvider() { + return LanguageSettingsManager.getRawProvider(providerTab.getProvider(providerId)); + } + + /** + * Get working copy of the provider to allow its options to be modified. + * @return working copy of the provider. + */ + public ILanguageSettingsProvider getProviderWorkingCopy() { + return providerTab.getWorkingCopy(providerId); + } + + /** + * Refresh provider item in the table and update buttons. + * This method is intended for use by an Options Page of the provider. + * + * @param provider - provider item in the table to refresh. + */ + public void refreshItem(ILanguageSettingsProvider provider) { + providerTab.refreshItem(provider); + } + + @Override + public void performApply(IProgressMonitor monitor) throws CoreException { + // normally should be handled by LanguageSettingsProviderTab + } + + @Override + public void performDefaults() { + // normally should be handled by LanguageSettingsProviderTab + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/language/settings/providers/LanguageSettingsProvidersImages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/language/settings/providers/LanguageSettingsProvidersImages.java new file mode 100644 index 00000000000..7317e6e8c4c --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/language/settings/providers/LanguageSettingsProvidersImages.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2012, 2012 Andrew Gvozdev 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: + * Andrew Gvozdev - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.ui.language.settings.providers; + +import java.net.URL; + +import org.eclipse.cdt.internal.ui.language.settings.providers.LanguageSettingsProviderAssociationManager; + +/** + * Utility class to provide API for language settings providers images. + * + * @since 5.4 + */ +public class LanguageSettingsProvidersImages { + /** + * Get image URL for language settings provider with the given ID. + * + * @param providerId - ID of language settings provider. + * @return image URL or {@code null}. + */ + public static URL getImageUrl(String providerId) { + return LanguageSettingsProviderAssociationManager.getImageUrl(providerId); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/AbstractCPropertyTab.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/AbstractCPropertyTab.java index aaa8b02edf1..ddd9791406d 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/AbstractCPropertyTab.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/AbstractCPropertyTab.java @@ -64,70 +64,72 @@ import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; import org.eclipse.cdt.internal.ui.newui.Messages; /** - * It is a parent for all standard property tabs + * 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 + * 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. + * 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). + * uniform manner (setupLabel(), setupText() etc). * - means to handle control messages which are the main - * communication way for new CDT model pages and tabs. + * 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; - 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 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 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 Image icon = null; + private String helpId = EMPTY_STR; + protected boolean visible; @Override @@ -139,8 +141,8 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { /** * Creates basic widgets for property tab. * Descendants should, normally, override - * this method but call super.createControls(). - * + * this method but call super.createControls(). + * * @param parent */ protected void createControls(Composite parent) { @@ -153,27 +155,27 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { 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" + * null instead of name means "skip place" */ protected void initButtons(String[] names) { initButtons(buttoncomp, names, 80); @@ -181,7 +183,7 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { protected void initButtons(String[] names, int width) { initButtons(buttoncomp, names, width); } - + /** * Ability to create standard button on any composite. * @param c @@ -201,15 +203,15 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { gdb.grabExcessHorizontalSpace = false; gdb.horizontalAlignment = SWT.FILL; gdb.minimumWidth = width; - + if (names[i] != null) buttons[i].setText(names[i]); - else { // no button, but placeholder ! + 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 @@ -219,15 +221,15 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { }); } } - + /** - * Called when user changes + * 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. */ @@ -244,13 +246,13 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { visible = _visible; if (visible) updateData(page.getResDesc()); } - + /** - * Descendant tabs should implement this method so - * that it copies it's data from one description + * 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 */ @@ -272,32 +274,32 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { } } } - + /** - * Method should be rewritten to handle button presses + * Method should be rewritten to handle button presses * @param i : number of button pressed - * - * Does nothing by default. + * + * 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 + * @return - true if button exists and enabled */ protected boolean buttonIsEnabled(int i) { - if (buttons == null || buttons.length <= 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 */ @@ -305,11 +307,11 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { 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 */ @@ -345,13 +347,13 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { 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); @@ -359,7 +361,7 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { setupControl(g, 1, mode); return g; } - + protected Button setupCheck(Composite c, String name, int span, int mode) { Button b = new Button(c, SWT.CHECK); b.setText(name); @@ -375,23 +377,23 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { } /** - * Selection handler for checkbox created - * by methods "setupCheck()" or "setupTri()" - * Descendants should override this method - * if they use "setupCheck". + * 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) { ... } + * 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. + // exceptions can occur: do nothing. if (c != null) { if (span != 0) { GridData gd = new GridData(mode); @@ -402,11 +404,11 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { c.setFont(p.getFont()); } } - + /* - * A set of methods providing selection dialogs for files or dirs. + * 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); @@ -431,12 +433,12 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { 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); + dialog.setTitle(Messages.AbstractCPropertyTab_0); if (dialog.open() == Window.OK) { Object[] selected = dialog.getResult(); if (selected.length > 0) { @@ -453,7 +455,19 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { 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; @@ -461,7 +475,7 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { /* 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()); @@ -470,7 +484,7 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { else dialog.setInput(prj); dialog.setComparator(new ResourceComparator(ResourceComparator.NAME)); - + if (dir) { IResource container = null; if(path.isAbsolute()){ @@ -512,14 +526,14 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { } if (dialog.open() == Window.OK) { IResource resource = (IResource) dialog.getFirstResult(); - if (resource != null) { + if (resource != null) { StringBuffer buf = new StringBuffer(); 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(); @@ -553,19 +567,19 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { dispose(); break; case ICPropertyTab.VISIBLE: - if (canBeVisible()) + if (canBeVisible()) setVisible(data != null); - else + else setVisible(false); break; case ICPropertyTab.SET_ICON: - icon = (Image)data; + icon = (Image)data; break; default: break; } } - + // By default, returns true (no visibility restriction) // But several pages should rewrite this functionality. @Override @@ -587,20 +601,20 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { } /** - * Sets checkbox to appropriate state: + * Sets checkbox to appropriate state: * unchecked or checked * @param b - checkbox to set - * @param state + * @param state */ public static void setTriSelection(Button b, boolean state) { setTriSelection(b, state ? TRI_YES : TRI_NO); } - + /** - * Sets checkbox to appropriate state: + * Sets checkbox to appropriate state: * unchecked, checked or unknown (grayed) * @param b - checkbox to set - * @param state + * @param state */ public static void setTriSelection(Button b, int state) { switch (state) { @@ -623,7 +637,7 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { * 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 @@ -636,7 +650,7 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { /** * 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() { @@ -652,8 +666,8 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { /** * Utility method to show/hide working panes - * When panes are hidden, message becomes visible - * + * When panes are hidden, message becomes visible + * * @param visible - true or false * @param msg - text to be shown instead of panes */ @@ -673,21 +687,21 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { b.setVisible(visible); } } - + /** * Allows changing message on background pane, * which becomes visible after usercomp hidden - * - * @param s - text to display or null for default + * + * @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()} */ @@ -714,7 +728,7 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { * 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
    @@ -729,12 +743,12 @@ public abstract class AbstractCPropertyTab implements ICPropertyTab { 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 * true the user will be asked whether she wants to rebuild the index. diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/AbstractLangsListTab.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/AbstractLangsListTab.java index 63e0fe4ec34..637b944fa27 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/AbstractLangsListTab.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/AbstractLangsListTab.java @@ -19,7 +19,6 @@ import java.util.Comparator; import java.util.LinkedList; import java.util.List; -import org.eclipse.core.resources.IProject; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.IFontProvider; import org.eclipse.jface.viewers.IStructuredContentProvider; @@ -242,7 +241,7 @@ public abstract class AbstractLangsListTab extends AbstractCPropertyTab { int index = table.getSelectionIndex(); if (index<0 || table.getSelectionIndices().length!=1) return null; - + return (ICLanguageSettingEntry)(table.getItem(index).getData()); } @@ -730,8 +729,7 @@ public abstract class AbstractLangsListTab extends AbstractCPropertyTab { public Image getColumnImage(Object element, int columnIndex) { if (columnIndex==0 && (element instanceof ICLanguageSettingEntry)) { ICConfigurationDescription cfg = getResDesc().getConfiguration(); - IProject project = cfg.getProjectDescription().getProject(); - return LanguageSettingsImages.getImage((ICLanguageSettingEntry) element, project.getName(), cfg); + return LanguageSettingsImages.getImage((ICLanguageSettingEntry) element, cfg); } return null; } @@ -760,7 +758,7 @@ public abstract class AbstractLangsListTab extends AbstractCPropertyTab { } else if (columnIndex == 0) { return element.toString(); } - + return null; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/ErrorParsTab.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/ErrorParsTab.java index fe692d14e27..c8e9e891a81 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/ErrorParsTab.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/ErrorParsTab.java @@ -166,7 +166,7 @@ public class ErrorParsTab extends AbstractCPropertyTab { return name; } } - return NLS.bind(Messages.ErrorParsTab_error_NonAccessibleID, id); + return NLS.bind(Messages.GeneralMessages_NonAccessibleID, id); } return OOPS; }