com.buildml.eclipse.actions.dialogs.MatchPatternSelectionDialog.java Source code

Java tutorial

Introduction

Here is the source code for com.buildml.eclipse.actions.dialogs.MatchPatternSelectionDialog.java

Source

/*******************************************************************************
 * 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.actions.dialogs;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import com.buildml.eclipse.utils.BmlTitleAreaDialog;
import com.buildml.model.IActionMgr;
import com.buildml.model.IBuildStore;
import com.buildml.model.types.ActionSet;

/**
 * A dialog allowing the user to select a pattern that will be used to provide a list
 * of actions that match the pattern. The user must then select which of the matching
 * actions will be used in an operation (such as delete, or make atomic).
 * 
 * @author Peter Smith <psmith@arapiki.com>
 */
public class MatchPatternSelectionDialog extends BmlTitleAreaDialog {

    /*=====================================================================================*
     * FIELDS/TYPES
     *=====================================================================================*/

    /** The buildStore's action manager */
    private IActionMgr actionMgr;

    /** The pattern (regular expression) that the user wants to match against */
    private String patternString;

    /** Textual string showing what the operation is (e.g. "Delete" or "Make Atomic"). */
    private String operation;

    /** The list box widget containing the matching actions */
    private List resultsListBox;

    /** The Control where the user enters the match string */
    private Text entryBox;

    /** The ActionMgr IDs of the actions being displayed in the resultsListBox */
    private Integer matchingActions[];

    /** The final set of selected actions - only valid after "OK" is pressed */
    private ActionSet resultActionSet;

    /*=====================================================================================*
     * CONSTRUCTOR
     *=====================================================================================*/

    /**
     * Create a new MatchPatternSelectionDialog.
     * 
     * @param buildStore     The IBuildStore that contains the actions.
     * @param initialPattern The action command string pattern (that the user may edit).
     * @param operation       Displayable string explaining what will happen when the
     *                       user presses OK. For example, "Delete" or "Make Atomic".
     */
    public MatchPatternSelectionDialog(IBuildStore buildStore, String initialPattern, String operation) {
        super(new Shell(), 0.3, 0.5, 0.5, 0);

        this.actionMgr = buildStore.getActionMgr();
        this.patternString = initialPattern;
        this.operation = operation;
    }

    /*=====================================================================================*
     * PUBLIC METHODS
     *=====================================================================================*/

    /**
     * Return the actions that have been selected. This method should only be called
     * after the "OK" (Delete, Make Atomic) button has been pressed.
     * 
     * @return The set of actions that have been selected. 
     */
    public ActionSet getMatchingActions() {
        return resultActionSet;
    }

    /*=====================================================================================*
     * PROTECTED METHODS
     *=====================================================================================*/

    /* (non-Javadoc)
     * @see com.buildml.eclipse.utils.BmlTitleAreaDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
     */
    @Override
    protected Control createDialogArea(Composite parent) {

        /* Create the main panel widget for the body of the dialog box */
        Composite panel = new Composite(parent, SWT.NONE);
        panel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        GridLayout layout = new GridLayout();
        layout.marginHeight = 10;
        layout.marginWidth = 20;
        layout.verticalSpacing = 10;
        layout.numColumns = 1;
        panel.setLayout(layout);

        /*
         * Introductory label
         */
        new Label(panel, SWT.NONE).setText("Please specify a pattern to identify which actions " + "you wish to "
                + operation.toLowerCase() + ". Use * as a wildcard:");

        /*
         * Text entry box (for specifying the pattern). We populate the entry box with the
         * initial pattern provided by our caller.
         */
        Composite entryPanel = new Composite(panel, SWT.NONE);
        entryPanel.setLayout(new GridLayout(2, false));
        entryPanel.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false));
        entryBox = new Text(entryPanel, SWT.NONE);
        entryBox.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        entryBox.setText(patternString);
        entryBox.selectAll();
        entryBox.setFocus();

        /*
         * Create a "Match" button, which should only be enabled if the
         * pattern in the entry box is valid. Monitor when the list box
         * changes so that we can update the button's "enabled" status.
         */
        final Button matchButton = new Button(entryPanel, SWT.PUSH);
        matchButton.setText("Match");
        matchButton.setEnabled(isValidPattern(patternString));
        entryBox.addModifyListener(new ModifyListener() {
            @Override
            public void modifyText(ModifyEvent e) {
                matchButton.setEnabled(isValidPattern(entryBox.getText()));
            }
        });

        /*
         * Once the pattern is matched, the user must select which of the matching
         * actions are to be deleted. State this in a label.
         */
        new Label(panel, SWT.NONE)
                .setText("Select which of the matching actions you wish to " + operation.toLowerCase() + ":");

        /*
         * A list box (which consumes the rest of the dialog box) shows all the matching
         * actions. The "OK" (Delete, Make Atomic) button is only enabled if at
         * least one action is highlighted.
         */
        resultsListBox = new List(panel, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI);
        resultsListBox.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        resultsListBox.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                getButton(OK).setEnabled(resultsListBox.getSelectionIndices().length >= 1);
            }
        });
        populateListWithMatches(patternString);

        /*
         * When the "Match" button is pressed, populate the list box.
         */
        matchButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                populateListWithMatches(entryBox.getText());
            }
        });

        return parent;
    }

    /*-------------------------------------------------------------------------------------*/

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.Dialog#okPressed()
     */
    @Override
    protected void okPressed() {

        /* compute the ActionSet of selected actions */
        resultActionSet = new ActionSet(actionMgr);
        int[] selected = resultsListBox.getSelectionIndices();
        for (int i = 0; i < selected.length; i++) {
            int actionId = matchingActions[selected[i]];
            resultActionSet.add(actionId);
        }

        /* destroy the dialog and all Controls it contains */
        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);

        newShell.setText("Select Actions by Pattern");
    }

    /*-------------------------------------------------------------------------------------*/

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.TrayDialog#createButtonBar(org.eclipse.swt.widgets.Composite)
     */
    @Override
    protected Control createButtonBar(Composite parent) {
        Control result = super.createButtonBar(parent);

        /* until something is selected, the OK button is greyed out */
        getButton(IDialogConstants.OK_ID).setEnabled(false);

        return result;
    }

    /*-------------------------------------------------------------------------------------*/

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
     */
    @Override
    protected void createButtonsForButtonBar(Composite parent) {

        /* 
         * Replace the standard "OK" label with the name of the operation we're performing
         * (e.g "Delete" or "Make Atomic".
         */
        createButton(parent, IDialogConstants.OK_ID, operation, true);
        createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
    }

    /*=====================================================================================*
     * PRIVATE METHODS
     *=====================================================================================*/

    /**
     * When the user pressed the "Match" button, query the IBuildStore for matching actions,
     * then populate the list with the command strings.
     * 
     * @param pattern The pattern to match against.
     */
    private void populateListWithMatches(String pattern) {

        /* replace * with % - to satisfy the matching algorithm */
        pattern = pattern.replace('*', '%');

        /* search for matches */
        matchingActions = actionMgr.getActionsWhereSlotIsLike(IActionMgr.COMMAND_SLOT_ID, pattern);

        /* add matches to results list box */
        resultsListBox.removeAll();
        for (int i = 0; i < matchingActions.length; i++) {
            String cmdString = (String) actionMgr.getSlotValue(matchingActions[i], IActionMgr.COMMAND_SLOT_ID);
            resultsListBox.add(cmdString);
        }
    }

    /*-------------------------------------------------------------------------------------*/

    /**
     * Determine whether a pattern is "valid" (i.e. we're willing to search for actions
     * based on this pattern).
     * 
     * @param pattern The pattern to be evaluated.
     * @return True if valid, else false.
     */
    protected boolean isValidPattern(String pattern) {
        return pattern.length() >= 3;
    }

    /*-------------------------------------------------------------------------------------*/
}