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

org.drombler.commons.docking.spi.DockingAreaManager Maven / Gradle / Ivy

/*
 *         COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Notice
 *
 * The contents of this file are subject to the COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL)
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.opensource.org/licenses/cddl1.txt
 *
 * The Original Code is Drombler.org. The Initial Developer of the
 * Original Code is Florian Brunner (Sourceforge.net user: puce).
 * Copyright 2012 Drombler.org. All Rights Reserved.
 *
 * Contributor(s): .
 */
package org.drombler.commons.docking.spi;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 *
 * @param  the type of the Docking Area
 * @author puce
 */
// TODO: check thread safty
// TODO: move this class to Client - Docking - SPI
public class DockingAreaManager> {

    private final Map dockingAreas = new HashMap<>();
    private final Map> dockingAreaManagers = new HashMap<>();
    private final DockingAreaManager parent;
    private final int position;
    private final SplitLevel level;

    public DockingAreaManager(DockingAreaManager parent, int position, int level) {
        this(parent, position, SplitLevel.valueOf(level));
    }

    public DockingAreaManager(DockingAreaManager parent, int position, SplitLevel level) {
        this.parent = parent;
        this.position = position;
        this.level = level;
    }

    public void addDockingArea(List path, A dockingArea) {
        addDockingArea(path.iterator(), dockingArea);
    }

    private void addDockingArea(Iterator path, A dockingArea) {
        if (path.hasNext()) {
            Integer childPosition = path.next();
            if (!dockingAreaManagers.containsKey(childPosition)) {
                dockingAreaManagers.put(childPosition, new DockingAreaManager<>(this, childPosition,
                        SplitLevel.valueOf(level.getLevel() + 1)));
            }
            dockingAreaManagers.get(childPosition).addDockingArea(path, dockingArea);
        } else {
            // TODO: handle case where 2 dockingAreas have the same position
            // TODO: handle case where dockingArea and dockingAreaManager have the same position
            dockingArea.setParentManager(this);
            dockingAreas.put(dockingArea.getPosition(), dockingArea);
        }
    }

    private ShortPathPart createShortPathPart(int position) {
        return new ShortPathPart(position, level);
    }

    private boolean isShortPathRelevant(int position, boolean emptyPath) {
        return (!isOnlyActualContent(position)) || (emptyPath && parent == null);
    }

    private boolean isOnlyActualContent(int position) {
        return isCurrentlyOnlyActualContent(position)
                || isFutureOnlyActualContent(position);
    }

    private boolean isCurrentlyOnlyActualContent(int position) {
        return containsActualPosition(position) && getActualContentSize() == 1;
    }

    private boolean isFutureOnlyActualContent(int position) {
        return !containsActualPosition(position) && getActualContentSize() == 0;
    }

    private int getActualContentSize() {
        return getNonEmptyAreaManagers().size() + getVisualizableDockingAreas().size();
    }

    private Map> getNonEmptyAreaManagers() {
        Map> nonEmptyAreaManagers = new HashMap<>();
        dockingAreaManagers.entrySet().stream().
                filter(entry -> entry.getValue().getActualContentSize() > 0).
                forEach(entry -> nonEmptyAreaManagers.put(entry.getKey(), entry.getValue()));
        return nonEmptyAreaManagers;
    }

    private Map getVisualizableDockingAreas() {
        Map visualizableDockingAreas = new HashMap<>();
        dockingAreas.entrySet().stream().
                filter(entry -> entry.getValue().isVisual()).
                forEach(entry -> visualizableDockingAreas.put(entry.getKey(), entry.getValue()));
        return visualizableDockingAreas;
    }

    private boolean containsActualPosition(int position) {
        return (dockingAreaManagers.containsKey(position)
                && dockingAreaManagers.get(position).getActualContentSize() > 0)
                || (dockingAreas.containsKey(position)
                && dockingAreas.get(position).isVisual());
    }

    public List getShortPath(A dockingArea) {
        if (!(dockingAreas.containsKey(dockingArea.getPosition())
                && dockingAreas.get(dockingArea.getPosition()).equals(dockingArea))) {
            throw new IllegalStateException(
                    "The specified docking area must be a child of this manager: " + dockingArea);
        }

        if (dockingArea.isVisual()) {
            return calculateShortPath(dockingArea);
        } else {
            return Collections.emptyList();
        }
    }

    private List calculateShortPath(A dockingArea) {
        List shortPath = calculateReversedShortPath(dockingArea);
        Collections.reverse(shortPath);
        return shortPath;
    }

    private List calculateReversedShortPath(A dockingArea) {
        List shortPath = new ArrayList<>();
        int currentChildPosition = dockingArea.getPosition();
        for (DockingAreaManager currentParent = this; currentParent != null; currentParent = currentParent.parent) {
            if (currentParent.isShortPathRelevant(currentChildPosition, shortPath.isEmpty())) {
                shortPath.add(currentParent.createShortPathPart(currentChildPosition));
            }
            currentChildPosition = currentParent.position;
        }
        return shortPath;
    }

    @Override
    public String toString() {
        return String.format("%s[position=%d, level=%s]", DockingAreaManager.class.getSimpleName(), position, level);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy