org.jtheque.ui.utils.windows.WindowState.java Source code

Java tutorial

Introduction

Here is the source code for org.jtheque.ui.utils.windows.WindowState.java

Source

package org.jtheque.ui.utils.windows;

import org.jtheque.core.Core;
import org.jtheque.core.utils.OSGiUtils;
import org.jtheque.errors.Error;
import org.jtheque.errors.ErrorService;
import org.jtheque.i18n.Internationalizable;
import org.jtheque.i18n.LanguageService;
import org.jtheque.images.ImageService;
import org.jtheque.ui.Controller;
import org.jtheque.ui.constraints.Constraint;
import org.jtheque.utils.StringUtils;
import org.jtheque.utils.collections.ArrayUtils;
import org.jtheque.utils.collections.CollectionUtils;
import org.jtheque.utils.ui.SwingUtils;

import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.plaf.ext.LockableUI;
import org.osgi.framework.BundleContext;
import org.springframework.context.ApplicationContext;

import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import java.awt.Component;
import java.awt.Cursor;
import java.awt.Image;
import java.awt.Window;
import java.util.Collection;
import java.util.Map;

/*
 * Copyright JTheque (Baptiste Wicht)
 *
 * Licensed 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.
 */

/**
 * A Window state implementation. This state manage the state of Dialogs and Frames.
 *
 * @author Baptiste Wicht
 */
public final class WindowState implements org.jtheque.ui.WindowState {
    private String titleKey;
    private Object[] titleReplaces;

    private final Collection<Internationalizable> internationalizables = CollectionUtils.newList();
    private final Map<Object, Constraint> constraintCache = CollectionUtils.newHashMap(5);

    private final Window window;
    private JXLayer<JComponent> content;

    private Controller<?> controller;
    private LockableUI waitUI;

    private BundleContext bundleContext;
    private ApplicationContext applicationContext;

    private boolean builded;

    /**
     * Construct a new WindowState.
     *
     * @param window The window to manage.
     */
    public WindowState(Window window) {
        super();

        this.window = window;
    }

    /**
     * Build the state.
     */
    public void build() {
        content = new JXLayer<JComponent>();

        window.setIconImage(getDefaultWindowIcon());

        builded = true;
    }

    /**
     * Return the default icon for the window icon.
     *
     * @return The default icon.
     */
    protected Image getDefaultWindowIcon() {
        return getService(ImageService.class).getImage(Core.WINDOW_ICON);
    }

    /**
     * Return the service of the given class.
     *
     * @param classz The class to get the service.
     * @param <T>    The type of service.
     *
     * @return The service of the given class if it's exists otherwise null.
     */
    protected <T> T getService(Class<T> classz) {
        return OSGiUtils.getService(bundleContext, classz);
    }

    @Override
    public void startWait() {
        installWaitUIIfNecessary();
        content.setUI(waitUI);
        waitUI.setLocked(true);
        window.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    }

    @Override
    public void stopWait() {
        if (waitUI != null) {
            waitUI.setLocked(false);
            window.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
            content.setUI(null);
        }
    }

    /**
     * Create the wait UI only if this has not been done before.
     */
    private void installWaitUIIfNecessary() {
        if (waitUI == null) {
            waitUI = new BusyPainterUI(window);
        }
    }

    /**
     * Return the content pane of the view.
     *
     * @return The content pane of the view.
     */
    public JXLayer<JComponent> getContent() {
        return content;
    }

    /**
     * Set a glass pane over the view.
     *
     * @param glassPane The glass pane to set over the view.
     */
    public void setGlassPane(Component glassPane) {
        SwingUtils.inEdt(new GlassPaneSetter(glassPane));
    }

    /**
     * Display the view.
     */
    public void display() {
        if (!builded) {
            SwingUtils.inEdt(new Runnable() {
                @Override
                public void run() {
                    ((ManagedWindow) window).build();
                }
            });
        }

        SwingUtils.inEdt(new Runnable() {
            @Override
            public void run() {
                window.setVisible(true);
            }
        });
    }

    /**
     * Return the controller of the view.
     *
     * @return The controller of the view.
     */
    public Controller<?> getController() {
        return controller;
    }

    /**
     * Set the controller of the view.
     *
     * @param controller The controller of the view.
     */
    public void setController(Controller<?> controller) {
        this.controller = controller;
    }

    /**
     * Return the bundle context.
     *
     * @return The bundle context of the view.
     */
    public BundleContext getBundleContext() {
        return bundleContext;
    }

    /**
     * Return the bundle context.
     *
     * @param bundleContext The bundle context.
     */
    public void setBundleContext(BundleContext bundleContext) {
        this.bundleContext = bundleContext;
    }

    /**
     * Return the application context.
     *
     * @return The application context.
     */
    public ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * Return the application context.
     *
     * @param applicationContext The application context.
     */
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    /**
     * Add an internationalizable to the container.
     *
     * @param internationalizable The internationalizable to add.
     */
    public void addInternationalizable(Internationalizable internationalizable) {
        internationalizables.add(internationalizable);
    }

    /**
     * Refresh the title of the window.
     *
     * @param languageService The language service to use for i18n.
     */
    public void refreshText(LanguageService languageService) {
        if (StringUtils.isNotEmpty(titleKey)) {
            setTitleKey(titleKey, titleReplaces);
        }

        for (Internationalizable internationalizable : internationalizables) {
            internationalizable.refreshText(languageService);
        }
    }

    /**
     * Set the title key of the window.
     *
     * @param key      The key of the title.
     * @param replaces The replaces of the title.
     */
    public void setTitleKey(String key, Object... replaces) {
        titleKey = key;

        if (!ArrayUtils.isEmpty(replaces)) {
            titleReplaces = ArrayUtils.copyOf(replaces);
        }

        ((ManagedWindow) window).setTitle(getMessage(key, replaces));
    }

    /**
     * Return the internationalized message.
     *
     * @param key The internationalization key.
     *
     * @return The internationalized message.
     */
    protected String getMessage(String key) {
        return getService(LanguageService.class).getMessage(key);
    }

    /**
     * Return the internationalized message.
     *
     * @param key      The internationalization key.
     * @param replaces The replacement objects to use.
     *
     * @return the internationalized message.
     */
    protected String getMessage(String key, Object... replaces) {
        return getService(LanguageService.class).getMessage(key, replaces);
    }

    /**
     * Add a constraint to the view.
     *
     * @param field      The field to validate.
     * @param constraint The constraint to add to the view.
     */
    public void addConstraint(Object field, Constraint constraint) {
        constraintCache.put(field, constraint);

        constraint.configure(field);
    }

    /**
     * Validate the content of the view.
     *
     * @return true if the view content is valid else false.
     */
    public boolean validateContent() {
        Collection<Error> errors = CollectionUtils.newList(5);

        ((ManagedWindow) window).validate(errors);

        ErrorService errorService = getService(ErrorService.class);

        for (Error error : errors) {
            errorService.addError(error);
        }

        return errors.isEmpty();
    }

    /**
     * Validate the view using the setted constraints.
     *
     * @param errors The errors collection to fill.
     */
    public void validate(Collection<Error> errors) {
        for (Map.Entry<Object, Constraint> constraint : constraintCache.entrySet()) {
            constraint.getValue().validate(constraint.getKey(), errors);
        }
    }

    /**
     * A simple runnable to apply a glass pane to the view associated with this state.
     *
     * @author Baptiste Wicht
     */
    private final class GlassPaneSetter implements Runnable {
        private final Component glassPane;

        /**
         * Construct a new GlassPaneSetter for the given glass pane.
         *
         * @param glassPane The glass pane to set on the view.
         */
        private GlassPaneSetter(Component glassPane) {
            this.glassPane = glassPane;
        }

        @Override
        public void run() {
            if (glassPane == null) {
                JPanel glasspane = content.createGlassPane();

                glasspane.setVisible(false);
                glasspane.setOpaque(false);

                content.setGlassPane(glasspane);
            } else {
                content.setGlassPane((JPanel) glassPane);

                glassPane.setVisible(true);
                glassPane.repaint();

                SwingUtilities.updateComponentTreeUI(glassPane);
            }

            SwingUtilities.updateComponentTreeUI(content);
        }
    }
}