提交 6eaf9e46 编写于 作者: M Mathieu Bastian

Work in progress adding back timeline module

上级 fb557daf
......@@ -5,7 +5,7 @@
<artifactId>gephi-parent</artifactId>
<groupId>org.gephi</groupId>
<version>0.9-SNAPSHOT</version>
<relativePath>../..</relativePath>
<relativePath>../..</relativePath>
</parent>
<groupId>org.gephi</groupId>
......@@ -22,19 +22,23 @@
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>data-attributes-api</artifactId>
<artifactId>desktop-banner</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>desktop-perspective</artifactId>
<artifactId>lib.validation</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>lib.validation</artifactId>
<artifactId>graph-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>timeline-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>timeline</artifactId>
<artifactId>visualization</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
......@@ -56,6 +60,10 @@
<groupId>${project.groupId}</groupId>
<artifactId>ui-library-wrapper</artifactId>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-openide-util-ui</artifactId>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-openide-dialogs</artifactId>
......
......@@ -42,7 +42,8 @@
package org.gephi.desktop.timeline;
import javax.swing.JComponent;
import org.gephi.desktop.perspective.spi.BottomComponent;
import org.gephi.desktop.banner.perspective.spi.BottomComponent;
import org.gephi.visualization.VizController;
import org.openide.util.lookup.ServiceProvider;
/**
......@@ -52,16 +53,19 @@ import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service=BottomComponent.class)
public class BottomComponentImpl implements BottomComponent {
private TimelineTopComponent timelineTopComponent = new TimelineTopComponent();
private final TimelineTopComponent timelineTopComponent = new TimelineTopComponent();
@Override
public JComponent getComponent() {
return timelineTopComponent;
}
@Override
public void setVisible(boolean visible) {
timelineTopComponent.setTimeLineVisible(visible);
}
@Override
public boolean isVisible() {
return timelineTopComponent.isVisible();
}
......
......@@ -44,21 +44,18 @@ package org.gephi.desktop.timeline;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import javax.swing.JTextField;
import org.gephi.dynamic.DynamicUtilities;
import org.gephi.dynamic.api.DynamicModel.TimeFormat;
import org.gephi.graph.api.AttributeUtils;
import org.gephi.graph.api.TimeFormat;
import org.gephi.timeline.api.TimelineController;
import org.gephi.timeline.api.TimelineModel;
import org.joda.time.format.ISODateTimeFormat;
import org.netbeans.validation.api.Problems;
import org.netbeans.validation.api.Validator;
import org.netbeans.validation.api.builtin.Validators;
import org.netbeans.validation.api.ui.ValidationGroup;
import org.netbeans.validation.api.ui.ValidationPanel;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
......@@ -68,8 +65,6 @@ import org.openide.util.NbBundle;
*/
public class CustomBoundsDialog extends javax.swing.JPanel {
private final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
private final SimpleDateFormat DATETIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SS");
private TimelineModel model;
private TimelineController controller;
......@@ -85,34 +80,28 @@ public class CustomBoundsDialog extends javax.swing.JPanel {
}
public void setDefaults() {
if (model.getTimeFormat().equals(TimeFormat.DATE)) {
Date min = DynamicUtilities.getDateFromDouble(model.getMin());
Date max = DynamicUtilities.getDateFromDouble(model.getMax());
Date from = DynamicUtilities.getDateFromDouble(model.getMin());
Date to = DynamicUtilities.getDateFromDouble(model.getMax());
minTextField.setText(DATE_FORMAT.format(min));
maxTextField.setText(DATE_FORMAT.format(max));
startTextField.setText(DATE_FORMAT.format(from));
endTextField.setText(DATE_FORMAT.format(to));
} else if (model.getTimeFormat().equals(TimeFormat.DATETIME)) {
Date min = DynamicUtilities.getDateFromDouble(model.getMin());
Date max = DynamicUtilities.getDateFromDouble(model.getMax());
Date from = DynamicUtilities.getDateFromDouble(model.getMin());
Date to = DynamicUtilities.getDateFromDouble(model.getMax());
minTextField.setText(DATETIME_FORMAT.format(min));
maxTextField.setText(DATETIME_FORMAT.format(max));
startTextField.setText(DATETIME_FORMAT.format(from));
endTextField.setText(DATETIME_FORMAT.format(to));
} else {
NumberFormat f = NumberFormat.getInstance(Locale.ENGLISH);
f.setGroupingUsed(false);
f.setMaximumFractionDigits(20);
minTextField.setText(f.format(model.getMin()));
maxTextField.setText(f.format(model.getMax()));
startTextField.setText(f.format(model.getMin()));
endTextField.setText(f.format(model.getMax()));
switch (model.getTimeFormat()) {
case DATE:
minTextField.setText(AttributeUtils.printDate(model.getMin()));
maxTextField.setText(AttributeUtils.printDate(model.getMax()));
startTextField.setText(AttributeUtils.printDate(model.getMin()));
endTextField.setText(AttributeUtils.printDate(model.getMax()));
break;
case DATETIME:
minTextField.setText(AttributeUtils.printDateTime(model.getMin()));
maxTextField.setText(AttributeUtils.printDateTime(model.getMax()));
startTextField.setText(AttributeUtils.printDateTime(model.getMin()));
endTextField.setText(AttributeUtils.printDateTime(model.getMax()));
break;
default:
NumberFormat f = NumberFormat.getInstance(Locale.ENGLISH);
f.setGroupingUsed(false);
f.setMaximumFractionDigits(20);
minTextField.setText(f.format(model.getMin()));
maxTextField.setText(f.format(model.getMax()));
startTextField.setText(f.format(model.getMin()));
endTextField.setText(f.format(model.getMax()));
break;
}
}
......@@ -120,65 +109,42 @@ public class CustomBoundsDialog extends javax.swing.JPanel {
this.model = timelineModel;
this.controller = Lookup.getDefault().lookup(TimelineController.class);
setDefaults();
if (model.getTimeFormat().equals(TimeFormat.DATE)) {
Date min = DynamicUtilities.getDateFromDouble(model.getCustomMin());
Date max = DynamicUtilities.getDateFromDouble(model.getCustomMax());
Date from = DynamicUtilities.getDateFromDouble(model.getIntervalStart());
Date to = DynamicUtilities.getDateFromDouble(model.getIntervalEnd());
minTextField.setText(DATE_FORMAT.format(min));
maxTextField.setText(DATE_FORMAT.format(max));
startTextField.setText(DATE_FORMAT.format(from));
endTextField.setText(DATE_FORMAT.format(to));
} else if (model.getTimeFormat().equals(TimeFormat.DATETIME)) {
Date min = DynamicUtilities.getDateFromDouble(model.getCustomMin());
Date max = DynamicUtilities.getDateFromDouble(model.getCustomMax());
Date from = DynamicUtilities.getDateFromDouble(model.getIntervalStart());
Date to = DynamicUtilities.getDateFromDouble(model.getIntervalEnd());
minTextField.setText(DATETIME_FORMAT.format(min));
maxTextField.setText(DATETIME_FORMAT.format(max));
startTextField.setText(DATETIME_FORMAT.format(from));
endTextField.setText(DATETIME_FORMAT.format(to));
} else {
NumberFormat f = NumberFormat.getInstance(Locale.ENGLISH);
f.setGroupingUsed(false);
f.setMaximumFractionDigits(20);
minTextField.setText(f.format(model.getCustomMin()));
maxTextField.setText(f.format(model.getCustomMax()));
startTextField.setText(f.format(model.getIntervalStart()));
endTextField.setText(f.format(model.getIntervalEnd()));
switch (model.getTimeFormat()) {
case DATE:
minTextField.setText(AttributeUtils.printDate(model.getCustomMin()));
maxTextField.setText(AttributeUtils.printDate(model.getCustomMax()));
startTextField.setText(AttributeUtils.printDate(model.getIntervalStart()));
endTextField.setText(AttributeUtils.printDate(model.getIntervalEnd()));
break;
case DATETIME:
minTextField.setText(AttributeUtils.printDateTime(model.getCustomMin()));
maxTextField.setText(AttributeUtils.printDateTime(model.getCustomMax()));
startTextField.setText(AttributeUtils.printDateTime(model.getIntervalStart()));
endTextField.setText(AttributeUtils.printDateTime(model.getIntervalEnd()));
break;
default:
NumberFormat f = NumberFormat.getInstance(Locale.ENGLISH);
f.setGroupingUsed(false);
f.setMaximumFractionDigits(20);
minTextField.setText(f.format(model.getCustomMin()));
maxTextField.setText(f.format(model.getCustomMax()));
startTextField.setText(f.format(model.getIntervalStart()));
endTextField.setText(f.format(model.getIntervalEnd()));
break;
}
}
public void unsetup() {
if (model.getTimeFormat().equals(TimeFormat.DATE)) {
try {
double min = DynamicUtilities.getDoubleFromDate(DATE_FORMAT.parse(minTextField.getText()));
double max = DynamicUtilities.getDoubleFromDate(DATE_FORMAT.parse(maxTextField.getText()));
double start = DynamicUtilities.getDoubleFromDate(DATE_FORMAT.parse(startTextField.getText()));
double end = DynamicUtilities.getDoubleFromDate(DATE_FORMAT.parse(endTextField.getText()));
start = Math.max(min, start);
end = Math.min(max, end);
controller.setCustomBounds(min, max);
controller.setInterval(start, end);
} catch (ParseException ex) {
Exceptions.printStackTrace(ex);
}
} else if (model.getTimeFormat().equals(TimeFormat.DATETIME)) {
try {
double min = DynamicUtilities.getDoubleFromDate(DATETIME_FORMAT.parse(minTextField.getText()));
double max = DynamicUtilities.getDoubleFromDate(DATETIME_FORMAT.parse(maxTextField.getText()));
double start = DynamicUtilities.getDoubleFromDate(DATETIME_FORMAT.parse(startTextField.getText()));
double end = DynamicUtilities.getDoubleFromDate(DATETIME_FORMAT.parse(endTextField.getText()));
start = Math.max(min, start);
end = Math.min(max, end);
controller.setCustomBounds(min, max);
controller.setInterval(start, end);
} catch (ParseException ex) {
Exceptions.printStackTrace(ex);
}
if (model.getTimeFormat().equals(TimeFormat.DATE) || model.getTimeFormat().equals(TimeFormat.DATETIME)) {
double min = AttributeUtils.parseDateTime(minTextField.getText());
double max = AttributeUtils.parseDateTime(maxTextField.getText());
double start = AttributeUtils.parseDateTime(startTextField.getText());
double end = AttributeUtils.parseDateTime(endTextField.getText());
start = Math.max(min, start);
end = Math.min(max, end);
controller.setCustomBounds(min, max);
controller.setInterval(start, end);
} else {
double min = Double.parseDouble(minTextField.getText());
double max = Double.parseDouble(maxTextField.getText());
......@@ -223,42 +189,17 @@ public class CustomBoundsDialog extends javax.swing.JPanel {
public boolean validate(Problems prblms, String string, String t) {
double thisDate;
double otherDate;
if (model.getTimeFormat().equals(TimeFormat.DATE)) {
try {
thisDate = DynamicUtilities.getDoubleFromDate(DATE_FORMAT.parse(t));
otherDate = DynamicUtilities.getDoubleFromDate(DATE_FORMAT.parse(other.getText()));
double minDate = max ? otherDate : thisDate;
double maxDate = max ? thisDate : otherDate;
if(minDate < model.getMin()) {
prblms.add(NbBundle.getMessage(CustomBoundsDialog.class, "CustomBoundsDialog.TimeValidator.min"));
return false;
}
if(maxDate > model.getMax()) {
prblms.add(NbBundle.getMessage(CustomBoundsDialog.class, "CustomBoundsDialog.TimeValidator.max"));
return false;
}
if (minDate >= maxDate) {
prblms.add(NbBundle.getMessage(CustomBoundsDialog.class, "CustomBoundsDialog.TimeValidator"));
return false;
} else if (maxDate <= minDate) {
prblms.add(NbBundle.getMessage(CustomBoundsDialog.class, "CustomBoundsDialog.TimeValidator"));
return false;
}
} catch (ParseException ex) {
prblms.add(NbBundle.getMessage(CustomBoundsDialog.class, "CustomBoundsDialog.FormatValidator.date", DATE_FORMAT.toPattern()));
return false;
}
} else if (model.getTimeFormat().equals(TimeFormat.DATETIME)) {
if (model.getTimeFormat().equals(TimeFormat.DATE) || model.getTimeFormat().equals(TimeFormat.DATETIME)) {
try {
thisDate = DynamicUtilities.getDoubleFromDate(DATETIME_FORMAT.parse(t));
otherDate = DynamicUtilities.getDoubleFromDate(DATETIME_FORMAT.parse(other.getText()));
thisDate = AttributeUtils.parseDateTime(t);
otherDate = AttributeUtils.parseDateTime(other.getText());
double minDate = max ? otherDate : thisDate;
double maxDate = max ? thisDate : otherDate;
if(minDate < model.getMin()) {
if (minDate < model.getMin()) {
prblms.add(NbBundle.getMessage(CustomBoundsDialog.class, "CustomBoundsDialog.TimeValidator.min"));
return false;
}
if(maxDate > model.getMax()) {
if (maxDate > model.getMax()) {
prblms.add(NbBundle.getMessage(CustomBoundsDialog.class, "CustomBoundsDialog.TimeValidator.max"));
return false;
}
......@@ -269,21 +210,22 @@ public class CustomBoundsDialog extends javax.swing.JPanel {
prblms.add(NbBundle.getMessage(CustomBoundsDialog.class, "CustomBoundsDialog.TimeValidator"));
return false;
}
} catch (ParseException ex) {
prblms.add(NbBundle.getMessage(CustomBoundsDialog.class, "CustomBoundsDialog.FormatValidator.date", DATETIME_FORMAT.toPattern()));
} catch (Exception ex) {
prblms.add(NbBundle.getMessage(CustomBoundsDialog.class, "CustomBoundsDialog.FormatValidator.date", ISODateTimeFormat.dateTime()));
return false;
}
} else {
try {
thisDate = Double.parseDouble(t);
otherDate = Double.parseDouble(other.getText());
double minDate = max ? otherDate : thisDate;
double maxDate = max ? thisDate : otherDate;
if(minDate < model.getMin()) {
if (minDate < model.getMin()) {
prblms.add(NbBundle.getMessage(CustomBoundsDialog.class, "CustomBoundsDialog.TimeValidator.min"));
return false;
}
if(maxDate > model.getMax()) {
if (maxDate > model.getMax()) {
prblms.add(NbBundle.getMessage(CustomBoundsDialog.class, "CustomBoundsDialog.TimeValidator.max"));
return false;
}
......@@ -308,16 +250,16 @@ public class CustomBoundsDialog extends javax.swing.JPanel {
public boolean validate(Problems prblms, String string, String t) {
if (model.getTimeFormat().equals(TimeFormat.DATE)) {
try {
DATE_FORMAT.parse(t);
} catch (ParseException ex) {
prblms.add(NbBundle.getMessage(CustomBoundsDialog.class, "CustomBoundsDialog.FormatValidator.date", DATE_FORMAT.toPattern()));
AttributeUtils.parseDateTime(t);
} catch (Exception ex) {
prblms.add(NbBundle.getMessage(CustomBoundsDialog.class, "CustomBoundsDialog.FormatValidator.date", ISODateTimeFormat.date()));
return false;
}
} else if (model.getTimeFormat().equals(TimeFormat.DATETIME)) {
try {
DATETIME_FORMAT.parse(t);
} catch (ParseException ex) {
prblms.add(NbBundle.getMessage(CustomBoundsDialog.class, "CustomBoundsDialog.FormatValidator.date", DATETIME_FORMAT.toPattern()));
AttributeUtils.parseDateTime(t);
} catch (Exception ex) {
prblms.add(NbBundle.getMessage(CustomBoundsDialog.class, "CustomBoundsDialog.FormatValidator.date", ISODateTimeFormat.dateTime()));
return false;
}
} else {
......@@ -332,10 +274,10 @@ public class CustomBoundsDialog extends javax.swing.JPanel {
}
}
/** 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.
/**
* 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.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
......
......@@ -41,7 +41,6 @@ Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.desktop.timeline;
import org.gephi.dynamic.DynamicUtilities;
import org.joda.time.DateTime;
import org.joda.time.DateTimeFieldType;
import org.joda.time.DurationFieldType;
......
......@@ -46,7 +46,7 @@ import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import org.gephi.dynamic.api.DynamicModel.TimeFormat;
import org.gephi.graph.api.TimeFormat;
import org.gephi.timeline.api.TimelineModel;
import org.joda.time.Interval;
......
......@@ -20,11 +20,13 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="headerTitle" alignment="0" pref="400" max="32767" attributes="0"/>
<Component id="headerTitle" alignment="0" pref="422" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="126" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="23" max="-2" attributes="0"/>
<Component id="numericRadio" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="dateTimeRadio" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="dateRadio" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
......@@ -38,6 +40,7 @@
<Group type="103" groupAlignment="3" attributes="0">
<Component id="numericRadio" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="dateRadio" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="dateTimeRadio" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="22" max="32767" attributes="0"/>
</Group>
......@@ -78,5 +81,15 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JRadioButton" name="dateTimeRadio">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="buttonGroup"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/gephi/desktop/timeline/Bundle.properties" key="TimeFormatDialog.dateTimeRadio.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>
......@@ -41,8 +41,8 @@ Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.desktop.timeline;
import org.gephi.dynamic.api.DynamicController;
import org.gephi.dynamic.api.DynamicModel;
import org.gephi.graph.api.TimeFormat;
import org.gephi.timeline.api.TimelineController;
import org.gephi.timeline.api.TimelineModel;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
......@@ -53,7 +53,7 @@ import org.openide.util.NbBundle;
*/
public class TimeFormatDialog extends javax.swing.JPanel {
private DynamicController dynamicController;
private TimelineController timelineController;
/**
* Creates new form DateFormatDialog
......@@ -63,17 +63,30 @@ public class TimeFormatDialog extends javax.swing.JPanel {
}
public void setup(TimelineModel model) {
this.dynamicController = Lookup.getDefault().lookup(DynamicController.class);
if (dynamicController.getModel().getTimeFormat().equals(DynamicModel.TimeFormat.DOUBLE)) {
numericRadio.setSelected(true);
} else {
dateRadio.setSelected(true);
this.timelineController = Lookup.getDefault().lookup(TimelineController.class);
TimeFormat timeFormat = model.getTimeFormat();
switch(timeFormat) {
case DATE:
dateRadio.setSelected(true);
break;
case DATETIME:
dateTimeRadio.setSelected(true);
break;
case DOUBLE:
numericRadio.setSelected(true);
break;
}
}
public void unsetup() {
dynamicController.setTimeFormat(dateRadio.isSelected() ? DynamicModel.TimeFormat.DATE : DynamicModel.TimeFormat.DOUBLE);
if(dateRadio.isSelected()) {
timelineController.setTimeFormat(TimeFormat.DATE);
} else if(dateTimeRadio.isSelected()) {
timelineController.setTimeFormat(TimeFormat.DATETIME);
} else {
timelineController.setTimeFormat(TimeFormat.DOUBLE);
}
}
/**
......@@ -89,6 +102,7 @@ public class TimeFormatDialog extends javax.swing.JPanel {
headerTitle = new org.jdesktop.swingx.JXHeader();
dateRadio = new javax.swing.JRadioButton();
numericRadio = new javax.swing.JRadioButton();
dateTimeRadio = new javax.swing.JRadioButton();
headerTitle.setDescription(NbBundle.getMessage (TimelineTopComponent.class, "TimeFormatDialog.headerTitle.description")); // NOI18N
headerTitle.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/gephi/desktop/timeline/resources/time_format.png"))); // NOI18N
......@@ -100,17 +114,22 @@ public class TimeFormatDialog extends javax.swing.JPanel {
buttonGroup.add(numericRadio);
numericRadio.setText(NbBundle.getMessage (TimelineTopComponent.class, "TimeFormatDialog.numericRadio.text")); // NOI18N
buttonGroup.add(dateTimeRadio);
dateTimeRadio.setText(org.openide.util.NbBundle.getMessage(TimeFormatDialog.class, "TimeFormatDialog.dateTimeRadio.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(headerTitle, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
.addComponent(headerTitle, javax.swing.GroupLayout.DEFAULT_SIZE, 422, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGap(126, 126, 126)
.addGap(23, 23, 23)
.addComponent(numericRadio)
.addGap(18, 18, 18)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(dateTimeRadio)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(dateRadio)
.addContainerGap())
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
......@@ -119,13 +138,15 @@ public class TimeFormatDialog extends javax.swing.JPanel {
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(numericRadio)
.addComponent(dateRadio))
.addComponent(dateRadio)
.addComponent(dateTimeRadio))
.addGap(0, 22, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.ButtonGroup buttonGroup;
private javax.swing.JRadioButton dateRadio;
private javax.swing.JRadioButton dateTimeRadio;
private org.jdesktop.swingx.JXHeader headerTitle;
private javax.swing.JRadioButton numericRadio;
// End of variables declaration//GEN-END:variables
......
<?xml version="1.1" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.4" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<Properties>
......
......@@ -595,6 +595,7 @@ public class TimelineDrawer extends JPanel implements MouseListener, MouseMotion
to = Math.min(to, model.getCustomMax());
if (from < to) {
controller.setInterval(from, to);
repaint();
}
}
}
......
......@@ -49,7 +49,6 @@ import java.util.TimerTask;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.swing.JComponent;
import org.gephi.dynamic.api.DynamicModel.TimeFormat;
import org.gephi.timeline.api.TimelineChart;
import org.gephi.timeline.api.TimelineModel;
import org.gephi.ui.components.richtooltip.RichTooltip;
......@@ -121,40 +120,43 @@ public class TimelineTooltip {
}
private void buildData(double currentPosition) {
if (model.getTimeFormat().equals(TimeFormat.DOUBLE)) {
int exponentMin = (int) Math.round(Math.log10(model.getCustomMin()));
DecimalFormat decimalFormat = new DecimalFormat();
decimalFormat.setRoundingMode(RoundingMode.HALF_EVEN);
if (exponentMin > 0) {
min = String.valueOf(model.getCustomMin());
max = String.valueOf(model.getCustomMax());
position = String.valueOf(currentPosition);
} else {
decimalFormat.setMaximumFractionDigits(Math.abs(exponentMin) + 2);
min = decimalFormat.format(model.getCustomMin());
max = decimalFormat.format(model.getCustomMax());
position = decimalFormat.format(currentPosition);
}
} else if (model.getTimeFormat().equals(TimeFormat.DATE)) {
DateTime minDate = new DateTime((long) model.getCustomMin());
DateTime maxDate = new DateTime((long) model.getCustomMax());
DateTime posDate = new DateTime((long) currentPosition);
DateTimeFormatter formatter = ISODateTimeFormat.date();
min = formatter.print(minDate);
max = formatter.print(maxDate);
position = formatter.print(posDate);
} else {
DateTime minDate = new DateTime((long) model.getCustomMin());
DateTime maxDate = new DateTime((long) model.getCustomMax());
DateTime posDate = new DateTime((long) currentPosition);
DateTimeFormatter formatter = ISODateTimeFormat.dateTime();
min = formatter.print(minDate);
max = formatter.print(maxDate);
position = formatter.print(posDate);
switch (model.getTimeFormat()) {
case DOUBLE:
int exponentMin = (int) Math.round(Math.log10(model.getCustomMin()));
DecimalFormat decimalFormat = new DecimalFormat();
decimalFormat.setRoundingMode(RoundingMode.HALF_EVEN);
if (exponentMin > 0) {
min = String.valueOf(model.getCustomMin());
max = String.valueOf(model.getCustomMax());
position = String.valueOf(currentPosition);
} else {
decimalFormat.setMaximumFractionDigits(Math.abs(exponentMin) + 2);
min = decimalFormat.format(model.getCustomMin());
max = decimalFormat.format(model.getCustomMax());
position = decimalFormat.format(currentPosition);
} break;
case DATE:
{
DateTime minDate = new DateTime((long) model.getCustomMin());
DateTime maxDate = new DateTime((long) model.getCustomMax());
DateTime posDate = new DateTime((long) currentPosition);
DateTimeFormatter formatter = ISODateTimeFormat.date();
min = formatter.print(minDate);
max = formatter.print(maxDate);
position = formatter.print(posDate);
break;
}
default:
{
DateTime minDate = new DateTime((long) model.getCustomMin());
DateTime maxDate = new DateTime((long) model.getCustomMax());
DateTime posDate = new DateTime((long) currentPosition);
DateTimeFormatter formatter = ISODateTimeFormat.dateTime();
min = formatter.print(minDate);
max = formatter.print(maxDate);
position = formatter.print(posDate);
break;
}
}
if (model.getChart() != null) {
......@@ -183,7 +185,7 @@ public class TimelineTooltip {
//Chart
if (getY() != null) {
richTooltip.addFooterSection(model.getChart().getColumn().getTitle());
richTooltip.addFooterSection(model.getChart().getColumn());
richTooltip.addFooterSection(NbBundle.getMessage(TimelineTooltip.class, "TimelineTooltip.chart") + ": " + getY());
//Img
......
......@@ -48,13 +48,14 @@ import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.gephi.data.attributes.api.AttributeColumn;
import org.gephi.graph.api.Column;
import org.gephi.timeline.api.TimelineController;
import org.gephi.timeline.api.TimelineModel;
import org.gephi.timeline.api.TimelineModelEvent;
import org.gephi.timeline.api.TimelineModelListener;
import org.gephi.ui.components.CloseButton;
import org.gephi.ui.utils.UIUtils;
import org.gephi.visualization.VizController;
import org.netbeans.validation.api.ui.ValidationPanel;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
......@@ -132,7 +133,6 @@ public final class TimelineTopComponent extends JPanel implements TimelineModelL
}
});
columnsButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
......@@ -140,14 +140,14 @@ public final class TimelineTopComponent extends JPanel implements TimelineModelL
JPopupMenu menu = new JPopupMenu();
//Add columns
AttributeColumn selectedColumn = model.getChart() != null ? model.getChart().getColumn() : null;
String selectedColumn = model.getChart() != null ? model.getChart().getColumn() : null;
//Dynamic columns
AttributeColumn[] columns = controller.getDynamicGraphColumns();
String[] columns = controller.getDynamicGraphColumns();
for (final AttributeColumn col : columns) {
boolean selected = col == selectedColumn;
JRadioButtonMenuItem item = new JRadioButtonMenuItem(col.getTitle(), selected);
for (final String col : columns) {
boolean selected = (col == null ? selectedColumn == null : col.equals(selectedColumn));
JRadioButtonMenuItem item = new JRadioButtonMenuItem(col, selected);
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
......@@ -176,7 +176,7 @@ public final class TimelineTopComponent extends JPanel implements TimelineModelL
});
menu.add(disableItem);
if(selectedColumn == null) {
if (selectedColumn == null) {
disableItem.setEnabled(false);
}
}
......@@ -255,7 +255,6 @@ public final class TimelineTopComponent extends JPanel implements TimelineModelL
});
menu.add(dateFormatItem);
menu.show(settingsButton, 0, -menu.getPreferredSize().height);
}
});
......@@ -339,10 +338,11 @@ public final class TimelineTopComponent extends JPanel implements TimelineModelL
public void setTimeLineVisible(final boolean visible) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (visible != TimelineTopComponent.this.isVisible()) {
TimelineTopComponent.this.setVisible(visible);
VizController.getInstance().getDrawable().reinitWindow();
}
}
});
......
......@@ -53,3 +53,4 @@ TimeFormatDialog.headerTitle.title=Time format settings
TimeFormatDialog.headerTitle.description=Set up the time format
TimeFormatDialog.numericRadio.text=Numeric
TimeFormatDialog.dateRadio.text=Date
TimeFormatDialog.dateTimeRadio.text=Datetime
///*
//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.filters.plugin.dynamic;
//
//import java.util.ArrayList;
//import java.util.List;
//import javax.swing.Icon;
//import javax.swing.JPanel;
//import org.gephi.filters.api.Range;
//import org.gephi.filters.spi.Category;
//import org.gephi.filters.spi.CategoryBuilder;
//import org.gephi.filters.spi.EdgeFilter;
//import org.gephi.filters.spi.Filter;
//import org.gephi.filters.spi.FilterBuilder;
//import org.gephi.filters.spi.FilterProperty;
//import org.gephi.filters.spi.NodeFilter;
//import org.gephi.graph.api.Edge;
//import org.gephi.graph.api.Graph;
//import org.gephi.graph.api.Node;
//import org.openide.util.Lookup;
//import org.openide.util.NbBundle;
//import org.openide.util.lookup.ServiceProvider;
//
///**
// *
// * @author Mathieu Bastian
// */
//@ServiceProvider(service = CategoryBuilder.class)
//public class DynamicRangeBuilder implements CategoryBuilder {
//
// private final static Category DYNAMIC = new Category(
// NbBundle.getMessage(DynamicRangeBuilder.class, "DynamicRangeBuilder.category"),
// null,
// null);
//
// @Override
// public Category getCategory() {
// return DYNAMIC;
// }
//
// @Override
// public FilterBuilder[] getBuilders() {
// List<FilterBuilder> builders = new ArrayList<FilterBuilder>();
// AttributeModel am = Lookup.getDefault().lookup(AttributeController.class).getModel();
// AttributeColumn nodeColumn = am.getNodeTable().getColumn(DynamicModel.TIMEINTERVAL_COLUMN);
// AttributeColumn edgeColumn = am.getEdgeTable().getColumn(DynamicModel.TIMEINTERVAL_COLUMN);
// if (nodeColumn != null || edgeColumn != null) {
// builders.add(new DynamicRangeFilterBuilder(nodeColumn, edgeColumn));
// }
// return builders.toArray(new FilterBuilder[0]);
// }
//
// private static class DynamicRangeFilterBuilder implements FilterBuilder {
//
// private final AttributeColumn nodeColumn;
// private final AttributeColumn edgeColumn;
//
// public DynamicRangeFilterBuilder(AttributeColumn nodeColumn, AttributeColumn edgeColumn) {
// this.nodeColumn = nodeColumn;
// this.edgeColumn = edgeColumn;
// }
//
// @Override
// public Category getCategory() {
// return DYNAMIC;
// }
//
// @Override
// public String getName() {
// return "Time Interval";
// }
//
// @Override
// public Icon getIcon() {
// return null;
// }
//
// @Override
// public String getDescription() {
// return null;
// }
//
// @Override
// public DynamicRangeFilter getFilter() {
// TimelineController timelineController = Lookup.getDefault().lookup(TimelineController.class);
// DynamicController dynamicController = Lookup.getDefault().lookup(DynamicController.class);
// return new DynamicRangeFilter(timelineController, dynamicController, nodeColumn, edgeColumn);
// }
//
// @Override
// public JPanel getPanel(Filter filter) {
// final DynamicRangeFilter dynamicRangeFilter = (DynamicRangeFilter) filter;
// DynamicRangeUI ui = Lookup.getDefault().lookup(DynamicRangeUI.class);
// if (ui != null) {
// return ui.getPanel(dynamicRangeFilter);
// }
// return null;
// }
//
// @Override
// public void destroy(Filter filter) {
// ((DynamicRangeFilter) filter).destroy();
// }
// }
//
// public static class DynamicRangeFilter implements NodeFilter, EdgeFilter, DynamicModelListener {
//
// private AttributeColumn nodeColumn;
// private AttributeColumn edgeColumn;
// private DynamicController dynamicController;
// private DynamicModel dynamicModel;
// private TimelineController timelineController;
// private TimeInterval visibleInterval;
// private FilterProperty[] filterProperties;
// private Range range;
// private boolean keepNull = true;
//
// public DynamicRangeFilter(TimelineController timelineController, DynamicController dynamicController, AttributeColumn nodeColumn, AttributeColumn edgeColumn) {
// this.nodeColumn = nodeColumn;
// this.edgeColumn = edgeColumn;
// this.dynamicController = dynamicController;
// this.dynamicModel = dynamicController.getModel();
// this.timelineController = timelineController;
// }
//
// @Override
// public boolean init(Graph graph) {
// dynamicController.addModelListener(this);
// visibleInterval = dynamicModel.getVisibleInterval();
// return true;
// }
//
// @Override
// public boolean evaluate(Graph graph, Node node) {
// if (nodeColumn != null) {
// Object obj = node.getNodeData().getAttributes().getValue(nodeColumn.getIndex());
// if (obj != null) {
// TimeInterval timeInterval = (TimeInterval) obj;
// return timeInterval.isInRange(visibleInterval.getLow(), visibleInterval.getHigh());
// }
// return keepNull;
// }
// return true;
// }
//
// @Override
// public boolean evaluate(Graph graph, Edge edge) {
// if (edgeColumn != null) {
// Object obj = edge.getEdgeData().getAttributes().getValue(edgeColumn.getIndex());
// if (obj != null) {
// TimeInterval timeInterval = (TimeInterval) obj;
// return timeInterval.isInRange(visibleInterval.getLow(), visibleInterval.getHigh());
// }
// return keepNull;
// }
// return true;
// }
//
// @Override
// public void finish() {
// }
//
// @Override
// public String getName() {
// return NbBundle.getMessage(DynamicRangeBuilder.class, "DynamicRangeBuilder.name");
// }
//
// @Override
// public FilterProperty[] getProperties() {
// if (filterProperties == null) {
// filterProperties = new FilterProperty[0];
// try {
// filterProperties = new FilterProperty[]{
// FilterProperty.createProperty(this, Range.class, "range"),
// FilterProperty.createProperty(this, Boolean.class, "keepNull")};
// } catch (Exception ex) {
// ex.printStackTrace();
// }
// }
// return filterProperties;
// }
//
// public void dynamicModelChanged(DynamicModelEvent event) {
// switch (event.getEventType()) {
// case VISIBLE_INTERVAL:
// TimeInterval interval = (TimeInterval) event.getData();
// getProperties()[0].setValue(new Range(interval.getLow(), interval.getHigh()));
// break;
// }
// }
//
// public FilterProperty getRangeProperty() {
// return getProperties()[0];
// }
//
// public boolean isKeepNull() {
// return keepNull;
// }
//
// public void setKeepNull(boolean keepNull) {
// this.keepNull = keepNull;
// }
//
// public Range getRange() {
// if (visibleInterval != null) {
// return new Range(visibleInterval.getLow(), visibleInterval.getHigh());
// }
// return null;
// }
//
// public void setRange(Range range) {
// dynamicController.setVisibleInterval(range.getLowerDouble(), range.getUpperDouble());
// }
//
// public void destroy() {
// dynamicController.removeModelListener(this);
// }
// }
//}
/*
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.filters.plugin.dynamic;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JPanel;
import org.gephi.filters.api.Range;
import org.gephi.filters.spi.Category;
import org.gephi.filters.spi.CategoryBuilder;
import org.gephi.filters.spi.ComplexFilter;
import org.gephi.filters.spi.Filter;
import org.gephi.filters.spi.FilterBuilder;
import org.gephi.filters.spi.FilterProperty;
import org.gephi.graph.api.Edge;
import org.gephi.graph.api.Element;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.GraphController;
import org.gephi.graph.api.GraphModel;
import org.gephi.graph.api.Interval;
import org.gephi.graph.api.Node;
import org.gephi.graph.api.TimeRepresentation;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
/**
*
* @author Mathieu Bastian
*/
@ServiceProvider(service = CategoryBuilder.class)
public class DynamicRangeBuilder implements CategoryBuilder {
private final static Category DYNAMIC = new Category(
NbBundle.getMessage(DynamicRangeBuilder.class, "DynamicRangeBuilder.category"),
null,
null);
@Override
public Category getCategory() {
return DYNAMIC;
}
@Override
public FilterBuilder[] getBuilders() {
List<FilterBuilder> builders = new ArrayList<FilterBuilder>();
GraphModel am = Lookup.getDefault().lookup(GraphController.class).getGraphModel();
if (am.isDynamic()) {
builders.add(new DynamicRangeFilterBuilder(am));
}
return builders.toArray(new FilterBuilder[0]);
}
private static class DynamicRangeFilterBuilder implements FilterBuilder {
private GraphModel graphModel;
public DynamicRangeFilterBuilder(GraphModel graphModel) {
this.graphModel = graphModel;
}
@Override
public Category getCategory() {
return DYNAMIC;
}
@Override
public String getName() {
return "Time Interval";
}
@Override
public Icon getIcon() {
return null;
}
@Override
public String getDescription() {
return null;
}
@Override
public DynamicRangeFilter getFilter() {
return new DynamicRangeFilter(graphModel);
}
@Override
public JPanel getPanel(Filter filter) {
final DynamicRangeFilter dynamicRangeFilter = (DynamicRangeFilter) filter;
DynamicRangeUI ui = Lookup.getDefault().lookup(DynamicRangeUI.class);
if (ui != null) {
return ui.getPanel(dynamicRangeFilter);
}
return null;
}
@Override
public void destroy(Filter filter) {
}
}
public static class DynamicRangeFilter implements ComplexFilter {
private TimeRepresentation timeRepresentation;
private FilterProperty[] filterProperties;
private Interval visibleInterval;
private Range range = new Range(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
private boolean keepNull = true;
public DynamicRangeFilter(GraphModel graphModel) {
this.timeRepresentation = graphModel.getConfiguration().getTimeRepresentation();
}
@Override
public Graph filter(Graph graph) {
visibleInterval = new Interval(range.getLowerDouble(), range.getUpperDouble());
List<Node> toRemoveNodes = new ArrayList<Node>();
for (Node n : graph.getNodes()) {
if (!evaluateElement(n)) {
toRemoveNodes.add(n);
}
}
graph.removeAllNodes(toRemoveNodes);
List<Edge> toRemoveEdge = new ArrayList<Edge>();
for (Edge e : graph.getEdges()) {
if (!evaluateElement(e)) {
toRemoveEdge.add(e);
}
}
graph.removeAllEdges(toRemoveEdge);
graph.getModel().setTimeInterval(graph.getView(), visibleInterval);
return graph;
}
private boolean evaluateElement(Element element) {
if (timeRepresentation.equals(TimeRepresentation.INTERVAL)) {
for (Interval i : element.getIntervals()) {
if (visibleInterval.compareTo(i) == 0) {
return true;
}
}
} else {
for (double t : element.getTimestamps()) {
if (visibleInterval.compareTo(t) == 0) {
return true;
}
}
}
return false;
}
@Override
public String getName() {
return NbBundle.getMessage(DynamicRangeBuilder.class, "DynamicRangeBuilder.name");
}
@Override
public FilterProperty[] getProperties() {
if (filterProperties == null) {
filterProperties = new FilterProperty[0];
try {
filterProperties = new FilterProperty[]{
FilterProperty.createProperty(this, Range.class, "range"),
FilterProperty.createProperty(this, Boolean.class, "keepNull")};
} catch (Exception ex) {
ex.printStackTrace();
}
}
return filterProperties;
}
public FilterProperty getRangeProperty() {
return getProperties()[0];
}
public boolean isKeepNull() {
return keepNull;
}
public void setKeepNull(boolean keepNull) {
this.keepNull = keepNull;
}
public Range getRange() {
return range;
}
public void setRange(Range range) {
this.range = range;
}
public void destroy() {
}
}
}
///*
//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.filters.plugin.dynamic;
//
//import javax.swing.JPanel;
//import org.gephi.filters.plugin.dynamic.DynamicRangeBuilder.DynamicRangeFilter;
//
///**
// *
// * @author mbastian
// */
//public interface DynamicRangeUI {
//
// public JPanel getPanel(DynamicRangeFilter filter);
//}
/*
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.filters.plugin.dynamic;
import javax.swing.JPanel;
import org.gephi.filters.plugin.dynamic.DynamicRangeBuilder.DynamicRangeFilter;
/**
*
* @author mbastian
*/
public interface DynamicRangeUI {
public JPanel getPanel(DynamicRangeFilter filter);
}
......@@ -60,10 +60,10 @@
<groupId>org.netbeans.api</groupId>
<artifactId>org-openide-windows</artifactId>
</dependency>
<!-- <dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>desktop-perspective</artifactId>
</dependency>-->
<artifactId>desktop-banner</artifactId>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-openide-filesystems</artifactId>
......
......@@ -45,12 +45,12 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import org.gephi.desktop.banner.perspective.spi.BottomComponent;
import org.gephi.filters.plugin.dynamic.DynamicRangeBuilder.DynamicRangeFilter;
//import org.gephi.desktop.perspective.spi.BottomComponent;
//import org.gephi.filters.plugin.dynamic.DynamicRangeBuilder.DynamicRangeFilter;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
/**
*
......@@ -67,37 +67,37 @@ public class DynamicRangePanel extends javax.swing.JPanel {
CLOSE = NbBundle.getMessage(DynamicRangePanel.class, "DynamicRangePanel.timelineButton.closetext");
}
// public void setup(final DynamicRangeFilter filter) {
// final BottomComponent bottomComponent = Lookup.getDefault().lookup(BottomComponent.class);
// timelineButton.setText(bottomComponent.isVisible() ? CLOSE : OPEN);
// timelineButton.addActionListener(new ActionListener() {
//
// public void actionPerformed(ActionEvent e) {
//
// if (!bottomComponent.isVisible()) {
// bottomComponent.setVisible(true);
// timelineButton.setText(CLOSE);
// } else {
// bottomComponent.setVisible(false);
// timelineButton.setText(OPEN);
// }
// }
// });
// keepEmptyCheckbox.setSelected(filter.isKeepNull());
// keepEmptyCheckbox.addItemListener(new ItemListener() {
//
// public void itemStateChanged(ItemEvent e) {
// if (!filter.isKeepNull() == keepEmptyCheckbox.isSelected()) {
// filter.getProperties()[1].setValue(keepEmptyCheckbox.isSelected());
// }
// }
// });
// }
/** 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.
public void setup(final DynamicRangeFilter filter) {
final BottomComponent bottomComponent = Lookup.getDefault().lookup(BottomComponent.class);
timelineButton.setText(bottomComponent.isVisible() ? CLOSE : OPEN);
timelineButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!bottomComponent.isVisible()) {
bottomComponent.setVisible(true);
timelineButton.setText(CLOSE);
} else {
bottomComponent.setVisible(false);
timelineButton.setText(OPEN);
}
}
});
keepEmptyCheckbox.setSelected(filter.isKeepNull());
keepEmptyCheckbox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (!filter.isKeepNull() == keepEmptyCheckbox.isSelected()) {
filter.getProperties()[1].setValue(keepEmptyCheckbox.isSelected());
}
}
});
}
/**
* 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.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
......
///*
//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.ui.filters.plugin.dynamic;
//
//import javax.swing.JPanel;
//import org.gephi.filters.plugin.dynamic.DynamicRangeBuilder.DynamicRangeFilter;
//import org.gephi.filters.plugin.dynamic.DynamicRangeUI;
//import org.openide.util.lookup.ServiceProvider;
//
///**
// *
// * @author mbastian
// */
//@ServiceProvider(service = DynamicRangeUI.class)
//public class DynamicRangeUIImpl implements DynamicRangeUI {
//
// public JPanel getPanel(DynamicRangeFilter filter) {
// DynamicRangePanel panel = new DynamicRangePanel();
// panel.setup(filter);
// return panel;
// }
//}
/*
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.ui.filters.plugin.dynamic;
import javax.swing.JPanel;
import org.gephi.filters.plugin.dynamic.DynamicRangeBuilder.DynamicRangeFilter;
import org.gephi.filters.plugin.dynamic.DynamicRangeUI;
import org.openide.util.lookup.ServiceProvider;
/**
*
* @author mbastian
*/
@ServiceProvider(service = DynamicRangeUI.class)
public class DynamicRangeUIImpl implements DynamicRangeUI {
public JPanel getPanel(DynamicRangeFilter filter) {
DynamicRangePanel panel = new DynamicRangePanel();
panel.setup(filter);
return panel;
}
}
......@@ -20,6 +20,10 @@
<groupId>${project.groupId}</groupId>
<artifactId>io-generator-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>graph-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>io-importer-api</artifactId>
......
......@@ -42,6 +42,7 @@
package org.gephi.io.generator.plugin;
import java.util.Random;
import org.gephi.graph.api.TimeRepresentation;
import org.gephi.io.generator.spi.Generator;
import org.gephi.io.generator.spi.GeneratorUI;
import org.gephi.io.importer.api.ColumnDraft;
......@@ -69,6 +70,7 @@ public class DynamicGraph implements Generator {
double end = 2015.0;
double tick = 1.0;
ColumnDraft col = container.addNodeColumn("score", Integer.class, true);
container.setTimeRepresentation(TimeRepresentation.TIMESTAMP);
NodeDraft[] nodeArray = new NodeDraft[numberOfNodes];
for (int i = 0; i < numberOfNodes; i++) {
......
......@@ -5,11 +5,11 @@
<artifactId>gephi-parent</artifactId>
<groupId>org.gephi</groupId>
<version>0.9-SNAPSHOT</version>
<relativePath>../..</relativePath>
<relativePath>../..</relativePath>
</parent>
<groupId>org.gephi</groupId>
<artifactId>timeline</artifactId>
<artifactId>timeline-api</artifactId>
<version>0.9-SNAPSHOT</version>
<packaging>nbm</packaging>
......@@ -18,11 +18,15 @@
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>data-attributes-api</artifactId>
<artifactId>graph-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>graph-api</artifactId>
<artifactId>filters-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>filters-plugin</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
......
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.gephi.timeline;
import org.gephi.graph.api.GraphModel;
import org.gephi.graph.api.Interval;
/**
*
* @author mbastian
*/
public class GraphObserverThread extends Thread {
private final TimelineControllerImpl timelineController;
private final TimelineModelImpl timelineModel;
private boolean stop;
private Interval interval;
public GraphObserverThread(TimelineControllerImpl controller, TimelineModelImpl model) {
this.timelineModel = model;
this.timelineController = controller;
this.interval = model.getGraphModel().getTimeBounds();
}
@Override
public void run() {
while (!stop) {
GraphModel graphModel = timelineModel.getGraphModel();
Interval bounds = graphModel.getTimeBounds();
if(!bounds.equals(interval)) {
interval = bounds;
timelineController.setMinMax(interval.getLow(), interval.getHigh());
}
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
}
}
public void stopThread() {
stop = true;
}
}
......@@ -43,7 +43,6 @@ package org.gephi.timeline;
import java.math.BigDecimal;
import java.math.BigInteger;
import org.gephi.data.attributes.api.AttributeColumn;
import org.gephi.timeline.api.TimelineChart;
/**
......@@ -52,7 +51,7 @@ import org.gephi.timeline.api.TimelineChart;
*/
public class TimelineChartImpl implements TimelineChart {
private final AttributeColumn column;
private final String column;
private final Number[] x;
private final Number[] y;
private final Number minY;
......@@ -60,7 +59,7 @@ public class TimelineChartImpl implements TimelineChart {
private final Number minX;
private final Number maxX;
public TimelineChartImpl(AttributeColumn column, Number[] x, Number y[]) {
public TimelineChartImpl(String column, Number[] x, Number y[]) {
this.column = column;
this.x = x;
this.y = y;
......@@ -117,7 +116,7 @@ public class TimelineChartImpl implements TimelineChart {
}
@Override
public AttributeColumn getColumn() {
public String getColumn() {
return column;
}
......@@ -128,13 +127,13 @@ public class TimelineChartImpl implements TimelineChart {
}
Number t = yValues[0];
if (t instanceof Double) {
return new Double(min);
return min;
} else if (t instanceof Float) {
return new Float(min);
} else if (t instanceof Short) {
return new Short((short) min);
return (short) min;
} else if (t instanceof Long) {
return new Long((long) min);
return (long) min;
} else if (t instanceof BigInteger) {
return new BigDecimal(min);
}
......@@ -148,13 +147,13 @@ public class TimelineChartImpl implements TimelineChart {
}
Number t = yValues[0];
if (t instanceof Double) {
return new Double(max);
return max;
} else if (t instanceof Float) {
return new Float(max);
} else if (t instanceof Short) {
return new Short((short) max);
return (short) max;
} else if (t instanceof Long) {
return new Long((long) max);
return (long) max;
} else if (t instanceof BigInteger) {
return new BigDecimal(max);
}
......
......@@ -47,18 +47,19 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import org.gephi.data.attributes.api.AttributeColumn;
import org.gephi.data.attributes.api.AttributeController;
import org.gephi.data.attributes.api.AttributeModel;
import org.gephi.data.attributes.api.AttributeUtils;
import org.gephi.data.attributes.type.DynamicType;
import org.gephi.data.attributes.type.Interval;
import org.gephi.data.attributes.type.TimeInterval;
import org.gephi.dynamic.api.DynamicController;
import org.gephi.dynamic.api.DynamicModelEvent;
import org.gephi.dynamic.api.DynamicModelListener;
import org.gephi.filters.api.FilterController;
import org.gephi.filters.api.FilterModel;
import org.gephi.filters.api.Query;
import org.gephi.filters.api.Range;
import org.gephi.filters.plugin.dynamic.DynamicRangeBuilder;
import org.gephi.filters.plugin.dynamic.DynamicRangeBuilder.DynamicRangeFilter;
import org.gephi.filters.spi.FilterBuilder;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.GraphController;
import org.gephi.graph.api.GraphModel;
import org.gephi.graph.api.TimeFormat;
import org.gephi.graph.api.types.IntervalMap;
import org.gephi.graph.api.types.TimestampMap;
import org.gephi.project.api.ProjectController;
import org.gephi.project.api.Workspace;
import org.gephi.project.api.WorkspaceListener;
......@@ -72,20 +73,22 @@ import org.openide.util.lookup.ServiceProvider;
* @author Mathieu Bastian
*/
@ServiceProvider(service = TimelineController.class)
public class TimelineControllerImpl implements TimelineController, DynamicModelListener {
public class TimelineControllerImpl implements TimelineController {
private final List<TimelineModelListener> listeners;
private TimelineModelImpl model;
private final DynamicController dynamicController;
private AttributeModel attributeModel;
private GraphObserverThread observerThread;
private GraphModel graphModel;
private ScheduledExecutorService playExecutor;
private FilterModel filterModel;
private FilterController filterController;
public TimelineControllerImpl() {
listeners = new ArrayList<TimelineModelListener>();
//Workspace events
ProjectController pc = Lookup.getDefault().lookup(ProjectController.class);
dynamicController = Lookup.getDefault().lookup(DynamicController.class);
filterController = Lookup.getDefault().lookup(FilterController.class);
pc.addWorkspaceListener(new WorkspaceListener() {
......@@ -96,17 +99,24 @@ public class TimelineControllerImpl implements TimelineController, DynamicModelL
@Override
public void select(Workspace workspace) {
model = workspace.getLookup().lookup(TimelineModelImpl.class);
graphModel = Lookup.getDefault().lookup(GraphController.class).getGraphModel(workspace);
if (model == null) {
model = new TimelineModelImpl(dynamicController.getModel(workspace));
model = new TimelineModelImpl(graphModel);
workspace.add(model);
}
attributeModel = Lookup.getDefault().lookup(AttributeController.class).getModel(workspace);
observerThread = new GraphObserverThread(TimelineControllerImpl.this, model);
setup();
observerThread.start();
filterModel = filterController.getModel(workspace);
}
@Override
public void unselect(Workspace workspace) {
unsetup();
if (observerThread != null) {
observerThread.stopThread();
}
filterModel = null;
}
@Override
......@@ -116,18 +126,22 @@ public class TimelineControllerImpl implements TimelineController, DynamicModelL
@Override
public void disable() {
model = null;
attributeModel = null;
graphModel = null;
filterModel = null;
if (observerThread != null) {
observerThread.stopThread();
}
fireTimelineModelEvent(new TimelineModelEvent(TimelineModelEvent.EventType.MODEL, null, null));
}
});
if (pc.getCurrentWorkspace() != null) {
model = pc.getCurrentWorkspace().getLookup().lookup(TimelineModelImpl.class);
graphModel = Lookup.getDefault().lookup(GraphController.class).getGraphModel(pc.getCurrentWorkspace());
if (model == null) {
model = new TimelineModelImpl(dynamicController.getModel(pc.getCurrentWorkspace()));
model = new TimelineModelImpl(graphModel);
pc.getCurrentWorkspace().add(model);
}
attributeModel = Lookup.getDefault().lookup(AttributeController.class).getModel(pc.getCurrentWorkspace());
setup();
}
}
......@@ -144,32 +158,34 @@ public class TimelineControllerImpl implements TimelineController, DynamicModelL
private void setup() {
fireTimelineModelEvent(new TimelineModelEvent(TimelineModelEvent.EventType.MODEL, model, null));
dynamicController.addModelListener(this);
}
private void unsetup() {
dynamicController.removeModelListener(this);
}
@Override
public void dynamicModelChanged(DynamicModelEvent event) {
if (event.getEventType().equals(DynamicModelEvent.EventType.MIN_CHANGED)
|| event.getEventType().equals(DynamicModelEvent.EventType.MAX_CHANGED)) {
double newMax = event.getSource().getMax();
double newMin = event.getSource().getMin();
setMinMax(newMin, newMax);
} else if (event.getEventType().equals(DynamicModelEvent.EventType.VISIBLE_INTERVAL)) {
TimeInterval timeInterval = (TimeInterval) event.getData();
double min = timeInterval.getLow();
double max = timeInterval.getHigh();
fireTimelineModelEvent(new TimelineModelEvent(TimelineModelEvent.EventType.INTERVAL, model, new double[]{min, max}));
} else if (event.getEventType().equals(DynamicModelEvent.EventType.TIME_FORMAT)) {
fireTimelineModelEvent(new TimelineModelEvent(TimelineModelEvent.EventType.MODEL, model, null)); //refresh display
}
public void setTimeFormat(TimeFormat timeFormat) {
graphModel.setTimeFormat(timeFormat);
}
private boolean setMinMax(double min, double max) {
//
// @Override
// public void dynamicModelChanged(DynamicModelEvent event) {
// if (event.getEventType().equals(DynamicModelEvent.EventType.MIN_CHANGED)
// || event.getEventType().equals(DynamicModelEvent.EventType.MAX_CHANGED)) {
// double newMax = event.getSource().getMax();
// double newMin = event.getSource().getMin();
// setMinMax(newMin, newMax);
// } else if (event.getEventType().equals(DynamicModelEvent.EventType.VISIBLE_INTERVAL)) {
// TimeInterval timeInterval = (TimeInterval) event.getData();
// double min = timeInterval.getLow();
// double max = timeInterval.getHigh();
// fireTimelineModelEvent(new TimelineModelEvent(TimelineModelEvent.EventType.INTERVAL, model, new double[]{min, max}));
// } else if (event.getEventType().equals(DynamicModelEvent.EventType.TIME_FORMAT)) {
// fireTimelineModelEvent(new TimelineModelEvent(TimelineModelEvent.EventType.MODEL, model, null)); //refresh display
// }
// }
protected boolean setMinMax(double min, double max) {
if (model != null) {
if (min > max) {
throw new IllegalArgumentException("min should be less than max");
......@@ -228,7 +244,7 @@ public class TimelineControllerImpl implements TimelineController, DynamicModelL
//Interval
if (model.getIntervalStart() < min || model.getIntervalEnd() > max) {
dynamicController.setVisibleInterval(min, max);
// dynamicController.setVisibleInterval(min, max);
}
//Custom bounds
......@@ -249,7 +265,7 @@ public class TimelineControllerImpl implements TimelineController, DynamicModelL
}
if (!enabled) {
//Disable filtering
dynamicController.setVisibleInterval(new TimeInterval());
model.setInterval(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
}
}
}
......@@ -264,32 +280,78 @@ public class TimelineControllerImpl implements TimelineController, DynamicModelL
if (from < model.getCustomMin() || to > model.getCustomMax()) {
throw new IllegalArgumentException("From and to should be in the bounds");
}
dynamicController.setVisibleInterval(from, to);
model.setInterval(from, to);
//Filter magic
Query dynamicQuery = null;
boolean selecting = false;
//Get or create Dynamic Query
if (filterModel.getCurrentQuery() != null) {
//Look if current query is dynamic - filtering must be active
Query query = filterModel.getCurrentQuery();
Query[] dynamicQueries = query.getQueries(DynamicRangeFilter.class);
if (dynamicQueries.length > 0) {
dynamicQuery = query;
selecting = filterModel.isSelecting();
}
} else if (filterModel.getQueries().length == 1) {
//Look if a dynamic query alone exists
Query query = filterModel.getQueries()[0];
Query[] dynamicQueries = query.getQueries(DynamicRangeFilter.class);
if (dynamicQueries.length > 0) {
dynamicQuery = query;
}
}
if (Double.isInfinite(from) && Double.isInfinite(to)) {
if (dynamicQuery != null) {
filterController.remove(dynamicQuery);
}
} else {
if (dynamicQuery == null) {
//Create dynamic filter
DynamicRangeBuilder rangeBuilder = filterModel.getLibrary().getLookup().lookup(DynamicRangeBuilder.class);
FilterBuilder[] fb = rangeBuilder.getBuilders();
if (fb.length > 0) {
dynamicQuery = filterController.createQuery(fb[0]);
filterController.add(dynamicQuery);
}
}
if (dynamicQuery != null) {
dynamicQuery.getFilter().getProperties()[0].setValue(new Range(from, to));
if (selecting) {
filterController.selectVisible(dynamicQuery);
} else {
filterController.filterVisible(dynamicQuery);
}
}
}
}
}
}
@Override
public AttributeColumn[] getDynamicGraphColumns() {
if (attributeModel != null) {
List<AttributeColumn> columns = new ArrayList<AttributeColumn>();
AttributeUtils utils = AttributeUtils.getDefault();
for (AttributeColumn col : attributeModel.getGraphTable().getColumns()) {
if (utils.isDynamicNumberColumn(col)) {
columns.add(col);
public String[] getDynamicGraphColumns() {
if (graphModel != null) {
List<String> columns = new ArrayList<String>();
for (String k : graphModel.getGraph().getAttributeKeys()) {
Object a = graphModel.getGraph().getAttribute(k);
if (a instanceof IntervalMap || a instanceof TimestampMap) {
columns.add(k);
}
}
return columns.toArray(new AttributeColumn[0]);
return columns.toArray(new String[0]);
}
return new AttributeColumn[0];
return new String[0];
}
@Override
public void selectColumn(final AttributeColumn column) {
public void selectColumn(final String column) {
if (model != null) {
if (!(model.getChart() == null && column == null)
|| (model.getChart() != null && !model.getChart().getColumn().equals(column))) {
if (column != null && !attributeModel.getGraphTable().hasColumn(column.getId())) {
if (column != null && graphModel.getGraph().getAttribute(column) != null) {
throw new IllegalArgumentException("Not a graph column");
}
Thread thread = new Thread(new Runnable() {
......@@ -297,34 +359,34 @@ public class TimelineControllerImpl implements TimelineController, DynamicModelL
@Override
public void run() {
TimelineChart chart = null;
Graph graph = Lookup.getDefault().lookup(GraphController.class).getModel().getGraphVisible();
Graph graph = Lookup.getDefault().lookup(GraphController.class).getGraphModel().getGraphVisible();
if (column != null) {
DynamicType type = (DynamicType) graph.getAttributes().getValue(column.getIndex());
if (type != null) {
List<Interval> intervals = type.getIntervals(model.getCustomMin(), model.getCustomMax());
Number[] xs = new Number[intervals.size() * 2];
Number[] ys = new Number[intervals.size() * 2];
int i = 0;
Interval interval;
for (int j = 0; j < intervals.size(); j++) {
interval = intervals.get(j);
Number x = (Double) interval.getLow();
Number y = (Number) interval.getValue();
xs[i] = x;
ys[i] = y;
i++;
if (j != intervals.size() - 1 && intervals.get(j + 1).getLow() < interval.getHigh()) {
xs[i] = (Double) intervals.get(j + 1).getLow();
} else {
xs[i] = (Double) interval.getHigh();
}
ys[i] = y;
i++;
}
if (xs.length > 0) {
chart = new TimelineChartImpl(column, xs, ys);
}
}
// DynamicType type = (DynamicType) graph.getAttributes().getValue(column.getIndex());
// if (type != null) {
// List<Interval> intervals = type.getIntervals(model.getCustomMin(), model.getCustomMax());
// Number[] xs = new Number[intervals.size() * 2];
// Number[] ys = new Number[intervals.size() * 2];
// int i = 0;
// Interval interval;
// for (int j = 0; j < intervals.size(); j++) {
// interval = intervals.get(j);
// Number x = (Double) interval.getLow();
// Number y = (Number) interval.getValue();
// xs[i] = x;
// ys[i] = y;
// i++;
// if (j != intervals.size() - 1 && intervals.get(j + 1).getLow() < interval.getHigh()) {
// xs[i] = (Double) intervals.get(j + 1).getLow();
// } else {
// xs[i] = (Double) interval.getHigh();
// }
// ys[i] = y;
// i++;
// }
// if (xs.length > 0) {
// chart = new TimelineChartImpl(column, xs, ys);
// }
// }
}
model.setChart(chart);
......@@ -387,14 +449,12 @@ public class TimelineControllerImpl implements TimelineController, DynamicModelL
to += step;
someAction = true;
}
} else {
if (step > 0 && to < max) {
to += step;
someAction = true;
} else if (step < 0 && from > min) {
from += step;
someAction = true;
}
} else if (step > 0 && to < max) {
to += step;
someAction = true;
} else if (step < 0 && from > min) {
from += step;
someAction = true;
}
if (someAction) {
......
......@@ -42,8 +42,9 @@ Portions Copyrighted 2011 Gephi Consortium.
package org.gephi.timeline;
import java.util.concurrent.atomic.AtomicBoolean;
import org.gephi.dynamic.api.DynamicModel;
import org.gephi.dynamic.api.DynamicModel.TimeFormat;
import org.gephi.graph.api.GraphModel;
import org.gephi.graph.api.Interval;
import org.gephi.graph.api.TimeFormat;
import org.gephi.timeline.api.TimelineChart;
import org.gephi.timeline.api.TimelineModel;
......@@ -54,12 +55,12 @@ import org.gephi.timeline.api.TimelineModel;
public class TimelineModelImpl implements TimelineModel {
private boolean enabled;
private DynamicModel dynamicModel;
private final GraphModel graphModel;
private double customMin;
private double customMax;
//Animation
private int playDelay;
private AtomicBoolean playing;
private final AtomicBoolean playing;
private double playStep;
private PlayMode playMode;
//Chart
......@@ -67,17 +68,20 @@ public class TimelineModelImpl implements TimelineModel {
//MinMax
private double previousMin;
private double previousMax;
//
private Interval interval;
public TimelineModelImpl(DynamicModel dynamicModel) {
this.dynamicModel = dynamicModel;
this.customMin = dynamicModel.getMin();
this.customMax = dynamicModel.getMax();
public TimelineModelImpl(GraphModel dynamicModel) {
this.graphModel = dynamicModel;
this.customMin = dynamicModel.getTimeBounds().getLow();
this.customMax = dynamicModel.getTimeBounds().getHigh();
this.previousMin = customMin;
this.previousMax = customMax;
playDelay = 100;
playStep = 0.01;
playing = new AtomicBoolean(false);
playMode = PlayMode.TWO_BOUNDS;
interval = new Interval(customMin, customMax);
}
@Override
......@@ -87,12 +91,12 @@ public class TimelineModelImpl implements TimelineModel {
@Override
public double getMin() {
return dynamicModel.getMin();
return graphModel.getTimeBounds().getLow();
}
@Override
public double getMax() {
return dynamicModel.getMax();
return graphModel.getTimeBounds().getHigh();
}
public double getPreviousMin() {
......@@ -123,13 +127,14 @@ public class TimelineModelImpl implements TimelineModel {
@Override
public boolean hasCustomBounds() {
return customMax != dynamicModel.getMax() || customMin != dynamicModel.getMin();
Interval tm = graphModel.getTimeBounds();
return customMax != tm.getHigh() || customMin != tm.getLow();
}
@Override
public double getIntervalStart() {
double vi = dynamicModel.getVisibleInterval().getLow();
if(Double.isInfinite(vi)) {
double vi = interval.getLow();
if (Double.isInfinite(vi)) {
return getCustomMin();
}
return vi;
......@@ -137,8 +142,8 @@ public class TimelineModelImpl implements TimelineModel {
@Override
public double getIntervalEnd() {
double vi = dynamicModel.getVisibleInterval().getHigh();
if(Double.isInfinite(vi)) {
double vi = interval.getHigh();
if (Double.isInfinite(vi)) {
return getCustomMax();
}
return vi;
......@@ -146,11 +151,7 @@ public class TimelineModelImpl implements TimelineModel {
@Override
public TimeFormat getTimeFormat() {
return dynamicModel.getTimeFormat();
}
public DynamicModel getDynamicModel() {
return dynamicModel;
return graphModel.getTimeFormat();
}
public void setCustomMax(double customMax) {
......@@ -164,10 +165,19 @@ public class TimelineModelImpl implements TimelineModel {
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public void setInterval(double start, double end) {
this.interval = new Interval(start, end);
}
@Override
public boolean hasValidBounds() {
return !Double.isInfinite(dynamicModel.getMin()) && !Double.isInfinite(dynamicModel.getMax());
Interval i = graphModel.getTimeBounds();
return !Double.isInfinite(i.getLow()) && !Double.isInfinite(i.getHigh());
}
public GraphModel getGraphModel() {
return graphModel;
}
@Override
......
......@@ -41,44 +41,47 @@ Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.timeline.api;
import org.gephi.data.attributes.api.AttributeColumn;
import org.gephi.data.attributes.api.AttributeModel;
import org.gephi.graph.api.Graph;
/**
* Sparkline type chart visible in the timeline, for instance the number of nodes
* over time.
* Sparkline type chart visible in the timeline, for instance the number of
* nodes over time.
* <p>
* Charts are usually created from the Statistics module and data are saved
* within {@link Graph#getAttributes()}. Columns can be accessed from the graph table
* in the {@link AttributeModel#getGraphTable() }.
*
* within {@link Graph#getAttributes()}. Columns can be accessed from the graph
* table in the {@link AttributeModel#getGraphTable() }.
*
* @author Mathieu Bastian
* @see TimelineController#selectColumn(org.gephi.data.attributes.api.AttributeColumn)
* @see
* TimelineController#selectColumn(org.gephi.data.attributes.api.AttributeColumn)
*/
public interface TimelineChart {
/**
* The attribute column used to create this chart.
*
* @return the attribute column
*/
public AttributeColumn getColumn();
public String getColumn();
/**
* Returns the X values of this chart.
*
* @return the X values
*/
public Number[] getX();
/**
* Returns the Y values of this chart.
*
* @return the Y values
*/
public Number[] getY();
/**
* Return the Y value for the given <code>x</code> position. It returns the closest
* value, as <code>x</code> may not exist.
* Return the Y value for the given <code>x</code> position. It returns the
* closest value, as <code>x</code> may not exist.
*
* @param x the point in time
* @return the Y value
*/
......@@ -86,24 +89,28 @@ public interface TimelineChart {
/**
* Returns the min Y value .This is the minimum value in the chart.
*
* @return the min Y value
*/
public Number getMinY();
/**
* Returns the max Y value. This is the maximum value in the chart.
*
* @return the max Y value
*/
public Number getMaxY();
/**
* Returns the min X value .This is the minimum interval in the chart.
*
* @return the min X value
*/
public Number getMinX();
/**
* Returns the max X value. This is the maximum interval in the chart.
*
* @return the max X value
*/
public Number getMaxX();
......
......@@ -41,27 +41,28 @@ Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.timeline.api;
import org.gephi.data.attributes.api.AttributeColumn;
import org.gephi.dynamic.api.DynamicModel;
import org.gephi.graph.api.TimeFormat;
import org.gephi.project.api.Workspace;
/**
* Controls the timeline bounds and animation features.
* <p>
* By default the timeline is disabled and can be enabled with the <code>setEnabled()</code>
* method. Once enabled, the controller is setting its interval value to the
* {@link DynamicModel}.
* By default the timeline is disabled and can be enabled with the
* <code>setEnabled()</code> method. Once enabled, the controller is setting its
* interval value to the {@link DynamicModel}.
* <p>
* The interval can be animated using the <code>startPlay()</code> and <code>stopPlay()</code>
* methods. Configuration parameters are also available.
* The interval can be animated using the <code>startPlay()</code> and
* <code>stopPlay()</code> methods. Configuration parameters are also available.
* <p>
* This controller also allows to lookup graph attribute columns that can be used
* as sparklines (e.g. node count, average degree...). Use the <code>selectColumn()</code>
* to create a {@link TimelineChart} accessible from the <code>TimelineModel</code>
* This controller also allows to lookup graph attribute columns that can be
* used as sparklines (e.g. node count, average degree...). Use the
* <code>selectColumn()</code> to create a {@link TimelineChart} accessible from
* the <code>TimelineModel</code>
* <p>
* All interval values are in the same space as the <code>DynamicAPI</code> module and
* no value should eb out of the min/max bounds maintained by the <code>DynamicModel</code>.
*
* All interval values are in the same space as the <code>DynamicAPI</code>
* module and no value should eb out of the min/max bounds maintained by the
* <code>DynamicModel</code>.
*
* @author Julian Bilcke, Mathieu Bastian
* @see TimelineModel
*/
......@@ -69,6 +70,7 @@ public interface TimelineController {
/**
* Returns the timeline model from <code>workspace</code>.
*
* @param workspace the workspace to get the model from
* @return the timeline model for this workspace
*/
......@@ -82,8 +84,10 @@ public interface TimelineController {
public TimelineModel getModel();
/**
* Sets the timeline custom bounds. Custom bounds still need to be included in the
* min and max bound of the time scale. The timeline will resize accordingly.
* Sets the timeline custom bounds. Custom bounds still need to be included
* in the min and max bound of the time scale. The timeline will resize
* accordingly.
*
* @param min the lower bound
* @param max the upper bound
* @throws IllegalArgumentException if <code>min<code> is superior or equal than
......@@ -93,22 +97,29 @@ public interface TimelineController {
/**
* Sets the timeline enable status.
*
* @param enabled the enabled value to set
*/
public void setEnabled(boolean enabled);
/**
* Sets the current timeline interval. This is propagated to the <code>DynamicModel</code>
* and defines the interval the graph is filtered with.
* Sets the current timeline interval. This is propagated to the
* <code>DynamicModel</code> and defines the interval the graph is filtered
* with.
*
* @param from the lower bound
* @param to the upper bound
* @throws IllegalArgumentException if <code>min<code> is superior or equal than
* <code>max</code> or out of bounds
*/
public void setInterval(double from, double to);
public void setTimeFormat(TimeFormat timeFormat);
/**
* Starts the timeline animation using the current delay, step size and play mode.
* Starts the timeline animation using the current delay, step size and play
* mode.
*/
public void startPlay();
......@@ -118,8 +129,9 @@ public interface TimelineController {
public void stopPlay();
/**
* Sets the play delay in milliseconds. Defines the time between each interval
* shift.
* Sets the play delay in milliseconds. Defines the time between each
* interval shift.
*
* @param delay the delay in milliseconds
*/
public void setPlaySpeed(int delay);
......@@ -127,39 +139,46 @@ public interface TimelineController {
/**
* Sets the play step. Defines how much the interval is moved at each step
* during animation. Defined in percentage of the total interval.
*
* @param step the step, between 0 and 1
*/
public void setPlayStep(double step);
/**
* Sets the play mode. This defines how the interval is moved.
*
* @param playMode the play mode
*/
public void setPlayMode(TimelineModel.PlayMode playMode);
/**
* Returns all the possible dynamic attribute columns. This is essentially all
* number-based dynamic columns defined in the graph table.
* Returns all the possible dynamic attribute columns. This is essentially
* all number-based dynamic columns defined in the graph table.
*
* @return all dynamic number columns in the graph table
*/
public AttributeColumn[] getDynamicGraphColumns();
public String[] getDynamicGraphColumns();
/**
* Select a column to make a {@link TimelineChart} of it. The column must be member
* of the graph table.
* Select a column to make a {@link TimelineChart} of it. The column must be
* member of the graph table.
*
* @param column the column to select
* @throws IllegalArgumentException if <code>column</code> is not a graph column
* @throws IllegalArgumentException if <code>column</code> is not a graph
* column
*/
public void selectColumn(AttributeColumn column);
public void selectColumn(String column);
/**
* Add <code>listener</code> to the list of event listerners.
*
* @param listener the listener to add
*/
public void addListener(TimelineModelListener listener);
/**
* Remove <code>listerner</code> from the list of event listeners.
*
* @param listener the listener to remove
*/
public void removeListener(TimelineModelListener listener);
......
......@@ -41,7 +41,7 @@ Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.timeline.api;
import org.gephi.dynamic.api.DynamicModel;
import org.gephi.graph.api.TimeFormat;
/**
* Timeline model which holds timeline bounds, interval and animation flags.
......@@ -136,7 +136,7 @@ public interface TimelineModel {
* Returns the current time format. Default is <code>DOUBLE</code>
* @return the current tie
*/
public DynamicModel.TimeFormat getTimeFormat();
public TimeFormat getTimeFormat();
/**
* Returns the play delay in milliseconds. Defines the time between each interval
......
......@@ -97,4 +97,6 @@ public interface GraphDrawable {
public void destroy();
public Point getLocationOnScreen();
public void reinitWindow();
}
......@@ -182,4 +182,8 @@ public class OffscreenCanvas extends GLAbstractListener implements TileRendererB
public void endTileRendering(TileRendererBase trb) {
}
@Override
public void reinitWindow() {
}
}
......@@ -110,4 +110,8 @@ public class GraphCanvas extends GLAbstractListener {
protected void reshape3DScene(GL2 gl) {
}
@Override
public void reinitWindow() {
}
}
......@@ -50,6 +50,7 @@ import com.jogamp.opengl.glu.GLU;
import java.awt.Dimension;
import javax.swing.JPopupMenu;
import javax.swing.ToolTipManager;
import org.gephi.ui.utils.UIUtils;
/**
*
......@@ -93,11 +94,14 @@ public class NewtGraphCanvas extends GLAbstractListener {
engine.startDisplay();
}
@Override
public void reinitWindow() {
// Only used when collapse panel is set visible
// Workaround for JOGL bug 1274
glCanvas.setNEWTChild(null);
glCanvas.setNEWTChild(glWindow);
if (UIUtils.isAquaLookAndFeel()) {
// Only used when collapse panel is set visible
// Workaround for JOGL bug 1274
glCanvas.setNEWTChild(null);
glCanvas.setNEWTChild(glWindow);
}
}
@Override
......
......@@ -261,11 +261,10 @@
<groupId>${project.groupId}</groupId>
<artifactId>statistics-plugin-ui</artifactId>
</dependency>
<!-- <dependency>
<groupId>${project.groupId}</groupId>
<artifactId>timeline</artifactId>
</dependency>
-->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>timeline-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>tools-api</artifactId>
......@@ -433,11 +432,11 @@
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>desktop-tools</artifactId>
</dependency><!--
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>desktop-timeline</artifactId>
</dependency>-->
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>directory-chooser</artifactId>
......
......@@ -437,7 +437,7 @@
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>timeline</artifactId>
<artifactId>timeline-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
......@@ -1154,6 +1154,7 @@
<module>modules/DesktopRecentFiles</module>
<module>modules/DesktopStatistics</module>
<module>modules/DesktopTools</module>
<module>modules/DesktopTimeline</module>
<module>modules/DirectoryChooser</module>
<module>modules/ExportAPI</module>
<module>modules/ExportPlugin</module>
......@@ -1186,6 +1187,7 @@
<module>modules/StatisticsAPI</module>
<module>modules/StatisticsPlugin</module>
<module>modules/StatisticsPluginUI</module>
<module>modules/TimelineAPI</module>
<module>modules/ToolsAPI</module>
<module>modules/ToolsPlugin</module>
<module>modules/UIComponents</module>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册