org.polymap.rhei.batik.toolkit.SimpleDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.polymap.rhei.batik.toolkit.SimpleDialog.java

Source

/* 
 * polymap.org
 * Copyright (C) 2015-2018, Falko Brutigam. All rights reserved.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 3.0 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 */
package org.polymap.rhei.batik.toolkit;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.function.Consumer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.eclipse.swt.SWT;
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.FillLayout;
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.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.Dialog;

import org.polymap.core.runtime.config.Config2;
import org.polymap.core.runtime.config.ConfigurationFactory;
import org.polymap.core.ui.StatusDispatcher;
import org.polymap.core.ui.UIUtils;

/**
 * Provides a simple dialog consisting of a title, a contents area and action
 * buttons at the bottom.
 * 
 * @see <a href="http://www.google.com/design/spec/components/dialogs.html">Material
 *      Design</a>
 * @author <a href="http://www.polymap.de">Falko Brutigam</a>
 */
public class SimpleDialog extends Dialog {

    private static Log log = LogFactory.getLog(SimpleDialog.class);

    public Config2<SimpleDialog, String> title;

    public Config2<SimpleDialog, Control> centerOn;

    protected List<IAction> actions = new ArrayList();

    private Consumer<Composite> contentsBuilder;

    /**
     * Constructs a new dialog with {@link UIUtils#shellToParentOn()} as parent.
     */
    public SimpleDialog() {
        this(UIUtils.shellToParentOn());
    }

    /**
     * Constructs a new dialog with the given parent shell.
     */
    public SimpleDialog(Shell parentShell) {
        super(parentShell);
        ConfigurationFactory.inject(this);
    }

    public int openAndBlock() {
        setBlockOnOpen(true);
        return open();
    }

    /**
     * Sets the content of this dialog. The parent {@link Composite} has
     * {@link FillLayout} set. Change this if needed. The build should add children
     * directyl to the parent without an intermediate Composite.
     *
     * @param builder
     * @return this; 
     */
    public SimpleDialog setContents(Consumer<Composite> builder) {
        this.contentsBuilder = builder;
        return this;
    }

    /**
     * Adds a action to the button bar of this dialog.
     * @return this
     */
    public SimpleDialog addAction(IAction action) {
        actions.add(action);
        return this;
    }

    /**
     * Adds a 'Cancel' action to the button bar that just closes the dialog.
     */
    public SimpleDialog addCancelAction() {
        return addCancelAction("CANCEL");
    }

    /**
     * Adds a 'Cancel' action to the button bar that just closes the dialog.
     */
    public SimpleDialog addCancelAction(String label) {
        return addAction(new Action(label) {
            public void run() {
                SimpleDialog.this.close();
            }
        });
    }

    /**
     * Adds a 'No' action to the button bar that just closes the dialog.
     */
    public SimpleDialog addNoAction() {
        return addAction(new Action("NO") {
            public void run() {
                SimpleDialog.this.close();
            }
        });
    }

    /**
     * Adds a 'No' action to the button bar that performs the given task and closes
     * the dialog afterwards.
     */
    public SimpleDialog addNoAction(Consumer<Action> task) {
        return addAction(new Action("No") {
            public void run() {
                try {
                    task.accept(this);
                    SimpleDialog.this.close();
                } catch (Exception e) {
                    StatusDispatcher.handleError("Unable to perform task.", e);
                }
            }
        });
    }

    /**
     * Adds a 'Yes' action to the button bar that just closes the dialog.
     */
    public SimpleDialog addYesAction(Consumer<Action> task) {
        return addAction(new Action("YES") {
            public void run() {
                try {
                    task.accept(this);
                    SimpleDialog.this.close();
                } catch (Exception e) {
                    StatusDispatcher.handleError("Unable to perform task.", e);
                }
            }
        });
    }

    /**
     * See {@link #addOkAction(String, Callable)}
     */
    public SimpleDialog addOkAction(Callable<Boolean> task) {
        return addOkAction("OK", task);
    }

    /**
     * Adds a 'OK' action to the button bar that just closes the dialog.
     * 
     * @param task The task to perform when 'OK' is pressed. The dialog is closed
     *        afterwards if the task returns {@link Boolean#TRUE} or
     *        <code>null</code>. Otherwise it stays open.
     */
    public SimpleDialog addOkAction(String label, Callable<Boolean> task) {
        return addAction(new Action(label) {
            public void run() {
                try {
                    Boolean result = task.call();
                    if (result == null || result.booleanValue()) {
                        SimpleDialog.this.close();
                    }
                } catch (Exception e) {
                    StatusDispatcher.handleError("Unable to perform task.", e);
                }
            }
        });
    }

    @Override
    protected void initializeBounds() {
        super.initializeBounds();

        // adapt to display size
        Shell shell = getShell();
        Rectangle shellBounds = shell.getBounds();
        Rectangle displayBounds = shell.getDisplay().getBounds();
        shell.setSize(shellBounds.width = Math.min(displayBounds.width - 12, shellBounds.width),
                shellBounds.height = Math.min(displayBounds.height - 80, shellBounds.height));
        log.info("shell" + shell.getBounds());
        // center
        centerOn.ifPresent(parent -> {
            Rectangle parentBounds = parent.getBounds();
            Point pos = parent.toDisplay(0, 0);
            int x = pos.x + (parentBounds.width - shellBounds.width) / 2;
            int y = pos.y + (parentBounds.height - shellBounds.height) / 2;
            shell.setLocation(x, y);
        });
    }

    @Override
    protected void configureShell(Shell newShell) {
        super.configureShell(newShell);
        title.ifPresent(t -> newShell.setText(t));
    }

    @Override
    protected Control createDialogArea(Composite parent) {
        assert contentsBuilder != null : "No contents builder! Call setContents() before opening the dialog.";
        Composite area = (Composite) super.createDialogArea(parent);

        // allow other than GridLayout
        Composite composite = new Composite(area, SWT.NONE);
        composite.setLayout(new FillLayout(SWT.VERTICAL));
        contentsBuilder.accept(composite);
        return area;
    }

    @Override
    protected Control createButtonBar(Composite parent) {
        // no buttonBar if no actions
        return !actions.isEmpty() ? super.createButtonBar(parent) : null; //new Composite( parent, SWT.BORDER );
    }

    @Override
    protected void createButtonsForButtonBar(Composite parent) {
        actions.forEach(action -> {
            ((GridLayout) parent.getLayout()).numColumns++;

            //            assert action.getId() != null : "Dialog actions must have a unique id set.";
            //            int id = Integer.parseInt( action.getId() );

            Button btn = new Button(parent, SWT.PUSH | SWT.FLAT);
            btn.setText(action.getText());
            btn.setToolTipText(action.getToolTipText());
            //            btn.setData( new Integer( id ) );
            btn.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(SelectionEvent ev) {
                    action.run();
                }
            });
            //            if (defaultButton) {
            //                Shell shell = parent.getShell();
            //                if (shell != null) {
            //                    shell.setDefaultButton( btn );
            //                }
            //            }
            //            buttons.put( new Integer( id ), button );
            setButtonLayoutData(btn);
        });
    }

    @Override
    protected Button createButton(Composite parent, int id, String label, boolean defaultButton) {
        // increment the number of columns in the button bar
        ((GridLayout) parent.getLayout()).numColumns++;
        Button button = new Button(parent, SWT.PUSH);
        button.setText(label);
        button.setData(new Integer(id));
        button.addSelectionListener(new SelectionAdapter() {

            public void widgetSelected(SelectionEvent event) {
                buttonPressed(((Integer) event.widget.getData()).intValue());
            }
        });
        if (defaultButton) {
            Shell shell = parent.getShell();
            if (shell != null) {
                shell.setDefaultButton(button);
            }
        }
        //        buttons.put( new Integer( id ), button );
        setButtonLayoutData(button);
        return button;
    }

}