blob: 0afff2beacf8bcc81879ad618db2685240ec3b0e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2017 SAP AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Mathias Kinzler (SAP AG) - initial implementation
* Thomas Wolf <thomas.wolf@paranor.ch> - input validation
*******************************************************************************/
package org.eclipse.egit.ui.internal.preferences;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
import org.eclipse.egit.ui.internal.UIText;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridLayout;
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;
/**
* Requests a key and value for adding a configuration entry.
*/
public class AddConfigEntryDialog extends TitleAreaDialog {
/**
* Regular expression describing a valid git config key. See config.c in the
* CGit sources, or https://git-scm.com/docs/git-config. Basically it's
* section.subsection.name, where section and name must contain only
* alphanumeric characters or the dash, and name must start with a letter.
*
* Cgit also allows periods in the section name to support the legacy syntax
* [section.subsection]. For our use case, this is irrelevant, and EGit
* takes only the first segment as section name.
*
* Note that we allow arbitrary whitespace before and after; we'll trim that
* away in {@link #okPressed}.
*/
private static final Pattern VALID_KEY = Pattern
.compile(
"(\\h|\\v)*[-\\p{Alnum}]+(?:\\..*)?\\.\\p{Alpha}[-\\p{Alnum}]*(\\h|\\v)*"); //$NON-NLS-1$
private Text keyText;
private Text valueText;
private String key;
private String value;
private final String suggestedKey;
/**
* @param parentShell
* @param suggestedKey
* may be null
*/
public AddConfigEntryDialog(Shell parentShell, String suggestedKey) {
super(parentShell);
setHelpAvailable(false);
this.suggestedKey = suggestedKey;
setHelpAvailable(false);
}
@Override
protected Control createDialogArea(Composite parent) {
getShell().setText(UIText.AddConfigEntryDialog_AddConfigTitle);
setTitle(UIText.AddConfigEntryDialog_AddConfigTitle);
setMessage(UIText.AddConfigEntryDialog_DialogMessage);
Composite titleParent = (Composite) super.createDialogArea(parent);
Composite main = new Composite(titleParent, SWT.NONE);
main.setLayout(new GridLayout(2, false));
GridDataFactory.fillDefaults().grab(true, true).applyTo(main);
Label keylLabel = new Label(main, SWT.NONE);
keylLabel.setText(UIText.AddConfigEntryDialog_KeyLabel);
keylLabel.setToolTipText(UIText.AddConfigEntryDialog_ConfigKeyTooltip);
keyText = new Text(main, SWT.BORDER);
if (suggestedKey != null) {
keyText.setText(trimKey(suggestedKey));
keyText.selectAll();
}
keyText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
check();
}
});
GridDataFactory.fillDefaults().grab(true, false).applyTo(keyText);
new Label(main, SWT.NONE)
.setText(UIText.AddConfigEntryDialog_ValueLabel);
valueText = new Text(main, SWT.BORDER);
valueText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
check();
}
});
GridDataFactory.fillDefaults().grab(true, false).applyTo(valueText);
applyDialogFont(main);
return main;
}
private boolean isValidKey(String keyValue) {
return keyValue != null && VALID_KEY.matcher(keyValue).matches();
}
private String trimKey(String keyValue) {
return keyValue.replaceAll("^(?:\\h|\\v)*|(?:\\h|\\v)*$", ""); //$NON-NLS-1$ //$NON-NLS-2$
}
@Override
public void create() {
super.create();
// we need to enter something
getButton(OK).setEnabled(false);
}
private void check() {
setErrorMessage(null);
boolean hasError = false;
try {
if (keyText.getText().length() == 0) {
setErrorMessage(UIText.AddConfigEntryDialog_MustEnterKeyMessage);
hasError = true;
return;
}
StringTokenizer st = new StringTokenizer(keyText.getText(), "."); //$NON-NLS-1$
if (st.countTokens() < 2) {
setErrorMessage(UIText.AddConfigEntryDialog_KeyComponentsMessage);
hasError = true;
return;
}
if (!isValidKey(keyText.getText())) {
setErrorMessage(UIText.AddConfigEntryDialog_InvalidKeyMessage);
hasError = true;
return;
}
if (valueText.getText().length() == 0) {
setErrorMessage(UIText.AddConfigEntryDialog_EnterValueMessage);
hasError = true;
return;
}
} finally {
getButton(OK).setEnabled(!hasError);
}
}
@Override
protected void okPressed() {
key = trimKey(keyText.getText());
value = valueText.getText();
super.okPressed();
}
/**
* @return the key as entered by the user
*/
public String getKey() {
return key;
}
/**
* @return the value as entered by the user
*/
public String getValue() {
return value;
}
}