diff --git a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/JdtTextTestSuite.java b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/JdtTextTestSuite.java index ae6b859828e..c59e7208361 100644 --- a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/JdtTextTestSuite.java +++ b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/JdtTextTestSuite.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2024 IBM Corporation and others. + * Copyright (c) 2000, 2025 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -20,7 +20,7 @@ import org.eclipse.jdt.text.tests.codemining.CodeMiningTriggerTest; import org.eclipse.jdt.text.tests.codemining.ParameterNamesCodeMiningTest; import org.eclipse.jdt.text.tests.contentassist.ContentAssistTestSuite; -import org.eclipse.jdt.text.tests.folding.FoldingTest; +import org.eclipse.jdt.text.tests.folding.FoldingTestSuite; import org.eclipse.jdt.text.tests.semantictokens.SemanticTokensProviderTest; import org.eclipse.jdt.text.tests.spelling.SpellCheckEngineTestCase; import org.eclipse.jdt.text.tests.templates.TemplatesTestSuite; @@ -71,7 +71,7 @@ JavaElementPrefixPatternMatcherTest.class, CodeMiningTriggerTest.class, ParameterNamesCodeMiningTest.class, - FoldingTest.class, + FoldingTestSuite.class, }) public class JdtTextTestSuite { } \ No newline at end of file diff --git a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/folding/CustomFoldingRegionTest.java b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/folding/CustomFoldingRegionTest.java new file mode 100644 index 00000000000..2a2e287dfdd --- /dev/null +++ b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/folding/CustomFoldingRegionTest.java @@ -0,0 +1,435 @@ +/******************************************************************************* + * Copyright (c) 2025 Daniel Schmid 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: + * Daniel Schmid - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.text.tests.folding; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import org.eclipse.jdt.testplugin.JavaProjectHelper; + +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.jface.preference.IPreferenceStore; + +import org.eclipse.jface.text.IRegion; + +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IPackageFragmentRoot; + +import org.eclipse.jdt.ui.PreferenceConstants; +import org.eclipse.jdt.ui.tests.core.rules.ProjectTestSetup; + +import org.eclipse.jdt.internal.ui.JavaPlugin; + +public class CustomFoldingRegionTest { + @Rule + public ProjectTestSetup projectSetup= new ProjectTestSetup(); + + private IJavaProject fJProject1; + + private IPackageFragmentRoot fSourceFolder; + + private IPackageFragment fPackageFragment; + + @Before + public void setUp() throws CoreException { + fJProject1= projectSetup.getProject(); + fSourceFolder= JavaProjectHelper.addSourceContainer(fJProject1, "src"); + fPackageFragment= fSourceFolder.createPackageFragment("org.example.test", false, null); + } + + + @After + public void tearDown() throws CoreException { + JavaProjectHelper.delete(fJProject1); + IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore(); + store.setToDefault(PreferenceConstants.EDITOR_FOLDING_CUSTOM_REGION_START); + store.setToDefault(PreferenceConstants.EDITOR_FOLDING_CUSTOM_REGION_END); + } + + @Test + public void testNoCustomFoldingRegions() throws Exception { + String str= """ + package org.example.test; + public class Test { + } + """; + List projectionRanges= getProjectionRangesOfFile(str); + assertEquals(0, projectionRanges.size()); + } + + @Test + public void testCustomFoldingRegionInsideAndOutsideClass() throws Exception { + String str= """ + package org.example.test; + // #region + // something else + // #endregion + public class Test { + // #region + // something else + // #endregion + } + """; + List projectionRanges= getProjectionRangesOfFile(str); + assertEquals(2, projectionRanges.size()); + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 1, 3); + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 5, 7); + } + + @Test + public void testNestedCustomRegions() throws Exception { + String str= """ + package org.example.test; + + public class Test { + // #region outer + // #region inner + + // #endregion outer + // #endregion inner + } + """; + List projectionRanges= getProjectionRangesOfFile(str); + assertEquals(2, projectionRanges.size()); + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 3, 7);//outer + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 4, 6);//inner + } + + @Test + public void testNoCustomFoldingRegionsInMethod() throws Exception { + String str= """ + package org.example.test; + public class Test { + void a(){ + + } + } + """; + List projectionRanges= getProjectionRangesOfFile(str); + assertEquals(1, projectionRanges.size()); + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 2, 3); + } + + @Test + public void testCustomFoldingRegionsInMethod() throws Exception { + String str= """ + package org.example.test; + public class Test { + void a(){ + // #region + + // #endregion + } + } + """; + List projectionRanges= getProjectionRangesOfFile(str); + assertEquals(2, projectionRanges.size()); + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 2, 6); + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 3, 5); + } + + @Test + public void testNoCustomFoldingRegionsSingleImport() throws Exception { + String str= """ + package org.example.test; + + import java.util.List; + """; + List projectionRanges= getProjectionRangesOfFile(str); + assertEquals(0, projectionRanges.size()); + } + + @Test + public void testCustomFoldingRegionAroundSingleImport() throws Exception { + String str= """ + package org.example.test; + + // #region imports + import java.util.List; + // #endregion + """; + List projectionRanges= getProjectionRangesOfFile(str); + assertEquals(1, projectionRanges.size()); + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 2, 4); + } + + @Test + public void testCustomFoldingRegionAroundClasses() throws Exception { + String str= """ + package org.example.test; + + class A { + + } + + // #region + + class B { + + } + + class C { + + } + // #endregion + + class D { + + } + """; + List projectionRanges= getProjectionRangesOfFile(str); + assertEquals(1, projectionRanges.size()); + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 6, 15); + } + + @Test + public void testCustomFoldingRegionsMultipleLevels() throws Exception { + String str= """ + package org.example.test; + // #region outside class + public class Test { + // #endregion should be ignored + // #region outside method + void a(){ + // #endregion should be ignored + // #region inside method + System.out.println("Hello World"); + // #endregion inside method + } + // #endregion outside method + } + // #endregion outside class + """; + List projectionRanges= getProjectionRangesOfFile(str); + assertEquals(4, projectionRanges.size()); + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 1, 13);//outside class + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 4, 11);//outside method + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 5, 10);//void a() + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 7, 9);//inside method + } + + @Test + public void testCustomFoldingRegionsNotEndingTooEarly() throws Exception { + String str= """ + package org.example.test; + + public class Test { + void a(){ + // #region inside method + } + // #endregion outside method + } + // #endregion outside class + """; + List projectionRanges= getProjectionRangesOfFile(str); + assertEquals(1, projectionRanges.size()); + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 3, 4);//void a() + } + + @Test + public void testCustomFoldingRegionsUsingSpecialCommentTypes() throws Exception { + String str= """ + package org.example.test; + + public class Test { + void a(){ + /* #region multiline + */ + /** #region javadoc */ + /** #endregion javadoc */ + /* #endregion multiline + */ + } + } + """; + List projectionRanges= getProjectionRangesOfFile(str); + assertEquals(3, projectionRanges.size()); + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 3, 10);//void a() + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 4, 8);// multiline + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 6, 7);// javadoc + } + + @Test + public void testCustomRegionsWithLocalClass() throws Exception { + String str= """ + package org.example.test; + + public class Test { + void a(){ + // #region + int i; + + // #endregion + class Inner{ + + } + } + } + """; + List projectionRanges= getProjectionRangesOfFile(str); + assertEquals(3, projectionRanges.size()); + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 3, 10);//void a() + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 4, 7);//region + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 8, 10);//class Inner + } + + @Test + public void testNoCustomRegionAtDifferentLevelsWithOtherClass() throws Exception { + String str= """ + package org.example.test; + + public class Test{ + // #region outside + public class A { + public void helloWorld() { + + } + // #endregion inside + } + + public class B { + + + } + + } + """; + List projectionRanges= getProjectionRangesOfFile(str); + assertEquals(3, projectionRanges.size()); + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 4, 8);//class A + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 5, 6);//void helloWorld() + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 11, 13);//class B + } + + @Test + public void testCustomRegionsAroundFieldAndMethod() throws Exception { + String str= """ + package org.example.test; + + public class Test { + // #region + int a; + + void b(){ + + } + // #endregion + } + """; + List projectionRanges= getProjectionRangesOfFile(str); + assertEquals(2, projectionRanges.size()); + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 3, 9);//region + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 6, 8);//void b() + } + + @Test + public void testDifferentConfiguration() throws Exception { + IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore(); + store.setValue(PreferenceConstants.EDITOR_FOLDING_CUSTOM_REGION_START, "#regstart"); + store.setValue(PreferenceConstants.EDITOR_FOLDING_CUSTOM_REGION_END, "#regend"); + + + String str= """ + package org.example.test; + public class Test { + // #region should be ignored + // #regstart this is the region + // #regend should end here + // #endregion should be ignored + } + """; + List projectionRanges= getProjectionRangesOfFile(str); + assertEquals(1, projectionRanges.size()); + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 3, 4); + } + + @Test + public void testCommentsInEmptyBlocks() throws Exception { + String str= """ + package org.example.test; + public class Test { + void a(){ + {/* #region 1*/} + System.out.println("Hello World"); + {/* #endregion 1*/} + } + } + """; + List projectionRanges= getProjectionRangesOfFile(str); + assertEquals(2, projectionRanges.size()); + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 2, 6);//void a() + assertContainsRegionUsingStartAndEndLine(projectionRanges, str, 3, 5);//region 1 + } + + private void assertContainsRegionUsingStartAndEndLine(List projectionRanges, String input, int startLine, int endLine) { + assertTrue(startLine <= endLine, "start line must be smaller or equal to end line"); + int startLineBegin= findLineStartIndex(input, startLine); + + int endLineBegin= findLineStartIndex(input, endLine); + int endLineEnd= findNextLineStart(input, endLineBegin); + endLineEnd= getLengthIfNotFound(input, endLineEnd); + + for (IRegion region : projectionRanges) { + if (region.getOffset() == startLineBegin + 1 && region.getOffset() + region.getLength() == endLineEnd + 1) { + return; + } + } + + fail( + "missing region from line " + startLine + " (index " + (startLineBegin + 1) + ") " + + "to line " + endLine + " (index " + (endLineEnd + 1) + ")" + + ", actual regions: " + projectionRanges + ); + } + + + private int getLengthIfNotFound(String input, int startLineEnd) { + if (startLineEnd == -1) { + startLineEnd= input.length(); + } + return startLineEnd; + } + + + private int findLineStartIndex(String input, int lineNumber) { + int currentInputIndex= 0; + for (int i= 0; i < lineNumber; i++) { + currentInputIndex= findNextLineStart(input, currentInputIndex); + if (currentInputIndex == -1) { + fail("line number is greater than the total number of lines"); + } + } + return currentInputIndex; + } + + + private int findNextLineStart(String input, int currentInputIndex) { + return input.indexOf('\n', currentInputIndex + 1); + } + + private List getProjectionRangesOfFile(String str) throws Exception { + return FoldingTestUtils.getProjectionRangesOfFile(fPackageFragment, "Test.java", str); + } + +} diff --git a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/folding/FoldingTestSuite.java b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/folding/FoldingTestSuite.java new file mode 100644 index 00000000000..cdeb7598bdf --- /dev/null +++ b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/folding/FoldingTestSuite.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2025 Daniel Schmid 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: + * Daniel Schmid - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.text.tests.folding; + +import org.junit.platform.suite.api.SelectClasses; +import org.junit.platform.suite.api.Suite; + +@Suite +@SelectClasses({ + FoldingTest.class, + CustomFoldingRegionTest.class, +}) +public class FoldingTestSuite { +} diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/folding/DefaultJavaFoldingPreferenceBlock.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/folding/DefaultJavaFoldingPreferenceBlock.java index 43510a919e0..10325997bb6 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/folding/DefaultJavaFoldingPreferenceBlock.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/folding/DefaultJavaFoldingPreferenceBlock.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. + * Copyright (c) 2000, 2025 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -15,10 +15,10 @@ import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; @@ -28,6 +28,7 @@ import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; import org.eclipse.jface.preference.IPreferenceStore; @@ -60,6 +61,12 @@ public void widgetSelected(SelectionEvent e) { fOverlayStore.setValue(fCheckBoxes.get(button), button.getSelection()); } }; + private Map fStringInputs= new HashMap<>(); + private ModifyListener fModifyListener = e -> { + Text text = (Text)e.widget; + fOverlayStore.setValue(fStringInputs.get(text), text.getText()); + }; + public DefaultJavaFoldingPreferenceBlock() { @@ -77,6 +84,9 @@ private OverlayKey[] createKeys() { overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_IMPORTS)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_HEADERS)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_NEW_FOLDING_ENABLED)); + overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_CUSTOM_REGIONS)); + overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, PreferenceConstants.EDITOR_FOLDING_CUSTOM_REGION_START)); + overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, PreferenceConstants.EDITOR_FOLDING_CUSTOM_REGION_END)); return overlayKeys.toArray(new OverlayKey[overlayKeys.size()]); } @@ -88,32 +98,29 @@ public Control createControl(Composite composite) { fOverlayStore.load(); fOverlayStore.start(); - composite.setLayout(new GridLayout(1, false)); - composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - - Composite inner= new Composite(composite, SWT.NONE); GridLayout layout= new GridLayout(1, false); - layout.verticalSpacing= 10; + layout.verticalSpacing= 3; layout.marginWidth= 0; - layout.marginHeight= 0; - inner.setLayout(layout); - inner.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - - Group initialFoldGroup = new Group(inner, SWT.NONE); - GridLayout initialFoldLayout = new GridLayout(1, false); - initialFoldLayout.marginWidth = 10; - initialFoldLayout.marginHeight = 10; - initialFoldGroup.setLayout(initialFoldLayout); - initialFoldGroup.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); - initialFoldGroup.setText(FoldingMessages.DefaultJavaFoldingPreferenceBlock_title); - - addCheckBox(initialFoldGroup, FoldingMessages.DefaultJavaFoldingPreferenceBlock_comments, PreferenceConstants.EDITOR_FOLDING_JAVADOC, 0); - addCheckBox(initialFoldGroup, FoldingMessages.DefaultJavaFoldingPreferenceBlock_headers, PreferenceConstants.EDITOR_FOLDING_HEADERS, 0); - addCheckBox(initialFoldGroup, FoldingMessages.DefaultJavaFoldingPreferenceBlock_innerTypes, PreferenceConstants.EDITOR_FOLDING_INNERTYPES, 0); - addCheckBox(initialFoldGroup, FoldingMessages.DefaultJavaFoldingPreferenceBlock_methods, PreferenceConstants.EDITOR_FOLDING_METHODS, 0); - addCheckBox(initialFoldGroup, FoldingMessages.DefaultJavaFoldingPreferenceBlock_imports, PreferenceConstants.EDITOR_FOLDING_IMPORTS, 0); - - Group extendedFoldingGroup= new Group(inner, SWT.NONE); +// layout.marginHeight= 0; + composite.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); + + Composite outer= new Composite(composite, SWT.NONE); + outer.setLayout(layout); + outer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + Group initialFoldingGroup= new Group(outer, SWT.NONE); + initialFoldingGroup.setLayout(layout); + initialFoldingGroup.setText(FoldingMessages.DefaultJavaFoldingPreferenceBlock_title); + initialFoldingGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + addCheckBox(initialFoldingGroup, FoldingMessages.DefaultJavaFoldingPreferenceBlock_comments, PreferenceConstants.EDITOR_FOLDING_JAVADOC, 0); + addCheckBox(initialFoldingGroup, FoldingMessages.DefaultJavaFoldingPreferenceBlock_headers, PreferenceConstants.EDITOR_FOLDING_HEADERS, 0); + addCheckBox(initialFoldingGroup, FoldingMessages.DefaultJavaFoldingPreferenceBlock_innerTypes, PreferenceConstants.EDITOR_FOLDING_INNERTYPES, 0); + addCheckBox(initialFoldingGroup, FoldingMessages.DefaultJavaFoldingPreferenceBlock_methods, PreferenceConstants.EDITOR_FOLDING_METHODS, 0); + addCheckBox(initialFoldingGroup, FoldingMessages.DefaultJavaFoldingPreferenceBlock_imports, PreferenceConstants.EDITOR_FOLDING_IMPORTS, 0); + addCheckBox(initialFoldingGroup, FoldingMessages.DefaultJavaFoldingPreferenceBlock_customRegions, PreferenceConstants.EDITOR_FOLDING_CUSTOM_REGIONS, 0); + + Group extendedFoldingGroup= new Group(outer, SWT.NONE); GridLayout extendedFoldingLayout= new GridLayout(1, false); extendedFoldingLayout.marginWidth= 10; extendedFoldingLayout.marginHeight= 10; @@ -126,7 +133,17 @@ public Control createControl(Composite composite) { label.setLayoutData(gd); label.setText(FoldingMessages.DefaultJavaFoldingPreferenceBlock_Warning_New_Feature); addCheckBox(extendedFoldingGroup, FoldingMessages.DefaultJavaFoldingPreferenceBlock_New, PreferenceConstants.EDITOR_NEW_FOLDING_ENABLED, 0); - return inner; + + Group customRegionGroup= new Group(outer, SWT.NONE); + customRegionGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + GridLayout customRegionLayout= new GridLayout(2, false); + customRegionGroup.setLayout(customRegionLayout); + customRegionGroup.setText(FoldingMessages.DefaultJavaFoldingPreferenceBlock_custom_region_title); + addStringInput(customRegionGroup, FoldingMessages.DefaultJavaFoldingPreferenceBlock_CustomRegionStart, PreferenceConstants.EDITOR_FOLDING_CUSTOM_REGION_START); + addStringInput(customRegionGroup, FoldingMessages.DefaultJavaFoldingPreferenceBlock_CustomRegionEnd, PreferenceConstants.EDITOR_FOLDING_CUSTOM_REGION_END); + + return outer; } private Button addCheckBox(Composite parent, String label, String key, int indentation) { @@ -145,13 +162,29 @@ private Button addCheckBox(Composite parent, String label, String key, int inden return checkBox; } + private void addStringInput(Composite parent, String label, String key) { + Label labelElement = new Label(parent, SWT.LEFT); + labelElement.setText(label); + GridData labelGridData= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); + labelGridData.horizontalSpan= 1; + labelGridData.grabExcessVerticalSpace= false; + labelElement.setLayoutData(labelGridData); + + Text textInput = new Text(parent, SWT.SINGLE | SWT.BORDER); + textInput.setText(label); + textInput.addModifyListener(fModifyListener); + + GridData textGridData= new GridData(SWT.FILL, SWT.BEGINNING, true, false); + textGridData.horizontalSpan= 1; + textGridData.grabExcessVerticalSpace= true; + textInput.setLayoutData(textGridData); + + fStringInputs.put(textInput, key); + } + private void initializeFields() { - Iterator