提交 5f65af69 编写于 作者: E Eduardo Ramos

Progress in #1169

Integrate graphstore dynamics in data laboratory

Remove DynamicAPI and DynamicImpl modules
上级 88a8a8a9
......@@ -16,10 +16,6 @@
<name>AppearanceAPI</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>dynamic-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>graph-api</artifactId>
......
......@@ -24,10 +24,6 @@
<groupId>${project.groupId}</groupId>
<artifactId>graph-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>dynamic-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>core-library-wrapper</artifactId>
......
/*
Copyright 2008-2010 Gephi
Authors : Eduardo Ramos <eduramiba@gmail.com>
Website : http://www.gephi.org
This file is part of Gephi.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
Copyright 2008-2010 Gephi
Authors : Eduardo Ramos <eduramiba@gmail.com>
Website : http://www.gephi.org
This file is part of Gephi.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.datalab.plugin.manipulators.columns;
......@@ -55,8 +55,8 @@ import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
/**
* AttributeColumnsManipulator that deletes a Column of a AttributeTable.
* Only allows to delete columns with DATA AttributeOrigin.
* AttributeColumnsManipulator that deletes a Column of a AttributeTable. Only allows to delete columns with DATA AttributeOrigin.
*
* @author Eduardo Ramos
*/
@ServiceProvider(service = AttributeColumnsManipulator.class)
......@@ -86,7 +86,7 @@ public class DeleteColumn implements AttributeColumnsManipulator {
}
@Override
public AttributeColumnsManipulatorUI getUI(Table table,Column column) {
public AttributeColumnsManipulatorUI getUI(Table table, Column column) {
return null;
}
......
......@@ -51,7 +51,7 @@ import org.gephi.datalab.plugin.manipulators.columns.ConvertColumnToDynamic;
import org.gephi.datalab.spi.DialogControls;
import org.gephi.datalab.spi.columns.AttributeColumnsManipulator;
import org.gephi.datalab.spi.columns.AttributeColumnsManipulatorUI;
import org.gephi.dynamic.utils.DynamicUtilities;
import org.gephi.graph.api.AttributeUtils;
import org.gephi.ui.utils.ColumnTitleValidator;
import org.gephi.ui.utils.IntervalBoundValidator;
import org.netbeans.validation.api.ui.ValidationGroup;
......@@ -134,13 +134,9 @@ public class ConvertColumnToDynamicUI extends javax.swing.JPanel implements Attr
if (!validationPanel.isProblem()) {
manipulator.setTitle(titleTextField.getText());
try {
manipulator.setReplaceColumn(replaceColumn);
manipulator.setLow(DynamicUtilities.parseTime(intervalStart));
manipulator.setHigh(DynamicUtilities.parseTime(intervalEnd));
} catch (ParseException ex) {
Exceptions.printStackTrace(ex);
}
manipulator.setReplaceColumn(replaceColumn);
manipulator.setLow(AttributeUtils.parseDateTime(intervalStart));
manipulator.setHigh(AttributeUtils.parseDateTime(intervalEnd));
}
}
......
......@@ -18,14 +18,16 @@
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="1" max="-2" attributes="0">
<Component id="onlyVisibleCheckBox" alignment="0" max="32767" attributes="1"/>
<Component id="useSparklinesCheckBox" alignment="0" max="32767" attributes="1"/>
<Component id="showEdgesNodesLabelsCheckBox" alignment="0" max="32767" attributes="1"/>
<Component id="timeIntervalsGraphicsCheckBox" alignment="0" max="32767" attributes="1"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="onlyVisibleCheckBox" alignment="0" max="32767" attributes="1"/>
<Group type="102" alignment="0" attributes="0">
<Component id="timeFormatLabel" min="-2" pref="87" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="timeFormatComboBox" max="32767" attributes="0"/>
</Group>
<Component id="timeIntervalsAsDates" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="useSparklinesCheckBox" alignment="0" pref="324" max="32767" attributes="1"/>
<Component id="timeIntervalsGraphicsCheckBox" alignment="0" max="32767" attributes="1"/>
<Component id="showEdgesNodesLabelsCheckBox" alignment="0" max="32767" attributes="1"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
......@@ -36,15 +38,18 @@
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="32767" attributes="0"/>
<Component id="onlyVisibleCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="useSparklinesCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="timeIntervalsAsDates" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="useSparklinesCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="timeIntervalsGraphicsCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="showEdgesNodesLabelsCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="timeFormatLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="timeFormatComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
......@@ -90,15 +95,19 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="timeIntervalsGraphicsCheckBoxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="timeIntervalsAsDates">
<Component class="javax.swing.JComboBox" name="timeFormatComboBox">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="0"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="timeFormatLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/gephi/desktop/datalab/Bundle.properties" key="ConfigurationPanel.timeIntervalsAsDates.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/gephi/desktop/datalab/Bundle.properties" key="ConfigurationPanel.timeFormatLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="timeIntervalsAsDatesActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>
......@@ -41,6 +41,12 @@
*/
package org.gephi.desktop.datalab;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import org.gephi.graph.api.GraphModel;
import org.gephi.graph.api.TimeFormat;
import org.openide.util.NbBundle;
/**
* Configurations dialog for DataTableTopComponent
*
......@@ -49,20 +55,71 @@ package org.gephi.desktop.datalab;
public class ConfigurationPanel extends javax.swing.JPanel {
private final DataTableTopComponent dataTableTopComponent;
private final GraphModel graphModel;
/**
* Creates new form ConfigurationPanel
*/
public ConfigurationPanel(DataTableTopComponent dataTableTopComponent) {
public ConfigurationPanel(final DataTableTopComponent dataTableTopComponent, final GraphModel graphModel) {
this.dataTableTopComponent = dataTableTopComponent;
this.graphModel = graphModel;
initComponents();
for (TimeFormat tf : TimeFormat.values()) {
timeFormatComboBox.addItem(new TimeFormatWrapper(tf));
}
timeFormatComboBox.setSelectedItem(new TimeFormatWrapper(graphModel.getTimeFormat()));
timeFormatComboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
graphModel.setTimeFormat(((TimeFormatWrapper) timeFormatComboBox.getSelectedItem()).timeFormat);
dataTableTopComponent.refreshCurrentTable();
}
});
onlyVisibleCheckBox.setSelected(dataTableTopComponent.isShowOnlyVisible());
useSparklinesCheckBox.setSelected(dataTableTopComponent.isUseSparklines());
//TODO: adapt dynamics
// timeIntervalsAsDates.setSelected(dynamicController.getModel().getTimeFormat() != TimeFormat.DOUBLE);
timeIntervalsGraphicsCheckBox.setSelected(dataTableTopComponent.isTimeIntervalGraphics());
showEdgesNodesLabelsCheckBox.setSelected(dataTableTopComponent.isShowEdgesNodesLabels());
}
class TimeFormatWrapper {
private final TimeFormat timeFormat;
public TimeFormatWrapper(TimeFormat timeFormat) {
this.timeFormat = timeFormat;
}
@Override
public int hashCode() {
int hash = 3;
hash = 83 * hash + (this.timeFormat != null ? this.timeFormat.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final TimeFormatWrapper other = (TimeFormatWrapper) obj;
if (this.timeFormat != other.timeFormat) {
return false;
}
return true;
}
@Override
public String toString() {
return NbBundle.getMessage(ConfigurationPanel.class, "ConfigurationPanel.timeFormat." + timeFormat.name());
}
}
/**
* This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is always regenerated by the Form Editor.
......@@ -75,7 +132,8 @@ public class ConfigurationPanel extends javax.swing.JPanel {
useSparklinesCheckBox = new javax.swing.JCheckBox();
showEdgesNodesLabelsCheckBox = new javax.swing.JCheckBox();
timeIntervalsGraphicsCheckBox = new javax.swing.JCheckBox();
timeIntervalsAsDates = new javax.swing.JCheckBox();
timeFormatComboBox = new javax.swing.JComboBox();
timeFormatLabel = new javax.swing.JLabel();
onlyVisibleCheckBox.setText(org.openide.util.NbBundle.getMessage(ConfigurationPanel.class, "ConfigurationPanel.onlyVisibleCheckBox.text")); // NOI18N
onlyVisibleCheckBox.addActionListener(new java.awt.event.ActionListener() {
......@@ -105,12 +163,7 @@ public class ConfigurationPanel extends javax.swing.JPanel {
}
});
timeIntervalsAsDates.setText(org.openide.util.NbBundle.getMessage(ConfigurationPanel.class, "ConfigurationPanel.timeIntervalsAsDates.text")); // NOI18N
timeIntervalsAsDates.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
timeIntervalsAsDatesActionPerformed(evt);
}
});
timeFormatLabel.setText(org.openide.util.NbBundle.getMessage(ConfigurationPanel.class, "ConfigurationPanel.timeFormatLabel.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
......@@ -118,13 +171,15 @@ public class ConfigurationPanel extends javax.swing.JPanel {
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addComponent(onlyVisibleCheckBox, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(useSparklinesCheckBox, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(showEdgesNodesLabelsCheckBox, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(timeIntervalsGraphicsCheckBox, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(timeIntervalsAsDates))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(onlyVisibleCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(timeFormatLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 87, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(timeFormatComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(useSparklinesCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, 324, Short.MAX_VALUE)
.addComponent(timeIntervalsGraphicsCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(showEdgesNodesLabelsCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
layout.setVerticalGroup(
......@@ -132,14 +187,16 @@ public class ConfigurationPanel extends javax.swing.JPanel {
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(onlyVisibleCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(useSparklinesCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(timeIntervalsAsDates)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(useSparklinesCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(timeIntervalsGraphicsCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(showEdgesNodesLabelsCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(timeFormatLabel)
.addComponent(timeFormatComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
......@@ -160,15 +217,11 @@ public class ConfigurationPanel extends javax.swing.JPanel {
dataTableTopComponent.setShowEdgesNodesLabels(showEdgesNodesLabelsCheckBox.isSelected());
}//GEN-LAST:event_showEdgesNodesLabelsCheckBoxActionPerformed
private void timeIntervalsAsDatesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_timeIntervalsAsDatesActionPerformed
//TODO: adapt dynamics
// dynamicController.setTimeFormat(timeIntervalsAsDates.isSelected() ? TimeFormat.DATE : TimeFormat.DOUBLE);
dataTableTopComponent.refreshCurrentTable();
}//GEN-LAST:event_timeIntervalsAsDatesActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JCheckBox onlyVisibleCheckBox;
private javax.swing.JCheckBox showEdgesNodesLabelsCheckBox;
private javax.swing.JCheckBox timeIntervalsAsDates;
private javax.swing.JComboBox timeFormatComboBox;
private javax.swing.JLabel timeFormatLabel;
private javax.swing.JCheckBox timeIntervalsGraphicsCheckBox;
private javax.swing.JCheckBox useSparklinesCheckBox;
// End of variables declaration//GEN-END:variables
......
......@@ -219,10 +219,10 @@ public class DataTableTopComponent extends TopComponent implements AWTEventListe
nodeTable = new NodesDataTable();
edgeTable = new EdgesDataTable();
nodeTable.setUseSparklines(useSparklines);
nodeTable.setTimeIntervalGraphics(timeIntervalGraphics);
edgeTable.setUseSparklines(useSparklines);
edgeTable.setTimeIntervalGraphics(timeIntervalGraphics);
nodeTable.setDrawSparklines(useSparklines);
nodeTable.setDrawTimeIntervalGraphics(timeIntervalGraphics);
edgeTable.setDrawSparklines(useSparklines);
edgeTable.setDrawTimeIntervalGraphics(timeIntervalGraphics);
edgeTable.setShowEdgesNodesLabels(showEdgesNodesLabels);
//Init
......@@ -531,7 +531,7 @@ public class DataTableTopComponent extends TopComponent implements AWTEventListe
}
//Model
nodeTable.refreshModel(graph.getNodes().toArray(), cols, dataTablesModel);
nodeTable.refreshModel(graph.getNodes().toArray(), cols, graphModel, dataTablesModel);
refreshFilterColumns();
busylabel.setBusy(false);
......@@ -579,7 +579,7 @@ public class DataTableTopComponent extends TopComponent implements AWTEventListe
}
//Model
edgeTable.refreshModel(graph.getEdges().toArray(), cols, dataTablesModel);
edgeTable.refreshModel(graph.getEdges().toArray(), cols, graphModel, dataTablesModel);
refreshFilterColumns();
busylabel.setBusy(false);
......@@ -789,8 +789,8 @@ public class DataTableTopComponent extends TopComponent implements AWTEventListe
@Override
public void setUseSparklines(boolean useSparklines) {
this.useSparklines = useSparklines;
nodeTable.setUseSparklines(useSparklines);
edgeTable.setUseSparklines(useSparklines);
nodeTable.setDrawSparklines(useSparklines);
edgeTable.setDrawSparklines(useSparklines);
refreshCurrentTable();
}
......@@ -802,8 +802,8 @@ public class DataTableTopComponent extends TopComponent implements AWTEventListe
@Override
public void setTimeIntervalGraphics(boolean timeIntervalGraphics) {
this.timeIntervalGraphics = timeIntervalGraphics;
nodeTable.setTimeIntervalGraphics(timeIntervalGraphics);
edgeTable.setTimeIntervalGraphics(timeIntervalGraphics);
nodeTable.setDrawTimeIntervalGraphics(timeIntervalGraphics);
edgeTable.setDrawTimeIntervalGraphics(timeIntervalGraphics);
refreshCurrentTable();
}
......@@ -1469,7 +1469,7 @@ public class DataTableTopComponent extends TopComponent implements AWTEventListe
}//GEN-LAST:event_nodesButtonActionPerformed
private void configurationButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_configurationButtonActionPerformed
DialogDescriptor dd = new DialogDescriptor(new ConfigurationPanel(this), NbBundle.getMessage(DataTableTopComponent.class, "ConfigurationPanel.title"));
DialogDescriptor dd = new DialogDescriptor(new ConfigurationPanel(this, graphModel), NbBundle.getMessage(DataTableTopComponent.class, "ConfigurationPanel.title"));
dd.setOptions(new Object[]{DialogDescriptor.OK_OPTION});
DialogDisplayer.getDefault().notify(dd);
......
......@@ -53,9 +53,15 @@ import java.util.regex.PatternSyntaxException;
import javax.swing.RowFilter;
import org.gephi.graph.api.Column;
import org.gephi.datalab.api.AttributeColumnsController;
import org.gephi.desktop.datalab.tables.celleditors.CellEditorWithAttributeTypeParseValidator;
import org.gephi.desktop.datalab.tables.celleditors.AttributeTypesSupportCellEditor;
import org.gephi.desktop.datalab.utils.SparkLinesRenderer;
import org.gephi.desktop.datalab.utils.TimeIntervalsRenderer;
import org.gephi.graph.api.AttributeUtils;
import org.gephi.graph.api.Element;
import org.gephi.graph.api.GraphModel;
import org.gephi.graph.api.Interval;
import org.gephi.graph.api.TimeFormat;
import org.gephi.graph.api.types.IntervalSet;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.decorator.HighlighterFactory;
import org.openide.util.Lookup;
......@@ -67,64 +73,55 @@ import org.openide.util.Lookup;
*/
public abstract class AbstractElementsDataTable<T extends Element> {
protected boolean useSparklines = false;
protected boolean timeIntervalGraphics = false;
protected final JXTable table;
protected RowFilter rowFilter;
protected List<T> selectedElements;
protected final AttributeColumnsController attributeColumnsController;
protected boolean refreshingTable = false;
protected Column[] showingColumns = null;
protected ElementsDataTableModel<T> model;
// private TimeIntervalsRenderer timeIntervalsRenderer;
// private TimeIntervalCellEditor timeIntervalCellEditor;
// private TimeFormat currentTimeFormat;
// private SparkLinesRenderer sparkLinesRenderer;
protected final JXTable table;
protected RowFilter rowFilter;
protected List<T> selectedElements;
protected final AttributeColumnsController attributeColumnsController;
protected boolean refreshingTable = false;
protected Column[] showingColumns = null;
protected ElementsDataTableModel<T> model;
private final TimeIntervalsRenderer timeIntervalsRenderer;
private final List<AttributeTypesSupportCellEditor> cellEditors = new ArrayList<AttributeTypesSupportCellEditor>();
private final SparkLinesRenderer sparkLinesRenderer;
public AbstractElementsDataTable() {
attributeColumnsController = Lookup.getDefault().lookup(AttributeColumnsController.class);
table = new JXTable();
prepareCellEditors();
prepareRenderers();
table.setHighlighters(HighlighterFactory.createAlternateStriping());
table.setColumnControlVisible(false);
table.setSortable(true);
table.setAutoCreateRowSorter(true);
table.setRowFilter(rowFilter);
sparkLinesRenderer = new SparkLinesRenderer();
timeIntervalsRenderer = new TimeIntervalsRenderer();
prepareCellEditors();
prepareRenderers();
}
public abstract List<? extends ElementDataColumn<T>> getFakeDataColumns();
private void prepareCellEditors() {
for (Class<?> typeClass : AttributeUtils.getSupportedTypes()) {
if(AttributeUtils.isDynamicType(typeClass)){
table.setDefaultEditor(typeClass, new CellEditorWithAttributeTypeParseValidator(typeClass));
if (AttributeUtils.isDynamicType(typeClass)) {
AttributeTypesSupportCellEditor cellEditor = new AttributeTypesSupportCellEditor(typeClass);
cellEditors.add(cellEditor);
table.setDefaultEditor(typeClass, cellEditor);
}
}
}
private void prepareRenderers() {
//TODO: adapt dynamics
// DynamicModel dm = Lookup.getDefault().lookup(DynamicController.class).getModel();
// table.setDefaultRenderer(NumberList.class, sparkLinesRenderer = new SparkLinesRenderer());
// table.setDefaultRenderer(DynamicBigDecimal.class, new SparkLinesRenderer());
// table.setDefaultRenderer(DynamicBigInteger.class, new SparkLinesRenderer());
// table.setDefaultRenderer(DynamicByte.class, new SparkLinesRenderer());
// table.setDefaultRenderer(DynamicDouble.class, new SparkLinesRenderer());
// table.setDefaultRenderer(DynamicFloat.class, new SparkLinesRenderer());
// table.setDefaultRenderer(DynamicInteger.class, new SparkLinesRenderer());
// table.setDefaultRenderer(DynamicLong.class, new SparkLinesRenderer());
// table.setDefaultRenderer(DynamicShort.class, new SparkLinesRenderer());
// double min, max;
// if (dm != null) {
// min = dm.getMin();
// max = dm.getMax();
// } else {
// min = Double.NEGATIVE_INFINITY;
// max = Double.POSITIVE_INFINITY;
// }
// table.setDefaultRenderer(TimeInterval.class, timeIntervalsRenderer = new TimeIntervalsRenderer(min, max, timeIntervalGraphics));
for (Class<?> typeClass : AttributeUtils.getSupportedTypes()) {
boolean isDynamicNumber = AttributeUtils.isDynamicType(typeClass) && AttributeUtils.isNumberType(typeClass);
boolean isArrayNumber = Number[].class.isAssignableFrom(typeClass);
if (isDynamicNumber || isArrayNumber) {
table.setDefaultRenderer(typeClass, sparkLinesRenderer);
}
}
table.setDefaultRenderer(IntervalSet.class, timeIntervalsRenderer);
}
public JXTable getTable() {
......@@ -144,18 +141,27 @@ public abstract class AbstractElementsDataTable<T extends Element> {
return true;
}
public void refreshModel(T[] elements, Column[] cols, DataTablesModel dataTablesModel) {
public void refreshModel(T[] elements, Column[] cols, GraphModel graphModel, DataTablesModel dataTablesModel) {
showingColumns = cols;
//TODO: adapt dynamics
// DynamicModel dm = Lookup.getDefault().lookup(DynamicController.class).getModel();
// if (dm != null) {
// timeIntervalsRenderer.setMinMax(dm.getMin(), dm.getMax());
// currentTimeFormat = dm.getTimeFormat();
// timeIntervalsRenderer.setTimeFormat(currentTimeFormat);
// timeIntervalCellEditor.setTimeFormat(currentTimeFormat);
// sparkLinesRenderer.setTimeFormat(currentTimeFormat);
// }
// timeIntervalsRenderer.setDrawGraphics(timeIntervalGraphics);
Interval timeBounds = null;
try {
timeBounds = graphModel.getTimeBounds();
} catch (Exception e) {
//Current graphstore does not implement this for intervals... (TODO)
}
double min = timeBounds != null ? timeBounds.getLow() : Double.NEGATIVE_INFINITY;
double max = timeBounds != null ? timeBounds.getHigh() : Double.POSITIVE_INFINITY;
TimeFormat currentTimeFormat = graphModel.getTimeFormat();
sparkLinesRenderer.setTimeFormat(currentTimeFormat);
timeIntervalsRenderer.setTimeFormat(currentTimeFormat);
timeIntervalsRenderer.setMinMax(min, max);
for (AttributeTypesSupportCellEditor cellEditor : cellEditors) {
cellEditor.setTimeFormat(currentTimeFormat);
}
refreshingTable = true;
if (selectedElements == null) {
selectedElements = getElementsFromSelectedRows();
......@@ -182,21 +188,21 @@ public abstract class AbstractElementsDataTable<T extends Element> {
public boolean isRefreshingTable() {
return refreshingTable;
}
/**
*
* @param columnIndex View index, not model index
* @return
*
* @param columnIndex View index, not model index
* @return
*/
public Column getColumnAtIndex(int columnIndex){
public Column getColumnAtIndex(int columnIndex) {
int realColumnIndex = table.convertColumnIndexToModel(columnIndex) - getFakeDataColumns().size();//Get real attribute column index not counting fake columns.
if (realColumnIndex >= 0 && realColumnIndex < showingColumns.length) {
return showingColumns[realColumnIndex];
}else{
} else {
return null;
}
}
public void setElementsSelection(List<T> elements) {
this.selectedElements = elements;//Keep this selection request to be able to do it if the table is first refreshed later.
HashSet<T> elementsSet = new HashSet<T>();
......@@ -208,7 +214,7 @@ public abstract class AbstractElementsDataTable<T extends Element> {
}
}
}
public void setElementsSelection(T[] elements) {
setElementsSelection(Arrays.asList(elements));
}
......@@ -225,20 +231,20 @@ public abstract class AbstractElementsDataTable<T extends Element> {
return table.getRowCount() > 0;
}
public boolean isUseSparklines() {
return useSparklines;
public boolean isDrawSparklines() {
return sparkLinesRenderer.isDrawGraphics();
}
public void setUseSparklines(boolean useSparklines) {
this.useSparklines = useSparklines;
public void setDrawSparklines(boolean drawSparklines) {
sparkLinesRenderer.setDrawGraphics(drawSparklines);
}
public boolean isTimeIntervalGraphics() {
return timeIntervalGraphics;
public boolean isDrawTimeIntervalGraphics() {
return timeIntervalsRenderer.isDrawGraphics();
}
public void setTimeIntervalGraphics(boolean timeIntervalGraphics) {
this.timeIntervalGraphics = timeIntervalGraphics;
public void setDrawTimeIntervalGraphics(boolean drawTimeIntervalGraphics) {
timeIntervalsRenderer.setDrawGraphics(drawTimeIntervalGraphics);
}
public T getElementFromRow(int row) {
......@@ -248,11 +254,11 @@ public abstract class AbstractElementsDataTable<T extends Element> {
public List<T> getElementsFromSelectedRows() {
int[] selectedRows = table.getSelectedRows();
List<T> elements = new ArrayList<T>();
for (int i = 0; i < selectedRows.length; i++) {
elements.add(getElementFromRow(selectedRows[i]));
}
return elements;
}
}
......@@ -49,25 +49,41 @@ import javax.swing.JTextField;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import org.gephi.graph.api.AttributeUtils;
import org.gephi.graph.api.TimeFormat;
import org.gephi.graph.api.types.IntervalMap;
import org.gephi.graph.api.types.IntervalSet;
import org.gephi.graph.api.types.TimestampMap;
import org.gephi.graph.api.types.TimestampSet;
/**
*
* @author Eduardo Ramos<eduramiba@gmail.com>
*/
public class CellEditorWithAttributeTypeParseValidator extends DefaultCellEditor {
public class AttributeTypesSupportCellEditor extends DefaultCellEditor {
private static final Border RED_BORDER = new LineBorder(Color.red);
private final JTextField textField;
private final Border originalBorder;
private final Class<?> typeClass;
private final boolean isTimestampSetType;
private final boolean isTimestampMapType;
private final boolean isIntervalSetType;
private final boolean isIntervalMapType;
private TimeFormat timeFormat = TimeFormat.DOUBLE;
public CellEditorWithAttributeTypeParseValidator(Class<?> typeClass) {
public AttributeTypesSupportCellEditor(Class<?> typeClass) {
super(new JTextField());
this.typeClass = typeClass;
textField = new JTextField();
originalBorder = textField.getBorder();
isTimestampSetType = TimestampSet.class.isAssignableFrom(typeClass);
isTimestampMapType = TimestampMap.class.isAssignableFrom(typeClass);
isIntervalSetType = IntervalSet.class.isAssignableFrom(typeClass);
isIntervalMapType = IntervalMap.class.isAssignableFrom(typeClass);
}
@Override
......@@ -75,7 +91,6 @@ public class CellEditorWithAttributeTypeParseValidator extends DefaultCellEditor
String value = getCellEditorValue().toString();
if(!value.trim().isEmpty()){
try {
System.out.println(value);
AttributeUtils.parse(value, typeClass);
} catch (Exception e) {
textField.setBorder(RED_BORDER);
......@@ -95,14 +110,35 @@ public class CellEditorWithAttributeTypeParseValidator extends DefaultCellEditor
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
Object fieldValue = value;
if (null == fieldValue) {
fieldValue = "";
String valueStr;
if (value == null) {
valueStr = "";
}else{
if(isTimestampSetType){
valueStr = ((TimestampSet) value).toString(timeFormat);
}else if(isTimestampMapType){
valueStr = ((TimestampMap) value).toString(timeFormat);
}else if(isIntervalSetType){
valueStr = ((IntervalSet) value).toString(timeFormat);
}else if(isIntervalMapType){
valueStr = ((IntervalMap) value).toString(timeFormat);
}else{
valueStr = value.toString();
}
}
textField.setBorder(originalBorder);
textField.setEditable(true);
textField.setText(fieldValue.toString());
textField.setText(valueStr);
return textField;
}
public TimeFormat getTimeFormat() {
return timeFormat;
}
public void setTimeFormat(TimeFormat timeFormat) {
this.timeFormat = timeFormat;
}
}
///*
// Copyright 2008-2010 Gephi
// Authors : Eduardo Ramos
// Website : http://www.gephi.org
//
// This file is part of Gephi.
//
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
//
// Copyright 2011 Gephi Consortium. All rights reserved.
//
// The contents of this file are subject to the terms of either the GNU
// General Public License Version 3 only ("GPL") or the Common
// Development and Distribution License("CDDL") (collectively, the
// "License"). You may not use this file except in compliance with the
// License. You can obtain a copy of the License at
// http://gephi.org/about/legal/license-notice/
// or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
// specific language governing permissions and limitations under the
// License. When distributing the software, include this License Header
// Notice in each file and include the License files at
// /cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
// License Header, with the fields enclosed by brackets [] replaced by
// your own identifying information:
// "Portions Copyrighted [year] [name of copyright owner]"
//
// If you wish your version of this file to be governed by only the CDDL
// or only the GPL Version 3, indicate your decision by adding
// "[Contributor] elects to include this software in this distribution
// under the [CDDL or GPL Version 3] license." If you do not indicate a
// single choice of license, a recipient has the option to distribute
// your version of this file under either the CDDL, the GPL Version 3 or
// to extend the choice of license to its licensees as provided above.
// However, if you add GPL Version 3 code and therefore, elected the GPL
// Version 3 license, then the option applies only if the new code is
// made subject to such option by the copyright holder.
//
// Contributor(s):
//
// Portions Copyrighted 2011 Gephi Consortium.
// */
//package org.gephi.desktop.datalab.utils;
//
//import java.awt.Color;
//import java.awt.Component;
//import java.awt.image.BufferedImage;
//import java.util.ArrayList;
//import java.util.List;
//import javax.swing.ImageIcon;
//import javax.swing.JLabel;
//import javax.swing.JTable;
//import javax.swing.table.DefaultTableCellRenderer;
//import org.gephi.datalab.utils.TimeFormat;
//import org.gephi.utils.sparklines.SparklineGraph;
//import org.gephi.utils.sparklines.SparklineParameters;
//
///**
// * TableCellRenderer for drawing sparklines from cells that have a NumberList or DynamicNumber as their value.
// *
// * @author Eduardo Ramos
// */
//public class SparkLinesRenderer extends DefaultTableCellRenderer {
//
// private static final Color SELECTED_BACKGROUND = new Color(225, 255, 255);
// private static final Color UNSELECTED_BACKGROUND = Color.white;
// private TimeFormat timeFormat = TimeFormat.DOUBLE;
//
// @Override
// public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
// if (value == null) {
// //Render empty string when null
// return super.getTableCellRendererComponent(table, null, isSelected, hasFocus, row, column);
// }
//
// String stringRepresentation = null;
// Number[] xValues = null;
// Number[] yValues = null;
// if (value instanceof NumberList) {
// yValues = getNumberListNumbers((NumberList) value);
// stringRepresentation = value.toString();
// } else if (value instanceof DynamicType) {
// //Use the intervals start time as X values
// Number[][] values = getDynamicNumberNumbers((DynamicType) value);
// xValues = values[0];
// yValues = values[1];
// stringRepresentation = ((DynamicType) value).toString(timeFormat == TimeFormat.DOUBLE);
// } else {
// throw new IllegalArgumentException("Only number lists and dynamic numbers are supported for sparklines rendering");
// }
//
// //If there is less than 1 element, show as a String.
// if (yValues.length < 1) {
// return super.getTableCellRendererComponent(table, stringRepresentation, isSelected, hasFocus, row, column);
// }
//
// if (yValues.length == 1) {
// //SparklineGraph needs at least 2 values, duplicate the only one we have to get a sparkline with a single line showing that the value does not change over time
// xValues = null;
// yValues = new Number[]{yValues[0], yValues[0]};
// }
//
// JLabel label = new JLabel();
// Color background;
// if (isSelected) {
// background = SELECTED_BACKGROUND;
// } else {
// background = UNSELECTED_BACKGROUND;
// }
//
// //Note: Can't use interactive SparklineComponent because TableCellEditors don't receive mouse events.
// final SparklineParameters sparklineParameters = new SparklineParameters(table.getColumnModel().getColumn(column).getWidth() - 1, table.getRowHeight(row) - 1, Color.BLUE, background, Color.RED, Color.GREEN, null);
// final BufferedImage i = SparklineGraph.draw(xValues, yValues, sparklineParameters);
// label.setIcon(new ImageIcon(i));
// label.setToolTipText(stringRepresentation);//String representation as tooltip
//
// return label;
// }
//
// private Number[] getNumberListNumbers(NumberList numberList) {
// ArrayList<Number> numbers = new ArrayList<Number>();
// Number n;
// for (int i = 0; i < numberList.size(); i++) {
// n = (Number) numberList.getItem(i);
// if (n != null) {
// numbers.add(n);
// }
// }
// return numbers.toArray(new Number[0]);
// }
//
// private Number[][] getDynamicNumberNumbers(DynamicType dynamicNumber) {
// ArrayList<Number> xValues = new ArrayList<Number>();
// ArrayList<Number> yValues = new ArrayList<Number>();
// if (dynamicNumber == null) {
// return new Number[2][0];
// }
//
// List<Interval> intervals = dynamicNumber.getIntervals();
// Number n;
// for (Interval interval : intervals) {
// n = (Number) interval.getValue();
// if (n != null) {
// xValues.add(interval.getLow());
// yValues.add(n);
// }
// }
// return new Number[][]{xValues.toArray(new Number[0]), yValues.toArray(new Number[0])};
// }
//
// public TimeFormat getTimeFormat() {
// return timeFormat;
// }
//
// public void setTimeFormat(TimeFormat timeFormat) {
// this.timeFormat = timeFormat;
// }
//}
/*
Copyright 2008-2010 Gephi
Authors : Eduardo Ramos
Website : http://www.gephi.org
This file is part of Gephi.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.desktop.datalab.utils;
import java.awt.Color;
import java.awt.Component;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import org.gephi.graph.api.Interval;
import org.gephi.graph.api.TimeFormat;
import org.gephi.graph.api.types.IntervalMap;
import org.gephi.graph.api.types.TimestampMap;
import org.gephi.utils.sparklines.SparklineGraph;
import org.gephi.utils.sparklines.SparklineParameters;
/**
* TableCellRenderer for drawing sparklines from cells that have a NumberList or DynamicNumber as their value.
*
* @author Eduardo Ramos
*/
public class SparkLinesRenderer extends DefaultTableCellRenderer {
private static final Color SELECTED_BACKGROUND = new Color(225, 255, 255);
private static final Color UNSELECTED_BACKGROUND = Color.white;
private TimeFormat timeFormat = TimeFormat.DOUBLE;
private boolean drawGraphics = false;
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (value == null) {
//Render empty string when null
return super.getTableCellRendererComponent(table, null, isSelected, hasFocus, row, column);
}
String stringRepresentation = null;
if (value instanceof Number[]) {
stringRepresentation = Arrays.toString((Number[]) value);
} else if (value instanceof TimestampMap) {
stringRepresentation = ((TimestampMap) value).toString(timeFormat);
} else if (value instanceof IntervalMap) {
stringRepresentation = ((IntervalMap) value).toString(timeFormat);
}
if (drawGraphics) {
Number[] xValues = null;
Number[] yValues = null;
if (value instanceof Number[]) {
yValues = (Number[]) value;
} else if (value instanceof TimestampMap) {
//Use the intervals start time as X values
Number[][] values = getTimestampMapNumbers((TimestampMap) value);
xValues = values[0];
yValues = values[1];
} else if (value instanceof IntervalMap) {
//Use the intervals start time as X values
Number[][] values = getIntervalMapNumbers((IntervalMap) value);
xValues = values[0];
yValues = values[1];
} else {
throw new IllegalArgumentException("Only number lists and dynamic numbers are supported for sparklines rendering");
}
//If there is less than 1 element, show as a String.
if (yValues.length < 1) {
return super.getTableCellRendererComponent(table, stringRepresentation, isSelected, hasFocus, row, column);
}
if (yValues.length == 1) {
//SparklineGraph needs at least 2 values, duplicate the only one we have to get a sparkline with a single line showing that the value does not change over time
xValues = null;
yValues = new Number[]{yValues[0], yValues[0]};
}
JLabel label = new JLabel();
Color background;
if (isSelected) {
background = SELECTED_BACKGROUND;
} else {
background = UNSELECTED_BACKGROUND;
}
//Note: Can't use interactive SparklineComponent because TableCellEditors don't receive mouse events.
final SparklineParameters sparklineParameters = new SparklineParameters(table.getColumnModel().getColumn(column).getWidth() - 1, table.getRowHeight(row) - 1, Color.BLUE, background, Color.RED, Color.GREEN, null);
final BufferedImage i = SparklineGraph.draw(xValues, yValues, sparklineParameters);
label.setIcon(new ImageIcon(i));
label.setToolTipText(stringRepresentation);//String representation as tooltip
return label;
} else {
return super.getTableCellRendererComponent(table, stringRepresentation, isSelected, hasFocus, row, column);
}
}
private Number[][] getTimestampMapNumbers(TimestampMap timestampMap) {
Double[] timestamps = timestampMap.toKeysArray();
Number[] values = (Number[]) timestampMap.toValuesArray();
return new Number[][]{timestamps, values};
}
private Number[][] getIntervalMapNumbers(IntervalMap intervalMap) {
ArrayList<Number> xValues = new ArrayList<Number>();
ArrayList<Number> yValues = new ArrayList<Number>();
if (intervalMap == null) {
return new Number[2][0];
}
Interval[] intervals = intervalMap.toKeysArray();
Object[] values = intervalMap.toValuesArray();
Number n;
for (int i = 0; i < intervals.length; i++) {
n = (Number) values[i];
if (n != null) {
xValues.add(intervals[i].getLow());
yValues.add(n);
}
}
return new Number[][]{xValues.toArray(new Number[0]), yValues.toArray(new Number[0])};
}
public TimeFormat getTimeFormat() {
return timeFormat;
}
public void setTimeFormat(TimeFormat timeFormat) {
this.timeFormat = timeFormat;
}
public boolean isDrawGraphics() {
return drawGraphics;
}
public void setDrawGraphics(boolean drawGraphics) {
this.drawGraphics = drawGraphics;
}
}
///*
// Copyright 2008-2010 Gephi
// Authors : Eduardo Ramos
// Website : http://www.gephi.org
//
// This file is part of Gephi.
//
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
//
// Copyright 2011 Gephi Consortium. All rights reserved.
//
// The contents of this file are subject to the terms of either the GNU
// General Public License Version 3 only ("GPL") or the Common
// Development and Distribution License("CDDL") (collectively, the
// "License"). You may not use this file except in compliance with the
// License. You can obtain a copy of the License at
// http://gephi.org/about/legal/license-notice/
// or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
// specific language governing permissions and limitations under the
// License. When distributing the software, include this License Header
// Notice in each file and include the License files at
// /cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
// License Header, with the fields enclosed by brackets [] replaced by
// your own identifying information:
// "Portions Copyrighted [year] [name of copyright owner]"
//
// If you wish your version of this file to be governed by only the CDDL
// or only the GPL Version 3, indicate your decision by adding
// "[Contributor] elects to include this software in this distribution
// under the [CDDL or GPL Version 3] license." If you do not indicate a
// single choice of license, a recipient has the option to distribute
// your version of this file under either the CDDL, the GPL Version 3 or
// to extend the choice of license to its licensees as provided above.
// However, if you add GPL Version 3 code and therefore, elected the GPL
// Version 3 license, then the option applies only if the new code is
// made subject to such option by the copyright holder.
//
// Contributor(s):
//
// Portions Copyrighted 2011 Gephi Consortium.
// */
//package org.gephi.desktop.datalab.utils;
//
//import java.awt.Color;
//import java.awt.Component;
//import java.awt.image.BufferedImage;
//import java.util.List;
//import javax.swing.ImageIcon;
//import javax.swing.JLabel;
//import javax.swing.JTable;
//import javax.swing.table.DefaultTableCellRenderer;
//import org.gephi.attribute.time.TimestampSet;
//import org.gephi.datalab.utils.TimeFormat;
//import org.gephi.utils.TimeIntervalGraphics;
//
///**
// * TableCellRenderer for drawing time intervals graphics from cells that have a TimeInterval as their value.
// *
// * @author Eduardo Ramos
// */
//public class TimeIntervalsRenderer extends DefaultTableCellRenderer {
//
// private static final Color SELECTED_BACKGROUND = new Color(225, 255, 255);
// private static final Color UNSELECTED_BACKGROUND = Color.white;
// private static final Color FILL_COLOR = new Color(153, 255, 255);
// private static final Color BORDER_COLOR = new Color(2, 104, 255);
// private boolean drawGraphics;
// private TimeIntervalGraphics timeIntervalGraphics;
// private TimeFormat timeFormat = TimeFormat.DOUBLE;
//
// public TimeIntervalsRenderer(double min, double max, boolean drawGraphics) {
// timeIntervalGraphics = new TimeIntervalGraphics(min, max);
// this.drawGraphics = drawGraphics;
// }
//
// @Override
// public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
// if (value == null) {
// //Render empty string when null
// return super.getTableCellRendererComponent(table, null, isSelected, hasFocus, row, column);
// }
// TimestampSet timeInterval = (TimestampSet) value;
// String stringRepresentation = timeInterval.toString();//TODO
// if (drawGraphics) {
// JLabel label = new JLabel();
// Color background;
// if (isSelected) {
// background = SELECTED_BACKGROUND;
// } else {
// background = UNSELECTED_BACKGROUND;
// }
//
// int[] timestampsIndexes = timeInterval.getTimestamps();
// double starts[] = new double[timestampsIndexes.size()];
// double ends[] = new double[timestampsIndexes.size()];
// for (int i = 0; i < timestampsIndexes.size(); i++) {
// starts[i] = timestampsIndexes.get(i).getLow();
// ends[i] = timestampsIndexes.get(i).getHigh();
// }
//
// final BufferedImage i = timeIntervalGraphics.createTimeIntervalImage(starts, ends, table.getColumnModel().getColumn(column).getWidth() - 1, table.getRowHeight(row) - 1, FILL_COLOR, BORDER_COLOR, background);
// label.setIcon(new ImageIcon(i));
// label.setToolTipText(stringRepresentation);//String representation as tooltip
// return label;
// } else {
// return super.getTableCellRendererComponent(table, stringRepresentation, isSelected, hasFocus, row, column);
// }
// }
//
// public boolean isDrawGraphics() {
// return drawGraphics;
// }
//
// public void setDrawGraphics(boolean drawGraphics) {
// this.drawGraphics = drawGraphics;
// }
//
// public TimeFormat getTimeFormat() {
// return timeFormat;
// }
//
// public void setTimeFormat(TimeFormat timeFormat) {
// this.timeFormat = timeFormat;
// }
//
// public double getMax() {
// return timeIntervalGraphics.getMax();
// }
//
// public void setMax(double max) {
// timeIntervalGraphics.setMax(max);
// }
//
// public double getMin() {
// return timeIntervalGraphics.getMin();
// }
//
// public void setMin(double min) {
// timeIntervalGraphics.setMin(min);
// }
//
// public void setMinMax(double min, double max) {
// timeIntervalGraphics = new TimeIntervalGraphics(min, max);
// }
//}
/*
Copyright 2008-2010 Gephi
Authors : Eduardo Ramos
Website : http://www.gephi.org
This file is part of Gephi.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.desktop.datalab.utils;
import java.awt.Color;
import java.awt.Component;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import org.gephi.graph.api.TimeFormat;
import org.gephi.graph.api.types.IntervalSet;
import org.gephi.utils.TimeIntervalGraphics;
/**
* TableCellRenderer for drawing time intervals graphics from cells that have a IntervalSet as their value.
*
* @author Eduardo Ramos
*/
public class TimeIntervalsRenderer extends DefaultTableCellRenderer {
private static final Color SELECTED_BACKGROUND = new Color(225, 255, 255);
private static final Color UNSELECTED_BACKGROUND = Color.white;
private static final Color FILL_COLOR = new Color(153, 255, 255);
private static final Color BORDER_COLOR = new Color(2, 104, 255);
private boolean drawGraphics = false;
private final TimeIntervalGraphics timeIntervalGraphics;
private TimeFormat timeFormat = TimeFormat.DOUBLE;
public TimeIntervalsRenderer() {
this(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
}
public TimeIntervalsRenderer(double min, double max) {
timeIntervalGraphics = new TimeIntervalGraphics(min, max);
}
public TimeIntervalsRenderer(double min, double max, boolean drawGraphics) {
timeIntervalGraphics = new TimeIntervalGraphics(min, max);
this.drawGraphics = drawGraphics;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (value == null) {
//Render empty string when null
return super.getTableCellRendererComponent(table, null, isSelected, hasFocus, row, column);
}
IntervalSet intervalSet = (IntervalSet) value;
String stringRepresentation = intervalSet.toString(timeFormat);
if (drawGraphics) {
JLabel label = new JLabel();
Color background;
if (isSelected) {
background = SELECTED_BACKGROUND;
} else {
background = UNSELECTED_BACKGROUND;
}
double[] intervals = intervalSet.getIntervals();
double starts[] = new double[intervals.length / 2];
double ends[] = new double[intervals.length / 2];
for (int i = 0; i < intervals.length; i+=2) {
starts[i] = intervals[i];
ends[i] = intervals[i + 1];
}
final BufferedImage i = timeIntervalGraphics.createTimeIntervalImage(starts, ends, table.getColumnModel().getColumn(column).getWidth() - 1, table.getRowHeight(row) - 1, FILL_COLOR, BORDER_COLOR, background);
label.setIcon(new ImageIcon(i));
label.setToolTipText(stringRepresentation);//String representation as tooltip
return label;
} else {
return super.getTableCellRendererComponent(table, stringRepresentation, isSelected, hasFocus, row, column);
}
}
public boolean isDrawGraphics() {
return drawGraphics;
}
public void setDrawGraphics(boolean drawGraphics) {
this.drawGraphics = drawGraphics;
}
public TimeFormat getTimeFormat() {
return timeFormat;
}
public void setTimeFormat(TimeFormat timeFormat) {
this.timeFormat = timeFormat;
}
public double getMax() {
return timeIntervalGraphics.getMax();
}
public void setMax(double max) {
timeIntervalGraphics.setMax(max);
}
public double getMin() {
return timeIntervalGraphics.getMin();
}
public void setMin(double min) {
timeIntervalGraphics.setMin(min);
}
public void setMinMax(double min, double max) {
timeIntervalGraphics.setMin(min);
timeIntervalGraphics.setMax(max);
}
}
......@@ -40,9 +40,12 @@ DataTableTopComponent.availableColumnsButton.toolTipText=Configure displayed col
AvailableColumnsPanel.title=Display settings
AvailableColumnsPanel.descriptionLabel.text=Choose the columns to display:
AvailableColumnsPanel.maximum-available-columns.info=Maximum number of columns reached
ConfigurationPanel.timeIntervalsAsDates.text=Time intervals as dates
TableCSVExporter.dialog.success=Table exported with success
TableCSVExporter.dialog.error=An error happened when writing the file. Make sure the file is not in use and you have permissions
TableCSVExporter.dialog.error.title=Error
TableCSVExporter.filechooser.csvDescription=CSV
\ No newline at end of file
TableCSVExporter.filechooser.csvDescription=CSV
ConfigurationPanel.timeFormatLabel.text=Time format
ConfigurationPanel.timeFormat.DOUBLE=Double
ConfigurationPanel.timeFormat.DATE=Date
ConfigurationPanel.timeFormat.DATETIME=Date and time
......@@ -75,13 +75,3 @@ AvailableColumnsPanel.title=Nastaven\u00ed zobrazen\u00ed
AvailableColumnsPanel.descriptionLabel.text=Zvolte sloupce zobrazen\u00ed\:
AvailableColumnsPanel.maximum-available-columns.info=Dosa\u017eeno maxim\u00e1ln\u00edho po\u010dtu sloupc\u016f
ConfigurationPanel.timeIntervalsAsDates.text=\u010casov\u00e9 intervaly jako data
!TableCSVExporter.dialog.success=
!TableCSVExporter.dialog.error=
!TableCSVExporter.dialog.error.title=
!TableCSVExporter.filechooser.csvDescription=
......@@ -78,8 +78,6 @@ AvailableColumnsPanel.descriptionLabel.text=Escoge las columnas que deber\u00eda
AvailableColumnsPanel.maximum-available-columns.info=N\u00famero m\u00e1ximo de columnas disponibles alcanzado
ConfigurationPanel.timeIntervalsAsDates.text=Intervalos temporales como fechas
TableCSVExporter.dialog.success=Tabla exportada con \u00e9xito
TableCSVExporter.dialog.error=Un error ocurri\u00f3 mientras al escribir el fichero. Aseg\u00farate de que el archivo no est\u00e1 en uso y tienes los permisos necesarios
......
......@@ -76,13 +76,3 @@ AvailableColumnsPanel.title=Param\u00e8tres des colonnes disponibles
AvailableColumnsPanel.descriptionLabel.text=Choisir les colonnes disponibles \:
AvailableColumnsPanel.maximum-available-columns.info=Nombre maximum de colonnes atteint
ConfigurationPanel.timeIntervalsAsDates.text=Intervalles temporelles comme dates
!TableCSVExporter.dialog.success=
!TableCSVExporter.dialog.error=
!TableCSVExporter.dialog.error.title=
!TableCSVExporter.filechooser.csvDescription=
......@@ -75,13 +75,3 @@ AvailableColumnsPanel.title=\u30c7\u30a3\u30b9\u30d7\u30ec\u30a4\u306e\u8a2d\u5b
AvailableColumnsPanel.descriptionLabel.text=\u8868\u793a\u3059\u308b\u5217\u3092\u9078\u629e\:
AvailableColumnsPanel.maximum-available-columns.info=\u5217\u306e\u6700\u5927\u6570\u306b\u9054\u3057\u307e\u3057\u305f\u3002
ConfigurationPanel.timeIntervalsAsDates.text=\u65e5\u4ed8\u3068\u3057\u3066\u306e\u6642\u9593\u9593\u9694
!TableCSVExporter.dialog.success=
!TableCSVExporter.dialog.error=
!TableCSVExporter.dialog.error.title=
!TableCSVExporter.filechooser.csvDescription=
......@@ -75,13 +75,3 @@ AvailableColumnsPanel.title=Configura\u00e7\u00f5es de exibi\u00e7\u00e3o
AvailableColumnsPanel.descriptionLabel.text=Escolha as colunas para exibir\:
AvailableColumnsPanel.maximum-available-columns.info=N\u00famero m\u00e1ximo de colunas dispon\u00edveis alcan\u00e7ado
ConfigurationPanel.timeIntervalsAsDates.text=Intervalos de tempo como datas
!TableCSVExporter.dialog.success=
!TableCSVExporter.dialog.error=
!TableCSVExporter.dialog.error.title=
!TableCSVExporter.filechooser.csvDescription=
......@@ -76,13 +76,3 @@ AvailableColumnsPanel.title=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0
AvailableColumnsPanel.descriptionLabel.text=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0442\u043e\u043b\u0431\u0446\u044b \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f
AvailableColumnsPanel.maximum-available-columns.info=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432 \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0443\u0442\u043e
ConfigurationPanel.timeIntervalsAsDates.text=\u0412\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u044b
!TableCSVExporter.dialog.success=
!TableCSVExporter.dialog.error=
!TableCSVExporter.dialog.error.title=
!TableCSVExporter.filechooser.csvDescription=
......@@ -74,13 +74,3 @@ AvailableColumnsPanel.title=\u663e\u793a\u8bbe\u7f6e
AvailableColumnsPanel.descriptionLabel.text=\u9009\u62e9\u73b0\u5b9e\u7684\u5217\uff1a
AvailableColumnsPanel.maximum-available-columns.info=\u5217\u7684\u6700\u5927\u503c
ConfigurationPanel.timeIntervalsAsDates.text=\u65f6\u95f4\u95f4\u9694\u4e3adates
!TableCSVExporter.dialog.success=
!TableCSVExporter.dialog.error=
!TableCSVExporter.dialog.error.title=
!TableCSVExporter.filechooser.csvDescription=
......@@ -20,10 +20,6 @@
<groupId>${project.groupId}</groupId>
<artifactId>graph-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>dynamic-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>lib.validation</artifactId>
......
......@@ -50,8 +50,6 @@ import java.util.concurrent.TimeUnit;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JPanel;
import org.gephi.dynamic.api.DynamicController;
import org.gephi.dynamic.api.DynamicModel;
import org.gephi.graph.api.GraphController;
import org.gephi.graph.api.GraphModel;
import org.gephi.graph.api.Interval;
......@@ -170,15 +168,16 @@ public class DynamicSettingsPanel extends javax.swing.JPanel {
}
public void unsetup(DynamicStatistics dynamicStatistics) {
DynamicController dynamicController = Lookup.getDefault().lookup(DynamicController.class);
DynamicModel model = dynamicController.getModel();
GraphController graphController = Lookup.getDefault().lookup(GraphController.class);
GraphModel graphModel = graphController.getGraphModel();
TimeFormat timeFormat = graphModel.getTimeFormat();
//Bounds is the same
dynamicStatistics.setBounds(bounds);
//Window
double window = 0.;
if (model.getTimeFormat().equals(DynamicModel.TimeFormat.DOUBLE)) {
double window;
if (timeFormat == TimeFormat.DOUBLE) {
window = Double.parseDouble(windowTextField.getText());
} else {
TimeUnit timeUnit = getSelectedTimeUnit(windowTimeUnitCombo.getModel());
......@@ -187,8 +186,8 @@ public class DynamicSettingsPanel extends javax.swing.JPanel {
dynamicStatistics.setWindow(window);
//Tick
double tick = 0.;
if (model.getTimeFormat().equals(DynamicModel.TimeFormat.DOUBLE)) {
double tick;
if (timeFormat == TimeFormat.DOUBLE) {
tick = Double.parseDouble(tickTextField.getText());
} else {
TimeUnit timeUnit = getSelectedTimeUnit(tickTimeUnitCombo.getModel());
......@@ -197,15 +196,17 @@ public class DynamicSettingsPanel extends javax.swing.JPanel {
dynamicStatistics.setTick(tick);
//Save latest selected item
if (!model.getTimeFormat().equals(DynamicModel.TimeFormat.DOUBLE)) {
if (timeFormat != TimeFormat.DOUBLE) {
saveDefaultTimeUnits();
}
}
public void createValidation(ValidationGroup group) {
DynamicController dynamicController = Lookup.getDefault().lookup(DynamicController.class);
DynamicModel model = dynamicController.getModel();
if (model.getTimeFormat().equals(DynamicModel.TimeFormat.DOUBLE)) {
GraphController graphController = Lookup.getDefault().lookup(GraphController.class);
GraphModel graphModel = graphController.getGraphModel();
TimeFormat timeFormat = graphModel.getTimeFormat();
if (timeFormat == TimeFormat.DOUBLE) {
group.add(windowTextField, Validators.REQUIRE_NON_EMPTY_STRING,
Validators.numberRange(Double.MIN_VALUE, (bounds.getHigh() - bounds.getLow())));
group.add(tickTextField, Validators.REQUIRE_NON_EMPTY_STRING,
......@@ -218,7 +219,7 @@ public class DynamicSettingsPanel extends javax.swing.JPanel {
group.add(tickTextField, Validators.REQUIRE_NON_EMPTY_STRING,
new PositiveNumberValidator(),
new DateRangeValidator(tickTimeUnitCombo.getModel()),
new TickUnderWindowValidator(!model.getTimeFormat().equals(DynamicModel.TimeFormat.DOUBLE)));
new TickUnderWindowValidator(timeFormat != TimeFormat.DOUBLE));
}
}
private final String DAYS = NbBundle.getMessage(DynamicSettingsPanel.class, "DynamicSettingsPanel.TimeUnit.DAYS");
......
......@@ -28,10 +28,6 @@
<groupId>${project.groupId}</groupId>
<artifactId>desktop-perspective</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>dynamic-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>lib.validation</artifactId>
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>gephi-parent</artifactId>
<groupId>org.gephi</groupId>
<version>0.9-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent>
<groupId>org.gephi</groupId>
<artifactId>dynamic-api</artifactId>
<version>0.9-SNAPSHOT</version>
<packaging>nbm</packaging>
<name>DynamicAPI</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>project-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>graph-api</artifactId>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-openide-util</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>nbm-maven-plugin</artifactId>
<configuration>
<publicPackages>
<publicPackage>org.gephi.dynamic</publicPackage>
<publicPackage>org.gephi.dynamic.api</publicPackage>
<publicPackage>org.gephi.dynamic.utils</publicPackage>
</publicPackages>
</configuration>
</plugin>
</plugins>
</build>
</project>
/*
* Copyright 2008-2010 Gephi
* Authors : Cezary Bartosiak
* Mathieu Bastian <mathieu.bastian@gephi.org>
* Website : http://www.gephi.org
*
* This file is part of Gephi.
*
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.dynamic.api;
import org.gephi.project.api.Workspace;
/**
* This controller maintains the dynamic models, one per {@code Workspace}. <p>
* It is a service and can therefore be found in Lookup:
* <pre>
* DynamicController dc = Lookup.getDefault().lookup(DynamicController.class);
* </pre>
*
* @author Cezary Bartosiak
* @author Mathieu Bastian
*/
public interface DynamicController {
/**
* Returns the dynamic model for the current workspace, or {@code null} if
* the project is empty.
*
* @return the current dynamic model.
*/
public DynamicModel getModel();
/**
* Returns the dynamic model for the given {@code workspace}.
*
* @param workspace the workspace that dynamic model is to be returned
*
* @return the {@code workspace}'s dynamic model.
*/
public DynamicModel getModel(Workspace workspace);
/**
* Sets the time interval wrapped by the {@code DynamicGraph} of the current
* workspace.
*
* @param interval an object to get endpoints from
*/
// public void setVisibleInterval(TimeInterval interval);
/**
* Sets the time interval wrapped by the {@code DynamicGraph} of the current
* workspace.
*
* @param low the left endpoint
* @param high the right endpoint
*/
public void setVisibleInterval(double low, double high);
/**
* Sets the current time format. This should be done when the model is
* inited.
*
* @param timeFormat the time format that is to be set as current
*/
public void setTimeFormat(DynamicModel.TimeFormat timeFormat);
/**
* Sets the current time format. This is done on the model provided by the
* workspace.
*
* @param timeFormat the time format that is to be set as current
* @param workspace the workspace to get the model
*/
public void setTimeFormat(DynamicModel.TimeFormat timeFormat, Workspace workspace);
/**
* Sets the current
* <code>ESTIMATOR</code> used to get values from
* {@link org.gephi.data.attributes.type.DynamicType}. Default is
* <b><code>Estimator.FIRST</code></b>.
*
* @param estimator the estimator that is to be set
*/
// public void setEstimator(Estimator estimator);
/**
* Sets the current
* <code>ESTIMATOR</code> used to get values from
* {@link org.gephi.data.attributes.type.DynamicType}. Default is
* <b><code>Estimator.FIRST</code></b>.
*
* @param estimator the estimator that is to be set
* @param workspace the workspace to get the model
*/
// public void setEstimator(Estimator estimator, Workspace workspace);
/**
* Sets the current number
* <code>ESTIMATOR</code> used to get values from
* {@link org.gephi.data.attributes.type.DynamicType}. Default is
* <b><code>Estimator.AVERAGE</code></b>.
*
* @param estimator the number estimator that is to be set
*/
// public void setNumberEstimator(Estimator estimator);
/**
* Sets the current number
* <code>ESTIMATOR</code> used to get values from
* {@link org.gephi.data.attributes.type.DynamicType}. Default is
* <b><code>Estimator.AVERAGE</code></b>.
*
* @param estimator the number estimator that is to be set
* @param workspace the workspace to get the model
*/
// public void setNumberEstimator(Estimator estimator, Workspace workspace);
/**
* Adds
* <code>listener</code> to the listeners of this model. It receives events
* when model is changed.
*
* @param listener the listener that is to be added
*/
public void addModelListener(DynamicModelListener listener);
/**
* Removes
* <code>listener</code> to the listeners of this model.
*
* @param listener the listener that is to be removed
*/
public void removeModelListener(DynamicModelListener listener);
}
/*
* Copyright 2008-2010 Gephi
* Authors : Cezary Bartosiak
* Mathieu Bastian <mathieu.bastian@gephi.org>
* Website : http://www.gephi.org
*
* This file is part of Gephi.
*
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.dynamic.api;
import org.gephi.graph.api.Graph;
/**
* Model that maintains the dynamic states of the application, which include the
* minimum and the maximum bounds, as well as the current visible interval.
* <p>
* The min and the max are used to know what are the limits of the time in the
* current data. The visible interval is typically configured by a timeline
* component to select a range of time. The model also maintains what is the
* current time format, either
* <code>DOUBLE</code> or
* <code>DATE</code>. Internally, all times are double, but it can be converted
* to dates for user display. In addition the model stores the current
* estimators used to compute dynamic values.
* <p>
* The model is listening to graph and attributes events to track all intervals
* and deduce minimum and maximum. It thows
* <code>MIN_CHANGED</code> or
* <code>MAX_CHANGED</code> events when these values are changed.
* <p>
* The model can also build {@link DynamicGraph} objets on demand. These objects
* can work independently to states of this model.
*
* @author Cezary Bartosiak
* @author Mathieu Bastian
*
* @see DynamicController
*/
public interface DynamicModel {
/**
* The name of the column containing time intervals.
*/
public static final String TIMEINTERVAL_COLUMN = "time_interval";
/**
* The way the time is represented, either a simple real value (DOUBLE), a
* unix timestamp, a date or a datetime.
*/
public enum TimeFormat {
DATE, DATETIME, DOUBLE, TIMESTAMP
};
/**
* Builds a new {@code DynamicGraph} from the given {@code Graph} instance.
*
* @param graph the underlying graph
*
* @return a new a new {@code DynamicGraph}.
*/
public DynamicGraph createDynamicGraph(Graph graph);
/**
* Builds a new {@code DynamicGraph} from the given {@code Graph} instance
* wrapping the given {@code Interval}.
*
* @param graph the underlying graph
* @param interval the interval to filter the graph
*
* @return a new a new {@code DynamicGraph}.
*/
// public DynamicGraph createDynamicGraph(Graph graph, Interval interval);
/**
* Returns the time interval wrapped by the {@code DynamicGraph} of the
* current workspace.
*
* @return the time interval wrapped by the {@code DynamicGraph} of the
* current workspace.
*/
// public TimeInterval getVisibleInterval();
/**
* Returns the minimum of the time intervals defined in elements (i.e. nodes
* and edges) in the current workspace. This minimum is updated when data
* change and excludes
* <code>Double.NEGATIVE_INFINITY</code>.
*
* @return the minimum time in the current workspace
*/
public double getMin();
/**
* Returns the maximum of the time intervals defined in elements (i.e. nodes
* and edges) in the current workspace. This maximum is updated when data
* change and excludes
* <code>Double.POSITIVE_INFINITY</code>.
*
* @return the maximum time in the current workspace
*/
public double getMax();
/**
* Gets the current time format for this model. Though all time values are
* stored in double numbers, the time format inform how this values should
* be converted to display to users.
*
* @return the current time format
*/
public TimeFormat getTimeFormat();
/**
* Returns the current
* <code>ESTIMATOR</code>, used to get values from {@link DynamicType}.
* Default is <b><code>Estimator.FIRST</code></b>.
* <p>
* See the {@link #getNumberEstimator()} method for number types.
*
* @return the current estimator
*/
// public Estimator getEstimator();
/**
* Returns the current number
* <code>ESTIMATOR</code>, used to get values from number
* {@link DynamicType}, like {@link DynamicInteger}. Default is
* <b><code>Estimator.AVERAGE</code></b>.
* <p>
* See the {@link #getEstimator()} method for non-number types.
*
* @return the current number estimator
*/
// public Estimator getNumberEstimator();
/**
* Returns
* <code>true</code> if the graph in the current workspace is dynamic, i.e.
* when the graph has either dynamic topology, attributes or both.
*
* @return <code>true</code> if the graph is dynamic, <code>false</code>
* otherwise
*/
public boolean isDynamicGraph();
/**
* Returns
* <code>true</code> if the graph in the current workspace has dynamic
* nodes. In other words if nodes are added or removed dynamically.
*
* @return <code>true</code> if the graph has dynamic nodes
*/
public boolean hasDynamicNodes();
/**
* Returns
* <code>true</code> if the graph in the current workspace has dynamic
* edges. In other words if edges are added or removed dynamically.
*
* @return <code>true</code> if the graph has dynamic edges
*/
public boolean hasDynamicEdges();
}
/*
* Copyright 2008-2010 Gephi
* Authors : Cezary Bartosiak
* Mathieu Bastian <mathieu.bastian@gephi.org>
* Website : http://www.gephi.org
*
* This file is part of Gephi.
*
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.dynamic.api;
/**
* Event from the dynamic model.
* <ul>
* <li><b>VISIBLE_INTERVAL:</b> The visible interval set by the timeline has changed</li>
* <li><b>MIN_CHANGED:</b> The minimum bound in time has changed</li>
* <li><b>MAX_CHANGED:</b> The maximum bound in time has changed</li>
* </ul>
* @author Cezary Bartosiak
* @author Mathieu Bastian
*/
public final class DynamicModelEvent {
/**
* Event from the dynamic model.
* <p>
* The visible interval is a <code>TimeInterval</code> object. For min and
* max changed, data are <code>Double</code> objects.
* <ul>
* <li><b>VISIBLE_INTERVAL:</b> The visible interval set by the timeline has changed</li>
* <li><b>MIN_CHANGED:</b> The minimum bound in time has changed</li>
* <li><b>MAX_CHANGED:</b> The maximum bound in time has changed</li>
* <li><b>IS_DYNAMIC_GRAPH:</b> The graph is now a dynamic graph</li>
* </ul>
*/
public enum EventType {
VISIBLE_INTERVAL, MIN_CHANGED, MAX_CHANGED, IS_DYNAMIC_GRAPH, TIME_FORMAT
};
private final EventType type;
private final DynamicModel source;
private final Object data;
public DynamicModelEvent(EventType type, DynamicModel source, Object data) {
this.type = type;
this.source = source;
this.data = data;
}
public EventType getEventType() {
return type;
}
public DynamicModel getSource() {
return source;
}
public Object getData() {
return data;
}
}
/*
* Copyright 2008-2010 Gephi
* Authors : Cezary Bartosiak
* Mathieu Bastian <mathieu.bastian@gephi.org>
* Website : http://www.gephi.org
*
* This file is part of Gephi.
*
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.dynamic.api;
import java.util.EventListener;
/**
* Listener for the dynamicModel.
*
* @author Cezary Bartosiak
* @author Mathieu Bastian
* @see DynamicModelEvent
*/
public interface DynamicModelListener extends EventListener {
public void dynamicModelChanged(DynamicModelEvent event);
}
/*
Copyright 2008-2012 Gephi
Authors : Martin Škurla <bujacik@gmail.com>, Mathieu Bastian <mathieu.bastian@gephi.org>, Eduardo Ramos<eduramiba@gmail.com>
Website : http://www.gephi.org
This file is part of Gephi.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.dynamic.utils;
import java.io.IOException;
import java.io.StringReader;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import org.gephi.graph.api.AttributeUtils;
import org.gephi.graph.api.Interval;
/**
* <p>
* Class for parsing dynamic types with several intervals.
* </p>
*
* <p>
* Examples of valid dynamic intervals are:
* <ul>
* <li>&lt;(1, 2, v1); [3, 5, v2]&gt;</li>
* <li>[1,2]</li>
* <li>[1,2] (5,6)</li>
* <li>[1,2]; [1.15,2.21, 'literal value " \' ,[]()']</li>
* <li>&lt;[1,2]; [1.15,2.21, "literal value \" ' ,[]()"]&gt;</li>
* </ul>
* </p>
*
* <p>
* The most correct examples are those that include &lt; &gt; and proper commas and semicolons for separation, but the parser will be permissive when possible.</p>
* <p>
* Gephi will always format intervals in the correct way.</p>
*
* <p>
* See https://gephi.org/users/supported-graph-formats/spreadsheet for more examples</p>
*
* @author Eduardo Ramos
*/
public final class DynamicIntervalsParser {
private static final char LOPEN = '(';
private static final char LCLOSE = '[';
private static final char ROPEN = ')';
private static final char RCLOSE = ']';
private static final char COMMA = ',';
/**
* Parses a dynamic type with one or more intervals (without values, only start and end)
*
* @param input Input string to parse
* @return List of parsed intervals, or null if the input equals '&lt;empty&gt;'
* @throws IOException Thrown if error while reading input
* @throws ParseException Thronw if the intervals could not be parsed
*/
public static List<Interval> parseIntervals(String input) throws IOException, ParseException, IllegalArgumentException {
List<IntervalWithValue<Object>> intervals = parseIntervals(null, input);
List<Interval> result = new ArrayList<Interval>();
for (IntervalWithValue<Object> interval : intervals) {
result.add(interval.getInterval());
}
return result;
}
/**
* Parses a dynamic type with one or more intervals, with associated values
*
* @param <T>
* @param clazz Simple type for the result intervals values
* @param input Input string to parse
* @return List of parsed intervals, or null if the input equals '&lt;empty&gt;'
* @throws IOException Thrown if error while reading input
* @throws ParseException Thronw if the intervals could not be parsed
*/
public static <T> List<IntervalWithValue<T>> parseIntervalsWithValues(Class<T> clazz, String input) throws IOException, ParseException, IllegalArgumentException {
return parseIntervals(clazz, input);
}
/**
* Parses intervals with values (of <code>type</code> Class) or without values (null <code>type</code> Class)
* @param <T> Type of the interval value
* @param type Class of the intervals' values or null to parse intervals without values
* @param input Input to parse
* @return List of Interval
*/
public static <T> List<IntervalWithValue<T>> parseIntervals(Class<T> type, String input) throws IOException, ParseException, IllegalArgumentException {
if (input.equalsIgnoreCase("<empty>")) {
return null;
}
List<IntervalWithValue<T>> intervals = new ArrayList<IntervalWithValue<T>>();
StringReader reader = new StringReader(input + ' ');//Add 1 space so reader.skip function always works when necessary (end of string not reached).
int r;
char c;
while ((r = reader.read()) != -1) {
c = (char) r;
switch (c) {
case LCLOSE:
case LOPEN:
intervals.add(parseInterval(type, reader, c == LOPEN));
break;
default:
//Ignore other chars outside of intervals
}
}
if (intervals.isEmpty()) {
throw new IllegalArgumentException("No dynamic intervals could be parsed");
}
return intervals;
}
private static <T> IntervalWithValue<T> parseInterval(Class<T> type, StringReader reader, boolean lopen) throws IOException, ParseException {
ArrayList<String> values = new ArrayList<String>();
boolean ropen = true;
int r;
char c;
while ((r = reader.read()) != -1) {
c = (char) r;
switch (c) {
case RCLOSE:
ropen = false;
case ROPEN:
return buildInterval(type, values, lopen, ropen);
case ' ':
case '\t':
case '\r':
case '\n':
case COMMA:
//Ignore leading whitespace or similar until a value or literal starts:
break;
case '"':
case '\'':
values.add(parseLiteral(reader, c));
break;
default:
reader.skip(-1);//Go backwards 1 position, for reading start of value
values.add(parseValue(reader));
}
}
return buildInterval(type, values, lopen, ropen);
}
/**
* Parse literal value until detecting the end of it (quote can be ' or ")
*
* @param reader Input reader
* @param quote Quote mode that started this literal (' or ")
* @return Parsed value
* @throws IOException
*/
private static String parseLiteral(StringReader reader, char quote) throws IOException {
StringBuilder sb = new StringBuilder();
boolean escapeEnabled = false;
int r;
char c;
while ((r = reader.read()) != -1) {
c = (char) r;
if (c == quote) {
if (escapeEnabled) {
sb.append(quote);
escapeEnabled = false;
} else {
return sb.toString();
}
} else {
switch (c) {
case '\\':
if (escapeEnabled) {
sb.append('\\');
escapeEnabled = false;
} else {
escapeEnabled = true;
}
break;
default:
if (escapeEnabled) {
escapeEnabled = false;
}
sb.append(c);
}
}
}
return sb.toString();
}
/**
* Parses a value until end is detected either by a comma or an interval closing character.
*
* @param reader Input reader
* @return Parsed value
* @throws IOException
*/
private static String parseValue(StringReader reader) throws IOException {
StringBuilder sb = new StringBuilder();
int r;
char c;
while ((r = reader.read()) != -1) {
c = (char) r;
switch (c) {
case ROPEN:
case RCLOSE:
reader.skip(-1);//Go backwards 1 position, for detecting end of interval
case COMMA:
return sb.toString().trim();
default:
sb.append(c);
}
}
return sb.toString().trim();
}
private static <T> IntervalWithValue<T> buildInterval(Class<T> type, ArrayList<String> values, boolean lopen, boolean ropen) throws ParseException {
double low, high;
low = DynamicUtilities.parseTime(values.get(0));
high = DynamicUtilities.parseTime(values.get(1));
if (type == null) {
return new IntervalWithValue(low, high, null);
} else {
Object value = null;
if (values.size() == 3) {
//Interval with value:
String valString = values.get(2);
if (type.equals(Byte.class)
|| type.equals(Short.class)
|| type.equals(Integer.class)
|| type.equals(Long.class)
|| type.equals(BigInteger.class)
) {
valString = DynamicUtilities.removeDecimalDigitsFromString(valString);
} else if (type.equals(Float.class)
|| type.equals(Double.class)
|| type.equals(BigDecimal.class)
) {
valString = DynamicUtilities.infinityIgnoreCase(valString);
}
value = AttributeUtils.parse(valString, type);
}
return new IntervalWithValue(low, high, value);
}
}
}
package org.gephi.dynamic.utils;
import org.gephi.graph.api.Interval;
/**
* Represents an Interval with an associated value for it
* @author Eduardo Ramos
* @param <T> Type of the value
*/
public class IntervalWithValue<T> implements Comparable<IntervalWithValue<T>> {
private final Interval interval;
private final T value;
public IntervalWithValue(double low, double high, T value) {
this.interval = new Interval(low, high);
this.value = value;
}
public IntervalWithValue(Interval interval, T value) {
this.interval = interval;
this.value = value;
}
public Interval getInterval() {
return interval;
}
public T getValue(){
return value;
}
@Override
public int compareTo(IntervalWithValue<T> other) {
return this.interval.compareTo(other.interval);
}
public double getLow() {
return interval.getLow();
}
public double getHigh() {
return interval.getHigh();
}
@Override
public int hashCode() {
int hash = 5;
hash = 59 * hash + (this.interval != null ? this.interval.hashCode() : 0);
hash = 59 * hash + (this.value != null ? this.value.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final IntervalWithValue<?> other = (IntervalWithValue<?>) obj;
if (this.interval != other.interval && (this.interval == null || !this.interval.equals(other.interval))) {
return false;
}
if (this.value != other.value && (this.value == null || !this.value.equals(other.value))) {
return false;
}
return true;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
sb.append(interval.getLow());
sb.append(", ");
sb.append(interval.getHigh());
if (value != null) {
sb.append(", ");
String stringValue = value.toString();
if (containsSpecialCharacters(stringValue) || stringValue.trim().isEmpty()) {
sb.append('"');
sb.append(stringValue.replace("\\", "\\\\").replace("\"", "\\\""));
sb.append('"');
} else {
sb.append(stringValue);
}
}
sb.append(']');
return sb.toString();
}
private static final char[] SPECIAL_CHARACTERS = ";,()[]\"'".toCharArray();
/**
* @param value String value
* @return True if the string contains special characters for dynamic intervals syntax
*/
public static boolean containsSpecialCharacters(String value) {
for (char c : SPECIAL_CHARACTERS) {
if (value.indexOf(c) != -1) {
return true;
}
}
return false;
}
}
Manifest-Version: 1.0
AutoUpdate-Essential-Module: true
OpenIDE-Module-Localizing-Bundle: org/gephi/dynamic/api/Bundle.properties
OpenIDE-Module-Specification-Version: ${gephi.modules.specification.version}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<nbm>
<!--
<moduleType>autoload</moduleType>
<codeNameBase>org.gephi.dynamic.api/1</codeNameBase>
<licenseName>Apache License, Version 2.0</licenseName>
<licenseFile>license.txt</licenseFile>
-->
</nbm>
OpenIDE-Module-Display-Category=Gephi Core
OpenIDE-Module-Long-Description=\
Provide features for dynamic graphs
OpenIDE-Module-Name=Dynamic API
OpenIDE-Module-Short-Description=Provide features for dynamic graphs
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
# Zbyn\u011bk Schwarz <zbynek.schwarz@gmail.com>, 2012.
!=Project-Id-Version\: Gephi\nReport-Msgid-Bugs-To\: https\://github.com/gephi/gephi/issues\nPOT-Creation-Date\: 2011-08-05 14\:52+0200\nPO-Revision-Date\: 2012-02-23 09\:51+0000\nLast-Translator\: Zbyn\u011bk Schwarz <zbynek.schwarz@gmail.com>\nLanguage-Team\: Czech (http\://www.transifex.com/projects/p/gephi/language/cs/)\nMIME-Version\: 1.0\nContent-Type\: text/plain; charset\=UTF-8\nContent-Transfer-Encoding\: 8bit\nLanguage\: cs\nPlural-Forms\: nplurals\=3; plural\=(n\=\=1) ? 0 \: (n>\=2 && n<\=4) ? 1 \: 2;\n
OpenIDE-Module-Long-Description=Poskytuje funkce pro dynamick\u00e9 grafy
OpenIDE-Module-Short-Description=Poskytuje funkce pro dynamick\u00e9 grafy
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
!=Project-Id-Version\: Gephi\nReport-Msgid-Bugs-To\: https\://github.com/gephi/gephi/issues\nPOT-Creation-Date\: 2011-08-05 14\:52+0200\nPO-Revision-Date\: 2011-08-04 23\:06+0000\nLast-Translator\: gephi <sebastien.heymann@gmail.com>\nLanguage-Team\: Spanish (http\://www.transifex.com/projects/p/gephi/language/es/)\nMIME-Version\: 1.0\nContent-Type\: text/plain; charset\=UTF-8\nContent-Transfer-Encoding\: 8bit\nLanguage\: es\nPlural-Forms\: nplurals\=2; plural\=(n \!\= 1);\n
OpenIDE-Module-Long-Description=Proporciona caracter\u00edsticas para grafos din\u00e1micos
OpenIDE-Module-Short-Description=Proporciona caracter\u00edsticas para grafos din\u00e1micos
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
!=Project-Id-Version\: Gephi\nReport-Msgid-Bugs-To\: https\://github.com/gephi/gephi/issues\nPOT-Creation-Date\: 2011-08-05 14\:52+0200\nPO-Revision-Date\: 2011-08-04 23\:06+0000\nLast-Translator\: gephi <sebastien.heymann@gmail.com>\nLanguage-Team\: French (http\://www.transifex.com/projects/p/gephi/language/fr/)\nMIME-Version\: 1.0\nContent-Type\: text/plain; charset\=UTF-8\nContent-Transfer-Encoding\: 8bit\nLanguage\: fr\nPlural-Forms\: nplurals\=2; plural\=(n > 1);\n
OpenIDE-Module-Long-Description=Fonctionnalit\u00e9s pour les graphes dynamiques
OpenIDE-Module-Short-Description=Fonctionnalit\u00e9s pour les graphes dynamiques
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
# Siro Kida <kida.siro@gmail.com>, 2011.
!=Project-Id-Version\: Gephi\nReport-Msgid-Bugs-To\: https\://github.com/gephi/gephi/issues\nPOT-Creation-Date\: 2011-08-05 14\:52+0200\nPO-Revision-Date\: 2011-08-18 10\:48+0000\nLast-Translator\: Siro Kida <kida.siro@gmail.com>\nLanguage-Team\: Japanese (http\://www.transifex.com/projects/p/gephi/language/ja/)\nMIME-Version\: 1.0\nContent-Type\: text/plain; charset\=UTF-8\nContent-Transfer-Encoding\: 8bit\nLanguage\: ja\nPlural-Forms\: nplurals\=1; plural\=0;\n
OpenIDE-Module-Long-Description=\u52d5\u7684\u306a\u30b0\u30e9\u30d5\u306e\u6a5f\u80fd\u3092\u63d0\u4f9b
OpenIDE-Module-Short-Description=\u52d5\u7684\u306a\u30b0\u30e9\u30d5\u306e\u6a5f\u80fd\u3092\u63d0\u4f9b
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
# C\u00e9lio CJr <celiofariajr@gmail.com>, 2011.
!=Project-Id-Version\: Gephi\nReport-Msgid-Bugs-To\: https\://github.com/gephi/gephi/issues\nPOT-Creation-Date\: 2011-08-05 14\:52+0200\nPO-Revision-Date\: 2011-08-05 17\:52+0000\nLast-Translator\: C\u00e9lio Faria Jr. <celiofariajr@gmail.com>\nLanguage-Team\: Portuguese (Brazil) (http\://www.transifex.com/projects/p/gephi/language/pt_BR/)\nMIME-Version\: 1.0\nContent-Type\: text/plain; charset\=UTF-8\nContent-Transfer-Encoding\: 8bit\nLanguage\: pt_BR\nPlural-Forms\: nplurals\=2; plural\=(n > 1);\n
OpenIDE-Module-Long-Description=Fornece recursos para grafos din\u00e2micos
OpenIDE-Module-Short-Description=Fornece recursos para grafos din\u00e2micos
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
# <altsoph@gmail.com>, 2011.
!=Project-Id-Version\: Gephi\nReport-Msgid-Bugs-To\: https\://github.com/gephi/gephi/issues\nPOT-Creation-Date\: 2011-08-05 14\:52+0200\nPO-Revision-Date\: 2011-12-21 22\:41+0000\nLast-Translator\: Altsoph <altsoph@gmail.com>\nLanguage-Team\: Russian (http\://www.transifex.com/projects/p/gephi/language/ru/)\nMIME-Version\: 1.0\nContent-Type\: text/plain; charset\=UTF-8\nContent-Transfer-Encoding\: 8bit\nLanguage\: ru\nPlural-Forms\: nplurals\=3; plural\=(n%10\=\=1 && n%100\!\=11 ? 0 \: n%10>\=2 && n%10<\=4 && (n%100<10 || n%100>\=20) ? 1 \: 2);\n
OpenIDE-Module-Long-Description=\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0433\u0440\u0430\u0444\u043e\u0432
OpenIDE-Module-Short-Description=\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0433\u0440\u0430\u0444\u043e\u0432
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
!=Project-Id-Version\: Gephi\nReport-Msgid-Bugs-To\: https\://github.com/gephi/gephi/issues\nPOT-Creation-Date\: 2011-08-05 14\:52+0200\nPO-Revision-Date\: 2012-01-08 00\:14+0000\nLast-Translator\: gephi <sebastien.heymann@gmail.com>\nLanguage-Team\: Chinese (China) (http\://www.transifex.com/projects/p/gephi/language/zh_CN/)\nMIME-Version\: 1.0\nContent-Type\: text/plain; charset\=UTF-8\nContent-Transfer-Encoding\: 8bit\nLanguage\: zh_CN\nPlural-Forms\: nplurals\=1; plural\=0;\n
OpenIDE-Module-Long-Description=\u63d0\u4f9b\u52a8\u6001\u56fe\u5f62\u529f\u80fd
OpenIDE-Module-Short-Description=\u63d0\u4f9b\u52a8\u6001\u56fe\u5f62\u529f\u80fd
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
# Zbyněk Schwarz <zbynek.schwarz@gmail.com>, 2012.
msgid ""
msgstr ""
"Project-Id-Version: Gephi\n"
"Report-Msgid-Bugs-To: https://github.com/gephi/gephi/issues\n"
"POT-Creation-Date: 2011-08-05 14:52+0200\n"
"PO-Revision-Date: 2012-02-23 09:51+0000\n"
"Last-Translator: Zbyněk Schwarz <zbynek.schwarz@gmail.com>\n"
"Language-Team: Czech (http://www.transifex.com/projects/p/gephi/language/cs/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: cs\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
msgid "OpenIDE-Module-Long-Description"
msgstr "Poskytuje funkce pro dynamické grafy"
msgid "OpenIDE-Module-Short-Description"
msgstr "Poskytuje funkce pro dynamické grafy"
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
msgid ""
msgstr ""
"Project-Id-Version: Gephi\n"
"Report-Msgid-Bugs-To: https://github.com/gephi/gephi/issues\n"
"POT-Creation-Date: 2011-08-05 14:52+0200\n"
"PO-Revision-Date: 2011-08-04 23:06+0000\n"
"Last-Translator: gephi <sebastien.heymann@gmail.com>\n"
"Language-Team: Spanish (http://www.transifex.com/projects/p/gephi/language/es/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "OpenIDE-Module-Long-Description"
msgstr "Proporciona características para grafos dinámicos"
msgid "OpenIDE-Module-Short-Description"
msgstr "Proporciona características para grafos dinámicos"
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
msgid ""
msgstr ""
"Project-Id-Version: Gephi\n"
"Report-Msgid-Bugs-To: https://github.com/gephi/gephi/issues\n"
"POT-Creation-Date: 2011-08-05 14:52+0200\n"
"PO-Revision-Date: 2011-08-04 23:06+0000\n"
"Last-Translator: gephi <sebastien.heymann@gmail.com>\n"
"Language-Team: French (http://www.transifex.com/projects/p/gephi/language/fr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: fr\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
msgid "OpenIDE-Module-Long-Description"
msgstr "Fonctionnalités pour les graphes dynamiques"
msgid "OpenIDE-Module-Short-Description"
msgstr "Fonctionnalités pour les graphes dynamiques"
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
# Siro Kida <kida.siro@gmail.com>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: Gephi\n"
"Report-Msgid-Bugs-To: https://github.com/gephi/gephi/issues\n"
"POT-Creation-Date: 2011-08-05 14:52+0200\n"
"PO-Revision-Date: 2011-08-18 10:48+0000\n"
"Last-Translator: Siro Kida <kida.siro@gmail.com>\n"
"Language-Team: Japanese (http://www.transifex.com/projects/p/gephi/language/ja/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ja\n"
"Plural-Forms: nplurals=1; plural=0;\n"
msgid "OpenIDE-Module-Long-Description"
msgstr "動的なグラフの機能を提供"
msgid "OpenIDE-Module-Short-Description"
msgstr "動的なグラフの機能を提供"
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
# Gephi Team <gephi.team@lists.launchpad.net>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: Gephi 0.8\n"
"Report-Msgid-Bugs-To: gephi.team@lists.launchpad.net\n"
"POT-Creation-Date: 2011-08-05 14:52+0200\n"
"PO-Revision-Date: 2011-08-05 14:52+0200\n"
"Last-Translator: Mathieu Bastian <gephi.team@lists.launchpad.net>\n"
"Language-Team: English <https://launchpad.net/~gephi.team>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "OpenIDE-Module-Long-Description"
msgstr "Provide features for dynamic graphs"
msgid "OpenIDE-Module-Short-Description"
msgstr "Provide features for dynamic graphs"
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<body bgcolor="white">
API responsible for dynamic states, including the current visible interval.
<p>
Gephi uses <b>Dynamic API</b> to store states relative to dynamic graph
exploration. The most notable data is the current visible interval,
what the timeline component is configuring. This interval is centralized
here and used in the rest of the application.
</p>
<p>
The <code>DynamicController</code> is managing models (one per workspace)
and is the access door to the system. This controller is a service, and can be
retrieved by using the following command:
</p>
<p><code>DynamicController dc = Lookup.getDefault().lookup(DynamicController.class);</code></p>
<p>
Use also the <code>DynamicModel</code> to get <code>DynamicGraph</code>
instances. They are independent wrappers that can be used analyse
dynamic graphs.
</p>
</body>
</html>
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
# Célio CJr <celiofariajr@gmail.com>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: Gephi\n"
"Report-Msgid-Bugs-To: https://github.com/gephi/gephi/issues\n"
"POT-Creation-Date: 2011-08-05 14:52+0200\n"
"PO-Revision-Date: 2011-08-05 17:52+0000\n"
"Last-Translator: Célio Faria Jr. <celiofariajr@gmail.com>\n"
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/gephi/language/pt_BR/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: pt_BR\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
msgid "OpenIDE-Module-Long-Description"
msgstr "Fornece recursos para grafos dinâmicos"
msgid "OpenIDE-Module-Short-Description"
msgstr "Fornece recursos para grafos dinâmicos"
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
# <altsoph@gmail.com>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: Gephi\n"
"Report-Msgid-Bugs-To: https://github.com/gephi/gephi/issues\n"
"POT-Creation-Date: 2011-08-05 14:52+0200\n"
"PO-Revision-Date: 2011-12-21 22:41+0000\n"
"Last-Translator: Altsoph <altsoph@gmail.com>\n"
"Language-Team: Russian (http://www.transifex.com/projects/p/gephi/language/ru/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ru\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
msgid "OpenIDE-Module-Long-Description"
msgstr "Предоставляет поддержку динамических графов"
msgid "OpenIDE-Module-Short-Description"
msgstr "Предоставляет поддержку динамических графов"
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: Gephi\n"
"Report-Msgid-Bugs-To: https://github.com/gephi/gephi/issues\n"
"POT-Creation-Date: 2011-08-05 14:52+0200\n"
"PO-Revision-Date: 2012-01-08 00:14+0000\n"
"Last-Translator: gephi <sebastien.heymann@gmail.com>\n"
"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/gephi/language/zh_CN/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: zh_CN\n"
"Plural-Forms: nplurals=1; plural=0;\n"
msgid "OpenIDE-Module-Long-Description"
msgstr "提供动态图形功能"
msgid "OpenIDE-Module-Short-Description"
msgstr "提供动态图形功能"
/*
Copyright 2008-2012 Gephi
Authors : Eduardo Ramos<eduramiba@gmail.com>
Website : http://www.gephi.org
This file is part of Gephi.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.dynamic.utils;
import java.util.Iterator;
import java.util.List;
import static org.junit.Assert.*;
import org.junit.Test;
/**
*
* @author Eduardo Ramos
*/
public class DynamicIntervalsParserTest {
private String parseDynamic(String str) throws Exception{
return parseDynamic(str, String.class);
}
/**
* Temporary until we have some dynamic types representation utility like classic intervals.
*/
private String representListAsIntervalsString(List list){
StringBuilder sb = new StringBuilder();
sb.append("<");
for (Iterator it = list.iterator(); it.hasNext();) {
Object object = it.next();
sb.append(object);
if(it.hasNext()){
sb.append("; ");
}
}
sb.append(">");
return sb.toString();
}
private String parseDynamic(String str, Class type) throws Exception{
if(type != null){
System.out.println(representListAsIntervalsString(DynamicIntervalsParser.parseIntervalsWithValues(type, str)));
return representListAsIntervalsString(DynamicIntervalsParser.parseIntervalsWithValues(type, str));
}else{
System.out.println(representListAsIntervalsString(DynamicIntervalsParser.parseIntervals(str)));
return representListAsIntervalsString(DynamicIntervalsParser.parseIntervals(str));
}
}
@Test
public void testParseIntervals() throws Exception {
assertEquals(parseDynamic("[2.0, 3.5, \"; A3R; JJG; JJG\"); [3.5, 8.0, \"; A3R; JJG; [ ] () , JJG\"]; [10,20,30]")
, "<[2.0, 3.5, \"; A3R; JJG; JJG\"); [3.5, 8.0, \"; A3R; JJG; [ ] () , JJG\"]; [10.0, 20.0, 30]>");
assertEquals(parseDynamic("<[' 2.0', '3.5', ';a b c')")
, "<[2.0, 3.5, \";a b c\")>");
assertEquals(parseDynamic(" ( 1, 2, ) (4,5, '[\\'a;b\\']']")
, "<(1.0, 2.0); (4.0, 5.0, \"['a;b']\"]>");
assertEquals(parseDynamic("[1.25,1.55, <test>]"), "<[1.25, 1.55, <test>]>");
assertEquals(parseDynamic("[1.25,'1.55' <test>]"), "<[1.25, 1.55, <test>]>");
assertEquals(parseDynamic("[1.25,1.55, \"21.12 \" ]", Double.class), "<[1.25, 1.55, 21.12]>");
assertEquals(parseDynamic("[1.25,1.55]", Double.class), "<[1.25, 1.55]>");
assertEquals(parseDynamic("[1.25,1.55]", null), "<[1.25, 1.55]>");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>gephi-parent</artifactId>
<groupId>org.gephi</groupId>
<version>0.9-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent>
<groupId>org.gephi</groupId>
<artifactId>dynamic-impl</artifactId>
<version>0.9-SNAPSHOT</version>
<packaging>nbm</packaging>
<name>DynamicImpl</name>
<dependencies>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-netbeans-api-annotations-common</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>dynamic-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>data-attributes-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>filters-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>filters-plugin</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>graph-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>project-api</artifactId>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-openide-util-lookup</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>nbm-maven-plugin</artifactId>
<configuration>
<publicPackages>
</publicPackages>
</configuration>
</plugin>
</plugins>
</build>
</project>
/*
* Copyright 2008-2010 Gephi
* Authors : Cezary Bartosiak
* Mathieu Bastian <mathieu.bastian@gephi.org>
* Website : http://www.gephi.org
*
* This file is part of Gephi.
*
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.dynamic;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicReference;
import org.gephi.data.attributes.api.Estimator;
import org.gephi.data.attributes.type.TimeInterval;
import org.gephi.dynamic.api.DynamicController;
import org.gephi.dynamic.api.DynamicModel.TimeFormat;
import org.gephi.dynamic.api.DynamicModelEvent;
import org.gephi.dynamic.api.DynamicModelListener;
import org.gephi.project.api.ProjectController;
import org.gephi.project.api.Workspace;
import org.gephi.project.api.WorkspaceListener;
import org.gephi.project.api.WorkspaceProvider;
import org.openide.util.Lookup;
import org.openide.util.lookup.ServiceProvider;
/**
* It is the default implementation of the {@code DynamicController} class.
*
* @author Cezary Bartosiak
* @author Mathieu Bastian
*/
@ServiceProvider(service = DynamicController.class)
public final class DynamicControllerImpl implements DynamicController {
private DynamicModelImpl model;
private List<DynamicModelListener> listeners;
private DynamicModelEventDispatchThread eventThread;
private SetVisibleIntervalThread setIntervalThread;
/**
* The default constructor.
*/
public DynamicControllerImpl() {
listeners = Collections.synchronizedList(new ArrayList<DynamicModelListener>());
eventThread = new DynamicModelEventDispatchThread();
eventThread.start();
setIntervalThread = new SetVisibleIntervalThread();
setIntervalThread.start();
ProjectController projectController = Lookup.getDefault().lookup(ProjectController.class);
projectController.addWorkspaceListener(new WorkspaceListener() {
@Override
public void initialize(Workspace workspace) {
workspace.add(new DynamicModelImpl(DynamicControllerImpl.this, workspace));
}
@Override
public void select(Workspace workspace) {
model = workspace.getLookup().lookup(DynamicModelImpl.class);
if (model == null) {
model = new DynamicModelImpl(DynamicControllerImpl.this, workspace);
workspace.add(model);
}
}
@Override
public void unselect(Workspace workspace) {
}
@Override
public void close(Workspace workspace) {
}
@Override
public void disable() {
model = null;
}
});
if (projectController.getCurrentProject() != null) {
Workspace[] workspaces = projectController.getCurrentProject().getLookup().
lookup(WorkspaceProvider.class).getWorkspaces();
for (Workspace workspace : workspaces) {
DynamicModelImpl m = (DynamicModelImpl) workspace.getLookup().lookup(DynamicModelImpl.class);
if (m == null) {
m = new DynamicModelImpl(this, workspace);
workspace.add(m);
}
if (workspace == projectController.getCurrentWorkspace()) {
model = m;
}
}
}
}
@Override
public synchronized DynamicModelImpl getModel() {
if (model == null) {
ProjectController projectController = Lookup.getDefault().lookup(ProjectController.class);
if (projectController.getCurrentWorkspace() != null) {
Workspace workspace = projectController.getCurrentWorkspace();
return workspace.getLookup().lookup(DynamicModelImpl.class);
}
}
return model;
}
@Override
public synchronized DynamicModelImpl getModel(Workspace workspace) {
if (workspace != null) {
DynamicModelImpl m = workspace.getLookup().lookup(DynamicModelImpl.class);
if (m != null) {
return m;
}
m = new DynamicModelImpl(this, workspace);
workspace.add(m);
return m;
}
return null;
}
@Override
public void setVisibleInterval(TimeInterval interval) {
if (model != null) {
setIntervalThread.setVisibleTimeInterval(interval);
//System.out.println("set visible interval "+interval);
}
}
@Override
public void setVisibleInterval(double low, double high) {
setVisibleInterval(new TimeInterval(low, high));
}
@Override
public void setTimeFormat(TimeFormat timeFormat) {
if (model != null) {
model.setTimeFormat(timeFormat);
}
}
@Override
public void setTimeFormat(TimeFormat timeFormat, Workspace workspace) {
DynamicModelImpl modelImpl = (DynamicModelImpl) getModel(workspace);
if (modelImpl != null) {
modelImpl.setTimeFormat(timeFormat);
}
}
@Override
public void setEstimator(Estimator estimator) {
if (model != null) {
model.setEstimator(estimator);
}
}
@Override
public void setEstimator(Estimator estimator, Workspace workspace) {
DynamicModelImpl modelImpl = (DynamicModelImpl) getModel(workspace);
if (modelImpl != null) {
modelImpl.setEstimator(estimator);
}
}
@Override
public void setNumberEstimator(Estimator numberEstimator) {
if (model != null) {
model.setNumberEstimator(numberEstimator);
}
}
@Override
public void setNumberEstimator(Estimator numberEstimator, Workspace workspace) {
DynamicModelImpl modelImpl = (DynamicModelImpl) getModel(workspace);
if (modelImpl != null) {
modelImpl.setNumberEstimator(numberEstimator);
}
}
@Override
public void addModelListener(DynamicModelListener listener) {
if (!listeners.contains(listener)) {
listeners.add(listener);
}
}
@Override
public void removeModelListener(DynamicModelListener listener) {
listeners.remove(listener);
}
public void fireModelEvent(DynamicModelEvent event) {
eventThread.fireEvent(event);
}
protected class SetVisibleIntervalThread extends Thread {
private boolean stop;
private final AtomicReference<TimeInterval> lastInterval = new AtomicReference<TimeInterval>();
private final Object lock = new Object();
public SetVisibleIntervalThread() {
super("Dynamic Set Visible Interval Thread");
setDaemon(true);
}
@Override
public void run() {
while (!stop) {
TimeInterval interval;
if ((interval = lastInterval.getAndSet(null)) != null) {
model.setVisibleTimeInterval(interval);
}
while (lastInterval.get() == null) {
try {
synchronized (lock) {
lock.wait();
}
} catch (InterruptedException e) {
}
}
}
}
public void stop(boolean stop) {
this.stop = stop;
}
public void setVisibleTimeInterval(TimeInterval interval) {
lastInterval.set(interval);
synchronized (lock) {
lock.notifyAll();
}
}
}
protected class DynamicModelEventDispatchThread extends Thread {
private boolean stop;
private final LinkedBlockingQueue<DynamicModelEvent> eventQueue;
private final Object lock = new Object();
public DynamicModelEventDispatchThread() {
super("Dynamic Model EventDispatchThread");
setDaemon(true);
this.eventQueue = new LinkedBlockingQueue<DynamicModelEvent>();
}
@Override
public void run() {
while (!stop) {
DynamicModelEvent evt;
while ((evt = eventQueue.poll()) != null) {
for (DynamicModelListener l : listeners.toArray(new DynamicModelListener[0])) {
l.dynamicModelChanged(evt);
}
}
while (eventQueue.isEmpty()) {
try {
synchronized (lock) {
lock.wait();
}
} catch (InterruptedException e) {
}
}
}
}
public void stop(boolean stop) {
this.stop = stop;
}
public void fireEvent(DynamicModelEvent event) {
eventQueue.add(event);
synchronized (lock) {
lock.notifyAll();
}
}
}
}
/*
* Copyright 2008-2010 Gephi
* Authors : Cezary Bartosiak
* Website : http://www.gephi.org
*
* This file is part of Gephi.
*
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.dynamic;
import java.util.TreeMap;
import org.gephi.data.attributes.type.Interval;
import org.gephi.dynamic.api.DynamicModelEvent;
/**
*
* @author Mathieu Bastian
*/
public class DynamicIndex {
protected final TreeMap<Double, Integer> lowMap;
protected final TreeMap<Double, Integer> highMap;
protected final DynamicModelImpl model;
public DynamicIndex(DynamicModelImpl model) {
this.model = model;
lowMap = new TreeMap<Double, Integer>();
highMap = new TreeMap<Double, Integer>();
}
public synchronized void add(Interval interval) {
Double low = interval.getLow();
Double high = interval.getHigh();
boolean valid = (!lowMap.isEmpty() && !highMap.isEmpty()) || (lowMap.size() > 1 || highMap.size() > 1);
if (!valid) {
//Manually verify bounds
double min = getMin();
double max = getMax();
valid = !Double.isInfinite(min) && !Double.isInfinite(max);
}
boolean minChanged = false;
boolean maxChanged = false;
if (!Double.isInfinite(low)) {
if (lowMap.get(low) != null) {
Integer counter = new Integer(lowMap.get(low) + 1);
lowMap.put(low, counter);
} else {
Double min = lowMap.isEmpty() ? Double.POSITIVE_INFINITY : lowMap.firstKey();
lowMap.put(low, 1);
if (low < min) {
minChanged = true;
}
}
}
if (!Double.isInfinite(high)) {
if (highMap.get(high) != null) {
Integer counter = new Integer(highMap.get(high) + 1);
highMap.put(high, counter);
} else {
Double max = highMap.isEmpty() ? Double.NEGATIVE_INFINITY : highMap.lastKey();
highMap.put(high, 1);
if (high > max) {
maxChanged = true;
}
}
}
if (!valid && (minChanged || maxChanged)) {
//Look if valid now
double min = getMin();
double max = getMax();
valid = !Double.isInfinite(min) && !Double.isInfinite(max);
if (valid) {
fireEvent(new DynamicModelEvent(DynamicModelEvent.EventType.IS_DYNAMIC_GRAPH, model, Boolean.TRUE));
}
}
if (minChanged && valid) {
fireEvent(new DynamicModelEvent(DynamicModelEvent.EventType.MIN_CHANGED, model, low));
}
if (maxChanged && valid) {
fireEvent(new DynamicModelEvent(DynamicModelEvent.EventType.MAX_CHANGED, model, high));
}
}
public synchronized void remove(Interval interval) {
Double low = interval.getLow();
Double high = interval.getHigh();
if (!Double.isInfinite(low) && lowMap.get(low) != null) {
Integer counter = new Integer(lowMap.get(low) - 1);
if (counter == 0) {
Double min = lowMap.firstKey();
lowMap.remove(low);
if (min.equals(low)) {
fireEvent(new DynamicModelEvent(DynamicModelEvent.EventType.MIN_CHANGED, model, getMin()));
}
} else {
lowMap.put(low, counter);
}
}
if (!Double.isInfinite(high) && highMap.get(high) != null) {
Integer counter = new Integer(highMap.get(high) - 1);
if (counter == 0) {
Double max = highMap.lastKey();
highMap.remove(high);
if (max.equals(high)) {
fireEvent(new DynamicModelEvent(DynamicModelEvent.EventType.MAX_CHANGED, model, getMax()));
}
} else {
highMap.put(high, counter);
}
}
if (lowMap.isEmpty() && highMap.isEmpty()) {
fireEvent(new DynamicModelEvent(DynamicModelEvent.EventType.IS_DYNAMIC_GRAPH, model, Boolean.FALSE));
}
}
public synchronized void clear() {
lowMap.clear();
highMap.clear();
fireEvent(new DynamicModelEvent(DynamicModelEvent.EventType.MIN_CHANGED, model, getMin()));
fireEvent(new DynamicModelEvent(DynamicModelEvent.EventType.MAX_CHANGED, model, getMax()));
fireEvent(new DynamicModelEvent(DynamicModelEvent.EventType.IS_DYNAMIC_GRAPH, model, Boolean.FALSE));
}
public synchronized double getMin() {
return lowMap.isEmpty() ? (highMap.isEmpty() ? Double.NEGATIVE_INFINITY : highMap.firstKey()) : lowMap.firstKey();
}
public synchronized double getMax() {
return highMap.isEmpty() ? (lowMap.isEmpty() ? Double.POSITIVE_INFINITY : lowMap.lastKey()) : highMap.lastKey();
}
private void fireEvent(DynamicModelEvent event) {
if (model != null) {
model.controller.fireModelEvent(event);
}
}
}
/*
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
Website : http://www.gephi.org
This file is part of Gephi.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.dynamic;
import org.gephi.project.api.Workspace;
import org.gephi.project.spi.WorkspaceDuplicateProvider;
import org.openide.util.Lookup;
import org.openide.util.lookup.ServiceProvider;
/**
*
* @author Mathieu Bastian
*/
@ServiceProvider(service = WorkspaceDuplicateProvider.class)
public class DynamicModelDuplicateProvider implements WorkspaceDuplicateProvider {
@Override
public void duplicate(Workspace source, Workspace destination) {
DynamicControllerImpl dynamicController = Lookup.getDefault().lookup(DynamicControllerImpl.class);
DynamicModelImpl sourceModel = dynamicController.getModel(source);
DynamicModelImpl destModel = dynamicController.getModel(destination);
//Attributes
destModel.setEstimator(sourceModel.getEstimator());
destModel.setNumberEstimator(sourceModel.getNumberEstimator());
destModel.setTimeFormat(sourceModel.getTimeFormat());
}
}
Manifest-Version: 1.0
AutoUpdate-Essential-Module: true
OpenIDE-Module-Localizing-Bundle: org/gephi/dynamic/Bundle.properties
OpenIDE-Module-Specification-Version: ${gephi.modules.specification.version}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<nbm>
<!--
<moduleType>autoload</moduleType>
<codeNameBase>org.gephi.dynamic/1</codeNameBase>
<licenseName>Apache License, Version 2.0</licenseName>
<licenseFile>license.txt</licenseFile>
-->
</nbm>
OpenIDE-Module-Display-Category=Gephi Core
OpenIDE-Module-Name=Dynamic Impl
OpenIDE-Module-Short-Description=Dynamic API default implementation
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
# Zbyn\u011bk Schwarz <zbynek.schwarz@gmail.com>, 2012.
!=Project-Id-Version\: Gephi\nReport-Msgid-Bugs-To\: https\://github.com/gephi/gephi/issues\nPOT-Creation-Date\: 2011-08-05 14\:52+0200\nPO-Revision-Date\: 2012-02-23 09\:51+0000\nLast-Translator\: Zbyn\u011bk Schwarz <zbynek.schwarz@gmail.com>\nLanguage-Team\: Czech (http\://www.transifex.com/projects/p/gephi/language/cs/)\nMIME-Version\: 1.0\nContent-Type\: text/plain; charset\=UTF-8\nContent-Transfer-Encoding\: 8bit\nLanguage\: cs\nPlural-Forms\: nplurals\=3; plural\=(n\=\=1) ? 0 \: (n>\=2 && n<\=4) ? 1 \: 2;\n
OpenIDE-Module-Short-Description=V\u00fdchoz\u00ed zaveden\u00e9 dynamick\u00e9 API
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
!=Project-Id-Version\: Gephi\nReport-Msgid-Bugs-To\: https\://github.com/gephi/gephi/issues\nPOT-Creation-Date\: 2011-08-05 14\:52+0200\nPO-Revision-Date\: 2011-08-04 23\:06+0000\nLast-Translator\: gephi <sebastien.heymann@gmail.com>\nLanguage-Team\: Spanish (http\://www.transifex.com/projects/p/gephi/language/es/)\nMIME-Version\: 1.0\nContent-Type\: text/plain; charset\=UTF-8\nContent-Transfer-Encoding\: 8bit\nLanguage\: es\nPlural-Forms\: nplurals\=2; plural\=(n \!\= 1);\n
OpenIDE-Module-Short-Description=Implementaci\u00f3n por defecto del m\u00f3dulo Dynamic API
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
!=Project-Id-Version\: Gephi\nReport-Msgid-Bugs-To\: https\://github.com/gephi/gephi/issues\nPOT-Creation-Date\: 2011-08-05 14\:52+0200\nPO-Revision-Date\: 2011-08-04 23\:06+0000\nLast-Translator\: gephi <sebastien.heymann@gmail.com>\nLanguage-Team\: French (http\://www.transifex.com/projects/p/gephi/language/fr/)\nMIME-Version\: 1.0\nContent-Type\: text/plain; charset\=UTF-8\nContent-Transfer-Encoding\: 8bit\nLanguage\: fr\nPlural-Forms\: nplurals\=2; plural\=(n > 1);\n
OpenIDE-Module-Short-Description=Fournit des fonctionnalit\u00e9s pour les graphes dynamiques
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
# Siro Kida <kida.siro@gmail.com>, 2011.
!=Project-Id-Version\: Gephi\nReport-Msgid-Bugs-To\: https\://github.com/gephi/gephi/issues\nPOT-Creation-Date\: 2011-08-05 14\:52+0200\nPO-Revision-Date\: 2011-08-18 10\:48+0000\nLast-Translator\: Siro Kida <kida.siro@gmail.com>\nLanguage-Team\: Japanese (http\://www.transifex.com/projects/p/gephi/language/ja/)\nMIME-Version\: 1.0\nContent-Type\: text/plain; charset\=UTF-8\nContent-Transfer-Encoding\: 8bit\nLanguage\: ja\nPlural-Forms\: nplurals\=1; plural\=0;\n
OpenIDE-Module-Short-Description=\u52d5\u7684API\u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u5b9f\u88c5
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
# C\u00e9lio CJr <celiofariajr@gmail.com>, 2011.
!=Project-Id-Version\: Gephi\nReport-Msgid-Bugs-To\: https\://github.com/gephi/gephi/issues\nPOT-Creation-Date\: 2011-08-05 14\:52+0200\nPO-Revision-Date\: 2011-08-05 17\:51+0000\nLast-Translator\: C\u00e9lio Faria Jr. <celiofariajr@gmail.com>\nLanguage-Team\: Portuguese (Brazil) (http\://www.transifex.com/projects/p/gephi/language/pt_BR/)\nMIME-Version\: 1.0\nContent-Type\: text/plain; charset\=UTF-8\nContent-Transfer-Encoding\: 8bit\nLanguage\: pt_BR\nPlural-Forms\: nplurals\=2; plural\=(n > 1);\n
OpenIDE-Module-Short-Description=Implementa\u00e7\u00e3o padr\u00e3o da Dynamic API
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
# <altsoph@gmail.com>, 2011.
!=Project-Id-Version\: Gephi\nReport-Msgid-Bugs-To\: https\://github.com/gephi/gephi/issues\nPOT-Creation-Date\: 2011-08-05 14\:52+0200\nPO-Revision-Date\: 2011-12-21 22\:41+0000\nLast-Translator\: Altsoph <altsoph@gmail.com>\nLanguage-Team\: Russian (http\://www.transifex.com/projects/p/gephi/language/ru/)\nMIME-Version\: 1.0\nContent-Type\: text/plain; charset\=UTF-8\nContent-Transfer-Encoding\: 8bit\nLanguage\: ru\nPlural-Forms\: nplurals\=3; plural\=(n%10\=\=1 && n%100\!\=11 ? 0 \: n%10>\=2 && n%10<\=4 && (n%100<10 || n%100>\=20) ? 1 \: 2);\n
OpenIDE-Module-Short-Description=Dynamic API default implementation
# Translation file for Gephi.
# Copyright (C) 2011 Gephi contributors.
# This file is distributed under the same license as the Gephi package.
#
# Translators:
!=Project-Id-Version\: Gephi\nReport-Msgid-Bugs-To\: https\://github.com/gephi/gephi/issues\nPOT-Creation-Date\: 2011-08-05 14\:52+0200\nPO-Revision-Date\: 2012-01-08 00\:14+0000\nLast-Translator\: gephi <sebastien.heymann@gmail.com>\nLanguage-Team\: Chinese (China) (http\://www.transifex.com/projects/p/gephi/language/zh_CN/)\nMIME-Version\: 1.0\nContent-Type\: text/plain; charset\=UTF-8\nContent-Transfer-Encoding\: 8bit\nLanguage\: zh_CN\nPlural-Forms\: nplurals\=1; plural\=0;\n
OpenIDE-Module-Short-Description=\u52a8\u6001\u5e94\u7528\u7a0b\u5e8f\u754c\u9762\u7684\u9ed8\u8ba4\u5b9e\u73b0
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册