/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see .
*
*/
package de.tud.kom.p2psim.impl.topology.views.visualization.world;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Vector;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.api.topology.social.SocialView;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector.MouseClickListener;
import de.tud.kom.p2psim.impl.topology.views.visualization.ui.ComponentOptions;
/**
* This component draw the Social connections.
*
* @author Christoph Muenker
* @version 1.0, 22.06.2013
*/
public class SocialViewComponentVis extends JComponent implements
MouseClickListener, ComponentOptions {
private static Vector CLUSTER_COLOR = new Vector();
static {
CLUSTER_COLOR.add(Color.BLUE);
CLUSTER_COLOR.add(Color.GREEN);
CLUSTER_COLOR.add(new Color(1f, 0.27f, 0f)); // OrangeRed
CLUSTER_COLOR.add(Color.CYAN);
CLUSTER_COLOR.add(Color.RED);
CLUSTER_COLOR.add(Color.YELLOW);
}
private SocialView view;
private Map posVecs = new HashMap();
private Map> clusterMap = new HashMap>();
private List optionBoxes = new Vector();
private SimHost selectedHost = null;
private boolean showCluster = false;
private boolean showRelationship = false;
public SocialViewComponentVis(SocialView view) {
this.view = view;
int i = 0;
for (Set cluster : view.getClusters()) {
for (SimHost host : cluster) {
posVecs.put(host, host.getTopologyComponent().getRealPosition());
}
if (i < CLUSTER_COLOR.size()) {
clusterMap.put(CLUSTER_COLOR.get(i), cluster);
i++;
}
}
setBounds(0, 0, VisualizationInjector.getWorldX(),
VisualizationInjector.getWorldY());
setOpaque(true);
setVisible(true);
VisualizationInjector.addMouseListener(this);
optionBoxes.add(createRelationshipCheckBox());
optionBoxes.add(createClusterCheckBox());
}
private JCheckBox createRelationshipCheckBox() {
final JCheckBox checkBox = new JCheckBox("Connections",
showRelationship);
checkBox.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
showRelationship = checkBox.isSelected();
SocialViewComponentVis.this.repaint();
}
});
return checkBox;
}
private JCheckBox createClusterCheckBox() {
final JCheckBox checkBox = new JCheckBox("Cluster", showCluster);
checkBox.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
showCluster = checkBox.isSelected();
SocialViewComponentVis.this.repaint();
}
});
return checkBox;
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
if (showRelationship) {
for (Entry entry : posVecs.entrySet()) {
SimHost source = entry.getKey();
Point sourcePos = entry.getValue().asPoint();
// neighbors
for (SimHost dest : view.getNeighbors(source)) {
if (selectedHost == null || source.equals(selectedHost)
|| dest.equals(selectedHost)) {
g2.setColor(new Color(0, 0, 0));
} else {
g2.setColor(new Color(0, 0, 0, 32));
}
Point destPos = posVecs.get(dest).asPoint();
g2.drawLine(sourcePos.x, sourcePos.y, destPos.x, destPos.y);
}
}
}
if (showCluster) {
for (Entry> clusters : clusterMap.entrySet()) {
for (SimHost host : clusters.getValue()) {
Point center = posVecs.get(host).asPoint();
// for a black border around the circle
g2.setColor(Color.BLACK);
g2.setStroke(new BasicStroke(4.5f));
g2.drawOval(center.x - 7, center.y - 7, 14, 14);
// draw the circle
g2.setColor(clusters.getKey());
g2.setStroke(new BasicStroke(3.5f));
g2.drawOval(center.x - 7, center.y - 7, 14, 14);
}
}
}
}
@Override
public void mouseClicked(int x, int y) {
List inNear = new Vector();
for (Entry e : posVecs.entrySet()) {
if (e.getValue().distanceTo(new PositionVector(x, y)) < 4) {
inNear.add(e.getKey());
}
}
if (inNear.size() == 1) {
selectedHost = inNear.iterator().next();
} else if (inNear.size() > 1) {
Collections.shuffle(inNear);
selectedHost = inNear.iterator().next();
} else {
selectedHost = null;
}
this.repaint();
}
@Override
public List getCheckBoxes() {
return optionBoxes;
}
}