blob: 18a48d5a5c23007e7ef5f5840fe00749b57bf957 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2010 Soyatec (http://www.soyatec.com) 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:
* Soyatec - initial API and implementation
*******************************************************************************/
package org.eclipse.xwt.tools.ui.designer.wizards.pages;
import java.io.IOException;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jface.dialogs.IDialogPage;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
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.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.xwt.tools.ui.designer.dialogs.AccessorConfigurationDialog;
import org.eclipse.xwt.tools.ui.designer.providers.ExternalizeStringContentProvider;
import org.eclipse.xwt.tools.ui.designer.providers.ExternalizeStringLabelProvider;
import org.eclipse.xwt.tools.ui.designer.wizards.AccessorConfigureInfo;
import org.eclipse.xwt.tools.ui.designer.wizards.ExternalizeStringsCommon;
import org.eclipse.xwt.tools.ui.designer.wizards.TableCellModifier;
import org.eclipse.xwt.tools.ui.designer.wizards.TableViewerListener;
import org.eclipse.xwt.tools.ui.designer.wizards.models.TextValueEntry;
import org.eclipse.xwt.tools.ui.designer.wizards.models.TextValueModel;
/**
* @author xrchen (xiaoru.chen@soyatec.com)
*/
public class ExternalizeStringsWizardPage extends WizardPage {
private TextValueModel checkedItems;
private TextValueModel textValueEntrys;
private TableViewer tableViewer;
private Text commonPrefixText;
private boolean isChecked = false;
private int checkCount = 0;
public static final String CHECK_COLUMN_ID = "";
public static final String VALUE_COLUMN_ID = "Value";
public static final String KEY_COLUMN_ID = "Key";
private String defaultFolder;
private String defaultPackage;
private IPackageFragmentRoot defaultRoot;
private AccessorConfigureInfo info = new AccessorConfigureInfo();
private Combo combo;
private ArrayList<String> duplicateKeys;
// create a PropertyFileListener instance.
private final TableViewerListener tableViewerListener = new TableViewerListener() {
public void valueChanged(TextValueEntry textValueEntry) {
tableViewer.refresh(textValueEntry, true);
changeContents();
}
};
/**
* Constructor for ExternalizeStringsWizardPage.
*
* @param selection
* @param textValueEntrys
*/
public ExternalizeStringsWizardPage(ISelection selection, TextValueModel textValueEntrys) {
super("wizardPage");
setTitle("Externalize Strings");
setDescription("Externalizes strings from code into a properties file. The auto-generated keys should be adjusted.");
this.textValueEntrys = textValueEntrys;
}
/**
* @see IDialogPage#createControl(Composite)
*/
public void createControl(Composite parent) {
Composite container = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
container.setLayout(layout);
// Create filed for user to change the prefix of the key
Composite childcontainer = new Composite(container, SWT.NONE);
layout = new GridLayout();
layout.numColumns = 2;
childcontainer.setLayout(layout);
GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
gridData.horizontalSpan = 2;
childcontainer.setLayoutData(gridData);
Label commonPrefixLabel = new Label(childcontainer, SWT.NONE);
commonPrefixLabel.setText("Enter common prefix for generated keys(optional):");
commonPrefixText = new Text(childcontainer, SWT.BORDER);
gridData = new GridData(GridData.FILL_HORIZONTAL);
commonPrefixText.setText("Text_");
commonPrefixText.setLayoutData(gridData);
commonPrefixText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
tableViewer.setLabelProvider(new ExternalizeStringLabelProvider(commonPrefixText.getText()));
if (checkCount > 0) {
checkPrefix();
}
changeContents();
}
});
setPageComplete(false);
// Create the tableViewer of the text value which have not been externalized or been binded.
createWidgetObserve(container);
// Create select all button.
createSelectAllButton(container);
// Create the the configure field.
createAccessorConfigure(container);
setControl(container);
// Initial the configure files information.
String defaultFilePath = "/" + defaultFolder + "/" + defaultPackage.replace(".", "/");
info.setClassFilePath(defaultFilePath);
info.setClassRoot(defaultRoot);
info.setSourceFolder(defaultFolder);
info.setSourcePackage(defaultPackage);
info.setClassName("Messages");
info.setPropertyFilePath(defaultFilePath);
info.setPropertyRoot(defaultRoot);
info.setPropertyFolder(defaultFolder);
info.setPropertyPackage(defaultPackage);
info.setPropertyName("messages");
}
/**
* Create select all button
*/
private void createSelectAllButton(Composite container) {
Button button = new Button(container, SWT.PUSH);
button.setText("Select All");
GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
button.setLayoutData(gridData);
gridData = new GridData(GridData.FILL_HORIZONTAL);
gridData.horizontalSpan = 2;
button.setLayoutData(gridData);
button.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
int length = tableViewer.getTable().getItems().length;
if (checkCount < length) {
for (int i = 0; i < length; i++) {
tableViewer.getTable().getItem(i).setChecked(true);
tableViewer.getTable().getItem(i).setBackground(new Color(Display.getDefault(), 226, 226, 226));
}
checkCount = length;
} else {
for (int i = 0; i < length; i++) {
tableViewer.getTable().getItem(i).setChecked(false);
tableViewer.getTable().getItem(i).setBackground(ColorConstants.listBackground);
}
checkCount = 0;
}
changeContents();
updatePageComplete(checkCount);
}
public void widgetDefaultSelected(SelectionEvent e) {
}
});
}
private void createAccessorConfigure(Composite container) {
combo = new Combo(container, SWT.READ_ONLY);
GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
gridData.widthHint = convertWidthInCharsToPixels(30);
combo.setLayoutData(gridData);
combo.setItems(new String[] { defaultPackage + ".Messages.java - " + defaultPackage + ".messages.properties" });
combo.select(0);
Button configureButton = new Button(container, SWT.PUSH);
configureButton.setText("Configure...");
gridData = new GridData();
configureButton.setLayoutData(gridData);
configureButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
AccessorConfigurationDialog dialog = new AccessorConfigurationDialog(getShell(), info);
dialog.setTitle("Configure Accessor Class");
if (dialog.open() == Window.OK) {
// Get the information of configure files.
info.setClassFilePath(dialog.getClassFilePath());
info.setClassRoot(dialog.getclassRoot());
info.setSourceFolder(dialog.getSourceFolder());
info.setSourcePackage(dialog.getSourcePackage());
info.setClassName(dialog.getClassName());
info.setPropertyFilePath(dialog.getPropertyFilePath());
info.setPropertyRoot(dialog.getPropertyRoot());
info.setPropertyFolder(dialog.getPropertyFolder());
info.setPropertyPackage(dialog.getPropertyPackage());
info.setPropertyName(dialog.getPropertyName());
combo.setItems(new String[] { dialog.getSourcePackage() + ((dialog.getSourcePackage() == null || "".equals(dialog.getSourcePackage())) ? "" : ".") + dialog.getClassName() + ".java - " + dialog.getPropertyPackage() + "." + dialog.getPropertyName() + ".properties" });
combo.select(0);
changeContents();
}
}
public void widgetDefaultSelected(SelectionEvent e) {
}
});
}
/**
* Create the widget's text values observe container
*
* @param container
*/
private void createWidgetObserve(Composite container) {
Composite viewContainer = new Composite(container, SWT.BORDER);
GridLayout layout = new GridLayout();
viewContainer.setLayout(layout);
GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
gridData.horizontalSpan = 2;
viewContainer.setLayoutData(gridData);
tableViewer = new TableViewer(viewContainer, SWT.CHECK | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL);
Table table = tableViewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(true);
gridData.heightHint = table.getItemHeight() * 11;
table.setLayoutData(gridData);
// Create the header of the table
String[] colNames = { "", "Value", "Key" };
int[] colWidths = { 50, 300, 300 };
for (int i = 0; i < colNames.length; i++) {
TableColumn tableColumn = new TableColumn(table, SWT.NONE);
tableColumn.setText(colNames[i]);
tableColumn.setWidth(colWidths[i]);
}
tableViewer.setLabelProvider(new ExternalizeStringLabelProvider(commonPrefixText.getText()));
tableViewer.setContentProvider(new ExternalizeStringContentProvider());
tableViewer.setInput(textValueEntrys);
tableViewer.getTable().getDisplay().asyncExec(new Runnable() {
public void run() {
TextValueModel textValueModel = (TextValueModel) tableViewer.getInput();
textValueModel.addPropertyChangeListener(tableViewerListener);
}
});
initTableEditor();
tableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
changeContents();
updatePageComplete(checkCount);
}
});
}
/**
* make cell of the tableViewer editable.
*/
private void initTableEditor() {
tableViewer.setColumnProperties(new String[] { CHECK_COLUMN_ID, VALUE_COLUMN_ID, KEY_COLUMN_ID });
final TextCellEditor valueEditor = new TextCellEditor(tableViewer.getTable());
final TextCellEditor keyEditor = new TextCellEditor(tableViewer.getTable());
tableViewer.setCellEditors(new CellEditor[] { null, valueEditor, keyEditor });
tableViewer.setCellModifier(new TableCellModifier());
}
public TextValueModel getCheckedItems() {
return checkedItems;
}
private void updatePageComplete(int checkNum) {
isChecked = false;
if (checkNum > 0) {
isChecked = true;
if (getErrorMessage() != null) {
setPageComplete(false);
} else {
setPageComplete(true);
}
} else {
updateStatus(null);
}
}
/**
* check the prefix string format.
*/
private void checkPrefix() {
String checkValue = commonPrefixText.getText();
if (!"".equals(checkValue)) {
String regex = "^([_|a-zA-Z])[_\\w]*$";
checkFormat(checkValue, regex);
}
}
/**
* check the prefix string format.
*/
private boolean checkKeyValue(String keyValue) {
String regex = "^([_|a-zA-Z])[_\\w]*$";
return checkFormat(keyValue, regex);
}
/**
* check string format
*
* @param value
*/
private boolean checkFormat(String value, String regex) {
Matcher matcher = Pattern.compile(regex).matcher(value);
if (!(matcher.find())) {
updateStatus("Some selected keys are not valid Java identifiers.");
return false;
} else {
updateStatus(null);
return true;
}
}
/**
* Update the page's status.
*
* @param message
*/
private void updateStatus(String message) {
setErrorMessage(message);
setPageComplete((message == null) && isChecked);
}
/**
* Check the change nameMap and get the selected values.
*/
private void changeContents() {
int count = tableViewer.getTable().getItemCount();
String checkValue = "";
checkedItems = new TextValueModel();
for (int i = 0; i < count; i++) {
if (tableViewer.getTable().getItem(i).getChecked()) {
tableViewer.getTable().getItem(i).setBackground(new Color(Display.getDefault(), 226, 226, 226));
if (tableViewer.getElementAt(i) instanceof TextValueEntry) {
String value = ((TextValueEntry) (tableViewer.getElementAt(i))).getValue();
String key = commonPrefixText.getText() + ((TextValueEntry) (tableViewer.getElementAt(i))).getKey();
checkedItems.add(new TextValueEntry(value, key));
}
checkValue = commonPrefixText.getText() + ((TextValueEntry) (tableViewer.getElementAt(i))).getKey();
if (!checkKeyValue(checkValue)) {
break;
}
} else {
tableViewer.getTable().getItem(i).setBackground(ColorConstants.listBackground);
}
}
checkSameValue();
checkDuplicate(info.getClassFilePath(), info.getClassName() + ".java", info.getPropertyFilePath(), info.getPropertyName() + ".properties");
checkCount = getCheckNum();
}
/**
* Get the checked number of tableViewer's items.
*
* @return checkNum
*/
private int getCheckNum() {
int checkNum = 0;
for (int i = 0; i < tableViewer.getTable().getItems().length; i++) {
if (tableViewer.getTable().getItem(i).getChecked()) {
checkNum++;
}
}
return checkNum;
}
/**
* check the selected keys whether have a same key.
*/
private void checkSameValue() {
Object selectedKeys[] = checkedItems.elements();
String key;
String value;
String compareKey;
String comparevalue;
String errorMsg = "Conflicting entries: Same key but different values";
for (int i = 0; i < selectedKeys.length; i++) {
if (selectedKeys[i] instanceof TextValueEntry) {
key = ((TextValueEntry) selectedKeys[i]).getKey();
value = ((TextValueEntry) selectedKeys[i]).getValue();
for (int j = i + 1; j < selectedKeys.length; j++) {
compareKey = ((TextValueEntry) selectedKeys[j]).getKey();
comparevalue = ((TextValueEntry) selectedKeys[j]).getValue();
if (compareKey.equals(key) && !comparevalue.equals(value)) {
updateStatus(errorMsg);
break;
}
}
}
}
}
/**
* Check whether have the same key values in the File.
*
* @param sourceFolderName
* @param className
* @param propertyFolderName
* @param propertyName
* @throws CoreException
* @throws IOException
* @throws returnWizardPage
*/
private void checkDuplicate(String sourceFolderName, String className, String propertyFolderName, String propertyName) {
try {
duplicateKeys = new ArrayList<String>();
if (ExternalizeStringsCommon.getIFile(sourceFolderName, className).exists()) {
StringBuffer classHistoryContents = ExternalizeStringsCommon.getHistoryContents((ExternalizeStringsCommon.getIFile(sourceFolderName, className)));
checkDuplicateKey(checkedItems, classHistoryContents, true);
}
if (ExternalizeStringsCommon.getIFile(propertyFolderName, propertyName).exists()) {
StringBuffer PropertyHistoryContents = ExternalizeStringsCommon.getHistoryContents(ExternalizeStringsCommon.getIFile(propertyFolderName, propertyName));
checkDuplicateKey(checkedItems, PropertyHistoryContents, false);
}
if (duplicateKeys.size() > 0) {
StringBuffer dialogMessage = new StringBuffer("Key: ");
ArrayList<String> keys = new ArrayList<String>();
for (int i = 0; i < duplicateKeys.size(); i++) {
if (keys.indexOf(duplicateKeys.get(i)) == -1) {
keys.add(duplicateKeys.get(i));
dialogMessage.append("\"" + duplicateKeys.get(i)
+ "\" ");
}
}
dialogMessage.append("already exist in files. Please rename.");
updateStatus(dialogMessage.toString());
}
} catch (CoreException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
/**
* To match the duplicate key values in the File.
*
* @param checkedItems
* @param historyContent
*/
private void checkDuplicateKey(TextValueModel checkedItems, StringBuffer historyContent, boolean isClassFile) {
String regexSuffix;
String regexPrefix;
if (isClassFile) {
regexPrefix = "[\t ]+";
regexSuffix = "([\t ]*[\r ]*[\t ]*)*[;]";
} else {
regexPrefix = "[\t ]*";
regexSuffix = "[\t ]*[=]";
}
for (int i = 0; i < checkedItems.elements().length; i++) {
String key = ((TextValueEntry) checkedItems.elements()[i]).getKey();
if (!checkKeyValue(key))
return;
String regex = regexPrefix + key + regexSuffix;
Matcher matcher = Pattern.compile(regex).matcher(historyContent.toString());
if (matcher.find()) {
duplicateKeys.add(key);
}
}
}
public void setDefaultFolder(String defaultFolder) {
this.defaultFolder = defaultFolder;
}
public void setDefaultRoot(IPackageFragmentRoot defaultRoot) {
this.defaultRoot = defaultRoot;
}
public void setDefaultPackage(String defaultPackage) {
this.defaultPackage = defaultPackage;
}
public AccessorConfigureInfo getInfo() {
return info;
}
}