/*******************************************************************************
* Copyright (c) 2005, 2010 Intel 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:
* Intel Corporation - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.ui.properties;
import com.ibm.icu.text.Collator;
import java.util.Arrays;
import java.util.Comparator;
import org.eclipse.cdt.core.cdtvariables.CdtVariableException;
import org.eclipse.cdt.core.cdtvariables.ICdtVariable;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICMultiItemsHolder;
import org.eclipse.cdt.managedbuilder.core.IOption;
import org.eclipse.cdt.managedbuilder.internal.macros.BuildMacro;
import org.eclipse.cdt.managedbuilder.macros.IBuildMacro;
import org.eclipse.cdt.managedbuilder.internal.ui.Messages;
import org.eclipse.cdt.utils.cdtvariables.CdtVariableResolver;
import org.eclipse.cdt.utils.ui.controls.FileListControl;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
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.graphics.Point;
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.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
/**
* the dialog used to create or edit the build macro
*
* @noextend This class is not intended to be subclassed by clients.
* @noinstantiate This class is not intended to be instantiated by clients.
*/
public class NewVarDialog extends Dialog {
private static final String EMPTY_STRING = new String();
// The title of the dialog.
private String fTitle;
// hold the macro being edited(in the case of the "edit" mode)
private ICdtVariable fEditedMacro;
//the resulting macro. Can be accessed only when the dialog is closed
private ICdtVariable fResultingMacro;
private boolean fTotalSizeCalculated;
private String fTypedName;
private int fTypedType = -1;
public boolean isForAllCfgs = false;
// Widgets
private Composite fContainer;
private CCombo fMacroNameEdit;
private Label fMacroValueLabel;
private Text fMacroValueEdit;
private Button fBrowseButton;
private Combo fTypeSelector;
private Composite fListEditorContainier;
private FileListControl fListEditor;
private ICConfigurationDescription cfgd;
private ICdtVariable[] vars;
public NewVarDialog(Shell parentShell, ICdtVariable editedMacro, ICConfigurationDescription _cfgd, ICdtVariable[] _vars) {
super(parentShell);
cfgd = _cfgd;
if(editedMacro != null)
fTitle = Messages.NewBuildMacroDialog_label_title_edit;
else
fTitle = Messages.NewBuildMacroDialog_label_title_new;
fEditedMacro = editedMacro;
vars = _vars;
}
/* (non-Javadoc)
* @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
*/
@Override
protected void configureShell(Shell shell) {
super.configureShell(shell);
if (fTitle != null)
shell.setText(fTitle);
}
/* (non-Javadoc)
* @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
*/
@Override
protected Control createDialogArea(Composite parent) {
Composite comp = new Composite(parent, SWT.NULL);
comp.setFont(parent.getFont());
comp.setLayout(new GridLayout(3, false));
GridData gd = new GridData(GridData.FILL_BOTH);
comp.setLayoutData(gd);
fContainer = comp;
Label nameLabel = new Label(comp, SWT.LEFT);
nameLabel.setFont(comp.getFont());
nameLabel.setText(Messages.NewVarDialog_0);
nameLabel.setLayoutData(new GridData());
fMacroNameEdit = new CCombo(comp, SWT.BORDER);
fMacroNameEdit.setItems(getMacroNames());
fMacroNameEdit.setFont(comp.getFont());
gd = new GridData(); // don't use GridData.FILL_HORIZONTAL; see bugzilla 229793
gd.horizontalSpan = 2;
gd.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH + 50;
fMacroNameEdit.setLayoutData(gd);
fMacroNameEdit.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
handleMacroNameModified();
}
});
fMacroNameEdit.addSelectionListener(new SelectionAdapter(){
@Override
public void widgetSelected(SelectionEvent e){
handleMacroNameSelection();
}
});
if (fEditedMacro == null && cfgd != null && !(cfgd instanceof ICMultiItemsHolder)) {
Button c_all = new Button(comp, SWT.CHECK);
c_all.setText(Messages.NewVarDialog_1);
gd = new GridData(GridData.BEGINNING);
gd.horizontalSpan = 3;
c_all.setLayoutData(gd);
c_all.addSelectionListener(new SelectionAdapter(){
@Override
public void widgetSelected(SelectionEvent e){
isForAllCfgs = ((Button)e.widget).getSelection();
}
});
}
Label typeLabel = new Label(comp, SWT.LEFT);
typeLabel.setFont(comp.getFont());
typeLabel.setText(Messages.NewBuildMacroDialog_label_type);
gd = new GridData();
typeLabel.setLayoutData(gd);
fTypeSelector = new Combo(comp, SWT.READ_ONLY | SWT.DROP_DOWN | SWT.BORDER);
gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gd.horizontalSpan = 2;
// gd.widthHint = 100;
fTypeSelector.setLayoutData(gd);
fTypeSelector.setItems(new String[]{
Messages.NewBuildMacroDialog_label_type_text,
Messages.NewBuildMacroDialog_label_type_text_list,
Messages.NewBuildMacroDialog_label_type_path_file,
Messages.NewBuildMacroDialog_label_type_path_file_list,
Messages.NewBuildMacroDialog_label_type_path_dir,
Messages.NewBuildMacroDialog_label_type_path_dir_list,
Messages.NewBuildMacroDialog_label_type_path_any,
Messages.NewBuildMacroDialog_label_type_path_any_list
});
setSelectedType(IBuildMacro.VALUE_TEXT);
fTypeSelector.addListener(SWT.Selection, new Listener () {
public void handleEvent(Event e) {
handleTypeModified();
}
});
fMacroValueLabel = new Label(comp, SWT.LEFT);
fMacroValueLabel.setFont(comp.getFont());
fMacroValueLabel.setText(Messages.NewBuildMacroDialog_label_value);
gd = new GridData();
gd.horizontalSpan = 1;
fMacroValueLabel.setLayoutData(gd);
fMacroValueEdit = new Text(comp, SWT.SINGLE | SWT.BORDER);
fMacroValueEdit.setFont(comp.getFont());
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH + 100;
gd.horizontalSpan = 1;
fMacroValueEdit.setLayoutData(gd);
fMacroValueEdit.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
handleMacroValueModified();
}
});
fBrowseButton = new Button(comp,SWT.PUSH);
fBrowseButton.setFont(comp.getFont());
fBrowseButton.setText(Messages.NewBuildMacroDialog_label_browse);
fBrowseButton.addSelectionListener(new SelectionAdapter(){
@Override
public void widgetSelected(SelectionEvent e){
handleBrowseButtonPressed();
}
});
gd = new GridData();
gd.widthHint = IDialogConstants.BUTTON_WIDTH;
gd.horizontalSpan = 1;
fBrowseButton.setLayoutData(gd);
fListEditorContainier = new Composite(comp,0);
gd = new GridData(GridData.FILL_BOTH);
gd.horizontalSpan = 3;
fListEditorContainier.setLayoutData(gd);
fListEditorContainier.setLayout(new GridLayout());
fListEditor = new FileListControl(fListEditorContainier, Messages.NewBuildMacroDialog_label_list_title, IOption.BROWSE_NONE);
/* Enable workspace support for list editor */
fListEditor.setWorkspaceSupport(true);
// TODO: getContextInfo
// fListEditor.setContext(fMacrosBlock.getContextInfo());
if(fEditedMacro != null){
loadVar(fEditedMacro);
fMacroNameEdit.setEnabled(false);
}
return comp;
}
/*
* get the names to be displayed in the var Name combo.
*/
private String[] getMacroNames(){
String names[] = null;
if(vars == null || vars.length == 0)
names = new String[0];
else{
names = new String[vars.length];
for(int i = 0; i < vars.length; i++)
names[i] = vars[i].getName();
final Collator collator = Collator.getInstance();
Arrays.sort(names, new Comparator<String>() {
public int compare(final String a, final String b) {
final String strA = a.toUpperCase();
final String strB = b.toUpperCase();
return collator.compare(strA,strB);
}
});
}
return names;
}
private void handleBrowseButtonPressed(){
switch(getBrowseType(getSelectedType())){
case IOption.BROWSE_FILE:
FileDialog fileDlg = new FileDialog(fBrowseButton.getShell());
String file = fileDlg.open();
if(file != null)
fMacroValueEdit.setText(file);
break;
case IOption.BROWSE_DIR:
DirectoryDialog dirDlg = new DirectoryDialog(fBrowseButton.getShell());
String dir = dirDlg.open();
if(dir != null)
fMacroValueEdit.setText(dir);
break;
}
}
private int getBrowseType(int type){
int browseType = IOption.BROWSE_NONE;
switch(type){
case IBuildMacro.VALUE_PATH_FILE:
case IBuildMacro.VALUE_PATH_FILE_LIST:
browseType = IOption.BROWSE_FILE;
break;
case IBuildMacro.VALUE_PATH_DIR:
case IBuildMacro.VALUE_PATH_DIR_LIST:
browseType = IOption.BROWSE_DIR;
break;
case IBuildMacro.VALUE_PATH_ANY:
case IBuildMacro.VALUE_PATH_ANY_LIST:
break;
case IBuildMacro.VALUE_TEXT:
case IBuildMacro.VALUE_TEXT_LIST:
default:
}
return browseType;
}
/*
* called when the variable name is selected, loads all the dialog fields with the variable settings
*/
private void handleMacroNameSelection(){
int index = fMacroNameEdit.getSelectionIndex();
if (index != -1)
loadVarSettings(fMacroNameEdit.getItem(index));
}
private void loadVarSettings(String name) {
ICdtVariable v = null;
for (int i=0; i<vars.length; i++) {
if (vars[i].getName().equals(name)) {
v = vars[i];
break;
}
}
if(v != null)
loadVar(v);
else
loadVar(name,IBuildMacro.VALUE_TEXT,EMPTY_STRING);
}
private void loadVar(String name, int type, String value[]){
setSelectedType(type);
setSelectedMacroName(notNull(name));
fListEditor.setList(value);
updateWidgetState();
}
private void loadVar(String name, int type, String value){
setSelectedType(type);
setSelectedMacroName(notNull(name));
fMacroValueEdit.setText(notNull(value));
updateWidgetState();
}
/*
* loads all the dialog fields with the variable settings
*/
private void loadVar(ICdtVariable var){
try{
if(CdtVariableResolver.isStringListVariable(var.getValueType()))
loadVar(var.getName(),var.getValueType(),var.getStringListValue());
else
loadVar(var.getName(),var.getValueType(),var.getStringValue());
}catch(CdtVariableException e){}
}
/*
* returns an empty string in the case the string passed is null.
* otherwise returns the string passed
*/
private String notNull(String str){
return str == null ? EMPTY_STRING : str;
}
/*
* returns the name typed in the dialog var name edit triming spaces
*/
private String getSelectedVarName(){
return fMacroNameEdit.getText().trim();
}
/*
* sets the variable name to the dialog "variable name" edit control
*/
private void setSelectedMacroName(String name){
if(!macroNamesEqual(fMacroNameEdit.getText(),name)){
fTypedName = name;
fMacroNameEdit.setText(notNull(name).trim());
}
}
private boolean macroNamesEqual(String name1, String name2){
name1 = name1.trim();
name2 = name2.trim();
return name1.equalsIgnoreCase(name2);
}
/*
* returns the selected type
*/
private int getSelectedType(){
switch(fTypeSelector.getSelectionIndex()){
case 1:
return IBuildMacro.VALUE_TEXT_LIST;
case 2:
return IBuildMacro.VALUE_PATH_FILE;
case 3:
return IBuildMacro.VALUE_PATH_FILE_LIST;
case 4:
return IBuildMacro.VALUE_PATH_DIR;
case 5:
return IBuildMacro.VALUE_PATH_DIR_LIST;
case 6:
return IBuildMacro.VALUE_PATH_ANY;
case 7:
return IBuildMacro.VALUE_PATH_ANY_LIST;
case 0:
default:
return IBuildMacro.VALUE_TEXT;
}
}
/*
* sets the selected type
*/
private void setSelectedType(int type){
switch(type){
case IBuildMacro.VALUE_TEXT_LIST:
fTypeSelector.select(1);
break;
case IBuildMacro.VALUE_PATH_FILE:
fTypeSelector.select(2);
break;
case IBuildMacro.VALUE_PATH_FILE_LIST:
fTypeSelector.select(3);
break;
case IBuildMacro.VALUE_PATH_DIR:
fTypeSelector.select(4);
break;
case IBuildMacro.VALUE_PATH_DIR_LIST:
fTypeSelector.select(5);
break;
case IBuildMacro.VALUE_PATH_ANY:
fTypeSelector.select(6);
break;
case IBuildMacro.VALUE_PATH_ANY_LIST:
fTypeSelector.select(7);
break;
case IBuildMacro.VALUE_TEXT:
default:
fTypeSelector.select(0);
break;
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.dialogs.Dialog#okPressed()
*/
@Override
protected void okPressed(){
String name = getSelectedVarName();
if(name != null || !EMPTY_STRING.equals(name)){
int type = getSelectedType();
if(CdtVariableResolver.isStringListVariable(type))
fResultingMacro = new BuildMacro(name,type,getSelectedStringListValue());
else
fResultingMacro = new BuildMacro(name,type,getSelectedStringValue());
}
super.okPressed();
}
/* (non-Javadoc)
* @see org.eclipse.jface.window.Window#open()
*/
@Override
public int open(){
fResultingMacro = null;
return super.open();
}
/*
* returns the macro value that should be stored in the resulting variable
*/
private String getSelectedStringValue(){
return fMacroValueEdit.getText();
}
private String[] getSelectedStringListValue(){
return fListEditor.getItems();
}
/*
* this method should be called after the dialog is closed
* to obtain the created variable.
* if the variable was not created, e.g. because a user has pressed
* the cancel button this method returns null
*/
public ICdtVariable getDefinedMacro(){
return fResultingMacro;
}
/*
* called when the variable name is modified
*/
private void handleMacroNameModified(){
String name = getSelectedVarName();
if(fTypedName == null || !fTypedName.equals(name)){
loadVarSettings(name);
}
}
private void handleMacroValueModified(){}
/*
* called when the operation is modified
*/
private void handleTypeModified(){
int type = getSelectedType();
if(fTypedType != -1 && fTypedType == type)
return;
fTypedType = type;
adjustLayout(type);
}
private void adjustLayout(int type){
GridData listGd = (GridData)fListEditorContainier.getLayoutData();
GridData labelGd = (GridData)fMacroValueLabel.getLayoutData();
GridData editGd = (GridData)fMacroValueEdit.getLayoutData();
GridData browseGd = (GridData)fBrowseButton.getLayoutData();
if(CdtVariableResolver.isStringListVariable(type)){
listGd.exclude = false;
labelGd.exclude = true;
editGd.exclude = true;
browseGd.exclude = true;
fListEditorContainier.setVisible(true);
fListEditor.setType(getBrowseType(type));
fMacroValueLabel.setVisible(false);
fMacroValueEdit.setVisible(false);
fBrowseButton.setVisible(false);
} else
{
listGd.exclude = true;
labelGd.exclude = false;
editGd.exclude = false;
int editSpan;
fListEditorContainier.setVisible(false);
fMacroValueLabel.setVisible(true);
fMacroValueEdit.setVisible(true);
if(getBrowseType(type) != IOption.BROWSE_NONE){
browseGd.exclude = false;
editSpan = 1;
fBrowseButton.setVisible(true);
} else {
browseGd.exclude = true;
editSpan = 2;
fBrowseButton.setVisible(false);
}
editGd.horizontalSpan = editSpan;
}
fContainer.layout(true,true);
}
/*
* updates the state of the dialog controls
*/
private void updateWidgetState(){
if(!fTotalSizeCalculated)
return;
handleTypeModified();
Button b = getButton(IDialogConstants.OK_ID);
if (b != null) {
String name = getSelectedVarName();
b.setEnabled(!EMPTY_STRING.equals(name));
}
}
@Override
protected Point getInitialSize() {
Point size = super.getInitialSize();
fTotalSizeCalculated = true;
updateWidgetState();
return size;
}
}