/******************************************************************************* * Copyright (c) 2007 IBM Corporation. * 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: * Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation *******************************************************************************/ package org.eclipse.imp.preferences.fields; import java.io.File; import java.util.Stack; import org.eclipse.imp.preferences.IPreferencesService; import org.eclipse.imp.preferences.PreferencesTab; import org.eclipse.jface.preference.PreferencePage; import org.eclipse.jface.preference.StringFieldEditor; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.DirectoryDialog; import org.eclipse.swt.widgets.Text; public class DirectoryListFieldEditor extends StringButtonFieldEditor { protected PreferencePage prefPage = null; protected PreferencesTab prefTab = null; public DirectoryListFieldEditor( PreferencePage page, PreferencesTab tab, IPreferencesService service, String level, String name, String labelText, int width, int strategy, Composite parent) { super(page, tab, service, level, name, labelText, width, strategy, parent); prefPage = page; prefTab = tab; this.getChangeControl(parent).setText(PreferenceDialogConstants.BROWSE_LABEL); } /** * Creates an IMP directory-list field editor. * Use the method <code>setTextLimit</code> to limit the text. * * @param name the name of the preference this field editor works on * @param labelText the label text of the field editor * @param width the width of the text input field in characters, * or <code>UNLIMITED</code> for no limit * @param parent the parent of the field editor's control */ public DirectoryListFieldEditor( PreferencePage page, PreferencesTab tab, IPreferencesService service, String level, String name, String labelText, int width, Composite parent) { super(page, tab, service, level, name, labelText, width, StringFieldEditor.VALIDATE_ON_KEY_STROKE, parent); prefPage = page; prefTab = tab; this.getChangeControl(parent).setText(PreferenceDialogConstants.BROWSE_LABEL); } /** * Creates an IMP directory-list field editor. * Use the method <code>setTextLimit</code> to limit the text. * * @param name the name of the preference this field editor works on * @param labelText the label text of the field editor * @param parent the parent of the field editor's control */ public DirectoryListFieldEditor( PreferencePage page, PreferencesTab tab, IPreferencesService service, String level, String name, String labelText, Composite parent) { super(page, tab, service, level, name, labelText, parent); prefPage = page; prefTab = tab; this.getChangeControl(parent).setText(PreferenceDialogConstants.BROWSE_LABEL); } /* * Below copied from DirectoryListFieldEditor */ protected String changePressed() { Text text= getTextControl(parent); String curText= text.getText(); Point sel= text.getSelection(); boolean replace= (text.getSelectionCount() > 0); // any non-empty selection? boolean replaceAll= text.getSelectionCount() == text.getCharCount(); // all selected? File f = new File(getTextControl(parent).getText()); if (!f.exists()) f = null; File d = getDirectory(f); if (d == null) return null; final String dirPath= d.getAbsolutePath(); if (replaceAll) return dirPath; int prevSep= curText.lastIndexOf(';', sel.x); if (prevSep < 0) prevSep= 0; String leadingPart= (prevSep > 0) ? curText.substring(0, prevSep) + ';' : ""; if (replace) { // Replace the selected entries with the browse result int followSep= curText.indexOf(';', sel.y); if (followSep < 0) followSep= curText.length(); return leadingPart + dirPath + curText.substring(followSep); } if (sel.x == text.getCharCount()) // caret at end of field? => append new entry return curText + ';' + dirPath; // insertion point in middle of text; insert new entry before this entry return leadingPart + dirPath + (prevSep > 0 ? "" : ";") + curText.substring(prevSep); } protected boolean doCheckState() { //String path= getTextControl().getText(); //if (path.length() == 0 && isEmptyStringAllowed()) { // return true; //} String msg = null; // Here we check for empty or null strings, although // this may very well be checked at a higher level // (so we might not ever get here with this problem) String path = getTextControl(parent).getText(); path= preferencesService.performSubstitutions(path); if (path != null) path = path.trim(); else path = "";//$NON-NLS-1$ if (path.length() == 0 && !emptyStringAllowed) { setErrorMessage(getFieldMessagePrefix() + "Path length is zero when empty string is not allowed"); return false; } // Check for balanced quotes final String singleQuote = "'"; final String doubleQuote = "\""; Stack stack = new Stack(); for (int i = 0; i < path.length(); i++) { if (path.charAt(i) == '\'') { if (!stack.empty() && singleQuote.equals(stack.peek())) stack.pop(); else stack.push(singleQuote); } if (path.charAt(i) == '"') { if (!stack.empty() && doubleQuote.equals(stack.peek())) stack.pop(); else stack.push(doubleQuote); } } if (stack.size() != 0) { setErrorMessage(getFieldMessagePrefix() + "Path has quotes that are not balanced"); return false; } // Now validate list segments between quotes path = path.replace("\"", "'"); String[] splits = path.split("'"); boolean splitsVerified = true; for (int i = 0; i < splits.length; i++) { splitsVerified = splitsVerified && doCheckState(splits[i]); if (!splitsVerified) { if (!hasErrorMessage()) { setErrorMessage(getFieldMessagePrefix() + "Path segment \"splits[i]\" failed verification "); } return false; } } clearErrorMessage(); return true; } protected boolean doCheckState(String path) { // This is the real work of the original doCheckState() if (path.length() == 0) { return true; } String[] pathElems= path.split(";"); for(int i= 0; i < pathElems.length; i++) { String pathElem= pathElems[i].trim(); File dir= new File(pathElem); if (!dir.isDirectory()) { setErrorMessage(getFieldMessagePrefix() + "Path list contains a name that is not a directory name"); return false; } } // Error message cleared in doCheckState(); //clearErrorMessage(); return true; } /** * Helper that opens the directory chooser dialog. * @param startingDirectory The directory the dialog will open in. * @return File File or <code>null</code>. * */ private File getDirectory(File startingDirectory) { DirectoryDialog fileDialog = new DirectoryDialog(getShell(), SWT.OPEN); if (startingDirectory != null) fileDialog.setFilterPath(startingDirectory.getPath()); String dir = fileDialog.open(); if (dir != null) { dir = dir.trim(); if (dir.length() > 0) return new File(dir); } return null; } }