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

org.jacpfx.rcp.perspective.AFXPerspective Maven / Gradle / Ivy

There is a newer version: 2.1
Show newest version
/************************************************************************
 *
 * Copyright (C) 2010 - 2014
 *
 * [AFX2Perspective.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.perspective;


import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import org.jacpfx.api.annotations.perspective.Perspective;
import org.jacpfx.api.component.Injectable;
import org.jacpfx.api.component.PerspectiveView;
import org.jacpfx.api.component.SubComponent;
import org.jacpfx.api.componentLayout.PerspectiveLayoutInterface;
import org.jacpfx.api.context.JacpContext;
import org.jacpfx.api.coordinator.Coordinator;
import org.jacpfx.api.handler.ComponentHandler;
import org.jacpfx.api.launcher.Launcher;
import org.jacpfx.api.message.DelegateDTO;
import org.jacpfx.api.message.Message;
import org.jacpfx.api.util.UIType;
import org.jacpfx.rcp.component.AComponent;
import org.jacpfx.rcp.componentLayout.FXComponentLayout;
import org.jacpfx.rcp.componentLayout.PerspectiveLayout;
import org.jacpfx.rcp.context.JacpContextImpl;
import org.jacpfx.rcp.message.MessageImpl;
import org.jacpfx.rcp.registry.ComponentRegistry;
import org.jacpfx.rcp.util.FXUtil;
import org.jacpfx.rcp.util.PerspectiveUtil;

import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * represents a basic javafx2 perspective that handles subcomponents,
 * perspective are not handled in thread so avoid long running tasks in
 * perspective.
 *
 * @author Andy Moncsek
 */
public abstract class AFXPerspective extends AComponent implements
        PerspectiveView, Event, Object>,
        Initializable {
    private final Logger logger = Logger.getLogger(this.getClass().getName());
    private ComponentHandler, Event, Object>, Message> componentHandler;
    private BlockingQueue, Event, Object>> componentDelegateQueue;
    private BlockingQueue> messageDelegateQueue;
    private Coordinator, Event, Object> messageCoordinator;
    private String viewLocation;
    private URL documentURL;
    private PerspectiveLayoutInterface perspectiveLayout;
    private UIType type = UIType.PROGRAMMATIC;
    private String localeID = "";
    private final Object lock = new Object();
    private Launcher launcher;

    Injectable perspective;

    /**
     * {@inheritDoc}
     */
    @Override
    public final void init(
            final BlockingQueue, Event, Object>> componentDelegateQueue,
            final BlockingQueue> messageDelegateQueue,
            final Coordinator, Event, Object> messageCoordinator, final Launcher launcher) {

        this.messageCoordinator = messageCoordinator;
        this.componentDelegateQueue = componentDelegateQueue;
        this.messageDelegateQueue = messageDelegateQueue;
        this.globalMessageQueue = this.messageCoordinator.getMessageQueue();
        this.launcher = launcher;
        this.context = new JacpContextImpl(this.globalMessageQueue);
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void postInit(
            final ComponentHandler, Event, Object>, Message> componentHandler) {
        // init component handler
        this.componentHandler = componentHandler;
        this.messageCoordinator.setComponentHandler(this.componentHandler);
        final List, Event, Object>> subcomponents = createAllDeclaredSubcomponents();
        if (subcomponents != null) this.registerSubcomponents(subcomponents);
    }

    /**
     * Create an returns all declared subcomponents by Perspective annotation.
     *
     * @return all declared subcomponents
     */
    private List, Event, Object>> createAllDeclaredSubcomponents() {
        final Injectable handler = this.perspective;
        if (handler == null) throw new IllegalArgumentException("No perspective annotatation found");
        final Perspective perspectiveAnnotation = handler.getClass()
                .getAnnotation(Perspective.class);
        return PerspectiveUtil.getInstance(this.launcher).createSubcomponents(perspectiveAnnotation);

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void handlePerspective(final Message action) {
        getFXPerspectiveHandler().handlePerspective(action,
                (PerspectiveLayout) this.perspectiveLayout);

    }

    @Override
    public final void registerComponent(
            final SubComponent, Event, Object> component) {
        component.initEnv(this.getContext().getId(),
                this.messageCoordinator.getMessageQueue());
        final JacpContextImpl currentContext = JacpContextImpl.class.cast(component.getContext());
        currentContext.setParentId(this.context.getId());
        PerspectiveUtil.handleComponentMetaAnnotation(component);
        currentContext.setFXComponentLayout(getFXComponentLayoutInstance(currentContext));
        if (currentContext.isActive()) {
            addComponent(component);
        }

    }

    private  FXComponentLayout getFXComponentLayoutInstance(final JacpContextImpl currentContext) {
        final FXComponentLayout currentLayout =      JacpContextImpl.class.cast(this.context).getComponentLayout();
        return new FXComponentLayout(currentLayout.getMenu(),currentLayout.getGlassPane(),currentContext.getParentId(),currentContext.getId());

    }

    @Override
    public final void addComponent(
            final SubComponent, Event, Object> component) {
        synchronized (lock) {
            this.log("register component: " + component.getContext().getId());
            ComponentRegistry.registerComponent(component);
        }
    }


    @Override
    public final void unregisterComponent(
            final SubComponent, Event, Object> component) {
        synchronized (lock) {
            this.log("unregister component: " + component.getContext().getId());
            ComponentRegistry.removeComponent(component);
            component.initEnv(null, null);
        }
    }

    @Override
    public final void removeAllCompnents() {

    }

    @Override
    public final void initComponents(final Message action) {
        final String targetId = FXUtil.getTargetComponentId(action
                .getTargetId());
        this.log("3.4.4.1: subcomponent targetId: " + targetId);
        final List, Event, Object>> components = getSubcomponents();
        if (components == null) return;
        components.parallelStream().forEach(component -> initComponent(component, action, targetId));
    }

    private void initComponent(final SubComponent, Event, Object> component, final Message action, final String targetId) {
        if (component.getContext().getId().equals(targetId)) {
            this.log("3.4.4.2: subcomponent init with custom message");
            this.componentHandler.initComponent(action, component);
        } // else END
        else if (component.getContext().isActive() && !component.isStarted()) {
            this.log("3.4.4.2: subcomponent init with default message");
            this.componentHandler.initComponent(
                    new MessageImpl(component.getContext().getId(), component.getContext().getId(),
                            "init", null), component);
        } // if END
    }

    private void log(final String message) {
        if (this.logger.isLoggable(Level.FINE)) {
            this.logger.fine(">> " + message);
        }
    }

    /**
     * Register component at componentHandler.
     *
     * @param          , a list of component extending ISubComponents
     * @param components, a list of registered component
     */
    private , Event, Object>> void registerSubcomponents(
            final List components) {
        components.forEach(this::registerComponent);
    }

    @Override
    public List, Event, Object>> getSubcomponents() {
        return ComponentRegistry.findComponentsByParentId(this.getContext().getId());
    }

    @Override
    public final PerspectiveLayoutInterface getIPerspectiveLayout() {
        return this.perspectiveLayout;
    }

    @Override
    public final void setIPerspectiveLayout(final PerspectiveLayoutInterface layout) {
        this.perspectiveLayout = layout;
    }

    @Override
    public final BlockingQueue, Event, Object>> getComponentDelegateQueue() {
        return this.componentDelegateQueue;
    }

    @Override
    public final BlockingQueue> getMessageDelegateQueue() {
        return this.messageDelegateQueue;
    }

    @Override
    public final BlockingQueue> getMessageQueue() {
        return this.messageCoordinator.getMessageQueue();

    }

    @Override
    public final ComponentHandler, Event, Object>, Message> getComponentHandler() {
        return this.componentHandler;
    }

    @Override
    public final String getViewLocation() {
        if (type.equals(UIType.PROGRAMMATIC))
            throw new UnsupportedOperationException("Only supported when @Declarative annotation is used");
        return this.viewLocation;
    }

    @Override
    public final void setViewLocation(String documentURL) {
        this.viewLocation = documentURL;
        this.type = UIType.DECLARATIVE;
    }

    @Override
    public final void initialize(URL url, ResourceBundle resourceBundle) {
        this.documentURL = url;
        JacpContextImpl.class.cast(context).setResourceBundle(resourceBundle);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final URL getDocumentURL() {
        if (type.equals(UIType.PROGRAMMATIC))
            throw new UnsupportedOperationException("Only supported when @Declarative annotation is used");
        return documentURL;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public final UIType getType() {
        return type;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setUIType(UIType type) {
        this.type = type;
    }


    FXPerspective getFXPerspectiveHandler() {
        return FXPerspective.class.cast(perspective);
    }

    @Override
    public Injectable getPerspective() {
        return this.perspective;
    }

    @Override
    public JacpContext getContext() {
        return this.context;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy