提交 504d253c 编写于 作者: M Mathieu Bastian

Fixes and dynamically update partitions via separate localScale parameter

上级 751a0aff
......@@ -157,9 +157,16 @@ public class AppearanceControllerImpl implements AppearanceController {
}
@Override
public void setUseLocalScale(boolean useLocalScale) {
public void setUseRankingLocalScale(boolean useLocalScale) {
if (model != null) {
model.setLocalScale(useLocalScale);
model.setRankingLocalScale(useLocalScale);
}
}
@Override
public void setUsePartitionLocalScale(boolean useLocalScale) {
if (model != null) {
model.setPartitionLocalScale(useLocalScale);
}
}
}
......@@ -94,7 +94,8 @@ public class AppearanceModelImpl implements AppearanceModel {
private final List<FunctionImpl> nodeStaticFunctions;
private final List<FunctionImpl> edgeStaticFunctions;
// LocalScale (if true, uses visible graph)
private boolean localScale = false;
private boolean rankingLocalScale = false;
private boolean partitionLocalScale = false;
public AppearanceModelImpl(Workspace workspace) {
this.workspace = workspace;
......@@ -103,11 +104,12 @@ public class AppearanceModelImpl implements AppearanceModel {
this.nodeTransformers = initNodeTransformers();
this.edgeTransformers = initEdgeTransformers();
degreeRanking = new DegreeRankingImpl();
inDegreeRanking = new InDegreeRankingImpl();
outDegreeRanking = new OutDegreeRankingImpl();
degreeRanking = new DegreeRankingImpl(graphModel.defaultColumns().degree());
inDegreeRanking = new InDegreeRankingImpl(graphModel.defaultColumns().inDegree());
outDegreeRanking = new OutDegreeRankingImpl(graphModel.defaultColumns().outDegree());
edgeWeightRanking = new EdgeWeightRankingImpl();
edgeTypePartition = new EdgeTypePartitionImpl(graphModel.getConfiguration().getEdgeLabelType());
edgeTypePartition = new EdgeTypePartitionImpl(graphModel.defaultColumns().edgeType(),
graphModel.getConfiguration().getEdgeLabelType());
nodeAttributeRankings = new WeakHashMap<>();
edgeAttributeRankings = new WeakHashMap<>();
nodeAttributePartitions = new WeakHashMap<>();
......@@ -123,8 +125,16 @@ public class AppearanceModelImpl implements AppearanceModel {
initAttributeRankingsAndPartitions();
}
protected Graph getGraph() {
if (localScale) {
protected Graph getRankingGraph() {
if (rankingLocalScale) {
return graphModel.getGraphVisible();
} else {
return graphModel.getGraph();
}
}
protected Graph getPartitionGraph() {
if (partitionLocalScale) {
return graphModel.getGraphVisible();
} else {
return graphModel.getGraph();
......@@ -223,12 +233,21 @@ public class AppearanceModelImpl implements AppearanceModel {
}
@Override
public boolean isLocalScale() {
return localScale;
public boolean isRankingLocalScale() {
return rankingLocalScale;
}
public void setRankingLocalScale(boolean localScale) {
this.rankingLocalScale = localScale;
}
@Override
public boolean isPartitionLocalScale() {
return partitionLocalScale;
}
public void setLocalScale(boolean localScale) {
this.localScale = localScale;
public void setPartitionLocalScale(boolean localScale) {
this.partitionLocalScale = localScale;
}
private List<FunctionImpl> getNodeRankingFunctions() {
......
......@@ -53,7 +53,8 @@ public class AppearanceModelPersistenceProvider implements WorkspaceXMLPersisten
protected void writeXML(XMLStreamWriter writer, AppearanceModelImpl model)
throws XMLStreamException {
writer.writeStartElement("localscale");
writer.writeAttribute("value", String.valueOf(model.isLocalScale()));
writer.writeAttribute("ranking", String.valueOf(model.isRankingLocalScale()));
writer.writeAttribute("partition", String.valueOf(model.isPartitionLocalScale()));
writer.writeEndElement();
//Rankings
......@@ -72,8 +73,10 @@ public class AppearanceModelPersistenceProvider implements WorkspaceXMLPersisten
if (eventType.equals(XMLEvent.START_ELEMENT)) {
String name = reader.getLocalName();
if ("localscale".equalsIgnoreCase(name)) {
String val = reader.getAttributeValue(null, "value");
model.setLocalScale(Boolean.parseBoolean(val));
String partition = reader.getAttributeValue(null, "partition");
String ranking = reader.getAttributeValue(null, "ranking");
model.setPartitionLocalScale(Boolean.parseBoolean(partition));
model.setRankingLocalScale(Boolean.parseBoolean(ranking));
} else if ("rankings".equalsIgnoreCase(name)) {
String elementClass = reader.getAttributeValue(null, "for");
readRankings(reader,
......@@ -170,19 +173,23 @@ public class AppearanceModelPersistenceProvider implements WorkspaceXMLPersisten
}
}
protected void readInterpolator(XMLStreamReader reader, RankingImpl ranking) throws XMLStreamException {
protected void readInterpolator(XMLStreamReader reader, RankingImpl ranking) {
String type = reader.getAttributeValue(null, "type");
Interpolator interpolator = null;
if (type.equals("log2")) {
interpolator = Interpolator.LOG2;
} else if (type.equals("linear")) {
interpolator = Interpolator.LINEAR;
} else if (type.equals("bezier")) {
float x1 = Float.parseFloat(reader.getAttributeValue(null, "x1"));
float y1 = Float.parseFloat(reader.getAttributeValue(null, "y1"));
float x2 = Float.parseFloat(reader.getAttributeValue(null, "x2"));
float y2 = Float.parseFloat(reader.getAttributeValue(null, "y2"));
interpolator = new Interpolator.BezierInterpolator(x1, y1, x2, y2);
switch (type) {
case "log2":
interpolator = Interpolator.LOG2;
break;
case "linear":
interpolator = Interpolator.LINEAR;
break;
case "bezier":
float x1 = Float.parseFloat(reader.getAttributeValue(null, "x1"));
float y1 = Float.parseFloat(reader.getAttributeValue(null, "y1"));
float x2 = Float.parseFloat(reader.getAttributeValue(null, "x2"));
float y2 = Float.parseFloat(reader.getAttributeValue(null, "y2"));
interpolator = new Interpolator.BezierInterpolator(x1, y1, x2, y2);
break;
}
if (interpolator != null) {
ranking.setInterpolator(interpolator);
......
......@@ -119,7 +119,7 @@ public class AttributePartitionImpl extends PartitionImpl {
@Override
public int getVersion(Graph graph) {
if (isValid(graph)) {
return getIndex(graph.getModel().getGraph()).getColumnIndex(column.get()).getVersion();
return getIndex(graph).getColumnIndex(column.get()).getVersion();
}
return 0;
}
......
......@@ -42,9 +42,12 @@
package org.gephi.appearance;
import java.lang.ref.WeakReference;
import org.gephi.graph.api.Column;
import org.gephi.graph.api.DirectedGraph;
import org.gephi.graph.api.Element;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.Index;
import org.gephi.graph.api.Node;
/**
......@@ -52,8 +55,11 @@ import org.gephi.graph.api.Node;
*/
public class DegreeRankingImpl extends RankingImpl {
public DegreeRankingImpl() {
protected final Column column;
public DegreeRankingImpl(Column degreeColumn) {
super();
this.column = degreeColumn;
}
@Override
......@@ -63,28 +69,16 @@ public class DegreeRankingImpl extends RankingImpl {
@Override
public Number getMinValue(Graph graph) {
if (graph.getNodeCount() > 0) {
int min = Integer.MAX_VALUE;
DirectedGraph directedGraph = (DirectedGraph) graph;
for (Node node : directedGraph.getNodes()) {
min = Math.min(directedGraph.getDegree(node), min);
}
return min;
}
return 0;
return getIndex(graph).getMinValue(column);
}
@Override
public Number getMaxValue(Graph graph) {
if (graph.getNodeCount() > 0) {
int max = Integer.MIN_VALUE;
DirectedGraph directedGraph = (DirectedGraph) graph;
for (Node node : directedGraph.getNodes()) {
max = Math.max(directedGraph.getDegree(node), max);
}
return max;
}
return 0;
return getIndex(graph).getMaxValue(column);
}
private Index<Node> getIndex(Graph graph) {
return graph.getModel().getNodeIndex(graph.getView());
}
@Override
......
......@@ -49,6 +49,7 @@ import org.gephi.graph.api.Column;
import org.gephi.graph.api.Edge;
import org.gephi.graph.api.Element;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.Index;
/**
* @author mbastian
......@@ -56,10 +57,12 @@ import org.gephi.graph.api.Graph;
public class EdgeTypePartitionImpl extends PartitionImpl {
private final Class valueType;
private final Column column;
public EdgeTypePartitionImpl(Class valueType) {
public EdgeTypePartitionImpl(Column column, Class valueType) {
super();
this.valueType = valueType;
this.column = column;
}
@Override
......@@ -82,24 +85,28 @@ public class EdgeTypePartitionImpl extends PartitionImpl {
@Override
public int count(Object value, Graph graph) {
return graph.getEdgeCount(graph.getModel().getEdgeType(value));
return getIndex(graph).count(column, value);
}
@Override
public float percentage(Object value, Graph graph) {
int count = count(value, graph);
return ((float) count) / graph.getEdgeCount();
Index<Edge> index = getIndex(graph);
int count = index.count(column, value);
return 100f * ((float) count / index.countElements(column));
}
@Override
public int size(Graph graph) {
int size = graph.getModel().getEdgeTypeCount();
return graph.getEdgeCount(0) == 0 ? size - 1 : size;
return getIndex(graph).countValues(column);
}
private Index<Edge> getIndex(Graph graph) {
return graph.getModel().getEdgeIndex(graph.getView());
}
@Override
public Column getColumn() {
return null;
return column;
}
@Override
......@@ -114,7 +121,9 @@ public class EdgeTypePartitionImpl extends PartitionImpl {
@Override
public int getVersion(Graph graph) {
// TODO
if (isValid(graph)) {
return getIndex(graph).getColumnIndex(column).getVersion();
}
return 0;
}
}
......@@ -42,6 +42,7 @@
package org.gephi.appearance;
import java.lang.ref.WeakReference;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import org.gephi.appearance.api.Function;
......@@ -67,8 +68,9 @@ public abstract class FunctionImpl implements Function {
protected final TransformerUI transformerUI;
protected final PartitionImpl partition;
protected final RankingImpl ranking;
// Version
protected final AtomicInteger version;
// Version
protected WeakReference<Graph> lastGraph;
protected FunctionImpl(AppearanceModelImpl model, String name, Class<? extends Element> elementClass, Column column,
Transformer transformer, TransformerUI transformerUI, PartitionImpl partition,
......@@ -88,7 +90,8 @@ public abstract class FunctionImpl implements Function {
this.transformerUI = transformerUI;
this.partition = partition;
this.ranking = ranking;
this.version = new AtomicInteger(Integer.MIN_VALUE);
this.version = new AtomicInteger(partition != null ? partition.getVersion(model.getPartitionGraph()) : Integer.MIN_VALUE);
this.lastGraph = partition != null ? new WeakReference<>(model.getPartitionGraph()) : null;
}
@Override
......@@ -128,13 +131,28 @@ public abstract class FunctionImpl implements Function {
}
public boolean hasChanged() {
if(isSimple()) {
return false;
} else {
Graph graph = model.getGraph();
int newVersion = isPartition() ? partition.getVersion(graph) : 0;
return version.getAndSet(newVersion) != newVersion;
if (isPartition()) {
Graph graph = model.getPartitionGraph();
// Check if view has changed
boolean viewChanged = false;
synchronized (this) {
if (lastGraph == null) {
lastGraph = new WeakReference<>(graph);
} else {
Graph lg = lastGraph.get();
lastGraph = null;
if (lg == null || lg != graph) {
viewChanged = true;
lastGraph = new WeakReference<>(graph);
}
}
}
int newVersion = partition.getVersion(graph);
return version.getAndSet(newVersion) != newVersion || viewChanged;
}
return false;
}
public boolean isValid() {
......@@ -148,7 +166,12 @@ public abstract class FunctionImpl implements Function {
@Override
public Graph getGraph() {
return model.getGraph();
if (isRanking()) {
return model.getRankingGraph();
} else if (isPartition()) {
return model.getPartitionGraph();
}
return model.getGraphModel().getGraph();
}
@Override
......
......@@ -42,6 +42,7 @@
package org.gephi.appearance;
import org.gephi.graph.api.Column;
import org.gephi.graph.api.DirectedGraph;
import org.gephi.graph.api.Element;
import org.gephi.graph.api.Graph;
......@@ -50,10 +51,10 @@ import org.gephi.graph.api.Node;
/**
* @author mbastian
*/
public class InDegreeRankingImpl extends RankingImpl {
public class InDegreeRankingImpl extends DegreeRankingImpl {
public InDegreeRankingImpl() {
super();
public InDegreeRankingImpl(Column degreeColumn) {
super(degreeColumn);
}
@Override
......@@ -61,32 +62,6 @@ public class InDegreeRankingImpl extends RankingImpl {
return ((DirectedGraph) gr).getInDegree((Node) element);
}
@Override
public Number getMinValue(Graph graph) {
if (graph.getNodeCount() > 0) {
int min = Integer.MAX_VALUE;
DirectedGraph directedGraph = (DirectedGraph) graph;
for (Node node : directedGraph.getNodes()) {
min = Math.min(directedGraph.getInDegree(node), min);
}
return min;
}
return 0;
}
@Override
public Number getMaxValue(Graph graph) {
if (graph.getNodeCount() > 0) {
int max = Integer.MIN_VALUE;
DirectedGraph directedGraph = (DirectedGraph) graph;
for (Node node : directedGraph.getNodes()) {
max = Math.max(directedGraph.getInDegree(node), max);
}
return max;
}
return 0;
}
@Override
public boolean isValid(Graph graph) {
return graph.isDirected();
......
......@@ -42,6 +42,7 @@
package org.gephi.appearance;
import org.gephi.graph.api.Column;
import org.gephi.graph.api.DirectedGraph;
import org.gephi.graph.api.Element;
import org.gephi.graph.api.Graph;
......@@ -50,10 +51,10 @@ import org.gephi.graph.api.Node;
/**
* @author mbastian
*/
public class OutDegreeRankingImpl extends RankingImpl {
public class OutDegreeRankingImpl extends DegreeRankingImpl {
public OutDegreeRankingImpl() {
super();
public OutDegreeRankingImpl(Column degreeColumn) {
super(degreeColumn);
}
@Override
......@@ -61,32 +62,6 @@ public class OutDegreeRankingImpl extends RankingImpl {
return ((DirectedGraph) gr).getOutDegree((Node) element);
}
@Override
public Number getMinValue(Graph graph) {
if (graph.getNodeCount() > 0) {
int min = Integer.MAX_VALUE;
DirectedGraph directedGraph = (DirectedGraph) graph;
for (Node node : directedGraph.getNodes()) {
min = Math.min(directedGraph.getOutDegree(node), min);
}
return min;
}
return 0;
}
@Override
public Number getMaxValue(Graph graph) {
if (graph.getNodeCount() > 0) {
int max = Integer.MIN_VALUE;
DirectedGraph directedGraph = (DirectedGraph) graph;
for (Node node : directedGraph.getNodes()) {
max = Math.max(directedGraph.getOutDegree(node), max);
}
return max;
}
return 0;
}
@Override
public boolean isValid(Graph graph) {
return graph.isDirected();
......
package org.gephi.appearance;
import org.gephi.graph.api.Column;
import org.gephi.graph.api.Edge;
import org.gephi.graph.api.Element;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.Index;
import org.gephi.graph.api.Interval;
import org.gephi.graph.api.Node;
import org.gephi.graph.api.TimeIndex;
public class TimesetRankingImpl extends RankingImpl {
protected enum Mode {MIN, MAX};
private final Class elementClass;
private final Mode mode;
public TimesetRankingImpl(Class elementClass, Mode mode) {
super();
this.elementClass = elementClass;
this.mode = mode;
}
@Override
public Number getValue(Element element, Graph graph) {
Interval timeBound = element.getTimeBounds();
if(timeBound != null) {
return mode.equals(Mode.MIN) ? timeBound.getLow() : timeBound.getHigh();
}
return null;
}
@Override
public Number getMinValue(Graph graph) {
return getIndex(graph).getMinTimestamp();
}
@Override
public Number getMaxValue(Graph graph) {
return getIndex(graph).getMaxTimestamp();
}
private TimeIndex getIndex(Graph graph) {
return elementClass.isAssignableFrom(Node.class) ? graph.getModel().getNodeTimeIndex(graph.getView()) : graph.getModel().getEdgeTimeIndex(graph.getView());
}
@Override
public boolean isValid(Graph graph) {
return graph.getModel().isDynamic();
}
}
\ No newline at end of file
......@@ -64,7 +64,17 @@ public interface AppearanceController {
* @param useLocalScale <code>true</code> for local, <code>false</code> for
* global
*/
void setUseLocalScale(boolean useLocalScale);
void setUseRankingLocalScale(boolean useLocalScale);
/**
* Sets whether partitions use a local or a global scale. When calculating the
* partitions it can use the complete graph or only the currently visible graph. When using the visible graph
* it is called the <b>local</b> scale.
*
* @param useLocalScale <code>true</code> for local, <code>false</code> for
* global
*/
void setUsePartitionLocalScale(boolean useLocalScale);
/**
* Apply the function's transformer. If the function is for nodes all nodes
......
......@@ -63,12 +63,22 @@ public interface AppearanceModel {
/**
* Returns <code>true</code> if rankings are using the currently visible
* graph as a scale. If <code>false</code> the complete graph is used to
* determine minimum and maximum values, the ranking scale.
* determine minimum and maximum values.
*
* @return <code>true</code> if using a local scale, <code>false</code> if
* global scale
*/
boolean isLocalScale();
boolean isRankingLocalScale();
/**
* Returns <code>true</code> if partitions are using the currently visible
* graph as a source. If <code>false</code> the complete graph is used to
* determine partitions.
*
* @return <code>true</code> if using a local scale, <code>false</code> if
* global scale
*/
boolean isPartitionLocalScale();
/**
* Returns the node partition for thid column.
......
......@@ -30,7 +30,7 @@ public class AppearanceControllerTest {
AppearanceControllerImpl controller = new AppearanceControllerImpl();
controller.setModel(new AppearanceModelImpl(generator.getWorkspace()));
Assert.assertFalse(controller.getModel().isLocalScale());
Assert.assertFalse(controller.getModel().isRankingLocalScale());
Node node = generator.getGraph().getNode(GraphGenerator.FIRST_NODE);
......@@ -105,7 +105,7 @@ public class AppearanceControllerTest {
controller.transform(rankingFunction);
Assert.assertEquals(0, (int) node1.size());
controller.setUseLocalScale(true);
controller.setUseRankingLocalScale(true);
controller.transform(rankingFunction);
Assert.assertEquals(1, (int) node1.size());
}
......
package org.gephi.appearance;
import java.util.Arrays;
import org.gephi.appearance.api.Function;
import org.gephi.appearance.api.Partition;
import org.gephi.appearance.api.Ranking;
import org.gephi.appearance.spi.PartitionTransformer;
......@@ -9,6 +11,7 @@ import org.gephi.appearance.spi.Transformer;
import org.gephi.graph.GraphGenerator;
import org.gephi.graph.api.Column;
import org.gephi.graph.api.Element;
import org.gephi.graph.api.GraphView;
import org.junit.Assert;
import org.junit.Test;
import org.netbeans.junit.MockServices;
......@@ -58,6 +61,24 @@ public class AppearanceModelTest {
Assert.assertEquals(0, model.countNodeAttributeRanking());
}
@Test
public void testHasChanged() {
MockServices.setServices(DummyTransformer.class);
GraphGenerator generator = GraphGenerator.build().withWorkspace().generateTinyGraph().addIntNodeColumn();
AppearanceModelImpl model = new AppearanceModelImpl(generator.getWorkspace());
Function function =
Arrays.stream(model.getNodeFunctions()).filter(f -> f.isPartition() && f.isAttribute()).findFirst().get();
Assert.assertFalse(function.hasChanged());
GraphView view = generator.getGraphModel().createView();
generator.getGraphModel().setVisibleView(view);
Assert.assertFalse(function.hasChanged());
model.setPartitionLocalScale(true);
Assert.assertTrue(function.hasChanged());
Assert.assertFalse(function.hasChanged());
}
public static class DummyTransformer implements Transformer, RankingTransformer, PartitionTransformer,
SimpleTransformer {
......
......@@ -119,4 +119,16 @@ public class AttributePartitionTest {
graph.removeNode(n1);
Assert.assertNotEquals(version, p.getVersion(graph));
}
// @Test
// public void testVersionDynamic() {
// Graph graph = GraphGenerator.build().generateTinyGraph().addTimestampDoubleColumn().getGraph();
// Column column = graph.getModel().getNodeTable().getColumn(GraphGenerator.TIMESTAMP_DOUBLE_COLUMN);
// Node n1 = graph.getNode(GraphGenerator.FIRST_NODE);
//
// AttributePartitionImpl p = new AttributePartitionImpl(column);
// int version = p.getVersion(graph);
// n1.setAttribute(column, 99.0, 2000);
// Assert.assertNotEquals(version, p.getVersion(graph));
// }
}
......@@ -2,6 +2,7 @@ package org.gephi.appearance;
import org.gephi.graph.GraphGenerator;
import org.gephi.graph.api.Column;
import org.gephi.graph.api.Estimator;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.Node;
import org.junit.Assert;
......@@ -53,4 +54,30 @@ public class AttributeRankingTest {
AttributeRankingImpl p = new AttributeRankingImpl(column);
Assert.assertTrue(p.isValid(graph));
}
@Test
public void testArrayColumnNotValid() {
Graph graph = GraphGenerator.build().generateTinyGraph().addFloatArrayNodeColumn().getGraph();
Column column = graph.getModel().getNodeTable().getColumn(GraphGenerator.FLOAT_ARRAY_COLUMN);
AttributeRankingImpl p = new AttributeRankingImpl(column);
Assert.assertFalse(p.isValid(graph));
}
@Test
public void testDynamicTimestampColumn() {
Graph graph = GraphGenerator.build().generateTinyGraph().addTimestampDoubleColumn().getGraph();
Column column = graph.getModel().getNodeTable().getColumn(GraphGenerator.TIMESTAMP_DOUBLE_COLUMN);
AttributeRankingImpl p = new AttributeRankingImpl(column);
Assert.assertTrue(p.isValid(graph));
Assert.assertEquals(GraphGenerator.TIMESTAMP_DOUBLE_COLUMN_VALUES[0][0], p.getMinValue(graph));
Assert.assertEquals(GraphGenerator.TIMESTAMP_DOUBLE_COLUMN_VALUES[1][0], p.getMaxValue(graph));
Node n1 = graph.getNode(GraphGenerator.FIRST_NODE);
Assert.assertEquals(GraphGenerator.TIMESTAMP_DOUBLE_COLUMN_VALUES[0][0], p.getValue(n1, graph));
}
}
......@@ -2,6 +2,7 @@ package org.gephi.appearance;
import org.gephi.appearance.api.Interpolator;
import org.gephi.graph.GraphGenerator;
import org.gephi.graph.api.Column;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.Node;
import org.junit.Assert;
......@@ -12,15 +13,19 @@ public class DegreeRankingTest {
@Test
public void testEmpty() {
Graph graph = GraphGenerator.build().getGraph();
DegreeRankingImpl degreeRanking = new DegreeRankingImpl();
Column col = graph.getModel().defaultColumns().degree();
DegreeRankingImpl degreeRanking = new DegreeRankingImpl(col);
Assert.assertEquals(0, degreeRanking.getMinValue(graph));
Assert.assertEquals(0, degreeRanking.getMaxValue(graph));
Assert.assertNull(degreeRanking.getMinValue(graph));
Assert.assertNull(degreeRanking.getMaxValue(graph));
}
@Test
public void testInterpolator() {
DegreeRankingImpl degreeRanking = new DegreeRankingImpl();
Graph graph = GraphGenerator.build().getGraph();
Column col = graph.getModel().defaultColumns().degree();
DegreeRankingImpl degreeRanking = new DegreeRankingImpl(col);
Assert.assertSame(Interpolator.LINEAR, degreeRanking.getInterpolator());
degreeRanking.setInterpolator(Interpolator.LOG2);
Assert.assertSame(Interpolator.LOG2, degreeRanking.getInterpolator());
......@@ -29,7 +34,8 @@ public class DegreeRankingTest {
@Test
public void testOneEdge() {
Graph graph = GraphGenerator.build().generateTinyGraph().getGraph();
DegreeRankingImpl degreeRanking = new DegreeRankingImpl();
Column col = graph.getModel().defaultColumns().degree();
DegreeRankingImpl degreeRanking = new DegreeRankingImpl(col);
Assert.assertEquals(1, degreeRanking.getMinValue(graph));
Assert.assertEquals(1, degreeRanking.getMaxValue(graph));
......@@ -42,7 +48,8 @@ public class DegreeRankingTest {
@Test
public void testNormalization() {
Graph graph = GraphGenerator.build().generateSmallRandomGraph().getGraph();
DegreeRankingImpl degreeRanking = new DegreeRankingImpl();
Column col = graph.getModel().defaultColumns().degree();
DegreeRankingImpl degreeRanking = new DegreeRankingImpl(col);
int minDegree = degreeRanking.getMinValue(graph).intValue();
int maxDegree = degreeRanking.getMaxValue(graph).intValue();
......
package org.gephi.appearance;
import org.gephi.graph.GraphGenerator;
import org.gephi.graph.api.Column;
import org.gephi.graph.api.Edge;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.Node;
import org.gephi.graph.impl.GraphStoreConfiguration;
import org.junit.Assert;
import org.junit.Test;
public class EdgeTypePartitionTest {
@Test
public void testEmpty() {
Graph graph = GraphGenerator.build().getGraph();
Column col = graph.getModel().defaultColumns().edgeType();
EdgeTypePartitionImpl typePartition = new EdgeTypePartitionImpl(col, GraphStoreConfiguration.DEFAULT_EDGE_LABEL_TYPE);
Assert.assertEquals(0, typePartition.getElementCount(graph));
Assert.assertEquals(0, typePartition.getValues(graph).size());
Assert.assertEquals(0, typePartition.getSortedValues(graph).size());
Assert.assertEquals(0, typePartition.size(graph));
}
@Test
public void testSimpleGraph() {
Graph graph = GraphGenerator.build().generateTinyGraph().getGraph();
Column col = graph.getModel().defaultColumns().edgeType();
EdgeTypePartitionImpl typePartition = new EdgeTypePartitionImpl(col, GraphStoreConfiguration.DEFAULT_EDGE_LABEL_TYPE);
Assert.assertEquals(1, typePartition.getElementCount(graph));
Assert.assertEquals(1, typePartition.getValues(graph).size());
Assert.assertEquals(1, typePartition.getSortedValues(graph).size());
Assert.assertEquals(1, typePartition.size(graph));
}
@Test
public void testMultiGraph() {
Graph graph = GraphGenerator.build().generateTinyMultiGraph().getGraph();
Column col = graph.getModel().defaultColumns().edgeType();
EdgeTypePartitionImpl typePartition = new EdgeTypePartitionImpl(col, GraphStoreConfiguration.DEFAULT_EDGE_LABEL_TYPE);
Assert.assertEquals(2, typePartition.getElementCount(graph));
Assert.assertEquals(2, typePartition.getValues(graph).size());
Assert.assertEquals(2, typePartition.getSortedValues(graph).size());
Assert.assertEquals(2, typePartition.size(graph));
}
@Test
public void testIsValid() {
Graph graph = GraphGenerator.build().generateTinyMultiGraph().getGraph();
Column col = graph.getModel().defaultColumns().edgeType();
EdgeTypePartitionImpl typePartition = new EdgeTypePartitionImpl(col, GraphStoreConfiguration.DEFAULT_EDGE_LABEL_TYPE);
Assert.assertTrue(typePartition.isValid(graph));
}
@Test
public void testIsNotValid() {
Graph graph = GraphGenerator.build().generateTinyGraph().getGraph();
Column col = graph.getModel().defaultColumns().edgeType();
EdgeTypePartitionImpl typePartition = new EdgeTypePartitionImpl(col, GraphStoreConfiguration.DEFAULT_EDGE_LABEL_TYPE);
Assert.assertFalse(typePartition.isValid(graph));
}
@Test
public void testVersion() {
Graph graph = GraphGenerator.build().generateTinyMultiGraph().getGraph();
Column col = graph.getModel().defaultColumns().edgeType();
EdgeTypePartitionImpl p = new EdgeTypePartitionImpl(col, GraphStoreConfiguration.DEFAULT_EDGE_LABEL_TYPE);
Edge e2 = graph.getEdge(GraphGenerator.SECOND_EDGE);
int version = p.getVersion(graph);
graph.removeEdge(e2);
Assert.assertNotEquals(version, version = p.getVersion(graph));
Assert.assertEquals(version, p.getVersion(graph));
}
}
......@@ -3,12 +3,6 @@ Unique.name = Unique
Attribute.ranking.name = Ranking
Attribute.partition.name = Partition
ColorTransformerUI.name = Color
SizeTransformerUI.name = Size
LabelColorTransformerUI.name = Label Color
LabelSizeTransformerUI.name = Label Size
RankingColorTransformerPanel.labelColor.text=Color:
RankingSizeTransformerPanel.labelMaxSize.text=Max size:
RankingSizeTransformerPanel.labelMinSize.text=Min size:
......
......@@ -106,7 +106,8 @@ public class AppearanceTopComponent extends TopComponent implements Lookup.Provi
private javax.swing.JPanel controlPanel;
private javax.swing.JToolBar controlToolbar;
private javax.swing.JToggleButton enableAutoButton;
private javax.swing.JToggleButton localScaleButton;
private javax.swing.JToggleButton rankingLocalScaleButton;
private javax.swing.JToggleButton partitionLocalScaleButton;
private javax.swing.JPanel mainPanel;
private org.jdesktop.swingx.JXHyperlink splineButton;
private javax.swing.JToggleButton stopAutoApplyButton;
......@@ -334,7 +335,8 @@ public class AppearanceTopComponent extends TopComponent implements Lookup.Provi
applyButton.setVisible(true);
applyButton.setEnabled(true);
}
localScaleButton.setSelected(model.isLocalScale());
rankingLocalScaleButton.setSelected(model.isRankingLocalScale());
partitionLocalScaleButton.setSelected(model.isPartitionLocalScale());
return;
}
//Disable
......@@ -349,16 +351,23 @@ public class AppearanceTopComponent extends TopComponent implements Lookup.Provi
private void initControls() {
//Add ranking controls
toolbar.addRankingControl(localScaleButton);
toolbar.addRankingControl(rankingLocalScaleButton);
toolbar.addRankingControl(splineButton);
//Add partition controls
// toolbar.addPartitionControl(localScaleButton);
toolbar.addPartitionControl(partitionLocalScaleButton);
//Actions
localScaleButton.addActionListener(new ActionListener() {
rankingLocalScaleButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
controller.getAppearanceController().setUseRankingLocalScale(rankingLocalScaleButton.isSelected());
}
});
partitionLocalScaleButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
controller.getAppearanceController().setUseLocalScale(localScaleButton.isSelected());
controller.getAppearanceController().setUsePartitionLocalScale(partitionLocalScaleButton.isSelected());
}
});
splineButton.addActionListener(new ActionListener() {
......@@ -496,7 +505,8 @@ public class AppearanceTopComponent extends TopComponent implements Lookup.Provi
attibuteBox = new javax.swing.JComboBox();
centerPanel = new javax.swing.JPanel();
controlToolbar = toolbar.getControlToolbar();
localScaleButton = new javax.swing.JToggleButton();
rankingLocalScaleButton = new javax.swing.JToggleButton();
partitionLocalScaleButton = new javax.swing.JToggleButton();
splineButton = new org.jdesktop.swingx.JXHyperlink();
controlPanel = new javax.swing.JPanel();
applyButton = new javax.swing.JButton();
......@@ -567,15 +577,25 @@ public class AppearanceTopComponent extends TopComponent implements Lookup.Provi
controlToolbar.setMargin(new java.awt.Insets(0, 4, 0, 0));
controlToolbar.setOpaque(true);
localScaleButton.setIcon(new javax.swing.ImageIcon(
rankingLocalScaleButton.setIcon(new javax.swing.ImageIcon(
getClass().getResource("/org/gephi/desktop/appearance/resources/funnel.png"))); // NOI18N
localScaleButton.setToolTipText(org.openide.util.NbBundle
rankingLocalScaleButton.setToolTipText(org.openide.util.NbBundle
.getMessage(AppearanceTopComponent.class, "AppearanceTopComponent.localScaleButton.toolTipText")); // NOI18N
localScaleButton.setFocusable(false);
localScaleButton
rankingLocalScaleButton.setFocusable(false);
rankingLocalScaleButton
.setSelectedIcon(new javax.swing.ImageIcon(UIUtils.generateSelectedDarkImage((new javax.swing.ImageIcon(
getClass().getResource("/org/gephi/desktop/appearance/resources/funnel.png")).getImage())))); // NOI18N
controlToolbar.add(rankingLocalScaleButton);
partitionLocalScaleButton.setIcon(new javax.swing.ImageIcon(
getClass().getResource("/org/gephi/desktop/appearance/resources/funnel.png"))); // NOI18N
partitionLocalScaleButton.setToolTipText(org.openide.util.NbBundle
.getMessage(AppearanceTopComponent.class, "AppearanceTopComponent.partitionLocalScaleButton.toolTipText")); // NOI18N
partitionLocalScaleButton.setFocusable(false);
partitionLocalScaleButton
.setSelectedIcon(new javax.swing.ImageIcon(UIUtils.generateSelectedDarkImage((new javax.swing.ImageIcon(
getClass().getResource("/org/gephi/desktop/appearance/resources/funnel.png")).getImage())))); // NOI18N
controlToolbar.add(localScaleButton);
controlToolbar.add(partitionLocalScaleButton);
org.openide.awt.Mnemonics.setLocalizedText(splineButton, org.openide.util.NbBundle
.getMessage(AppearanceTopComponent.class, "AppearanceTopComponent.splineButton.text")); // NOI18N
......
......@@ -134,8 +134,12 @@ public class AppearanceUIModel {
functionObserverExecutor.stop();
}
public boolean isLocalScale() {
return appearanceModel.isLocalScale();
public boolean isRankingLocalScale() {
return appearanceModel.isRankingLocalScale();
}
public boolean isPartitionLocalScale() {
return appearanceModel.isPartitionLocalScale();
}
public void saveTransformerProperties() {
......
......@@ -10,7 +10,7 @@ import org.openide.util.Lookup;
public class FunctionObserverExecutor implements Runnable {
private static final long DEFAULT_DELAY = 1000; //ms
private static final long DEFAULT_DELAY = 1500; //ms
private final AppearanceUIModel model;
private final AppearanceUIController controller;
private ScheduledExecutorService executor;
......
......@@ -6,21 +6,9 @@ CTL_AppearanceTopComponent=Appearance
AppearanceTopComponent.choose.text=---Choose an attribute
PartitionChooser.applyButton.text=Apply
AppearanceToolbar.nodes.label = Nodes
AppearanceToolbar.edges.label = Edges
PartitionChooser.groupLink.text=Group
PartitionChooser.group.label=Group
PartitionChooser.ungroup.label=Ungroup
PartitionChooser.groupLink.toolTipText=Group the partition, one group per part
PartitionChooser.pieLink.text=Show Pie
PartitionChooser.showpie.label=Show Pie
PartitionChooser.hidepie.label=Hide Pie
PartitionChooser.refreshBusyLabel.text=
PartitionChooser.refreshButton.text=
PartitionChooser.refreshButton.toolTipText=Refresh
AppearanceTopComponent.applyButton.text=Apply
AppearanceTopComponent.enableAutoButton.toolTipText=Enable auto transformation - applied continuously
AppearanceTopComponent.splineButton.toolTipText=Configure rank interpolation
......@@ -28,6 +16,7 @@ AppearanceTopComponent.splineButton.text=Spline...
AppearanceTopComponent.splineEditor.title=Interpolate
AppearanceTopComponent.applyButton.toolTipText=Apply the current transformation to the graph
AppearanceTopComponent.localScaleButton.toolTipText=\ Use local scale. The bounds are calculated only on the visible graph instead of the complete graph.
AppearanceTopComponent.partitionLocalScaleButton.toolTipText=\ Use visible graph instead of complete graph for partition calculations
AppearanceTopComponent.stopAutoApplyButton.toolTipText=Stop auto apply
AppearanceTopComponent.stopAutoApplyButton.text=Stop
AppearanceTopComponent.autoApplyButton.toolTipText=Apply continuously even when the values changes
......
......@@ -19,6 +19,7 @@ public class GraphGenerator {
public static final String INT_COLUMN = "age";
public static final String DOUBLE_COLUMN = "value";
public static final String FLOAT_ARRAY_COLUMN = "values";
public static final String STRING_COLUMN = "country";
public static final String TIMESTAMP_SET_COLUMN = "events";
public static final String INTERVAL_SET_COLUMN = "events";
......@@ -27,8 +28,11 @@ public class GraphGenerator {
public static final String FIRST_NODE = "1";
public static final String SECOND_NODE = "2";
public static final String FIRST_EDGE = "1";
public static final String SECOND_EDGE = "2";
public static final String[] STRING_COLUMN_VALUES = new String[] {"France", "Germany"};
public static final float[][] FLOAT_ARRAY_COLUMN_VALUES = new float[][] {{1f, 2f}, {4f, 3f}};
public static final int INT_COLUMN_MIN_VALUE = 10;
public static final double[][] TIMESTAMP_DOUBLE_COLUMN_VALUES = new double[][] {{3.0}, {6.0}};
private final GraphModel graphModel;
private Workspace workspace;
......@@ -73,6 +77,18 @@ public class GraphGenerator {
return this;
}
public GraphGenerator generateTinyMultiGraph() {
Node n1 = graphModel.factory().newNode(FIRST_NODE);
Node n2 = graphModel.factory().newNode(SECOND_NODE);
Edge e1 = graphModel.factory().newEdge(FIRST_EDGE, n1, n2, 0, 1.0, true);
Edge e2 = graphModel.factory().newEdge(SECOND_EDGE, n1, n2, 1, 1.0, true);
graphModel.getDirectedGraph().addNode(n1);
graphModel.getDirectedGraph().addNode(n2);
graphModel.getDirectedGraph().addEdge(e1);
graphModel.getDirectedGraph().addEdge(e2);
return this;
}
public GraphGenerator addIntNodeColumn() {
graphModel.getNodeTable().addColumn(INT_COLUMN, Integer.class);
int age = INT_COLUMN_MIN_VALUE;
......@@ -82,6 +98,15 @@ public class GraphGenerator {
return this;
}
public GraphGenerator addFloatArrayNodeColumn() {
graphModel.getNodeTable().addColumn(FLOAT_ARRAY_COLUMN, float[].class);
Node n1 = graphModel.getGraph().getNode(FIRST_NODE);
Node n2 = graphModel.getGraph().getNode(SECOND_NODE);
n1.setAttribute(FLOAT_ARRAY_COLUMN, FLOAT_ARRAY_COLUMN_VALUES[0]);
n2.setAttribute(FLOAT_ARRAY_COLUMN, FLOAT_ARRAY_COLUMN_VALUES[1]);
return this;
}
public GraphGenerator addDoubleNodeColumn() {
graphModel.getNodeTable().addColumn(DOUBLE_COLUMN, Double.class);
double val = 10;
......@@ -109,9 +134,10 @@ public class GraphGenerator {
public GraphGenerator addTimestampDoubleColumn() {
graphModel.getNodeTable().addColumn(TIMESTAMP_DOUBLE_COLUMN, TimestampDoubleMap.class);
int index = 0;
for (Node node : graphModel.getGraph().getNodes()) {
node.setAttribute(TIMESTAMP_DOUBLE_COLUMN, new TimestampDoubleMap(new double[] {2000},
new double[] {Math.random() * 100.0}));
TIMESTAMP_DOUBLE_COLUMN_VALUES[index++]));
}
return this;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册