blob: dc6592a8a2b694d2833ec10e47164b3844d6ef31 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2016 Mateusz Matela and others.
*
* 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:
* Mateusz Matela <mateusz.matela@gmail.com> - [code manipulation] [dcr] toString() builder wizard - https://bugs.eclipse.org/bugs/show_bug.cgi?id=26070
* Mateusz Matela <mateusz.matela@gmail.com> - [toString] Template edit dialog has usability issues - https://bugs.eclipse.org/bugs/show_bug.cgi?id=267916
* Mateusz Matela <mateusz.matela@gmail.com> - [toString] finish toString() builder wizard - https://bugs.eclipse.org/bugs/show_bug.cgi?id=267710
* Mateusz Matela <mateusz.matela@gmail.com> - [toString] toString() generator: Fields in declaration order - https://bugs.eclipse.org/bugs/show_bug.cgi?id=279924
*******************************************************************************/
package org.eclipse.jdt.internal.ui.dialogs;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import com.ibm.icu.text.Collator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
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.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.Text;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.StatusDialog;
import org.eclipse.jface.fieldassist.IContentProposal;
import org.eclipse.jface.fieldassist.IContentProposalProvider;
import org.eclipse.jface.fieldassist.TextContentAdapter;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ISelectionStatusValidator;
import org.eclipse.ui.dialogs.SelectionDialog;
import org.eclipse.ui.fieldassist.ContentAssistCommandAdapter;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.internal.corext.codemanipulation.tostringgeneration.GenerateToStringOperation;
import org.eclipse.jdt.internal.corext.codemanipulation.tostringgeneration.ToStringGenerationSettings;
import org.eclipse.jdt.internal.corext.codemanipulation.tostringgeneration.ToStringGenerationSettingsCore.CustomBuilderSettings;
import org.eclipse.jdt.internal.corext.codemanipulation.tostringgeneration.ToStringTemplateParser;
import org.eclipse.jdt.internal.corext.util.JavaConventionsUtil;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.ui.IJavaElementSearchConstants;
import org.eclipse.jdt.ui.JavaElementImageDescriptor;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.dialogs.TypeSelectionExtension;
import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.internal.ui.JavaUIMessages;
import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor;
import org.eclipse.jdt.internal.ui.util.SWTUtil;
import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider;
import org.eclipse.jdt.internal.ui.viewsupport.JavaElementImageProvider;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
/**
* Dialog for the generate toString() action.
*
* @since 3.5
*/
public class GenerateToStringDialog extends SourceActionDialog {
private static class GenerateToStringContentProvider implements ITreeContentProvider {
private static final Object[] EMPTY= new Object[0];
private IVariableBinding[] fFields;
private IMethodBinding[] fMethods;
private IVariableBinding[] fInheritedFields;
private IMethodBinding[] fInheritedMethods;
private String[] mainNodes;
private static final String fieldsNode= JavaUIMessages.GenerateToStringDialog_fields_node;
private static final String methodsNode= JavaUIMessages.GenerateToStringDialog_methods_node;
private static final String inheritedFieldsNode= JavaUIMessages.GenerateToStringDialog_inherited_fields_node;
private static final String inheritedMethodsNode= JavaUIMessages.GenerateToStringDialog_inherited_methods_node;
public GenerateToStringContentProvider(IVariableBinding[] fields, IVariableBinding[] inheritedFields, IMethodBinding[] methods, IMethodBinding[] inheritedMethods) {
ArrayList<String> nodes= new ArrayList<>();
fFields= fields.clone();
if (fFields.length > 0)
nodes.add(fieldsNode);
fInheritedFields= inheritedFields.clone();
if (fInheritedFields.length > 0)
nodes.add(inheritedFieldsNode);
fMethods= methods.clone();
if (fMethods.length > 0)
nodes.add(methodsNode);
fInheritedMethods= inheritedMethods.clone();
if (fInheritedMethods.length > 0)
nodes.add(inheritedMethodsNode);
mainNodes= nodes.toArray(new String[nodes.size()]);
}
private int getElementPosition(Object element, Object[] array) {
for (int i= 0; i < array.length; i++) {
if (array[i].equals(element)) {
return i;
}
}
return -1;
}
private Object[] getContainingArray(Object element) {
if (element instanceof String)
return mainNodes;
if (element instanceof IVariableBinding) {
if (getElementPosition(element, fFields) >= 0)
return fFields;
if (getElementPosition(element, fInheritedFields) >= 0)
return fInheritedFields;
}
if (element instanceof IMethodBinding) {
if (getElementPosition(element, fMethods) >= 0)
return fMethods;
if (getElementPosition(element, fInheritedMethods) >= 0)
return fInheritedMethods;
}
return EMPTY;
}
public boolean canMoveDown(Object element) {
Object[] array= getContainingArray(element);
int position= getElementPosition(element, array);
return position != -1 && position != array.length - 1;
}
public boolean canMoveUp(Object element) {
return getElementPosition(element, getContainingArray(element)) > 0;
}
public void down(Object element, CheckboxTreeViewer tree) {
move(element, tree, 1);
}
public void up(Object element, CheckboxTreeViewer tree) {
move(element, tree, -1);
}
private void move(Object element, CheckboxTreeViewer tree, int direction) {
Object[] array= getContainingArray(element);
int position= getElementPosition(element, array);
Object temp= array[position];
array[position]= array[position + direction];
array[position + direction]= temp;
tree.setSelection(new StructuredSelection(element));
tree.refresh();
}
public void sort() {
Comparator<IBinding> comparator= new Comparator<IBinding>() {
Collator collator= Collator.getInstance();
@Override
public int compare(IBinding b1, IBinding b2) {
return collator.compare(b1.getName(), b2.getName());
}
};
Arrays.sort(fFields, comparator);
Arrays.sort(fMethods, comparator);
Arrays.sort(fInheritedFields, comparator);
Arrays.sort(fInheritedMethods, comparator);
}
@Override
public Object[] getChildren(Object parentElement) {
if (parentElement == fieldsNode)
return fFields;
if (parentElement == inheritedFieldsNode)
return fInheritedFields;
if (parentElement == methodsNode)
return fMethods;
if (parentElement == inheritedMethodsNode)
return fInheritedMethods;
return EMPTY;
}
@Override
public Object getParent(Object element) {
Object[] array= getContainingArray(element);
if (array == fFields)
return fieldsNode;
if (array == fInheritedFields)
return inheritedFieldsNode;
if (array == fMethods)
return methodsNode;
if (array == fInheritedMethods)
return inheritedMethodsNode;
return null;
}
@Override
public boolean hasChildren(Object element) {
if (element instanceof String)
return true;
return false;
}
@Override
public Object[] getElements(Object inputElement) {
return mainNodes;
}
@Override
public void dispose() {
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}
private static class GenerateToStringLabelProvider extends BindingLabelProvider {
@Override
public Image getImage(Object element) {
ImageDescriptor descriptor= null;
if (element == GenerateToStringContentProvider.fieldsNode || element == GenerateToStringContentProvider.inheritedFieldsNode)
descriptor= JavaPluginImages.DESC_FIELD_PUBLIC;
if (element == GenerateToStringContentProvider.methodsNode || element == GenerateToStringContentProvider.inheritedMethodsNode)
descriptor= JavaPluginImages.DESC_MISC_PUBLIC;
if (descriptor != null) {
descriptor= new JavaElementImageDescriptor(descriptor, 0, JavaElementImageProvider.BIG_SIZE);
return JavaPlugin.getImageDescriptorRegistry().get(descriptor);
}
return super.getImage(element);
}
}
private class GenerateToStringValidator implements ISelectionStatusValidator {
private int fNumFields;
private int fNumMethods;
private CustomBuilderValidator fValidator;
public GenerateToStringValidator(int fields, int methods) {
fNumFields= fields;
fNumMethods= methods;
}
@Override
public IStatus validate(Object[] selection) {
if (getGenerationSettings().toStringStyle == GenerateToStringOperation.CUSTOM_BUILDER) {
if (fValidator == null)
fValidator= new CustomBuilderValidator(getType().getJavaProject());
IStatus status= fValidator.revalidateAll(getGenerationSettings().getCustomBuilderSettings());
if (!status.isOK())
return new StatusInfo(IStatus.ERROR, JavaUIMessages.GenerateToStringDialog_selectioninfo_customBuilderConfigError);
}
int countFields= 0, countMethods= 0;
for (Object s : selection) {
if (s instanceof IVariableBinding) {
countFields++;
} else if (s instanceof IMethodBinding) {
countMethods++;
}
}
return new StatusInfo(IStatus.INFO, Messages.format(JavaUIMessages.GenerateToStringDialog_selectioninfo_more, new String[] { String.valueOf(countFields), String.valueOf(fNumFields),
String.valueOf(countMethods), String.valueOf(fNumMethods) }));
}
}
private class ToStringTemplatesDialog extends StatusDialog {
private class TemplateEditionDialog extends StatusDialog {
/**
* Template number, -1 for new template.
*/
private final int templateNumber;
/**
* Initial template name, can be <code>null</code>.
*/
private final String fInitialTemplateName;
private Text templateName;
private Text template;
private String resultTemplateName;
private String resultTemplate;
private StatusInfo nameValidationStatus= new StatusInfo();
public TemplateEditionDialog(Shell parent, int templateNumber) {
super(parent);
this.templateNumber= templateNumber;
fInitialTemplateName= templateNumber < 0 ? null : templateNames.get(templateNumber);
setHelpAvailable(false);
}
@Override
protected boolean isResizable() {
return true;
}
@Override
protected Control createDialogArea(Composite parent) {
getShell().setText(templateNumber >= 0 ? JavaUIMessages.GenerateToStringDialog_templateEdition_WindowTitle : JavaUIMessages.GenerateToStringDialog_templateEdition_NewWindowTitle);
Composite composite= (Composite)super.createDialogArea(parent);
GridLayout layout= (GridLayout)composite.getLayout();
layout.numColumns= 2;
layout.horizontalSpacing= 8;
Label label= new Label(composite, SWT.LEFT);
label.setText(JavaUIMessages.GenerateToStringDialog_template_name);
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
templateName= new Text(composite, SWT.BORDER | SWT.SINGLE);
templateName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
label= new Label(composite, SWT.LEFT);
label.setText(JavaUIMessages.GenerateToStringDialog_template_content);
label.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
template= new Text(composite, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
GridData gridData= new GridData(SWT.FILL, SWT.FILL, true, true);
gridData.heightHint= 80;
gridData.widthHint= 480;
template.setLayoutData(gridData);
new ContentAssistCommandAdapter(template, new TextContentAdapter(), new ToStringTemplateProposalProvider(), null, new char[] { '$' }, true).setPropagateKeys(false);
if (templateNumber >= 0) {
templateName.setText(fInitialTemplateName);
template.setText(templates.get(templateNumber));
} else {
templateName.setText(createNewTemplateName());
template.setText(ToStringTemplateParser.DEFAULT_TEMPLATE);
}
templateName.setSelection(0, templateName.getText().length());
templateName.addModifyListener(e -> validate(templateName.getText()));
//Ctrl+Enter should execute the default button, workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=145959
template.addTraverseListener(e -> {
if (e.detail == SWT.TRAVERSE_RETURN && (e.stateMask & SWT.MODIFIER_MASK) != 0) {
buttonPressed(((Integer)getShell().getDefaultButton().getData()));
}
});
return composite;
}
private void validate(String newName) {
if (newName.length() == 0) {
nameValidationStatus.setError(JavaUIMessages.GenerateToStringDialog_templateEdition_TemplateNameEmptyErrorMessage);
} else if (!newName.equals(fInitialTemplateName) && templateNames.contains(newName)) {
nameValidationStatus.setError(JavaUIMessages.GenerateToStringDialog_templateEdition_TemplateNameDuplicateErrorMessage);
} else {
nameValidationStatus.setOK();
}
updateStatus(nameValidationStatus);
}
private String createNewTemplateName() {
if (!templateNames.contains(JavaUIMessages.GenerateToStringDialog_newTemplateName))
return JavaUIMessages.GenerateToStringDialog_newTemplateName;
int copyCount= 2;
String newName;
do {
newName= Messages.format(JavaUIMessages.GenerateToStringDialog_newTemplateNameArg, Integer.valueOf(copyCount));
copyCount++;
} while (templateNames.contains(newName));
return newName;
}
@Override
public boolean close() {
resultTemplateName= templateName.getText();
resultTemplate= fixLineBreaks(template.getText());
return super.close();
}
public String getTemplateName() {
return resultTemplateName;
}
public String getTemplate() {
return resultTemplate;
}
private String fixLineBreaks(String input) {
String systemLineDelimiter= Text.DELIMITER;
final String javaLineDelimiter= "\n"; //$NON-NLS-1$
if (!javaLineDelimiter.equals(systemLineDelimiter)) {
StringBuilder outputBuffer= new StringBuilder(input);
int pos= outputBuffer.indexOf(systemLineDelimiter);
while (pos >= 0) {
outputBuffer.delete(pos, pos + systemLineDelimiter.length());
outputBuffer.insert(pos, javaLineDelimiter);
pos= outputBuffer.indexOf(systemLineDelimiter, pos + javaLineDelimiter.length());
}
return outputBuffer.toString();
}
return input;
}
}
private class ToStringTemplateProposalProvider implements IContentProposalProvider {
private class Proposal implements IContentProposal {
final private String proposal;
private int position;
public Proposal(String proposal) {
this.proposal= proposal;
this.position= proposal.length();
}
@Override
public String getContent() {
int overlap= stringOverlap(latestContents.substring(0, latestPosition), proposal);
position= proposal.length() - overlap;
return proposal.substring(overlap);
}
@Override
public int getCursorPosition() {
return position;
}
@Override
public String getDescription() {
return parser.getVariableDescriptions().get(proposal);
}
@Override
public String getLabel() {
return proposal;
}
}
private String latestContents;
private int latestPosition;
@Override
public IContentProposal[] getProposals(String contents, int position) {
List<Proposal> primaryProposals= new ArrayList<>();
List<Proposal> secondaryProposals= new ArrayList<>();
String[] proposalStrings= parser.getVariables();
String contentToCursor= contents.substring(0, position);
for (String proposalString : proposalStrings) {
if (stringOverlap(contentToCursor, proposalString) > 0) {
primaryProposals.add(new Proposal(proposalString));
} else {
secondaryProposals.add(new Proposal(proposalString));
}
}
this.latestContents= contents;
this.latestPosition= position;
primaryProposals.addAll(secondaryProposals);
return primaryProposals.toArray(new IContentProposal[0]);
}
/**
* Checks if the end of the first string is equal to the beginning of of the second
* string.
*
* @param s1 first String
* @param s2 second String
* @return length of overlapping segment (0 if strings don't overlap)
*/
private int stringOverlap(String s1, String s2) {
int l1= s1.length();
for (int l= 1; l <= Math.min(s1.length(), s2.length()); l++) {
boolean ok= true;
for (int i= 0; i < l; i++) {
if (s1.charAt(l1 - l + i) != s2.charAt(i)) {
ok= false;
break;
}
}
if (ok)
return l;
}
return 0;
}
}
private final int ADD_BUTTON= IDialogConstants.CLIENT_ID + 1;
private final int REMOVE_BUTTON= IDialogConstants.CLIENT_ID + 2;
private final int APPLY_BUTTON= IDialogConstants.CLIENT_ID + 3;
private final int EDIT_BUTTON= IDialogConstants.CLIENT_ID + 4;
private Text templateTextControl;
private org.eclipse.swt.widgets.List templateNameControl;
private ToStringTemplateParser parser;
private List<String> templateNames;
private List<String> templates;
private int selectedTemplateNumber;
private boolean somethingChanged= false;
private StatusInfo validationStatus= new StatusInfo();
protected ToStringTemplatesDialog(Shell parentShell, ToStringTemplateParser parser) {
super(parentShell);
this.parser= parser;
this.setShellStyle(this.getShellStyle() | SWT.RESIZE);
this.create();
PlatformUI.getWorkbench().getHelpSystem().setHelp(getShell(), IJavaHelpContextIds.GENERATE_TOSTRING_MANAGE_TEMPLATES_DIALOG);
}
@Override
protected Control createDialogArea(Composite parent) {
getShell().setText(JavaUIMessages.GenerateToStringDialog_templatesManagerTitle);
Composite composite= (Composite)super.createDialogArea(parent);
Label label= new Label(composite, SWT.LEFT);
label.setText(JavaUIMessages.GenerateToStringDialog_templatesManagerTemplatesList);
Composite templatesComposite= new Composite(composite, SWT.NONE);
templatesComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
GridLayout gl= new GridLayout(2, false);
gl.marginWidth= gl.marginHeight= 0;
templatesComposite.setLayout(gl);
templateNameControl= new org.eclipse.swt.widgets.List(templatesComposite, SWT.BORDER | SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL);
templateNameControl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
Composite rightComposite= new Composite(templatesComposite, SWT.NONE);
gl= new GridLayout();
gl.marginWidth= gl.marginHeight= 0;
rightComposite.setLayout(gl);
rightComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
createButton(rightComposite, ADD_BUTTON, JavaUIMessages.GenerateToStringDialog_templatesManagerNewButton, false);
createButton(rightComposite, REMOVE_BUTTON, JavaUIMessages.GenerateToStringDialog_templatesManagerRemoveButton, false);
createButton(rightComposite, EDIT_BUTTON, JavaUIMessages.GenerateToStringDialog_teplatesManagerEditButton, false);
((GridLayout)rightComposite.getLayout()).numColumns= 1;
label= new Label(composite, SWT.LEFT);
label.setText(JavaUIMessages.GenerateToStringDialog_templatesManagerPreview);
templateTextControl= new Text(composite, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.READ_ONLY);
SWTUtil.fixReadonlyTextBackground(templateTextControl);
GridData gd= new GridData(SWT.FILL, SWT.FILL, true, true);
gd.heightHint= 80;
gd.widthHint= 450;
templateTextControl.setLayoutData(gd);
templateNames= new ArrayList<>(Arrays.asList(getTemplateNames()));
templates= new ArrayList<>(Arrays.asList(getTemplates(getDialogSettings())));
selectedTemplateNumber= getGenerationSettings().stringFormatTemplateNumber;
refreshControls();
templateNameControl.addSelectionListener(new SelectionListener() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {
onEdit();
}
@Override
public void widgetSelected(SelectionEvent e) {
if (templateNameControl.getSelectionIndex() >= 0) {
selectedTemplateNumber= templateNameControl.getSelectionIndex();
templateTextControl.setText(templates.get(selectedTemplateNumber));
}
}
});
applyDialogFont(composite);
return composite;
}
@Override
protected void createButtonsForButtonBar(Composite parent) {
super.createButtonsForButtonBar(parent);
createButton(parent, APPLY_BUTTON, JavaUIMessages.GenerateToStringDialog_templateManagerApplyButton, false).setEnabled(false);
}
private void applyChanges() {
getDialogSettings().put(ToStringGenerationSettings.SETTINGS_TEMPLATE_NAMES, templateNames.toArray(new String[0]));
getDialogSettings().put(ToStringGenerationSettings.SETTINGS_TEMPLATES, templates.toArray(new String[0]));
getGenerationSettings().stringFormatTemplateNumber= Math.max(selectedTemplateNumber, 0);
somethingChanged= false;
getButton(APPLY_BUTTON).setEnabled(false);
}
@Override
protected void buttonPressed(int buttonId) {
switch (buttonId) {
case APPLY_BUTTON:
applyChanges();
break;
case IDialogConstants.OK_ID:
applyChanges();
close();
break;
case IDialogConstants.CANCEL_ID:
close();
break;
case ADD_BUTTON:
TemplateEditionDialog dialog= new TemplateEditionDialog(getShell(), -1);
dialog.open();
if (dialog.getReturnCode() == IDialogConstants.OK_ID) {
templateNames.add(dialog.getTemplateName());
templates.add(dialog.getTemplate());
selectedTemplateNumber= templateNames.size() - 1;
somethingChanged= true;
refreshControls();
}
break;
case REMOVE_BUTTON:
if (templateNames.size() > 0) {
templateNames.remove(selectedTemplateNumber);
templates.remove(selectedTemplateNumber);
}
if (selectedTemplateNumber >= templateNames.size())
selectedTemplateNumber= templateNames.size() - 1;
somethingChanged= true;
refreshControls();
break;
case EDIT_BUTTON:
onEdit();
}
}
private void onEdit() {
TemplateEditionDialog dialog;
dialog= new TemplateEditionDialog(getShell(), selectedTemplateNumber);
dialog.open();
if (dialog.getReturnCode() == IDialogConstants.OK_ID) {
templateNames.set(selectedTemplateNumber, dialog.getTemplateName());
templates.set(selectedTemplateNumber, dialog.getTemplate());
somethingChanged= true;
refreshControls();
}
}
public void refreshControls() {
templateNameControl.setItems(templateNames.toArray(new String[0]));
if (templateNames.size() > 0) {
templateNameControl.select(selectedTemplateNumber);
templateTextControl.setText(templates.get(selectedTemplateNumber));
} else {
templateTextControl.setText(""); //$NON-NLS-1$
}
revalidate();
if (getButton(APPLY_BUTTON) != null)
getButton(APPLY_BUTTON).setEnabled(somethingChanged && getButton(IDialogConstants.OK_ID).getEnabled());
if (getButton(REMOVE_BUTTON) != null)
getButton(REMOVE_BUTTON).setEnabled(templateNames.size() > 0);
if (getButton(EDIT_BUTTON) != null)
getButton(EDIT_BUTTON).setEnabled(templateNames.size() > 0);
}
private void revalidate() {
if (templateNames.size() > 0)
validationStatus.setOK();
else
validationStatus.setError(JavaUIMessages.GenerateToStringDialog_templateManagerNoTemplateErrorMessage);
updateStatus(validationStatus);
}
}
private static class CustomBuilderValidator implements ISelectionStatusValidator {
private final IJavaProject fJavaProject;
private IType fLastValidBuilderType;
private List<String> fLastValidAppendMethodSuggestions;
private List<String> fLastValidResultMethodSuggestions;
public CustomBuilderValidator(IJavaProject javaProject) {
fJavaProject= javaProject;
}
public IStatus validateBuilderType(IType type) {
if (fLastValidBuilderType != null && fLastValidBuilderType.equals(type)) {
return new StatusInfo();
}
try {
boolean foundConstructor= false;
for (IMethod method : type.getMethods()) {
if (method.isConstructor() && Flags.isPublic(method.getFlags())) {
String[] parameterTypes= method.getParameterTypes();
if (parameterTypes.length == 1 && "java.lang.Object".equals(JavaModelUtil.getResolvedTypeName(parameterTypes[0], type))) { //$NON-NLS-1$
foundConstructor= true;
break;
}
}
}
if (!foundConstructor)
return new StatusInfo(IStatus.ERROR, JavaUIMessages.GenerateToStringDialog_customBuilderConfig_noConstructorError);
List<String> appendMethodSuggestions= getAppendMethodSuggestions(type);
if (appendMethodSuggestions.isEmpty())
return new StatusInfo(IStatus.ERROR, JavaUIMessages.GenerateToStringDialog_customBuilderConfig_noAppendMethodError);
List<String> resultMethodSuggestions= getResultMethodSuggestions(type);
if (resultMethodSuggestions.isEmpty())
return new StatusInfo(IStatus.ERROR, JavaUIMessages.GenerateToStringDialog_customBuilderConfig_noResultMethodError);
fLastValidBuilderType= type;
fLastValidAppendMethodSuggestions= appendMethodSuggestions;
fLastValidResultMethodSuggestions= resultMethodSuggestions;
return new StatusInfo();
} catch (JavaModelException e1) {
return new StatusInfo(IStatus.WARNING, JavaUIMessages.GenerateToStringDialog_customBuilderConfig_typeValidationError);
}
}
@Override
public IStatus validate(Object[] selection) {
return validateBuilderType(((IType)selection[0]));
}
public IStatus revalidateAll(CustomBuilderSettings builderSettings) {
try {
if (builderSettings.className.length() == 0) {
return new StatusInfo(IStatus.ERROR, JavaUIMessages.GenerateToStringDialog_customBuilderConfig_noBuilderClassError);
}
IType type= findType(builderSettings.className);
if (type == null || !type.exists()) {
return new StatusInfo(IStatus.ERROR,
MessageFormat.format(JavaUIMessages.GenerateToStringDialog_customBuilderConfig_invalidClassError,
builderSettings.className));
}
IStatus typeValidation= validateBuilderType(type);
if (!typeValidation.isOK())
return typeValidation;
if (!getAppendMethodSuggestions(type).contains(builderSettings.appendMethod))
return new StatusInfo(IStatus.ERROR,
MessageFormat.format(JavaUIMessages.GenerateToStringDialog_customBuilderConfig_invalidAppendMethodError,
builderSettings.appendMethod));
if (!getResultMethodSuggestions(type).contains(builderSettings.resultMethod))
return new StatusInfo(IStatus.ERROR,
MessageFormat.format(JavaUIMessages.GenerateToStringDialog_customBuilderConfig_invalidResultMethodError,
builderSettings.resultMethod));
if (!isValidJavaIdentifier(builderSettings.variableName))
return new StatusInfo(IStatus.ERROR,
MessageFormat.format(JavaUIMessages.GenerateToStringDialog_customBuilderConfig_invalidVariableNameError,
builderSettings.variableName));
} catch (JavaModelException e) {
return new StatusInfo(IStatus.WARNING, JavaUIMessages.GenerateToStringDialog_customBuilderConfig_dataValidationError);
}
return new StatusInfo();
}
public IType findType(String builderClassName) throws JavaModelException {
if (fLastValidBuilderType != null && builderClassName.equals(fLastValidBuilderType.getFullyQualifiedParameterizedName())) {
return fLastValidBuilderType;
}
return fJavaProject.findType(builderClassName, (IProgressMonitor)null);
}
public List<String> getAppendMethodSuggestions(final IType type) throws JavaModelException {
if (fLastValidBuilderType != null && fLastValidBuilderType.equals(type)) {
return fLastValidAppendMethodSuggestions;
}
return getMethodSuggestions(type, method -> {
if (!Flags.isPublic(method.getFlags()) || method.isConstructor())
return false;
/* To be an append method, it must take exactly one
* Object parameter, and optionally one String parameter. */
String[] parameterTypes= method.getParameterTypes();
if (parameterTypes.length == 0 || parameterTypes.length > 2) {
return false;
}
int countObjects= 0, countStrings= 0;
for (String parameterType : parameterTypes) {
String resolvedParameterTypeName= JavaModelUtil.getResolvedTypeName(parameterType, type);
if ("java.lang.Object".equals(resolvedParameterTypeName))//$NON-NLS-1$
countObjects++;
if ("java.lang.String".equals(resolvedParameterTypeName))//$NON-NLS-1$
countStrings++;
}
return countObjects == 1 && countObjects + countStrings == parameterTypes.length;
});
}
public List<String> getResultMethodSuggestions(final IType type) throws JavaModelException {
if (fLastValidBuilderType != null && fLastValidBuilderType.equals(type)) {
return fLastValidResultMethodSuggestions;
}
return getMethodSuggestions(type, method -> Flags.isPublic(method.getFlags()) && method.getParameterTypes().length == 0 && "java.lang.String".equals(JavaModelUtil.getResolvedTypeName(method.getReturnType(), type))); //$NON-NLS-1$
}
private interface MethodChecker {
boolean isMethodOK(IMethod method) throws JavaModelException;
}
private List<String> getMethodSuggestions(IType type, MethodChecker checker) throws JavaModelException {
ArrayList<String> result= new ArrayList<>();
for (IType classe : type.newSupertypeHierarchy(null).getAllClasses()) {
for (IMethod method : classe.getMethods()) {
if (checker.isMethodOK(method)) {
String name= method.getElementName();
if (!result.contains(name))
result.add(name);
}
}
}
return result;
}
private boolean isValidJavaIdentifier(String identifier) {
return JavaConventionsUtil.validateIdentifier(identifier, fJavaProject).isOK();
}
}
private class CustomBuilderConfigurationDialog extends StatusDialog {
private final int APPLY_BUTTON= IDialogConstants.CLIENT_ID + 1;
/**
* Extension for class selection dialog - validates selected type
*/
private final TypeSelectionExtension fExtension= new TypeSelectionExtension() {
@Override
public ISelectionStatusValidator getSelectionValidator() {
return getValidator();
}
};
/**
* Listener for text fields - updates combos and validates entered data
*/
private final ModifyListener modifyListener= e -> {
if (e.widget == this.fBuilderClassName) {
this.fBuilderSettings.className= this.fBuilderClassName.getText();
updateCombos();
} else if (e.widget == this.fBuilderVariableName)
this.fBuilderSettings.variableName= this.fBuilderVariableName.getText();
IStatus status= getValidator().revalidateAll(this.fBuilderSettings);
updateStatus(status);
enableApplyButton();
};
private final CustomBuilderValidator fValidator= new CustomBuilderValidator(getType().getJavaProject());
private Text fBuilderClassName;
private Text fBuilderVariableName;
private Combo fAppendMethodName;
private Combo fResultMethodName;
private Button fChainInvocations;
private ToStringGenerationSettings.CustomBuilderSettings fBuilderSettings;
private boolean somethingChanged= false;
public CustomBuilderConfigurationDialog(Shell parent) {
super(parent);
this.setShellStyle(this.getShellStyle() | SWT.RESIZE);
fBuilderSettings= getGenerationSettings().getCustomBuilderSettings();
}
public CustomBuilderValidator getValidator() {
return fValidator;
}
@Override
protected Control createDialogArea(Composite parent) {
getShell().setText(JavaUIMessages.GenerateToStringDialog_customBuilderConfig_windowTitle);
Composite composite= (Composite)super.createDialogArea(parent);
((GridLayout)composite.getLayout()).numColumns= 3;
LayoutUtil.setWidthHint(composite, convertWidthInCharsToPixels(100));
Label label= new Label(composite, SWT.LEFT);
label.setText(JavaUIMessages.GenerateToStringDialog_customBuilderConfig_builderClassField);
fBuilderClassName= createTextField(composite, 1, fBuilderSettings.className);
Button button= new Button(composite, SWT.NONE);
button.setText(JavaUIMessages.GenerateToStringDialog_customBuilderConfig_browseButton);
setButtonLayoutData(button);
button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
browseForBuilderClass();
}
});
label= new Label(composite, SWT.LEFT);
label.setText(JavaUIMessages.GenerateToStringDialog_customBuilderConfig_varNameField);
fBuilderVariableName= createTextField(composite, 2, fBuilderSettings.variableName);
label= new Label(composite, SWT.LEFT);
label.setText(JavaUIMessages.GenerateToStringDialog_customBuilderConfig_appendMethodField);
fAppendMethodName= new Combo(composite, SWT.READ_ONLY);
fAppendMethodName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
label= new Label(composite, SWT.LEFT);
label.setText(JavaUIMessages.GenerateToStringDialog_customBuilderConfig_resultMethodField);
fResultMethodName= new Combo(composite, SWT.READ_ONLY);
fResultMethodName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
updateCombos();
ModifyListener comboListener= e -> {
Combo c= (Combo)e.widget;
if (c.getText().length() > 0) {
if (c == fAppendMethodName)
fBuilderSettings.appendMethod= c.getText();
if (c == fResultMethodName)
fBuilderSettings.resultMethod= c.getText();
}
updateStatus(fValidator.revalidateAll(fBuilderSettings));
enableApplyButton();
};
fAppendMethodName.addModifyListener(comboListener);
fResultMethodName.addModifyListener(comboListener);
if (!select(fAppendMethodName, fBuilderSettings.appendMethod)) {
fAppendMethodName.select(0);
}
if (!select(fResultMethodName, fBuilderSettings.resultMethod)) {
fResultMethodName.select(0);
}
fChainInvocations= new Button(composite, SWT.CHECK);
fChainInvocations.setText(JavaUIMessages.GenerateToStringDialog_customBuilderConfig_chainedCallsCheckbox);
fChainInvocations.setSelection(fBuilderSettings.chainCalls);
fChainInvocations.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
fChainInvocations.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
fBuilderSettings.chainCalls= fChainInvocations.getSelection();
enableApplyButton();
}
});
PlatformUI.getWorkbench().getHelpSystem().setHelp(getShell(), IJavaHelpContextIds.GENERATE_TOSTRING_CONFIGURE_CUSTOM_BUILDER_DIALOG);
return composite;
}
@Override
public void create() {
super.create();
IStatus status= getValidator().revalidateAll(fBuilderSettings);
updateStatus(status);
}
@Override
protected void createButtonsForButtonBar(Composite parent) {
super.createButtonsForButtonBar(parent);
createButton(parent, APPLY_BUTTON, JavaUIMessages.GenerateToStringDialog_customBuilderConfig_applyButton, false).setEnabled(false);
}
private void enableApplyButton() {
somethingChanged= true;
getButton(APPLY_BUTTON).setEnabled(!getStatus().matches(IStatus.ERROR));
}
@Override
protected void updateButtonsEnableState(IStatus status) {
super.updateButtonsEnableState(status);
getButton(APPLY_BUTTON).setEnabled(!status.matches(IStatus.ERROR) && somethingChanged);
}
@Override
protected void buttonPressed(int buttonId) {
switch (buttonId) {
case APPLY_BUTTON:
getButton(APPLY_BUTTON).setEnabled(false);
somethingChanged= false;
//$FALL-THROUGH$
case OK:
applyChanges();
}
super.buttonPressed(buttonId);
}
private boolean select(Combo combo, String item) {
int index= Arrays.asList(combo.getItems()).indexOf(item);
if (index >= 0) {
combo.select(index);
return true;
}
return false;
}
private void updateCombos() {
final String[] empty= new String[0];
try {
IType type= fValidator.findType(fBuilderSettings.className);
if (type == null) {
fAppendMethodName.setItems(empty);
fResultMethodName.setItems(empty);
} else {
fAppendMethodName.setItems(fValidator.getAppendMethodSuggestions(type).toArray(empty));
select(fAppendMethodName, fBuilderSettings.appendMethod);
fResultMethodName.setItems(fValidator.getResultMethodSuggestions(type).toArray(empty));
select(fResultMethodName, fBuilderSettings.resultMethod);
}
} catch (JavaModelException e1) {
fAppendMethodName.setItems(empty);
fResultMethodName.setItems(empty);
}
}
private void applyChanges() {
fBuilderSettings.appendMethod= fAppendMethodName.getText();
fBuilderSettings.resultMethod= fResultMethodName.getText();
getGenerationSettings().writeCustomBuilderSettings(fBuilderSettings);
}
private Text createTextField(Composite composite, int gridHSpan, String text) {
Text result= new Text(composite, SWT.BORDER);
result.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, gridHSpan, 1));
result.setText(text);
result.addModifyListener(modifyListener);
TextFieldNavigationHandler.install(result);
return result;
}
private void browseForBuilderClass() {
try {
IJavaSearchScope scope= SearchEngine.createJavaSearchScope(new IJavaElement[] { getType().getJavaProject() });
SelectionDialog dialog= JavaUI.createTypeDialog(getShell(), PlatformUI.getWorkbench().getProgressService(), scope,
IJavaElementSearchConstants.CONSIDER_CLASSES, false, "*ToString", fExtension); //$NON-NLS-1$
dialog.setTitle(JavaUIMessages.GenerateToStringDialog_customBuilderConfig_classSelection_windowTitle);
dialog.setMessage(JavaUIMessages.GenerateToStringDialog_customBuilderConfig_classSelection_message);
dialog.open();
if (dialog.getReturnCode() == OK) {
IType type= (IType)dialog.getResult()[0];
fBuilderClassName.setText(type.getFullyQualifiedParameterizedName());
List<String> suggestions= fValidator.getAppendMethodSuggestions(type);
if (!suggestions.contains(fAppendMethodName.getText()))
fAppendMethodName.setText(suggestions.get(0));
suggestions= fValidator.getResultMethodSuggestions(type);
if (!suggestions.contains(fResultMethodName.getText()))
fResultMethodName.setText(suggestions.get(0));
}
} catch (JavaModelException e) {
JavaPlugin.log(e);
}
}
}
private ToStringGenerationSettings fGenerationSettings;
private static final int DOWN_BUTTON= IDialogConstants.CLIENT_ID + 2;
private static final int UP_BUTTON= IDialogConstants.CLIENT_ID + 1;
private static final int SORT_BUTTON= IDialogConstants.CLIENT_ID + 3;
protected Button[] fButtonControls;
boolean[] fButtonsEnabled;
private static final int DOWN_INDEX= 1;
private static final int UP_INDEX= 0;
public ToStringGenerationSettings getGenerationSettings() {
return fGenerationSettings;
}
public static String[] getTemplates(IDialogSettings dialogSettings) {
String[] result= dialogSettings.getArray(ToStringGenerationSettings.SETTINGS_TEMPLATES);
if (result != null && result.length > 0)
return result;
return new String[] { ToStringTemplateParser.DEFAULT_TEMPLATE };
}
public String[] getTemplateNames() {
String[] result= getDialogSettings().getArray(ToStringGenerationSettings.SETTINGS_TEMPLATE_NAMES);
if (result != null && result.length > 0)
return result;
return new String[] { JavaUIMessages.GenerateToStringDialog_defaultTemplateName };
}
public int getSelectedTemplate() {
try {
int result= getDialogSettings().getInt(ToStringGenerationSettings.SETTINGS_SELECTED_TEMPLATE);
if (result < 0)
return 0;
return result;
} catch (NumberFormatException e) {
return 0;
}
}
public void setSelectedTemplate(int templateNumber) {
getDialogSettings().put(ToStringGenerationSettings.SETTINGS_SELECTED_TEMPLATE, templateNumber);
}
public GenerateToStringDialog(Shell shell, CompilationUnitEditor editor, IType type, IVariableBinding[] fields, IVariableBinding[] inheritedFields, IVariableBinding[] selectedFields,
IMethodBinding[] methods, IMethodBinding[] inheritededMethods) throws JavaModelException {
super(shell, new BindingLabelProvider(), new GenerateToStringContentProvider(fields, inheritedFields, methods, inheritededMethods), editor, type, false);
setEmptyListMessage(JavaUIMessages.GenerateHashCodeEqualsDialog_no_entries);
List<Object> selected= new ArrayList<>(Arrays.asList(selectedFields));
if (selectedFields.length == fields.length && selectedFields.length > 0)
selected.add(getContentProvider().getParent(selectedFields[0]));
setInitialElementSelections(selected);
setTitle(JavaUIMessages.GenerateToStringDialog_dialog_title);
setMessage(JavaUIMessages.GenerateToStringDialog_select_fields_to_include);
setValidator(new GenerateToStringValidator(fields.length + inheritedFields.length, methods.length + inheritededMethods.length));
setSize(60, 18);
setInput(new Object());
fGenerationSettings= new ToStringGenerationSettings(getDialogSettings());
}
@Override
public boolean close() {
fGenerationSettings.writeDialogSettings();
fGenerationSettings.stringFormatTemplate= getTemplates(getDialogSettings())[fGenerationSettings.stringFormatTemplateNumber];
fGenerationSettings.createComments= getGenerateComment();
return super.close();
}
@Override
public Object[] getResult() {
Object[] oldResult= super.getResult();
List<Object> newResult= new ArrayList<>();
for (Object r : oldResult) {
if (!(r instanceof String)) {
newResult.add(r);
}
}
return newResult.toArray();
}
@Override
protected void configureShell(Shell shell) {
super.configureShell(shell);
PlatformUI.getWorkbench().getHelpSystem().setHelp(shell, IJavaHelpContextIds.GENERATE_TOSTRING_SELECTION_DIALOG);
}
@Override
protected CheckboxTreeViewer createTreeViewer(Composite parent) {
CheckboxTreeViewer treeViewer= super.createTreeViewer(parent);
treeViewer.setLabelProvider(new GenerateToStringLabelProvider());
//expandAll because setSubtreeChecked() used in CheckStateListener below assumes that elements have been expanded
treeViewer.expandAll();
//but actually we only need one branch expanded
treeViewer.collapseAll();
treeViewer.expandToLevel(GenerateToStringContentProvider.fieldsNode, 1);
treeViewer.addSelectionChangedListener(event -> {
IStructuredSelection selection= (IStructuredSelection)getTreeViewer().getSelection();
Object selected= selection.size() > 0 ? selection.toList().get(0) : null;
GenerateToStringContentProvider cp= (GenerateToStringContentProvider)getContentProvider();
fButtonControls[UP_INDEX].setEnabled(cp.canMoveUp(selected));
fButtonControls[DOWN_INDEX].setEnabled(cp.canMoveDown(selected));
});
treeViewer.addCheckStateListener(event -> {
getTreeViewer().setSubtreeChecked(event.getElement(), event.getChecked());
getTreeViewer().setGrayed(event.getElement(), false);
Object parentElement= ((ITreeContentProvider)(getTreeViewer().getContentProvider())).getParent(event.getElement());
if (parentElement != null) {
Object[] siblings= ((ITreeContentProvider)(getTreeViewer().getContentProvider())).getChildren(parentElement);
int count= 0;
for (Object sibling : siblings) {
if (getTreeViewer().getChecked(sibling)) {
count++;
}
}
if (count == 0)
getTreeViewer().setGrayChecked(parentElement, false);
else if (count == siblings.length) {
getTreeViewer().setChecked(parentElement, true);
getTreeViewer().setGrayed(parentElement, false);
} else
getTreeViewer().setGrayChecked(parentElement, true);
}
updateOKStatus();
});
return treeViewer;
}
@Override
protected Composite createSelectionButtons(Composite composite) {
Composite buttonComposite= super.createSelectionButtons(composite);
GridLayout layout= new GridLayout();
buttonComposite.setLayout(layout);
createUpDownButtons(buttonComposite);
createButton(buttonComposite, SORT_BUTTON, JavaUIMessages.GenerateToStringDialog_sort_button, false);
layout.marginHeight= 0;
layout.marginWidth= 0;
layout.numColumns= 1;
return buttonComposite;
}
@Override
protected void createButtonsForButtonBar(Composite parent) {
createButton(parent, IDialogConstants.OK_ID, JavaUIMessages.GenerateToStringDialog_generate_button, true);
createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
}
@Override
protected void buttonPressed(int buttonId) {
super.buttonPressed(buttonId);
switch (buttonId) {
case UP_BUTTON: {
GenerateToStringContentProvider contentProvider= (GenerateToStringContentProvider)getTreeViewer().getContentProvider();
List<?> selection= ((IStructuredSelection)getTreeViewer().getSelection()).toList();
if (selection.size() > 0)
contentProvider.up(selection.get(0), getTreeViewer());
updateOKStatus();
break;
}
case DOWN_BUTTON: {
GenerateToStringContentProvider contentProvider= (GenerateToStringContentProvider)getTreeViewer().getContentProvider();
List<?> selection= ((IStructuredSelection)getTreeViewer().getSelection()).toList();
if (selection.size() > 0)
contentProvider.down(selection.get(0), getTreeViewer());
updateOKStatus();
break;
}
case SORT_BUTTON: {
GenerateToStringContentProvider contentProvider= (GenerateToStringContentProvider)getTreeViewer().getContentProvider();
contentProvider.sort();
getTreeViewer().refresh();
updateOKStatus();
break;
}
}
}
protected void createUpDownButtons(Composite buttonComposite) {
int numButtons= 2; // up, down
fButtonControls= new Button[numButtons];
fButtonsEnabled= new boolean[numButtons];
fButtonControls[UP_INDEX]= createButton(buttonComposite, UP_BUTTON, JavaUIMessages.GenerateToStringDialog_up_button, false);
fButtonControls[DOWN_INDEX]= createButton(buttonComposite, DOWN_BUTTON, JavaUIMessages.GenerateToStringDialog_down_button, false);
boolean defaultState= false;
fButtonControls[UP_INDEX].setEnabled(defaultState);
fButtonControls[DOWN_INDEX].setEnabled(defaultState);
fButtonsEnabled[UP_INDEX]= defaultState;
fButtonsEnabled[DOWN_INDEX]= defaultState;
}
private Label formatLabel;
private Combo formatCombo;
private Button skipNullsButton;
private Button styleButton;
@Override
protected Composite createCommentSelection(Composite parentComposite) {
Composite composite= super.createCommentSelection(parentComposite);
Group group= new Group(parentComposite, SWT.NONE);
group.setText(JavaUIMessages.GenerateToStringDialog_generated_code_group);
GridLayout groupLayout= new GridLayout();
group.setLayout(groupLayout);
group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
Composite composite2= new Composite(group, SWT.NONE);
GridLayout layout= new GridLayout(3, false);
layout.marginWidth= 0;
layout.marginHeight= 0;
composite2.setLayout(layout);
composite2.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
formatLabel= new Label(composite2, SWT.NONE);
formatLabel.setText(JavaUIMessages.GenerateToStringDialog_string_format_combo);
GridData gridData= new GridData(SWT.FILL, SWT.CENTER, false, false);
formatLabel.setLayoutData(gridData);
formatCombo= new Combo(composite2, SWT.READ_ONLY);
formatCombo.setItems(getTemplateNames());
formatCombo.select(fGenerationSettings.stringFormatTemplateNumber);
formatCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
SWTUtil.setDefaultVisibleItemCount(formatCombo);
formatCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
fGenerationSettings.stringFormatTemplateNumber= ((Combo)e.widget).getSelectionIndex();
}
});
final Button formatButton= new Button(composite2, SWT.NONE);
formatButton.setText(JavaUIMessages.GenerateToStringDialog_manage_templates_button);
setButtonLayoutData(formatButton);
formatButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
manageTemplatesButtonSelected();
}
});
final Label styleLabel= new Label(composite2, SWT.NONE);
styleLabel.setText(JavaUIMessages.GenerateToStringDialog_code_style_combo);
gridData= new GridData(SWT.FILL, SWT.CENTER, false, false);
styleLabel.setLayoutData(gridData);
final Combo styleCombo= new Combo(composite2, SWT.READ_ONLY);
styleCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
styleCombo.setItems(GenerateToStringOperation.getStyleNames());
styleCombo.select(Math.min(fGenerationSettings.toStringStyle, styleCombo.getItemCount() - 1));
SWTUtil.setDefaultVisibleItemCount(styleCombo);
styleCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
changeToStringStyle(((Combo)e.widget).getSelectionIndex());
}
});
styleButton= new Button(composite2, SWT.NONE);
styleButton.setText(JavaUIMessages.GenerateToStringDialog_codeStyleConfigureButton);
setButtonLayoutData(styleButton);
styleButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
configureStyleButtonSelected();
}
});
skipNullsButton= new Button(group, SWT.CHECK);
skipNullsButton.setText(JavaUIMessages.GenerateToStringDialog_skip_null_button);
skipNullsButton.setSelection(fGenerationSettings.skipNulls);
skipNullsButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
fGenerationSettings.skipNulls= ((Button)event.widget).getSelection();
}
});
final Button arrayButton= new Button(group, SWT.CHECK);
arrayButton.setText(JavaUIMessages.GenerateToStringDialog_ignore_default_button);
arrayButton.setSelection(fGenerationSettings.customArrayToString);
arrayButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
fGenerationSettings.customArrayToString= ((Button)e.widget).getSelection();
}
});
Composite limitRow= new Composite(group, SWT.NONE);
RowLayout rowLayout= new RowLayout();
rowLayout.center= true;
rowLayout.marginLeft= rowLayout.marginRight= rowLayout.marginTop= rowLayout.marginBottom= 0;
limitRow.setLayout(rowLayout);
final Button limitButton= new Button(limitRow, SWT.CHECK);
limitButton.setText(JavaUIMessages.GenerateToStringDialog_limit_elements_button);
limitButton.setSelection(fGenerationSettings.limitElements);
limitButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
fGenerationSettings.limitElements= ((Button)e.widget).getSelection();
}
});
final Spinner limitSpinner= new Spinner(limitRow, SWT.BORDER);
limitSpinner.setMinimum(0);
limitSpinner.setSelection(fGenerationSettings.limitValue);
limitSpinner.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
fGenerationSettings.limitValue= ((Spinner)e.widget).getSelection();
}
});
//invoked to change initial enable state of controls
changeToStringStyle(styleCombo.getSelectionIndex());
return composite;
}
private void manageTemplatesButtonSelected() {
ToStringTemplatesDialog dialog= new ToStringTemplatesDialog(getShell(), GenerateToStringOperation.createTemplateParser(fGenerationSettings.toStringStyle));
dialog.open();
formatCombo.setItems(getTemplateNames());
formatCombo.select(Math.min(fGenerationSettings.stringFormatTemplateNumber, formatCombo.getItemCount() - 1));
}
private void configureStyleButtonSelected() {
CustomBuilderConfigurationDialog dialog= new CustomBuilderConfigurationDialog(getShell());
dialog.open();
updateOKStatus();
}
private void changeToStringStyle(int style) {
fGenerationSettings.toStringStyle= style;
skipNullsButton.setEnabled(style != GenerateToStringOperation.STRING_FORMAT);
boolean enableFormat= (style != GenerateToStringOperation.CUSTOM_BUILDER);
formatLabel.setEnabled(enableFormat);
formatCombo.setEnabled(enableFormat);
styleButton.setEnabled(style == GenerateToStringOperation.CUSTOM_BUILDER);
updateOKStatus();
}
}