org.apache.sling.ide.eclipse.ui.actions.NewNodeDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.sling.ide.eclipse.ui.actions.NewNodeDialog.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.sling.ide.eclipse.ui.actions;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;

import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.NodeType;

import org.apache.sling.ide.eclipse.ui.nav.model.JcrNode;
import org.apache.sling.ide.transport.NodeTypeRegistry;
import org.apache.sling.ide.transport.RepositoryException;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.fieldassist.ComboContentAdapter;
import org.eclipse.jface.fieldassist.ContentProposalAdapter;
import org.eclipse.jface.fieldassist.SimpleContentProposalProvider;
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.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;

public class NewNodeDialog extends InputDialog {

    private static String lastChosenNodeType = null;

    private final String parentNodeType;
    private final NodeTypeRegistry ntManager;
    protected String comboSelection;
    private Collection<String> allowedChildren;
    private Combo combo;
    private ContentProposalAdapter proposalAdapter;
    private NodeDefinition[] allChildNodeDefs;

    public NewNodeDialog(Shell parentShell, JcrNode node, NodeTypeRegistry ntManager) throws RepositoryException {
        super(parentShell, "Enter Node Name", "Enter name for new node under:\n path: " + node.getJcrPath(), "",
                null);
        this.parentNodeType = node.getPrimaryType();
        this.ntManager = ntManager;
        if (ntManager != null) {
            final LinkedList<String> ac = new LinkedList<>(
                    ntManager.getAllowedPrimaryChildNodeTypes(parentNodeType));
            final NodeType parentNt = ntManager.getNodeType(parentNodeType);
            allChildNodeDefs = parentNt.getChildNodeDefinitions();
            Collections.sort(ac);
            this.allowedChildren = ac;
        }
    }

    @Override
    protected Control createDialogArea(Composite parent) {
        Composite composite = (Composite) super.createDialogArea(parent);

        Control[] children = composite.getChildren();
        Control errorMessageText = children[children.length - 1];
        GridData errorMessageGridData = new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL);
        errorMessageGridData.heightHint = convertHeightInCharsToPixels(2);
        errorMessageText.setLayoutData(errorMessageGridData);

        // now add the node type dropbox-combo
        Label label = new Label(composite, SWT.WRAP);
        label.moveAbove(errorMessageText);
        label.setText("Define node type");
        GridData data = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL
                | GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_CENTER);
        data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH);
        label.setLayoutData(data);
        label.setFont(parent.getFont());

        combo = new Combo(composite, SWT.DROP_DOWN);
        combo.moveAbove(errorMessageText);
        if (allowedChildren != null) {
            combo.setItems(allowedChildren.toArray(new String[0]));
        }
        combo.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
        combo.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                comboSelection = combo.getText();
                validateInput();
            }
        });
        combo.addModifyListener(new ModifyListener() {

            @Override
            public void modifyText(ModifyEvent e) {
                comboSelection = combo.getText();
                validateInput();
            }

        });

        SimpleContentProposalProvider proposalProvider = new SimpleContentProposalProvider(combo.getItems());
        proposalProvider.setFiltering(true);
        final ComboContentAdapter controlContentAdapter = new ComboContentAdapter() {
            @Override
            public void insertControlContents(Control control, String text, int cursorPosition) {
                Point selection = combo.getSelection();
                combo.setText(text);
                selection.x = selection.x + cursorPosition;
                selection.y = selection.x;
                combo.setSelection(selection);
            }

            @Override
            public Rectangle getInsertionBounds(Control control) {
                final Rectangle insertionBounds = super.getInsertionBounds(control);
                // always insert at start
                insertionBounds.x = 0;
                insertionBounds.y = 0;
                return insertionBounds;
            }

        };
        // this variant opens auto-complete on each character
        proposalAdapter = new ContentProposalAdapter(combo, controlContentAdapter, proposalProvider, null, null);
        // this variant opens auto-complete only when invoking the auto-complete hotkey
        if (allowedChildren != null && allowedChildren.size() == 1) {
            combo.setText(allowedChildren.iterator().next());
        } else if (allowedChildren != null) {
            if (allowedChildren.contains(lastChosenNodeType)) {
                combo.setText(lastChosenNodeType);
            }
        }

        return composite;
    }

    @Override
    protected void initializeBounds() {
        super.initializeBounds();
        // fix autocomplete popup size:
        Point size = combo.getSize();
        size.x /= 2;
        size.y = 180;
        proposalAdapter.setPopupSize(size);
    }

    public String getChosenNodeType() {
        lastChosenNodeType = comboSelection;
        return comboSelection;
    }

    protected void validateInput() {
        final String firstInput = getText().getText();
        final String secondInput = comboSelection;
        try {
            if (secondInput == null || secondInput.length() == 0) {
                setErrorMessage("");
            } else if (ntManager == null) {
                setErrorMessage(null);
            } else if (ntManager.isAllowedPrimaryChildNodeType(parentNodeType, secondInput)) {
                // also check on the name, not only the type
                if (allChildNodeDefs == null) {
                    setErrorMessage("No child node definitions found for " + parentNodeType);
                } else {
                    boolean success = false;
                    for (int i = 0; i < allChildNodeDefs.length; i++) {
                        NodeDefinition aChildNodeDef = allChildNodeDefs[i];
                        if (aChildNodeDef.getName() != null && aChildNodeDef.getName().length() > 0) {
                            if (firstInput.equals(aChildNodeDef.getName())) {
                                setErrorMessage(null);
                                return;
                            }
                        } else {
                            // mark success if there's a child node definition without a name
                            // (ie then it can be any name)
                            success = true;
                        }
                    }
                    if (success) {
                        setErrorMessage(null);
                        return;
                    }
                    StringBuffer details = new StringBuffer();
                    for (NodeDefinition aChildNodeDef : allChildNodeDefs) {
                        if (details.length() != 0) {
                            details.append(", ");
                        }
                        details.append("(name=" + aChildNodeDef.getName() + ", required primary type(s)=");
                        String[] requiredPrimaryTypeNames = aChildNodeDef.getRequiredPrimaryTypeNames();
                        if (requiredPrimaryTypeNames == null) {
                            details.append("null");
                        } else {
                            for (int j = 0; j < requiredPrimaryTypeNames.length; j++) {
                                String rptn = requiredPrimaryTypeNames[j];
                                if (j > 0) {
                                    details.append(",");
                                }
                                details.append(rptn);
                            }
                        }
                        details.append(")");
                    }
                    setErrorMessage("No matching child node definition found for " + parentNodeType
                            + ". Expected one of: " + details);
                }
            } else {
                setErrorMessage("Error: Invalid child node type of " + parentNodeType);
            }
        } catch (RepositoryException e) {
            setErrorMessage("RepositoryException: " + e);
        }

    };
}