All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jacpfx.rcp.util.WorkerUtil Maven / Gradle / Ivy

The newest version!
/*
 * **********************************************************************
 *
 *  Copyright (C) 2010 - 2015
 *
 *  [WorkerUtil.java]
 *  JACPFX Project (https://github.com/JacpFX/JacpFX/)
 *  All rights reserved.
 *
 *  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.
 *
 *
 * *********************************************************************
 */

package org.jacpfx.rcp.util;

import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.Node;
import org.jacpfx.api.component.SubComponent;
import org.jacpfx.api.component.UIComponent;
import org.jacpfx.api.message.Message;
import org.jacpfx.api.util.UIType;
import org.jacpfx.rcp.component.EmbeddedFXComponent;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created with IntelliJ IDEA.
 * User: Andy Moncsek
 * Date: 11.10.13
 * Time: 14:22
 * This util class contains methods needed in all types  of workers
 */
public class WorkerUtil {

    /**
     * invokes a runnable on application thread and waits until execution is
     * finished
     *
     * @param runnable, a runnable which will be invoked and wait until execution is finished
     * @throws InterruptedException  when thread was interrupted on shutdown
     * @throws java.util.concurrent.ExecutionException when an exception was thrown in a component
     *
     */
    public static void invokeOnFXThreadAndWait(final Runnable runnable)
            throws InterruptedException, ExecutionException {
        final Lock lock = new ReentrantLock();
        final Condition condition = lock.newCondition();
        final AtomicBoolean conditionReady = new AtomicBoolean(false);
        final AtomicReference exchanger = new AtomicReference<>();
        lock.lock();
        try {
            Platform.runLater(() -> {
                lock.lock();
                try {
                    // prevent execution when application is closed
                    if (ShutdownThreadsHandler.APPLICATION_RUNNING.get())
                        runnable.run();
                } catch (Exception e) {
                    exchanger.set(new ThrowableWrapper(e));
                } finally {
                    conditionReady.set(true);
                    condition.signal();
                    lock.unlock();
                }

            });
            // wait until execution is finished and check if application is
            // still running to prevent wait
            while (!conditionReady.get()
                    && ShutdownThreadsHandler.APPLICATION_RUNNING.get())
                condition.await(ShutdownThreadsHandler.WAIT,
                        TimeUnit.MILLISECONDS);

            final ThrowableWrapper throwableWrapper = exchanger.get();
            if (throwableWrapper != null) {
                throw new ExecutionException(throwableWrapper.t);
            }
        } finally {
            lock.unlock();
        }
    }



    /**
     * find valid target and add type specific new component. Handles Container,
     * ScrollPanes, Menus and Bar Entries from user
     *
     * @param validContainer, a valid container where component root will be added
     * @param component,      the component
     */
    public static void addComponentByType(
            final Node validContainer,
            final UIComponent, Event, Object> component) {
        handleAdd(validContainer, component.getRoot());
    }

    /**
     * enables component an add to container
     *
     * @param validContainer , a valid container where component root will be added
     * @param componentViewNode   , the component
     */
    private static void handleAdd(final Node validContainer, final Node componentViewNode) {
        if (componentViewNode != null) {
            handleViewState(componentViewNode, true);
            final ObservableList children = FXUtil
                    .getChildren(validContainer);
            if(!children.contains(componentViewNode))children.add(componentViewNode);
        }

    }

    /**
     * set visibility and enable/disable
     *
     * @param componentViewNode, a Node where to set the state
     * @param state,        the boolean value of the state
     */
    public static void handleViewState(final Node componentViewNode,
                                       final boolean state) {
        componentViewNode.setVisible(state);
        componentViewNode.setDisable(!state);
        componentViewNode.setManaged(state);
    }

    /**
     * delegate component handle return value to specified target
     *
     * @param comp,     the component
     * @param targetId, the message target id
     * @param value,    the message value
     * @param action,   the message
     */
    public static void delegateReturnValue(
            final SubComponent, Event, Object> comp,
            final String targetId, final Object value,
            final Message action) {
        if (value != null && targetId != null
                && !action.messageBodyEquals("init")) {
            comp.getContext().send(targetId,value);
        }
    }

    /**
     * Executes post handle method in application main thread. The result value
     * of handle method (from worker thread) is Input for the postHandle Method.
     * The return value or the handleReturnValue are the root node of this
     * component.
     *
     * @param handleReturnValue the UI return value after "handle(message)" {@link org.jacpfx.api.component.ComponentHandle#handle(org.jacpfx.api.message.Message)} was executed
     * @param component, a component
     * @param message,    the current message
     * @throws java.lang.Exception when an Exception occures while execute {@link org.jacpfx.api.component.ComponentView#postHandle(Object, org.jacpfx.api.message.Message)}
     */
    public static void executeComponentViewPostHandle(final Node handleReturnValue,
                                                            final EmbeddedFXComponent component, final Message message) throws Exception {

        Node potsHandleReturnValue = component.getComponentViewHandle().postHandle(handleReturnValue,
                message);
        if (potsHandleReturnValue == null) {
            potsHandleReturnValue = handleReturnValue;
        } else if (component.getType().equals(UIType.DECLARATIVE)) {
            throw new UnsupportedOperationException(
                    "declarative component should not have a return value in postHandle method, otherwise you would overwrite the FXML root node.");
        }
        if (potsHandleReturnValue != null
                && component.getType().equals(UIType.PROGRAMMATIC)) {
            component.setRoot(potsHandleReturnValue);
        }
    }

    /**
     * Move component to new target in perspective.
     *
     * @param delegateQueue, the component delegate queue
     * @param component,     the component
     */
    public static void changeComponentTarget(
            final BlockingQueue, Event, Object>> delegateQueue,
            final SubComponent, Event, Object> component) {
        // delegate to perspective observer
        final Thread t = Thread.currentThread();
        try {
            delegateQueue.put(component);
        } catch (InterruptedException e) {
           t.getUncaughtExceptionHandler().uncaughtException(t,e);
        }
    }

    /**
     * Runs the handle method of a componentView.
     *
     * @param component, the component
     * @param action,    the current message
     * @return a returned node from component execution {@link org.jacpfx.api.component.ComponentHandle#handle(org.jacpfx.api.message.Message)}
     * @throws java.lang.Exception when an Exception occures while execute {@link org.jacpfx.api.component.ComponentHandle#handle(org.jacpfx.api.message.Message)}

     */
    public static Node prepareAndRunHandleMethod(
            final UIComponent, Event, Object> component,
            final Message action) throws Exception {
        return component.getComponentViewHandle().handle(action);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy