/******************************************************************************* * Copyright (c) 2013 Arapiki Solutions Inc. * 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: * psmith - initial API and * implementation and/or initial documentation *******************************************************************************/ package com.buildml.eclipse.packages.properties; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; 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.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import com.buildml.eclipse.utils.BmlTitleAreaDialog; /** * A Dialog class for allowing the user to add/edit a filter pattern. * * @author Peter Smith <psmith@arapiki.com> */ public class ConnectionPatternDialog extends BmlTitleAreaDialog { /*=====================================================================================* * FIELDS/TYPES *=====================================================================================*/ /** True if we're creating a new pattern - used for display appropriate text labels */ private boolean createNew; /** * The pattern that we're editing. This can be set before the dialog is created, or * queried after pressing OK. */ private String pattern; /** The radio Button widget for selecting an "include" pattern */ private Button includeButton; /** The radio Button widget for selecting an "exclude" pattern */ private Button excludeButton; /** The Text widget the user types into */ private Text textBox; /** Informational instructions for entering pattern */ private static final String MESSAGE = "<body style=\"font-size:small;\">" + "<p>Please enter a pattern for matching against input files.</p>" + "<h4>Syntax:</h4>" + "<table style=\"font-size:small;\">" + "<tr><td>?</td><td>Matches a single character.</td></tr>" + "<tr><td>*</td><td>Matches multiple characters, but doesn't cross directory boundaries (separated by /).</td></tr>" + "<tr><td>**</td><td>Matches multiple characters, possibly crossing directory boundaries.</td></tr>" + "</table>" + "<h4>Examples:</h4>" + "<table style=\"font-size:small;\">" + "<tr><td>**/*.c</td><td>Matches all C source files.</td></tr>" + "<tr><td>@zlib/**/*.c</td><td>Matches all C source files in the zlib package.</td></tr>" + "<tr><td>**/images/*.jpg</td><td>Matches all JPEG files in any \"images\" subdirectory.</td></tr>" + "<tr><td>**/work.?</td><td>Matches any file with basename of \"work\".</td></tr>" + "</table></body>"; /** list of characters that can not be entered into a pattern */ private static final char BAD_CHARS[] = { '\n', '\r', '\t', '\0', '\f', '`', '\'', '"', '\\', '<', '>', '|', ':', '[', ']', '!'}; /*=====================================================================================* * CONSTRUCTORS *=====================================================================================*/ /** * Create a new ConnectionPatternDialog box. * @param createNew True if we're creating a new pattern, or false if we're editing an * existing pattern. */ public ConnectionPatternDialog(boolean createNew) { super(new Shell(), 0.3, 0.5, 0.5, 0.5); this.createNew = createNew; } /*=====================================================================================* * PUBLIC METHODS *=====================================================================================*/ /** * Set the pattern that will be displayed (initially) by the dialog box. This is used * when we're editing an existing pattern. * * @param pattern The pattern to edit, including the prefix of "ia:" or "ea:" etc. */ public void setPattern(String pattern) { this.pattern = pattern; } /*-------------------------------------------------------------------------------------*/ /** * @return The pattern that was entered by the user. This should only be queried after * the OK button has been pressed. */ String getPattern() { return pattern; } /*=====================================================================================* * PROTECTED METHODS *=====================================================================================*/ /* (non-Javadoc) * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) */ @Override protected Control createDialogArea(Composite parent) { setTitle("Enter Filter Pattern:"); setHelpAvailable(false); Composite container = new Composite(parent, SWT.NULL); container.setLayout(new GridLayout()); GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); gd.verticalIndent = 20; gd.horizontalIndent = 10; container.setLayoutData(gd); /* Create a multi-line label that contains instructions */ Browser label = new Browser(container, SWT.NONE); label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); label.setText(MESSAGE); /* split the pattern into the ia/ea part, and the pattern itself */ String prefix, regex; if (createNew) { prefix = "ia"; regex = "enter pattern"; } else { String parts[] = pattern.split(":"); if (parts.length != 2) { return null; } prefix = parts[0]; regex = parts[1]; } /* create the text box that the pattern is entered into, making it the focus */ textBox = new Text(container, SWT.BORDER); textBox.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); textBox.setText(regex); textBox.selectAll(); textBox.setFocus(); /* we'll carefully monitor the user's input, to ensure the pattern is valid */ textBox.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { validateText(); } }); /* create the "include" and "exclude" radio buttons */ Composite buttonBar = new Composite(container, SWT.NONE); buttonBar.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, true, false)); buttonBar.setLayout(new GridLayout(2, false)); includeButton = new Button(buttonBar, SWT.RADIO); includeButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); includeButton.setText("Include Pattern"); excludeButton = new Button(buttonBar, SWT.RADIO); excludeButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); excludeButton.setText("Exclude Pattern"); if (prefix.equals("ia")) { includeButton.setSelection(true); } else { excludeButton.setSelection(true); } return container; } /*-------------------------------------------------------------------------------------*/ /* (non-Javadoc) * @see org.eclipse.jface.dialogs.Dialog#okPressed() */ @Override protected void okPressed() { /* the user has finished editing, save the text box value for querying by our caller */ String regex = textBox.getText(); String prefix; if (includeButton.getSelection()) { prefix = "ia"; } else { prefix = "ea"; } pattern = prefix + ":" + regex; /* now dispose the window */ super.okPressed(); } /*-------------------------------------------------------------------------------------*/ /* * (non-Javadoc) * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell) */ @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); /* The dialog's title depends on if we did "add" or "edit" */ if (createNew) { newShell.setText("Add New Filter Pattern"); } else { newShell.setText("Modify Existing Filter Pattern"); } } /*-------------------------------------------------------------------------------------*/ /* (non-Javadoc) * @see org.eclipse.jface.dialogs.TrayDialog#createButtonBar(org.eclipse.swt.widgets.Composite) */ @Override protected Control createButtonBar(Composite parent) { Control buttonBar = super.createButtonBar(parent); /* set the OK button status appropriately */ validateText(); return buttonBar; } /*=====================================================================================* * PRIVATE METHODS *=====================================================================================*/ /** * Set the enabled state of the "OK" button, based on the content of the text box. Only * valid characters (that could appear in file names), as well as * and ? will be allowed. */ private void validateText() { boolean enabled = true; /* check the minimum length */ String text = textBox.getText(); if (text.length() < 2) { enabled = false; } /* else scan through the string for illegal characters */ else { for (int i = 0; i != text.length(); i++) { char ch = text.charAt(i); for (int j = 0; j != BAD_CHARS.length; j++) { if (ch == BAD_CHARS[j]) { enabled = false; } } } if (enabled) { setErrorMessage(null); } else { setErrorMessage("Invalid Character in Pattern"); } } getButton(OK).setEnabled(enabled); } /*-------------------------------------------------------------------------------------*/ }