org.caleydo.view.domino.internal.NodeSelections.java Source code

Java tutorial

Introduction

Here is the source code for org.caleydo.view.domino.internal.NodeSelections.java

Source

/*******************************************************************************
 * Caleydo - Visualization for Molecular Biology - http://caleydo.org
 * Copyright (c) The Caleydo Team. All rights reserved.
 * Licensed under the new BSD license, available at http://caleydo.org/license
 *******************************************************************************/
package org.caleydo.view.domino.internal;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.caleydo.core.data.selection.SelectionCommand;
import org.caleydo.core.data.selection.SelectionType;
import org.caleydo.core.event.EventListenerManager.ListenTo;
import org.caleydo.core.event.data.SelectionCommandEvent;
import org.caleydo.core.util.base.ICallback;
import org.caleydo.view.domino.api.model.EDirection;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multiset;
import com.google.common.collect.SetMultimap;

/**
 * @author Samuel Gratzl
 *
 */
public class NodeSelections {
    private final SetMultimap<SelectionType, NodeGroup> selections = HashMultimap.create();
    private final SetMultimap<SelectionType, Block> blockSelections = HashMultimap.create();

    private Collection<ICallback<SelectionType>> selectionChanges = new ArrayList<>();
    private Collection<ICallback<SelectionType>> blockSelectionChanges = new ArrayList<>();

    public void onNodeGroupSelectionChanges(ICallback<SelectionType> callback) {
        this.selectionChanges.add(callback);
    }

    public void onBlockSelectionChanges(ICallback<SelectionType> callback) {
        this.blockSelectionChanges.add(callback);
    }

    public void removeOnNodeGroupSelectionChanges(ICallback<SelectionType> callback) {
        this.selectionChanges.remove(callback);
    }

    public void removeOnBlockSelectionChanges(ICallback<SelectionType> callback) {
        this.blockSelectionChanges.remove(callback);
    }

    private void fire(SelectionType type) {
        for (ICallback<SelectionType> c : selectionChanges)
            c.on(type);
    }

    private void fireBlock(SelectionType type) {
        for (ICallback<SelectionType> c : blockSelectionChanges)
            c.on(type);
    }

    public boolean isSelected(SelectionType type, NodeGroup group) {
        return selections.get(type).contains(group);
    }

    public boolean isSelected(SelectionType type, Block block) {
        return blockSelections.get(type).contains(block);
    }

    public void select(SelectionType type, NodeGroup group, boolean additional) {
        Set<NodeGroup> c = selections.get(type);
        if (!additional)
            c.clear();
        c.add(group);
        fire(type);
    }

    public Set<NodeGroup> getSelection(SelectionType type) {
        return selections.get(type);
    }

    public void select(SelectionType type, Block block, boolean additional) {
        Set<Block> c = blockSelections.get(type);
        if (!additional)
            c.clear();
        c.add(block);
        fireBlock(type);
    }

    public Set<Block> getBlockSelection(SelectionType type) {
        return blockSelections.get(type);
    }

    public void cleanup(Node node) {
        for (SelectionType type : ImmutableSet.copyOf(selections.keySet())) {
            Set<NodeGroup> c = selections.get(type);
            boolean changed = false;
            for (Iterator<NodeGroup> it = c.iterator(); it.hasNext();) {
                NodeGroup g = it.next();
                if (g.getNode() == node) {
                    it.remove();
                    changed = true;
                }
            }
            if (changed)
                fire(type);
        }
    }

    public void cleanup(Block block) {
        for (SelectionType type : ImmutableSet.copyOf(blockSelections.keySet())) {
            if (blockSelections.get(type).remove(block))
                fireBlock(type);
        }

        for (SelectionType type : ImmutableSet.copyOf(selections.keySet())) {
            Set<NodeGroup> c = selections.get(type);
            boolean changed = false;
            for (Iterator<NodeGroup> it = c.iterator(); it.hasNext();) {
                NodeGroup g = it.next();
                if (block.containsNode(g.getNode())) {
                    it.remove();
                    changed = true;
                }
            }
            if (changed)
                fire(type);
        }
    }

    public boolean clear(SelectionType type, NodeGroup group) {
        Set<NodeGroup> c = selections.get(type);
        boolean changed = !c.isEmpty();
        if (group != null)
            changed = c.remove(group);
        else
            c.clear();
        if (changed)
            fire(type);
        return changed;
    }

    public boolean clear(SelectionType type, Block block) {
        Set<Block> c = blockSelections.get(type);
        boolean changed = !c.isEmpty();
        if (block != null)
            changed = c.remove(block);
        else
            c.clear();
        if (changed)
            fireBlock(type);
        return changed;
    }

    @ListenTo
    private void on(SelectionCommandEvent event) {
        if (event.getSender() == this)
            return;
        SelectionCommand cmd = event.getSelectionCommand();

        switch (cmd.getSelectionCommandType()) {
        case CLEAR:
            clear(cmd.getSelectionType(), (NodeGroup) null);
            clear(cmd.getSelectionType(), (Block) null);
            break;
        case CLEAR_ALL:
        case RESET:
            ImmutableSet<SelectionType> toSend = ImmutableSet.copyOf(blockSelections.keySet());
            blockSelections.clear();
            for (SelectionType t : toSend)
                fireBlock(t);
            toSend = ImmutableSet.copyOf(selections.keySet());
            selections.clear();
            for (SelectionType t : toSend)
                fire(t);
            break;
        }
    }

    public static Node getSingleNode(Set<NodeGroup> selection) {
        return getSingleNode(selection, true);
    }

    public static Node getSingleNode(Set<NodeGroup> selection, boolean checkFull) {
        if (selection.isEmpty())
            return null;
        Set<Node> nodes = getNodes(selection, checkFull);
        if (nodes.size() == 1)
            return nodes.iterator().next();
        return null;
    }

    public static Set<Node> getFullNodes(Set<NodeGroup> selection) {
        return getNodes(selection, true);
    }

    private static Set<Node> getNodes(Set<NodeGroup> selection, boolean checkFull) {
        if (selection.isEmpty())
            return Collections.emptySet();
        Multiset<Node> nodes = HashMultiset.create();
        for (NodeGroup group : selection) {
            Node n = group.getNode();
            nodes.add(n);
        }
        if (checkFull) {
            for (Iterator<Node> it = nodes.elementSet().iterator(); it.hasNext();) {
                Node node = it.next();
                final int expected = node.groupCount();
                if (expected != nodes.count(node)) {
                    it.remove();// not all groups
                }
            }
        }
        return nodes.elementSet();
    }

    /**
     * @param selected
     * @return
     */
    public static Block getSingleBlock(Set<NodeGroup> selection) {
        if (selection.isEmpty())
            return null;
        Set<Block> blocks = getFullBlocks(selection);
        if (blocks.size() == 1)
            return blocks.iterator().next();
        return null;
    }

    public static Set<Block> getFullBlocks(Set<NodeGroup> selection) {
        if (selection.isEmpty())
            return Collections.emptySet();
        Set<Node> nodes = getFullNodes(selection);
        if (nodes.isEmpty())
            return Collections.emptySet();
        Multiset<Block> blocks = HashMultiset.create();
        for (Node node : nodes) {
            Block n = node.getBlock();
            blocks.add(n);
        }
        for (Iterator<Block> it = blocks.elementSet().iterator(); it.hasNext();) {
            Block block = it.next();
            if (block.nodeCount() != blocks.count(block)) {
                it.remove();// not all groups
            }
        }
        return blocks.elementSet();
    }

    /**
     * @param selected
     * @return
     */
    public static Set<NodeGroup> compress(NodeGroup start, Set<NodeGroup> selected) {
        Set<NodeGroup> linked = new HashSet<>(selected.size());
        compress(start, selected, linked, null);
        return linked;
    }

    private static void compress(NodeGroup n, Set<NodeGroup> selected, Set<NodeGroup> linked,
            EDirection commingFrom) {
        linked.add(n);
        selected.remove(n);
        for (EDirection dir : EDirection.values()) {
            if (dir == commingFrom)
                continue;
            NodeGroup f = n.findNeigbhor(dir, selected);
            if (f != null) {
                compress(f, selected, linked, dir);
            }
        }
    }
}