| /******************************************************************************* |
| * Copyright (c) 2006, 2008 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.pde.internal.ua.ui.wizards.cheatsheet; |
| |
| import java.util.ArrayList; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.jface.dialogs.Dialog; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.jface.wizard.WizardPage; |
| import org.eclipse.pde.core.IModel; |
| import org.eclipse.pde.core.plugin.*; |
| import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase; |
| import org.eclipse.pde.internal.core.util.PDETextHelper; |
| import org.eclipse.pde.internal.ua.core.icheatsheet.comp.ICompCSConstants; |
| import org.eclipse.pde.internal.ua.ui.PDEUserAssistanceUIPlugin; |
| import org.eclipse.pde.internal.ui.IHelpContextIds; |
| import org.eclipse.pde.internal.ui.util.SWTUtil; |
| 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.*; |
| import org.eclipse.ui.PlatformUI; |
| |
| public abstract class RegisterCSWizardPage extends WizardPage implements IRegisterCSData { |
| |
| public final static String F_PAGE_NAME = "register-cs"; //$NON-NLS-1$ |
| |
| public final static String F_CS_ELEMENT_CATEGORY = "category"; //$NON-NLS-1$ |
| |
| public final static String F_CS_ELEMENT_CHEATSHEET = "cheatsheet"; //$NON-NLS-1$ |
| |
| public final static String F_CS_ELEMENT_DESCRIPTION = "description"; //$NON-NLS-1$ |
| |
| private final static String F_LOCALE_VARIABLE = "$nl$/"; //$NON-NLS-1$ |
| |
| private Combo fCategoryCombo; |
| |
| private Button fCategoryButton; |
| |
| private Text fDescriptionText; |
| |
| protected IModel fCheatSheetModel; |
| |
| private ISharedExtensionsModel fExtensionsModel; |
| |
| private IProject fPluginProject; |
| |
| private String fDataCategoryName; |
| |
| private String fDataDescription; |
| |
| private String fDataCheatSheetID; |
| |
| private CSCategoryTrackerUtil fCategoryTrackerUtil; |
| |
| public RegisterCSWizardPage(IModel model) { |
| super(F_PAGE_NAME); |
| |
| fCheatSheetModel = model; |
| initialize(); |
| } |
| |
| private void initialize() { |
| |
| setTitle(CSWizardMessages.RegisterCSWizardPage_title); |
| setDescription(CSWizardMessages.RegisterCSWizardPage_description); |
| |
| fCategoryCombo = null; |
| fCategoryButton = null; |
| fDescriptionText = null; |
| |
| fCategoryTrackerUtil = new CSCategoryTrackerUtil(); |
| |
| fDataCategoryName = null; |
| fDataDescription = null; |
| |
| // Get the project the cheat sheet is stored in |
| fPluginProject = fCheatSheetModel.getUnderlyingResource().getProject(); |
| |
| fDataCheatSheetID = generateCheatSheetID(); |
| |
| initializePluginModel(); |
| } |
| |
| private void initializePluginModel() { |
| IPluginModelBase base = PluginRegistry.findModel(getPluginProject()); |
| // should never happen |
| if (base == null) |
| return; |
| if (base instanceof IBundlePluginModelBase) |
| fExtensionsModel = ((IBundlePluginModelBase) base).getExtensionsModel(); |
| else |
| fExtensionsModel = base; |
| } |
| |
| @Override |
| public String getDataDescription() { |
| return fDataDescription; |
| } |
| |
| @Override |
| public String getDataCategoryName() { |
| return fDataCategoryName; |
| } |
| |
| @Override |
| public int getDataCategoryType() { |
| String categoryID = getDataCategoryID(); |
| if (categoryID == null) { |
| return CSCategoryTrackerUtil.F_TYPE_NO_CATEGORY; |
| } |
| return fCategoryTrackerUtil.getCategoryType(categoryID); |
| } |
| |
| @Override |
| public String getDataCategoryID() { |
| if (fDataCategoryName != null) { |
| return fCategoryTrackerUtil.getCategoryID(fDataCategoryName); |
| } |
| return null; |
| } |
| |
| @Override |
| public String getDataContentFile() { |
| // Retrieve the project relative path to the cheat sheet |
| String portablePath = fCheatSheetModel.getUnderlyingResource().getProjectRelativePath().toPortableString(); |
| // Prepend the locale specific variable |
| return F_LOCALE_VARIABLE + portablePath; |
| } |
| |
| @Override |
| public String getDataCheatSheetID() { |
| return fDataCheatSheetID; |
| } |
| |
| @Override |
| public IProject getPluginProject() { |
| return fPluginProject; |
| } |
| |
| @Override |
| public abstract String getDataCheatSheetName(); |
| |
| @Override |
| public abstract boolean isCompositeCheatSheet(); |
| |
| @Override |
| public void createControl(Composite parent) { |
| |
| createUI(parent); |
| createUIListeners(); |
| |
| updateUI(); |
| validateUI(); |
| |
| } |
| |
| private void createUI(Composite parent) { |
| // Create the container |
| Composite container = createUIContainer(parent); |
| // Create the label |
| createUILabel(container); |
| // Create the group |
| Group group = createUIGroup(container); |
| // Create the category field |
| createUICategoryField(group); |
| // Create the description field |
| createUIDescriptionField(group); |
| // Set the control for the reciever |
| // Must be done otherwise a null assertion error is generated |
| setControl(container); |
| // Apply the dialog font to all controls using the default font |
| Dialog.applyDialogFont(container); |
| |
| // Provide functionality for the help button |
| PlatformUI.getWorkbench().getHelpSystem().setHelp(container, IHelpContextIds.REGISTER_CS); |
| } |
| |
| private void createUILabel(Composite container) { |
| Label label = new Label(container, SWT.WRAP); |
| label.setText(CSWizardMessages.RegisterCSWizardPage_label); |
| GridData data = new GridData(GridData.FILL_HORIZONTAL); |
| data.widthHint = 300; |
| label.setLayoutData(data); |
| } |
| |
| private Group createUIGroup(Composite container) { |
| Group group = new Group(container, SWT.NONE); |
| GridLayout layout = new GridLayout(3, false); |
| layout.marginWidth = 6; |
| layout.marginHeight = 6; |
| group.setLayout(layout); |
| GridData data = new GridData(GridData.FILL_HORIZONTAL); |
| data.horizontalSpan = 3; |
| data.verticalIndent = 10; |
| group.setLayoutData(data); |
| group.setText(CSWizardMessages.RegisterCSWizardPage_group); |
| return group; |
| } |
| |
| private Composite createUIContainer(Composite parent) { |
| Composite container = new Composite(parent, SWT.NONE); |
| GridLayout layout = new GridLayout(); |
| layout.numColumns = 3; |
| container.setLayout(layout); |
| return container; |
| } |
| |
| private void createUICategoryField(Composite parent) { |
| // Create the label |
| createUICategoryLabel(parent); |
| // Create the combo |
| createUICategoryCombo(parent); |
| // Create the button |
| createUICategoryButton(parent); |
| } |
| |
| private void createUICategoryLabel(Composite parent) { |
| Label label = new Label(parent, SWT.NONE); |
| label.setText(CSWizardMessages.RegisterCSWizardPage_category); |
| } |
| |
| private void createUICategoryCombo(Composite parent) { |
| int style = SWT.READ_ONLY | SWT.BORDER; |
| fCategoryCombo = new Combo(parent, style); |
| GridData data = new GridData(GridData.FILL_HORIZONTAL); |
| fCategoryCombo.setLayoutData(data); |
| fCategoryCombo.add(CSWizardMessages.RegisterCSWizardPage_none); |
| fCategoryCombo.setText(CSWizardMessages.RegisterCSWizardPage_none); |
| } |
| |
| private void createUICategoryButton(Composite parent) { |
| fCategoryButton = new Button(parent, SWT.PUSH); |
| GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END); |
| data.widthHint = 50; |
| fCategoryButton.setLayoutData(data); |
| fCategoryButton.setText(CSWizardMessages.RegisterCSWizardPage_new); |
| fCategoryButton.setToolTipText(CSWizardMessages.RegisterCSWizardPage_newTooltip); |
| SWTUtil.setButtonDimensionHint(fCategoryButton); |
| } |
| |
| private void createUIDescriptionField(Composite parent) { |
| // Create the label |
| createUIDescriptionLabel(parent); |
| // Create the text widget |
| createUIDescriptionText(parent); |
| } |
| |
| private void createUIDescriptionLabel(Composite parent) { |
| Label label = new Label(parent, SWT.NONE); |
| label.setText(CSWizardMessages.RegisterCSWizardPage_desc); |
| int style = GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_END; |
| GridData data = new GridData(style); |
| label.setLayoutData(data); |
| } |
| |
| private void createUIDescriptionText(Composite parent) { |
| int style = SWT.MULTI | SWT.WRAP | SWT.V_SCROLL | SWT.BORDER; |
| fDescriptionText = new Text(parent, style); |
| GridData data = new GridData(GridData.FILL_HORIZONTAL); |
| data.heightHint = 60; |
| data.horizontalSpan = 2; |
| fDescriptionText.setLayoutData(data); |
| } |
| |
| private void createUIListeners() { |
| // Create listeners for the category button |
| createUIListenersCategoryButton(); |
| // Create listeners for the category combo box |
| createUIListenersCategoryCombo(); |
| // Create listeners for the description text |
| createUIListenersDescriptionText(); |
| } |
| |
| private void createUIListenersCategoryButton() { |
| fCategoryButton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| handleWidgetSelectedCategoryButton(); |
| } |
| }); |
| } |
| |
| private void createUIListenersCategoryCombo() { |
| fCategoryCombo.addModifyListener(new ModifyListener() { |
| @Override |
| public void modifyText(ModifyEvent e) { |
| fDataCategoryName = fCategoryCombo.getText(); |
| } |
| }); |
| } |
| |
| private void createUIListenersDescriptionText() { |
| fDescriptionText.addModifyListener(new ModifyListener() { |
| @Override |
| public void modifyText(ModifyEvent e) { |
| fDataDescription = fDescriptionText.getText(); |
| } |
| }); |
| } |
| |
| private void handleWidgetSelectedCategoryButton() { |
| // Create a dialog allowing the user to input the category name |
| NewCategoryNameDialog dialog = new NewCategoryNameDialog(PDEUserAssistanceUIPlugin.getActiveWorkbenchShell()); |
| dialog.create(); |
| dialog.getShell().setText(CSWizardMessages.RegisterCSWizardPage_descTooltip); |
| |
| if (dialog.open() == Window.OK) { |
| String newCategoryName = dialog.getNameText(); |
| |
| if (PDETextHelper.isDefinedAfterTrim(newCategoryName)) { |
| String trimmedText = newCategoryName.trim(); |
| fCategoryCombo.add(trimmedText); |
| fCategoryCombo.setText(trimmedText); |
| fCategoryCombo.setFocus(); |
| String id = generateCategoryID(trimmedText); |
| fCategoryTrackerUtil.associate(id, trimmedText, CSCategoryTrackerUtil.F_TYPE_NEW_CATEGORY); |
| } |
| } |
| |
| } |
| |
| private void updateUI() { |
| |
| if (fExtensionsModel != null) { |
| // Find all cheat sheet extensions within the host plug-in |
| IPluginExtension[] extensions = RegisterCSOperation.findCheatSheetExtensions(fExtensionsModel); |
| // Process all category elements |
| processCategoryElements(extensions); |
| // Process all cheat sheet elements |
| processCheatSheetElements(extensions); |
| } |
| } |
| |
| private void processCategoryElements(IPluginExtension[] extensions) { |
| // Linear search: Process all cheat sheet extensions found |
| for (int i = 0; i < extensions.length; i++) { |
| if (extensions[i].getChildCount() == 0) { |
| // Extension has no children, skip to the next extension |
| continue; |
| } |
| IPluginExtension extension = extensions[i]; |
| IPluginObject[] pluginObjects = extension.getChildren(); |
| // Process all children |
| for (int j = 0; j < pluginObjects.length; j++) { |
| if (pluginObjects[j] instanceof IPluginElement) { |
| IPluginElement element = (IPluginElement) pluginObjects[j]; |
| if (element.getName().equals(F_CS_ELEMENT_CATEGORY)) { |
| // Category element |
| // Update the category combo |
| updateUICategoryComboElement(element); |
| } |
| } |
| } |
| } |
| } |
| |
| private void processCheatSheetElements(IPluginExtension[] extensions) { |
| // Query cheat sheet extensions for information required to update |
| // the description text and category combo widgets |
| // Linear search: Process all cheat sheet extensions found |
| for (int i = 0; i < extensions.length; i++) { |
| if (extensions[i].getChildCount() == 0) { |
| // Extension has no children, skip to the next extension |
| continue; |
| } |
| IPluginExtension extension = extensions[i]; |
| IPluginObject[] pluginObjects = extension.getChildren(); |
| // Process all children |
| for (int j = 0; j < pluginObjects.length; j++) { |
| if (pluginObjects[j] instanceof IPluginElement) { |
| IPluginElement element = (IPluginElement) pluginObjects[j]; |
| if (element.getName().equals(F_CS_ELEMENT_CHEATSHEET)) { |
| // Cheat sheet element |
| processCheatSheetElement(element, fDataCheatSheetID); |
| } |
| |
| } |
| } |
| } |
| } |
| |
| /** |
| * Process category elements |
| * @param parentElement |
| */ |
| private void updateUICategoryComboElement(IPluginElement parentElement) { |
| // Get the id attribute |
| IPluginAttribute idAttribute = parentElement.getAttribute(ICompCSConstants.ATTRIBUTE_ID); |
| // Get the name attribute |
| IPluginAttribute nameAttribute = parentElement.getAttribute(ICompCSConstants.ATTRIBUTE_NAME); |
| // Add the category to the combo box only if |
| // (1) the category name is defined |
| // (2) the category has not already been added to the combo box |
| if ((nameAttribute != null) && PDETextHelper.isDefined(nameAttribute.getValue()) && (idAttribute != null) && PDETextHelper.isDefined(idAttribute.getValue()) && (fCategoryTrackerUtil.containsCategoryName(nameAttribute.getValue()) == false)) { |
| // TODO: MP: LOW: CompCS: Reference translated value |
| fCategoryCombo.add(nameAttribute.getValue()); |
| // Assocate the category ID with the category name |
| fCategoryTrackerUtil.associate(idAttribute.getValue(), nameAttribute.getValue(), CSCategoryTrackerUtil.F_TYPE_OLD_CATEGORY); |
| } |
| } |
| |
| /** |
| * Process cheatsheet elements with a category attribute |
| * @param parentElement |
| */ |
| private void updateUICategoryComboAttribute(IPluginElement element) { |
| // Get the category attribute |
| IPluginAttribute categoryAttribute = element.getAttribute(F_CS_ELEMENT_CATEGORY); |
| // Process the category attribute |
| if ((categoryAttribute != null) && PDETextHelper.isDefined(categoryAttribute.getValue())) { |
| String id = categoryAttribute.getValue(); |
| // Check to see if the category ID has been defined |
| if (fCategoryTrackerUtil.containsCategoryID(id)) { |
| // Update the category combo selection |
| String name = fCategoryTrackerUtil.getCategoryName(id); |
| fCategoryCombo.setText(name); |
| } else { |
| // Add the category ID to the combo box (no assoicated name) |
| // This can only happen if the category is defined outside of |
| // the plug-in the cheat sheet is stored in |
| fCategoryCombo.add(id); |
| fCategoryCombo.setText(id); |
| fCategoryTrackerUtil.associate(id, id, CSCategoryTrackerUtil.F_TYPE_OLD_CATEGORY); |
| } |
| } |
| } |
| |
| private void processCheatSheetElement(IPluginElement parentElement, String generatedID) { |
| // Get the id attribute |
| IPluginAttribute idAttribute = parentElement.getAttribute(ICompCSConstants.ATTRIBUTE_ID); |
| |
| // Check for the generated ID for this cheat sheet |
| // If a cheat sheet exists with the generated ID already, read its |
| // description and populate the description text accordingly |
| if ((idAttribute != null) && PDETextHelper.isDefined(idAttribute.getValue()) && generatedID.equals(idAttribute.getValue())) { |
| // Matching cheat sheet extension found |
| // Process children if any |
| if (parentElement.getChildCount() > 0) { |
| // Update the description text widget |
| updateUIDescriptionText(parentElement); |
| } |
| updateUICategoryComboAttribute(parentElement); |
| } |
| } |
| |
| private void updateUIDescriptionText(IPluginElement parentElement) { |
| IPluginObject pluginObject = parentElement.getChildren()[0]; |
| if (pluginObject instanceof IPluginElement) { |
| IPluginElement element = (IPluginElement) pluginObject; |
| if (element.getName().equals(F_CS_ELEMENT_DESCRIPTION) && PDETextHelper.isDefinedAfterTrim(element.getText())) { |
| // Triggers listener to update data description on load |
| fDescriptionText.setText(element.getText().trim()); |
| } |
| } |
| } |
| |
| private void validateUI() { |
| setPageComplete(true); |
| } |
| |
| public IPluginExtension[] findExtensions(ISharedExtensionsModel model, String extensionPointID) { |
| IPluginExtension[] extensions = model.getExtensions().getExtensions(); |
| |
| ArrayList csExtensions = new ArrayList(); |
| for (int i = 0; i < extensions.length; i++) { |
| String point = extensions[i].getPoint(); |
| if (extensionPointID.equals(point)) { |
| csExtensions.add(extensions[i]); |
| } |
| } |
| return (IPluginExtension[]) csExtensions.toArray(new IPluginExtension[csExtensions.size()]); |
| } |
| |
| private String generateCheatSheetID() { |
| // Generate the hash code using the full path |
| long uniqueID = hash(fCheatSheetModel.getUnderlyingResource().getFullPath().toPortableString()); |
| // Qualify with the project name |
| // Append the hash code to make the name unique and allow cheat sheets |
| // with the same name (but different directories) be registered |
| // individually |
| String result = fPluginProject.getName() + '.' + F_CS_ELEMENT_CHEATSHEET + uniqueID; |
| return result; |
| } |
| |
| private String generateCategoryID(String name) { |
| // Generate the hash code using the category name |
| long uniqueID = hash(name); |
| // Qualify with the project name |
| // Append the hash code to make the name unique |
| String result = fPluginProject.getName() + '.' + F_CS_ELEMENT_CATEGORY + uniqueID; |
| return result; |
| } |
| |
| private long hash(String string) { |
| int b = 378551; |
| int a = 63689; |
| long hash = 0; |
| |
| for (int i = 0; i < string.length(); i++) { |
| hash = hash * a + string.charAt(i); |
| a = a * b; |
| } |
| return (hash & 0x7FFFFFFF); |
| } |
| |
| } |