Java tutorial
/******************************************************************************* * Copyright (c) 2010 SAP AG. * 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: * Mathias Kinzler (SAP AG) - initial implementation *******************************************************************************/ package org.eclipse.egit.ui.internal.repository; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import org.eclipse.egit.ui.Activator; import org.eclipse.egit.ui.UIIcons; import org.eclipse.egit.ui.UIText; import org.eclipse.egit.ui.internal.preferences.ConfigurationEditorComponent; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.ActionContributionItem; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.TitleAreaDialog; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.SystemReader; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; import org.eclipse.ui.IActionBars; import org.eclipse.ui.views.properties.IPropertyDescriptor; import org.eclipse.ui.views.properties.IPropertySource; import org.eclipse.ui.views.properties.PropertyDescriptor; import org.eclipse.ui.views.properties.PropertySheetPage; /** * Properties for repository and user configuration (read-only). * <p> * Depending on which mode is selected, either the user configuration, the * repository configuration, or the effective configuration is shown. */ public class RepositoryPropertySource implements IPropertySource { static final String CHANGEMODEACTIONID = "ChangeMode"; //$NON-NLS-1$ static final String SINGLEVALUEACTIONID = "SingleValueToggle"; //$NON-NLS-1$ static final String EDITACTIONID = "Edit"; //$NON-NLS-1$ private static final String USER_ID_PREFIX = "user"; //$NON-NLS-1$ private static final String REPO_ID_PREFIX = "repo"; //$NON-NLS-1$ private static final String EFFECTIVE_ID_PREFIX = "effe"; //$NON-NLS-1$ private final PropertySheetPage myPage; private final FileBasedConfig userHomeConfig; private final StoredConfig repositoryConfig; private final StoredConfig effectiveConfig; private ActionContributionItem changeModeAction; private ActionContributionItem editAction; private ActionContributionItem singleValueToggleAction; /** * @param repository * the repository * @param page * the page showing the properties */ public RepositoryPropertySource(Repository repository, PropertySheetPage page) { myPage = page; effectiveConfig = repository.getConfig(); userHomeConfig = SystemReader.getInstance().openUserConfig(FS.DETECTED); if (effectiveConfig instanceof FileBasedConfig) { File configFile = ((FileBasedConfig) effectiveConfig).getFile(); repositoryConfig = new FileBasedConfig(configFile, repository.getFS()); } else { repositoryConfig = effectiveConfig; } synchronized (myPage) { // check if the actions are already there, if not, create them IActionBars bars = myPage.getSite().getActionBars(); changeModeAction = (ActionContributionItem) bars.getToolBarManager().find(CHANGEMODEACTIONID); singleValueToggleAction = (ActionContributionItem) bars.getToolBarManager().find(SINGLEVALUEACTIONID); if (changeModeAction != null) { return; } changeModeAction = new ActionContributionItem( new Action(DisplayMode.REPO.getText(), IAction.AS_DROP_DOWN_MENU) { @Override public String getId() { return CHANGEMODEACTIONID; } @Override public void run() { MenuManager mgr = new MenuManager(); ToolItem item = (ToolItem) changeModeAction.getWidget(); ToolBar control = item.getParent(); final Menu ctxMenu = mgr.createContextMenu(control); for (final DisplayMode aMode : DisplayMode.values()) { mgr.add(new Action(aMode.getText()) { @Override public void run() { changeModeAction.getAction().setText(aMode.getText()); editAction.getAction().setEnabled(aMode != DisplayMode.EFFECTIVE); myPage.refresh(); } @Override public boolean isEnabled() { return aMode != getCurrentMode(); } @Override public boolean isChecked() { return aMode == getCurrentMode(); } @Override public int getStyle() { return IAction.AS_CHECK_BOX; } }); } ctxMenu.setVisible(true); } @Override public String getToolTipText() { return UIText.RepositoryPropertySource_SelectModeTooltip; } @Override public int getStyle() { return IAction.AS_DROP_DOWN_MENU; } }); editAction = new ActionContributionItem( new Action(UIText.RepositoryPropertySource_EditConfigButton, UIIcons.EDITCONFIG) { @Override public String getId() { return EDITACTIONID; } @Override public void run() { final StoredConfig config; switch (getCurrentMode()) { case EFFECTIVE: return; case USER: config = userHomeConfig; break; case REPO: config = repositoryConfig; break; default: return; } new EditDialog(myPage.getSite().getShell(), (FileBasedConfig) config, getCurrentMode().getText()).open(); myPage.refresh(); } @Override public int getStyle() { return IAction.AS_PUSH_BUTTON; } }); singleValueToggleAction = new ActionContributionItem( new Action(UIText.RepositoryPropertySource_SingleValueButton) { @Override public String getId() { return SINGLEVALUEACTIONID; } @Override public void run() { myPage.refresh(); } @Override public int getStyle() { return IAction.AS_CHECK_BOX; } @Override public String getToolTipText() { return UIText.RepositoryPropertySource_SuppressMultipleValueTooltip; } }); bars.getToolBarManager().add(new Separator()); bars.getToolBarManager().add(changeModeAction); bars.getToolBarManager().add(singleValueToggleAction); bars.getToolBarManager().add(editAction); bars.getToolBarManager().update(false); } } private DisplayMode getCurrentMode() { String actionText = changeModeAction.getAction().getText(); for (DisplayMode aMode : DisplayMode.values()) { if (aMode.getText().equals(actionText)) return aMode; } return null; } private boolean getSingleValueMode() { if (singleValueToggleAction != null) return singleValueToggleAction.getAction().isChecked(); return false; } private Object getValueFromConfig(Config config, String keyString) { StringTokenizer tok = new StringTokenizer(keyString, "."); //$NON-NLS-1$ String section; String subsection; String name; String[] valueList = null; if (tok.countTokens() == 2) { section = tok.nextToken(); subsection = null; name = tok.nextToken(); } else if (tok.countTokens() == 3) { section = tok.nextToken(); subsection = tok.nextToken(); name = tok.nextToken(); } else { return ""; //$NON-NLS-1$ } if (getSingleValueMode()) valueList = new String[] { config.getString(section, subsection, name) }; else valueList = config.getStringList(section, subsection, name); if (valueList == null || valueList.length == 0) return null; if (valueList.length == 1) { return valueList[0]; } StringBuilder sb = new StringBuilder(); for (String value : valueList) { sb.append('['); sb.append(value); sb.append(']'); } return sb.toString(); } public Object getEditableValue() { return null; } public IPropertyDescriptor[] getPropertyDescriptors() { try { userHomeConfig.load(); repositoryConfig.load(); effectiveConfig.load(); } catch (IOException e) { showExceptionMessage(e); } catch (ConfigInvalidException e) { showExceptionMessage(e); } List<IPropertyDescriptor> resultList = new ArrayList<IPropertyDescriptor>(); StoredConfig config; String category; String prefix; switch (getCurrentMode()) { case EFFECTIVE: prefix = EFFECTIVE_ID_PREFIX; category = UIText.RepositoryPropertySource_EffectiveConfigurationCategory; config = effectiveConfig; break; case REPO: { prefix = REPO_ID_PREFIX; String location = ""; //$NON-NLS-1$ if (repositoryConfig instanceof FileBasedConfig) { location = ((FileBasedConfig) repositoryConfig).getFile().getAbsolutePath(); } category = NLS.bind(UIText.RepositoryPropertySource_RepositoryConfigurationCategory, location); config = repositoryConfig; break; } case USER: { prefix = USER_ID_PREFIX; String location = userHomeConfig.getFile().getAbsolutePath(); category = NLS.bind(UIText.RepositoryPropertySource_GlobalConfigurationCategory, location); config = userHomeConfig; break; } default: return new IPropertyDescriptor[0]; } for (String key : config.getSections()) { for (String sectionItem : config.getNames(key)) { String sectionId = key + "." + sectionItem; //$NON-NLS-1$ PropertyDescriptor desc = new PropertyDescriptor(prefix + sectionId, sectionId); desc.setCategory(category); resultList.add(desc); } for (String sub : config.getSubsections(key)) { for (String sectionItem : config.getNames(key, sub)) { String sectionId = key + "." + sub + "." + sectionItem; //$NON-NLS-1$ //$NON-NLS-2$ PropertyDescriptor desc = new PropertyDescriptor(prefix + sectionId, sectionId); desc.setCategory(category); resultList.add(desc); } } } return resultList.toArray(new IPropertyDescriptor[0]); } public Object getPropertyValue(Object id) { String actId = ((String) id); Object value = null; if (actId.startsWith(USER_ID_PREFIX)) { value = getValueFromConfig(userHomeConfig, actId.substring(4)); } else if (actId.startsWith(REPO_ID_PREFIX)) { value = getValueFromConfig(repositoryConfig, actId.substring(4)); } else if (actId.startsWith(EFFECTIVE_ID_PREFIX)) { value = getValueFromConfig(effectiveConfig, actId.substring(4)); } if (value == null) // the text editor needs this to work return ""; //$NON-NLS-1$ return value; } public boolean isPropertySet(Object id) { return false; } public void resetPropertyValue(Object id) { // no editing here } public void setPropertyValue(Object id, Object value) { // no editing here } private void showExceptionMessage(Exception e) { Activator.handleError(UIText.RepositoryPropertySource_ErrorHeader, e, true); } private enum DisplayMode { /* The effective configuration as obtained from the repository */ EFFECTIVE(UIText.RepositoryPropertySource_EffectiveConfigurationAction), /* The user specific configuration */ USER(UIText.RepositoryPropertySource_GlobalConfigurationMenu), /* The repository specific configuration */ REPO(UIText.RepositoryPropertySource_RepositoryConfigurationButton); /** * @return the human-readable String for this mode */ String getText() { return this.text; } private final String text; private DisplayMode(String text) { this.text = text; } } /** * Wraps the editor component into a dialog */ private final static class EditDialog extends TitleAreaDialog { private final FileBasedConfig myConfig; private final String myTitle; ConfigurationEditorComponent editor; public EditDialog(Shell shell, FileBasedConfig config, String title) { super(shell); myConfig = config; setShellStyle(getShellStyle() | SWT.SHELL_TRIM); myTitle = title; setHelpAvailable(false); } @Override protected Control createDialogArea(Composite parent) { Composite main = (Composite) super.createDialogArea(parent); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(main); editor = new ConfigurationEditorComponent(main, myConfig, true) { @Override protected void setErrorMessage(String message) { EditDialog.this.setErrorMessage(message); } @Override protected void setDirty(boolean dirty) { getButton(IDialogConstants.OK_ID).setEnabled(dirty); } }; Control result = editor.createContents(); applyDialogFont(main); return result; } @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText(UIText.RepositoryPropertySource_EditConfigurationTitle); newShell.setSize(700, 600); } @Override public void create() { super.create(); setTitle(myTitle); setMessage(UIText.RepositoryPropertySource_EditorMessage); getButton(IDialogConstants.OK_ID).setEnabled(false); } @Override protected void okPressed() { try { editor.save(); super.okPressed(); } catch (IOException e) { Activator.handleError(e.getMessage(), e, true); } } } }