/******************************************************************************* * Copyright (c) 2007, 2008 Symbian Software Limited 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: * Bala Torati (Symbian) - Initial API and implementation *******************************************************************************/ package org.eclipse.cdt.ui.templateengine.uitree.uiwidgets; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.cdt.core.templateengine.TemplateEngineHelper; import org.eclipse.cdt.ui.templateengine.Messages; import org.eclipse.cdt.ui.templateengine.event.PatternEvent; import org.eclipse.cdt.ui.templateengine.uitree.IPatternMatchingTable; import org.eclipse.cdt.ui.templateengine.uitree.InputUIElement; import org.eclipse.cdt.ui.templateengine.uitree.UIAttributes; import org.eclipse.cdt.ui.templateengine.uitree.UIElement; /** * This gives a Label and Text widget. The Text widget can be SINGLE type of * MULTI type. This depends on the input type in TemplateDescriptor. The data * entered by the user is verified against an expected pattern. If the user * entered data doesn't confirms to the expected pattern, a PatternEvent is * fired to UIComposite. * * The UI***Widget classes which needs to handle patterns, can inherit the same * from this class. The inheriting class need not cache UIComposite instance * but should set the same for UITextWidget(super). */ public class UITextWidget extends InputUIElement implements ModifyListener { /** * Text widget. */ protected Text text; /** * Label of this widget. */ protected Label label; private String patternValue; /** * Composite to which this widget control is added. Classes extending this class, should make sure that they initialize this from the respective class createWidgets method. */ protected UIComposite uiComposite; protected String textValue; /** * Constructor. * * @param uiAttribute * attribute associated with this widget. */ public UITextWidget(UIAttributes uiAttribute) { super(uiAttribute); this.textValue = new String(); } /** * @return String, value contained in the Text Widget. */ @Override public Map<String, String> getValues() { Map<String, String> retMap = new HashMap<String, String>(); retMap.put(uiAttributes.get(InputUIElement.ID), textValue); return retMap; } /** * Set the Text widget with new value. * * @param valueMap */ @Override public void setValues(Map<String, String> valueMap) { String val = valueMap.get(uiAttributes.get(InputUIElement.ID)); String key = null; String subString = null; if (val != null) { if (val.indexOf(TemplateEngineHelper.OPEN_MARKER) != -1) { key = TemplateEngineHelper.getFirstMarkerID(val); subString = val.substring(key.length() + 3, val.length()); if (valueMap.get(key) != null) val = valueMap.get(key) + subString; else val = subString; } val = val.trim(); textValue = val; } } /** * create a Label and Text widget, add it to UIComposite. set Layout for the * widgets to be added to UIComposite. set required parameters to the * Widgets. * * @param uiComposite */ @Override public void createWidgets(UIComposite uiComposite) { GridData gd = new GridData(); this.uiComposite = uiComposite; label = new Label(uiComposite, SWT.LEFT); label.setText(uiAttributes.get(InputUIElement.WIDGETLABEL)); if ((uiAttributes.get(UIElement.TYPE)).equalsIgnoreCase(InputUIElement.MULTILINETYPE)) { gd = new GridData(); gd.verticalAlignment = SWT.BEGINNING; gd.verticalIndent = 5; label.setLayoutData(gd); } if (uiAttributes.get(UIElement.DESCRIPTION) != null){ String tipText = uiAttributes.get(UIElement.DESCRIPTION); tipText = tipText.replaceAll("\\\\r\\\\n", "\r\n"); //$NON-NLS-1$ //$NON-NLS-2$ label.setToolTipText(tipText); } text = getTextWidget(uiAttributes.get(UIElement.TYPE)); text.addModifyListener(this); text.setData(".uid", uiAttributes.get(UIElement.ID)); //$NON-NLS-1$ text.setText(textValue); } /** * call the dispose method on the widgets. This is to ensure that the * widgets are properly disposed. */ @Override public void disposeWidget() { label.dispose(); text.dispose(); } /** * evaluate the text entered by the user against the pattern associated with * this widget. checks the text entered. On violation of pattern associated * for this widget, by the user entered text. A pattern event is fired to * the container. If this widget has attribute 'checkproject' set to true, * the value entered in this widget is treated as project name. The same is * verified if there is a directory by the same name in workspace, * PatternEvent is thrown to Container. * * @param pattern */ public void evaluatePattern(String labelText, String userInputText, String pattern) { String message = labelText + InputUIElement.CONTENTS; Pattern pattern2 = Pattern.compile(pattern); Matcher matcher = pattern2.matcher(userInputText); if (!matcher.matches()) { String[] failed = pattern2.split(userInputText); for (int i = 1; i < failed.length; i++) message = message + " " + failed[i]; //$NON-NLS-1$ message += InputUIElement.ISINVALID; message += " Expected pattern is \"" + pattern + "\""; //$NON-NLS-1$ //$NON-NLS-2$ if (uiComposite != null) uiComposite.firePatternEvent(new PatternEvent(this, message, false)); } else { String checkproject = uiAttributes.get(InputUIElement.CHECKPROJECT); if ((checkproject != null) && (checkproject.equalsIgnoreCase(TemplateEngineHelper.BOOLTRUE)) && TemplateEngineHelper.checkDirectoryInWorkspace(userInputText)) { message = userInputText + Messages.getString("UITextWidget.0"); //$NON-NLS-1$ uiComposite.firePatternEvent(new PatternEvent(this, message, false)); } else { if (uiComposite != null) uiComposite.firePatternEvent(new PatternEvent(this, message, true)); } } } /** * Method from ModifyListener. Extracts the Text from the widget. calls * evaluatePattern. */ public void modifyText(ModifyEvent e) { String patternName = uiAttributes.get(InputUIElement.INPUTPATTERN); if (patternName == null) { patternValue = null; } else if (patternName.equals(IPatternMatchingTable.FREETEXT) || patternName.equals(IPatternMatchingTable.TEXT) || patternName.equals(IPatternMatchingTable.FILENAME)) { patternValue = getPatternValue(patternName); } else { patternValue = patternName; } // Get the source from event. This is done because this class can be // extended by // other classes, having Text widget. They can just make use of // modifyText, // evaluatePattern and isValid. textValue = text.getText(); if ((patternValue == null) || (textValue == null)) return; String mandatory = uiAttributes.get(InputUIElement.MANDATORY); if ((mandatory == null || !mandatory.equalsIgnoreCase("true")) && textValue.equals("")) { //$NON-NLS-1$ //$NON-NLS-2$ return; } evaluatePattern(label.getText(), textValue, patternValue); } /** * Returns the Pattern Value for the widget. * @param patternName * @return */ private String getPatternValue(String patternName) { if (patternName.equals(IPatternMatchingTable.TEXT)) { patternValue = IPatternMatchingTable.TEXTPATTERNVALUE; } if (patternName.equals(IPatternMatchingTable.FREETEXT)) { patternValue = IPatternMatchingTable.FREETEXTPATTERNVALUE; } if (patternName.equals(IPatternMatchingTable.FILENAME)) { patternValue = IPatternMatchingTable.FILEPATTERNVALUE; } return patternValue; } /** * Based on the sate of this Widget return true or false. This return value * will be used by the UIPage to update its(UIPage) state. Return value * depends on the value contained in TextWidget. If value contained is null, "" * and Mandatory value from attributes. * * @return boolean. */ @Override public boolean isValid() { boolean retVal = true; String mandatory = uiAttributes.get(InputUIElement.MANDATORY); if (((mandatory != null) && (mandatory.equalsIgnoreCase(TemplateEngineHelper.BOOLTRUE))) && ((textValue == null) || (textValue.equals("")) || //$NON-NLS-1$ (textValue.trim().length() < 1))) { retVal = false; } return retVal; } /** * Based on Input Type Text widget is created. The Text widget created can * be of Type SINGLE or MULTI. * * @param type * of Text widget required. * @return Text. */ private Text getTextWidget(String type) { Text retTextWidget = null; Composite textConatiner = new Composite(uiComposite, SWT.NONE | SWT.NO_REDRAW_RESIZE); textConatiner.setLayout(new GridLayout()); if (type.equalsIgnoreCase(InputUIElement.INPUTTYPE)) { GridData gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.widthHint = 70; textConatiner.setLayoutData(gridData); retTextWidget = new Text(textConatiner, SWT.SINGLE | SWT.BORDER); retTextWidget.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); } if (type.equalsIgnoreCase(InputUIElement.MULTILINETYPE)) { GridData multiTextData = new GridData(GridData.FILL_HORIZONTAL); multiTextData.widthHint = 70; String line = uiAttributes.get(InputUIElement.SIZE); int cnt = 1; if (line != null) { cnt = Integer.parseInt(line); if (cnt <= 0) cnt = 1; } multiTextData.heightHint = 30 + 12 * cnt; textConatiner.setLayoutData(multiTextData); retTextWidget = new Text(textConatiner, SWT.WRAP | SWT.MULTI | SWT.V_SCROLL | SWT.BORDER); GridData textData = new GridData(SWT.FILL, SWT.FILL, true, true); retTextWidget.setLayoutData(textData); } return retTextWidget; } }