com.schmeedy.relaxng.eclipse.ui.internal.preferences.EditRngSchemaBindingDialog.java Source code

Java tutorial

Introduction

Here is the source code for com.schmeedy.relaxng.eclipse.ui.internal.preferences.EditRngSchemaBindingDialog.java

Source

/*******************************************************************************
 * Copyright (c) 2002, 2008 IBM Corporation 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:
 *       IBM Corporation, Jens Lukowski/Innoopract - original implementation of 
 *          the EditCatalogEntryDialog
 *       Martin Schmied - customizations for the RELAX NG Bindings preference page
 *******************************************************************************/
package com.schmeedy.relaxng.eclipse.ui.internal.preferences;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.window.Window;
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.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.wst.common.ui.internal.dialogs.SelectSingleFileDialog;

import com.schmeedy.relaxng.contentassist.IRngSchema.RngSchemaSyntax;
import com.schmeedy.relaxng.eclipse.core.internal.binding.RngSchemaBinding;
import com.schmeedy.relaxng.eclipse.core.internal.binding.UserSchemaBindings;
import com.schmeedy.relaxng.eclipse.ui.internal.RngUiPlugin;
import com.schmeedy.relaxng.eclipse.core.internal.UriUtil;

public class EditRngSchemaBindingDialog extends Dialog {
    private static final int SCHEMA_TYPE_COMPACT_COMBO_IDX = 1;
    private static final int SCHEMA_TYPE_XML_COMBO_IDX = 0;

    private UserSchemaBindings userBindings;
    private RngSchemaBinding binding;
    private Text namespaceText;
    private Text schemaLocationText;
    private Combo schemaTypeCombo;
    private Label errorReportArea;

    private Color errorReportColor;
    private Color warningReportColor;
    private Image browseImage;
    private Button okButton;

    private EditMode editMode;

    /**
     * Form for a new binding
     * 
     * @param parentShell
     * @param userBindings
     */
    public EditRngSchemaBindingDialog(Shell parentShell, UserSchemaBindings userBindings) {
        this(parentShell, userBindings, EditMode.INSERT);
    }

    /**
     * Form for updating of an existing binding
     * 
     * @param parentShell
     * @param binding
     */
    public EditRngSchemaBindingDialog(Shell parentShell, UserSchemaBindings userBindings,
            RngSchemaBinding binding) {
        this(parentShell, userBindings, EditMode.UPDATE);
        this.binding = binding;
    }

    private EditRngSchemaBindingDialog(Shell parentShell, UserSchemaBindings userBindings, EditMode editMode) {
        super(parentShell);
        this.editMode = editMode;
        this.userBindings = userBindings;
    }

    @Override
    protected Control createContents(Composite parent) {
        errorReportColor = new Color(parent.getDisplay(), 200, 0, 0);
        warningReportColor = new Color(parent.getDisplay(), 204, 102, 0);
        browseImage = RngUiPlugin.getDefault().getIcon("file_expand.gif").createImage();

        Composite composite = new Composite(parent, SWT.NONE);
        composite.setLayout(GridLayoutFactory.createFrom(new GridLayout(3, false)).margins(10, 7).create());
        composite.setLayoutData(new GridData(GridData.FILL_BOTH));

        Label labelNamespace = new Label(composite, SWT.NONE);
        labelNamespace.setText("Namespace: ");

        GridData inputLayoutData = new GridData(GridData.FILL_HORIZONTAL);
        inputLayoutData.widthHint = 270;

        namespaceText = new Text(composite, SWT.SINGLE | SWT.BORDER);
        namespaceText.setLayoutData(GridDataFactory.createFrom(inputLayoutData).span(2, 1).create());

        Label labelSchemaLocation = new Label(composite, SWT.NONE);
        labelSchemaLocation.setText("Schema Location: ");

        schemaLocationText = new Text(composite, SWT.SINGLE | SWT.BORDER);
        schemaLocationText.setLayoutData(inputLayoutData);

        Button browseControl = createBrowseButton(composite);
        browseControl.addSelectionListener(new DropDownSelectionListener(schemaLocationText));

        Label labelSchemaType = new Label(composite, SWT.NONE);
        labelSchemaType.setText("Schema Syntax: ");

        schemaTypeCombo = new Combo(composite, SWT.READ_ONLY);
        schemaTypeCombo.setLayoutData(GridDataFactory.createFrom(inputLayoutData).span(2, 1).create());
        schemaTypeCombo.add("XML", SCHEMA_TYPE_XML_COMBO_IDX);
        schemaTypeCombo.add("Compact", SCHEMA_TYPE_COMPACT_COMBO_IDX);

        errorReportArea = new Label(composite, SWT.NONE);
        errorReportArea.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).span(3, 1).create());

        Composite buttonComposite = new Composite(composite, SWT.NONE);
        buttonComposite.setLayout(new GridLayout(2, false));
        buttonComposite
                .setLayoutData(GridDataFactory.fillDefaults().align(SWT.RIGHT, SWT.CENTER).span(3, 1).create());

        okButton = createButton(buttonComposite, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
        okButton.setEnabled(false);
        createButton(buttonComposite, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);

        if (binding != null) {
            initEditedValues();
        }

        revalidate();

        ModifyListener validationListener = new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                revalidate();
            }
        };

        namespaceText.addModifyListener(validationListener);
        schemaLocationText.addModifyListener(validationListener);
        schemaTypeCombo.addModifyListener(validationListener);

        return composite;
    }

    private void initEditedValues() {
        namespaceText.setText(binding.getNamespace());
        schemaLocationText.setText(binding.getSchemaUri().toString());

        int selection = binding.getSchemaSyntax() == RngSchemaSyntax.XML ? SCHEMA_TYPE_XML_COMBO_IDX
                : SCHEMA_TYPE_COMPACT_COMBO_IDX;
        schemaTypeCombo.select(selection);
    }

    @Override
    protected void okPressed() {
        String namespace = namespaceText.getText().trim();
        URI schemaUri = UriUtil.resolveUri(getUnresolvedLocation());
        RngSchemaSyntax schemaSyntax = schemaTypeCombo.getSelectionIndex() == SCHEMA_TYPE_XML_COMBO_IDX
                ? RngSchemaSyntax.XML
                : RngSchemaSyntax.COMPACT;

        RngSchemaBinding newBinding = new RngSchemaBinding(namespace, schemaUri, schemaSyntax);

        switch (editMode) {
        case INSERT:
            userBindings.addBinding(newBinding);
            break;
        case UPDATE:
            userBindings.replaceBinding(binding, newBinding);
            break;
        }
        super.okPressed();
    }

    @Override
    public boolean close() {
        if (errorReportColor != null) {
            errorReportColor.dispose();
        }
        if (warningReportColor != null) {
            warningReportColor.dispose();
        }
        if (browseImage != null) {
            browseImage.dispose();
        }
        return super.close();
    }

    private void revalidate() {
        boolean formValid = true;
        ValidationReport report = new ValidationReport();

        formValid = formValid && isNamepaceValid(report);
        formValid = formValid && isLocationValid(report);
        formValid = formValid && isSchemaTypeValid(report);

        report.setEntireFormValid(formValid);
        processValidationReport(report);
    }

    private boolean isNamepaceValid(ValidationReport report) {
        boolean valid = true;
        String text = namespaceText.getText();
        if (text == null || "".equals(text)) {
            valid = false;
        }
        text = text.trim();
        if (text.contains(" ") || text.contains("\t")) {
            valid = false;
            report.addError("Namespace cannot contain whitespaces.");
        }
        return valid;
    }

    private boolean isLocationValid(ValidationReport report) {
        boolean valid = true;
        String text = schemaLocationText.getText();
        if (text == null || "".equals(text)) {
            return false;
        }

        String unresolvedUri = getUnresolvedLocation();
        if (!UriUtil.resourceExists(unresolvedUri)) {
            valid = false;
            report.addError("Schema does not exist at the specified location.");
        }

        return valid;
    }

    private String getUnresolvedLocation() {
        String unresolvedLocation = schemaLocationText.getText();
        if (unresolvedLocation == null || "".equals(unresolvedLocation)) {
            return null;
        }
        try {
            if (new URI(unresolvedLocation).getScheme() == null) {
                return UriUtil.convertRelativePathToResourceUri(unresolvedLocation);
            }
        } catch (URISyntaxException e) {
        }

        return unresolvedLocation;
    }

    private boolean isSchemaTypeValid(ValidationReport report) {
        String unresolvedLocation = getUnresolvedLocation();
        if (unresolvedLocation != null) {
            if ((unresolvedLocation.endsWith(".rnc")
                    && schemaTypeCombo.getSelectionIndex() == SCHEMA_TYPE_XML_COMBO_IDX)
                    || (unresolvedLocation.endsWith(".xml")
                            && schemaTypeCombo.getSelectionIndex() == SCHEMA_TYPE_COMPACT_COMBO_IDX)) {

                report.addWarning("Selected schema syntax does not correspond to the schema file suffix.");
            }
        }

        if (schemaTypeCombo.getSelectionIndex() == -1) {
            return false;
        } else {
            return true;
        }
    }

    private void processValidationReport(ValidationReport report) {
        okButton.setEnabled(report.isEntireFormValid());

        if (report.getErrors().size() > 0) {
            errorReportArea.setForeground(errorReportColor);
            errorReportArea.setText(report.getErrors().get(0));
        } else if (report.getWarnings().size() > 0) {
            errorReportArea.setForeground(warningReportColor);
            errorReportArea.setText(report.getWarnings().get(0));
        } else {
            errorReportArea.setText("");
        }
    }

    private static class ValidationReport {
        private boolean valid = false;

        private List<String> errors = new LinkedList<String>();

        private List<String> warnings = new LinkedList<String>();

        void addError(String error) {
            errors.add(error);
        }

        void addWarning(String warning) {
            warnings.add(warning);
        }

        List<String> getErrors() {
            return errors;
        }

        List<String> getWarnings() {
            return warnings;
        }

        void setEntireFormValid(boolean valid) {
            this.valid = valid;
        }

        boolean isEntireFormValid() {
            return valid;
        }
    }

    private static class SchemaFileWorkspaceSelectionDialog extends SelectSingleFileDialog {
        private Combo filterCombo;

        public SchemaFileWorkspaceSelectionDialog(Shell parentShell) {
            super(parentShell, null, true);
        }

        public void show() {
            create();
            setBlockOnOpen(true);
            getShell().setText("RELAX NG Schema Selection");
            setTitle("Select RELAX NG Schema");
            setMessage("Select RELAX NG Schema that should be bound to the given namespace.");
            addFilterExtensions(new String[] { ".xml", ".rnc", ".rng" });
            open();
        }
    }

    private class DropDownSelectionListener extends SelectionAdapter {
        private Menu menu;
        private Control control;

        DropDownSelectionListener(Control aControl) {
            super();
            this.control = aControl;
        }

        @Override
        public void widgetSelected(SelectionEvent event) {
            // Create the menu if it has not already been created
            if (menu == null) {
                // Lazy create the menu.
                menu = new Menu(getShell());
                MenuItem menuItem = new MenuItem(menu, SWT.NONE);
                menuItem.setText("Workspace...");
                /*
                 * Add a menu selection listener so that the menu is hidden
                 * when the user selects an item from the drop down menu.
                 */
                menuItem.addSelectionListener(new SelectionAdapter() {
                    public void widgetSelected(SelectionEvent e) {
                        setMenuVisible(false);
                        invokeWorkspaceFileSelectionDialog();
                    }
                });

                menuItem = new MenuItem(menu, SWT.NONE);
                menuItem.setText("File System...");
                /*
                 * Add a menu selection listener so that the menu is hidden
                 * when the user selects an item from the drop down menu.
                 */
                menuItem.addSelectionListener(new SelectionAdapter() {
                    public void widgetSelected(SelectionEvent e) {
                        setMenuVisible(false);
                        invokeFileSelectionDialog();
                    }
                });

            }

            // Position the menu below and vertically aligned with the the
            // drop down tool button.
            Button button = (Button) event.widget;

            // set location
            Point ptBrowse = button.getLocation();
            Rectangle rcBrowse = button.getBounds();
            ptBrowse.y += rcBrowse.height;
            ptBrowse = button.getParent().toDisplay(ptBrowse);
            menu.setLocation(ptBrowse.x, ptBrowse.y);

            setMenuVisible(true);

        }

        void setMenuVisible(boolean visible) {
            menu.setVisible(visible);
            // this.visible = visible;
        }

        void invokeWorkspaceFileSelectionDialog() {
            SchemaFileWorkspaceSelectionDialog dialog = new SchemaFileWorkspaceSelectionDialog(getShell());
            dialog.show();

            IFile file = dialog.getFile();
            if (dialog.getReturnCode() == Window.OK && file != null) {
                // remove leading slash from the value to avoid the
                // whole leading slash ambiguity problem
                String uri = file.getFullPath().toString();
                while (uri.startsWith("/") || uri.startsWith("\\")) { //$NON-NLS-1$ //$NON-NLS-2$
                    uri = uri.substring(1);
                }

                deriveSchemaSyntax(uri);

                if (control instanceof Text) {
                    ((Text) control).setText(uri);
                }
            }
        }

        void invokeFileSelectionDialog() {
            FileDialog dialog = new FileDialog(getShell(), SWT.SINGLE);
            String file = dialog.open();

            deriveSchemaSyntax(file);

            if ((control instanceof Text) && (file != null)) {
                ((Text) control).setText("file:/" + file);
            }
        }

        private void deriveSchemaSyntax(String path) {
            if (path.endsWith(".rnc")) {
                schemaTypeCombo.select(SCHEMA_TYPE_COMPACT_COMBO_IDX);
            } else if (path.endsWith(".xml")) {
                schemaTypeCombo.select(SCHEMA_TYPE_XML_COMBO_IDX);
            }
        }
    }

    private Button createBrowseButton(Composite composite) {
        Button browseButton = new Button(composite, SWT.FLAT);
        browseButton.setImage(browseImage);
        Rectangle r = browseImage.getBounds();
        GridData gd = new GridData();
        int IMAGE_WIDTH_MARGIN = 6;
        int IMAGE_HEIGHT_MARGIN = 6;
        gd.heightHint = r.height + IMAGE_HEIGHT_MARGIN;
        gd.widthHint = r.width + IMAGE_WIDTH_MARGIN;
        browseButton.setLayoutData(gd);
        return browseButton;
    }

    private enum EditMode {
        INSERT, UPDATE;
    }
}