提交 13b7071d 编写于 作者: M Mathieu Bastian

Adding back Filters modules, work in progress

上级 8157d300
......@@ -70,6 +70,7 @@ public class ContextRefreshThread extends TimerTask {
private void initObserver() {
if (observer == null || observer.isDestroyed()) {
observer = graphModel.createGraphObserver(graphModel.getGraphVisible(), false);
listener.run();
}
}
......
......@@ -64,6 +64,10 @@
<groupId>org.netbeans.api</groupId>
<artifactId>org-netbeans-modules-settings</artifactId>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-openide-util-ui</artifactId>
</dependency>
</dependencies>
<build>
......
......@@ -38,10 +38,12 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.desktop.filters;
import java.awt.BorderLayout;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
......@@ -72,6 +74,7 @@ public class FilterPanelPanel extends JPanel implements ChangeListener {
}
}
@Override
public void stateChanged(ChangeEvent e) {
refreshModel();
}
......@@ -106,6 +109,7 @@ public class FilterPanelPanel extends JPanel implements ChangeListener {
private void setQuery(final Query query) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
//UI update
removeAll();
......@@ -121,7 +125,7 @@ public class FilterPanelPanel extends JPanel implements ChangeListener {
setBorder(javax.swing.BorderFactory.createTitledBorder(query.getFilter().getName() + " " + settingsString));
}
} catch (Exception e) {
e.printStackTrace();
Logger.getLogger("").log(Level.SEVERE, "Error while setting query", e);
}
}
......
......@@ -38,7 +38,7 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.desktop.filters;
import java.util.ArrayList;
......@@ -47,7 +47,6 @@ import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.gephi.filters.api.Query;
import org.gephi.filters.spi.Category;
import org.gephi.filters.spi.Filter;
/**
*
......@@ -56,10 +55,10 @@ import org.gephi.filters.spi.Filter;
public final class FilterUIModel {
private Query selectedQuery;
private List<Query> expandedQueryNodes;
private List<Query> expandedParametersNodes;
private List<Category> expandedCategoryNodes;
private List<ChangeListener> listeners;
private final List<Query> expandedQueryNodes;
private final List<Query> expandedParametersNodes;
private final List<Category> expandedCategoryNodes;
private final List<ChangeListener> listeners;
public FilterUIModel() {
listeners = new ArrayList<ChangeListener>();
......
<?xml version="1.1" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
......
......@@ -69,14 +69,14 @@ import org.openide.util.NbBundle;
*/
public class FiltersPanel extends javax.swing.JPanel implements ExplorerManager.Provider, ChangeListener {
private ExplorerManager manager = new ExplorerManager();
private final ExplorerManager manager = new ExplorerManager();
//Models
private FilterModel filterModel;
private FilterUIModel uiModel;
//Components
private FilterPanelPanel filterPanelPanel;
private final FilterPanelPanel filterPanelPanel;
private QueryExplorer queriesExplorer;
private QueriesPanel queriesPanel;
private final QueriesPanel queriesPanel;
public FiltersPanel() {
initComponents();
......@@ -100,6 +100,7 @@ public class FiltersPanel extends javax.swing.JPanel implements ExplorerManager.
private void initEvents() {
resetButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
FilterController controller = Lookup.getDefault().lookup(FilterController.class);
for (Query query : filterModel.getQueries()) {
......@@ -113,6 +114,7 @@ public class FiltersPanel extends javax.swing.JPanel implements ExplorerManager.
});
filterButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//selectButton.setSelected(false);
if (uiModel.getSelectedQuery() != null && filterButton.isSelected()) {
......@@ -126,6 +128,7 @@ public class FiltersPanel extends javax.swing.JPanel implements ExplorerManager.
});
selectButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//filterButton.setSelected(false);
if (uiModel.getSelectedQuery() != null && selectButton.isSelected()) {
......@@ -139,6 +142,7 @@ public class FiltersPanel extends javax.swing.JPanel implements ExplorerManager.
});
exportColumnButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (uiModel.getSelectedQuery() != null) {
FilterController controller = Lookup.getDefault().lookup(FilterController.class);
......@@ -156,6 +160,7 @@ public class FiltersPanel extends javax.swing.JPanel implements ExplorerManager.
});
exportWorkspaceButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (uiModel.getSelectedQuery() != null) {
FilterController controller = Lookup.getDefault().lookup(FilterController.class);
......@@ -165,6 +170,7 @@ public class FiltersPanel extends javax.swing.JPanel implements ExplorerManager.
});
exportLabelVisible.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (uiModel.getSelectedQuery() != null) {
FilterController controller = Lookup.getDefault().lookup(FilterController.class);
......@@ -211,6 +217,7 @@ public class FiltersPanel extends javax.swing.JPanel implements ExplorerManager.
add(queriesExplorer, BorderLayout.CENTER);
}
@Override
public ExplorerManager getExplorerManager() {
return manager;
}
......@@ -219,6 +226,7 @@ public class FiltersPanel extends javax.swing.JPanel implements ExplorerManager.
private void updateEnabled(final boolean enabled) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
resetButton.setEnabled(enabled);
selectButton.setEnabled(enabled);
......@@ -234,6 +242,7 @@ public class FiltersPanel extends javax.swing.JPanel implements ExplorerManager.
private void updateControls() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (filterModel != null) {
filterButton.setSelected(filterModel.isFiltering());
......@@ -249,6 +258,7 @@ public class FiltersPanel extends javax.swing.JPanel implements ExplorerManager.
}
@Override
public void stateChanged(ChangeEvent e) {
if (e.getSource() instanceof FilterUIModel) {
if (uiModel.getSelectedQuery() != null && filterButton.isSelected()) {
......@@ -261,7 +271,7 @@ public class FiltersPanel extends javax.swing.JPanel implements ExplorerManager.
} else if (e.getSource() instanceof FilterModel) {
if (uiModel.getSelectedQuery() != null && filterModel.getCurrentQuery() == null) {
//Remove case
if(!Arrays.asList(filterModel.getQueries()).contains(uiModel.getSelectedRoot())) {
if (!Arrays.asList(filterModel.getQueries()).contains(uiModel.getSelectedRoot())) {
uiModel.setSelectedQuery(null);
}
} else if (filterModel.getCurrentQuery() != null
......@@ -292,10 +302,10 @@ public class FiltersPanel extends javax.swing.JPanel implements ExplorerManager.
}
}
/** 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
......@@ -439,6 +449,7 @@ public class FiltersPanel extends javax.swing.JPanel implements ExplorerManager.
private javax.swing.JToolBar toolbar;
// End of variables declaration//GEN-END:variables
@Override
public ExplorerManager getExplorerManager() {
return manager;
}
......
......@@ -71,7 +71,7 @@ public final class FiltersTopComponent extends TopComponent {
static final String ICON_PATH = "org/gephi/desktop/filters/resources/small.png";
private static final String PREFERRED_ID = "FiltersTopComponent";
//Panel
private FiltersPanel panel;
private final FiltersPanel panel;
//Models
private FilterModel filterModel;
private FilterUIModel uiModel;
......@@ -91,10 +91,12 @@ public final class FiltersTopComponent extends TopComponent {
ProjectController pc = Lookup.getDefault().lookup(ProjectController.class);
pc.addWorkspaceListener(new WorkspaceListener() {
@Override
public void initialize(Workspace workspace) {
workspace.add(new FilterUIModel());
}
@Override
public void select(Workspace workspace) {
filterModel = workspace.getLookup().lookup(FilterModel.class);
uiModel = workspace.getLookup().lookup(FilterUIModel.class);
......@@ -105,12 +107,15 @@ public final class FiltersTopComponent extends TopComponent {
refreshModel();
}
@Override
public void unselect(Workspace workspace) {
}
@Override
public void close(Workspace workspace) {
}
@Override
public void disable() {
filterModel = null;
uiModel = null;
......
......@@ -53,20 +53,19 @@ import org.gephi.project.api.Workspace;
* <pre>FilterController fc = Lookup.getDefault().lookup(FilterController.class);</pre>
* <p>
* The controller has two ways to execute filtering, a one-shot one that
* immediately returns the <code>GraphView</code> and a more complex one suitable
* for user interface interaction, with live parameter change.
* immediately returns the <code>GraphView</code> and a more complex one
* suitable for user interface interaction, with live parameter change.
* <p>
* The one-shot filtering can be executed like below:
* <pre>
* Filter filter = ...
* Query query = controller.createQuery(filter);
* GraphView view = controller.filter(query);
* </pre>
* The normal mode is to call {@link #filterVisible(org.gephi.filters.api.Query)}
* which let this controller manage the execution. The benefit of this of this mode
* is that properties change on filters are listened and filtering is automatically
* reexecuted if values changes. See how to execute a filter with two different
* values:
* </pre> The normal mode is to call
* {@link #filterVisible(org.gephi.filters.api.Query)} which let this controller
* manage the execution. The benefit of this of this mode is that properties
* change on filters are listened and filtering is automatically reexecuted if
* values changes. See how to execute a filter with two different values:
* <pre>
* Filter filter = ...
* filter.getProperties()[0].setValue(1); //Set value 1, for example a threshold
......@@ -75,107 +74,124 @@ import org.gephi.project.api.Workspace;
* controller.filterVisible(query); //A background thread executes the query
* filter.getProperties[0].setValue(2) //The background thread reexecute the query
* </pre>
*
* @author Mathieu Bastian
* @see GraphView
*/
public interface FilterController {
/**
* Creates a query from <code>filter</code>. The created query is a root query.
* @param filter the filter that is to be wrapped in a new query
* @return a query that is wrapping <code>filter</code>
* Creates a query from <code>filter</code>. The created query is a root
* query.
*
* @param filter the filter that is to be wrapped in a new query
* @return a query that is wrapping <code>filter</code>
*/
public Query createQuery(Filter filter);
/**
* Adds <code>query</code> as a new query in the system. The query should be
* a root query.
* @param query the query that is to be added
*
* @param query the query that is to be added
*/
public void add(Query query);
/**
* Removes <code>query</code> from the systemn if exists.
* @param query the query that is to be removed
* Removes <code>query</code> from the system if exists.
*
* @param query the query that is to be removed
*/
public void remove(Query query);
/**
* Renames <code>query</code> with <code>name</code>.
* @param query the query that is to be renamed
* @param name the new query's name
*
* @param query the query that is to be renamed
* @param name the new query's name
*/
public void rename(Query query, String name);
/**
* Sets <code>subQuery</code> as a child of <code>query</code>. If
* <code>subQuery</code> already has a parent query, it will be removed first.
* @param query the query that <code>subQuery</code> is to be added
* as a new child
* @param subQuery the query that is to be added as a child of <code>
* <code>subQuery</code> already has a parent query, it will be removed
* first.
*
* @param query the query that <code>subQuery</code> is to be added as a new
* child
* @param subQuery the query that is to be added as a child of <code>
* query</code>
*/
public void setSubQuery(Query query, Query subQuery);
/**
* Removes <code>query</code> from <code>parent</code> query.
* @param query the query that is to be removed from <code>parent</code>
* @param parent the query that <code>query</code> is to be removed as
* a child
*
* @param query the query that is to be removed from <code>parent</code>
* @param parent the query that <code>query</code> is to be removed as a
* child
*/
public void removeSubQuery(Query query, Query parent);
/**
* Filters main graph with <code>query</code> and set result as the new
* visible graph. Note that the query will be executed in a background thread
* and results delivered as soon as ready. Then, <code>query</code> is defined
* as the currently active query and property's value changes are watched.
* If a query's property is changed the query is automatically reexecuted.
* @param query the query that is to be executed
* visible graph. Note that the query will be executed in a background
* thread and results delivered as soon as ready. Then, <code>query</code>
* is defined as the currently active query and property's value changes are
* watched. If a query's property is changed the query is automatically
* reexecuted.
*
* @param query the query that is to be executed
*/
public void filterVisible(Query query);
/**
* Selects <code>query</code> results on the main graph visualization
* window. Note that the query will be executed in a background thread
* and results delivered as soon as ready. Then, <code>query</code> is defined
* window. Note that the query will be executed in a background thread and
* results delivered as soon as ready. Then, <code>query</code> is defined
* as the currently active query and property's value changes are watched.
* If a query's property is changed the query is automatically reexecuted.
* @param query the query that is to be executed
*
* @param query the query that is to be executed
*/
public void selectVisible(Query query);
/**
* Filtering method for API users. The <code>query</code> is executed and
* the <code>GraphView</code> result is returned.
* @param query the query that is to be executed
* @return a graph view that represents the query result
*
* @param query the query that is to be executed
* @return a graph view that represents the query result
*/
public GraphView filter(Query query);
/**
* Exports <code>query</code> result in a new column <code>title</code>.
* Nodes and edges that pass the <code>query</code> have <b>true</b> value and
* Nodes and edges that pass the <code>query</code> have <b>true</b> value
* and
* <b>false</b> for others.
* @param title the column's title
* @param query the query that is to be executed
*
* @param title the column's title
* @param query the query that is to be executed
*/
public void exportToColumn(String title, Query query);
/**
* Exports <code>query</code> result in a new workspace. Note that query is
* executed in a separate thread and the workspace may not be ready immediately
* when this method returns.
* @param query the query that is to be executed
* executed in a separate thread and the workspace may not be ready
* immediately when this method returns.
*
* @param query the query that is to be executed
*/
public void exportToNewWorkspace(Query query);
/**
* Exports <code>query</code> result to visible/hidden labels. Each node and
* edge not present in the query result has its label set hidden. Label
* visibility is controlled from <code>TextData</code> object, accessible from
* <code>NodeData</code> or <code>EdgeData</code>.
* @param query the query that is to be used to hide labels
* visibility is controlled from <code>TextData</code> object, accessible
* from <code>NodeData</code> or <code>EdgeData</code>.
*
* @param query the query that is to be used to hide labels
*/
public void exportToLabelVisible(Query query);
......@@ -185,13 +201,16 @@ public interface FilterController {
/**
* Returns the filter's model.
* @return the filter's model
*
* @return the filter's model
*/
public FilterModel getModel();
/**
* Returns the filter's model for <code>workspace</code>.
* @return the filter's model in the given workspace
*
* @param workspace workspace
* @return the filter's model in the given workspace
*/
public FilterModel getModel(Workspace workspace);
}
......@@ -38,7 +38,7 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.filters.api;
import org.gephi.filters.spi.FilterLibraryMask;
......@@ -51,11 +51,12 @@ import org.openide.util.NbBundle;
/**
* The Filter Library is the place where filter builders are registered and
* ready to be used. It also has default <b>Categories</b> that filters use to be
* sorted and well-described.
* ready to be used. It also has default <b>Categories</b> that filters use to
* be sorted and well-described.
* <p>
* Modules can dynamically create new filter builders and serve it ot users
* by using {@link #addBuilder(org.gephi.filters.spi.FilterBuilder) }.
* Modules can dynamically create new filter builders and serve it ot users by
* using {@link #addBuilder(org.gephi.filters.spi.FilterBuilder) }.
*
* @author Mathieu Bastian
*/
public interface FilterLibrary extends Lookup.Provider {
......@@ -79,14 +80,6 @@ public interface FilterLibrary extends Lookup.Provider {
null,
null);
/**
* Default <code>Category</code> for filters working on the graph hierarchy.
*/
public final static Category HIERARCHY = new Category(
NbBundle.getMessage(FilterLibrary.class, "FiltersLibrary.Category.Hierarchy"),
null,
TOPOLOGY);
/**
* Default <code>Category</code> for filters working on edges only.
*/
......@@ -97,13 +90,15 @@ public interface FilterLibrary extends Lookup.Provider {
/**
* Adds <code>builder</code> to this library.
* @param builder the builder that is to be added
*
* @param builder the builder that is to be added
*/
public void addBuilder(FilterBuilder builder);
/**
* Removes <code>builder</code> from this library.
* @param builder the builder that is to be removed
*
* @param builder the builder that is to be removed
*/
public void removeBuilder(FilterBuilder builder);
......@@ -113,52 +108,59 @@ public interface FilterLibrary extends Lookup.Provider {
* <ul><li>{@link FilterBuilder}: Builders, these are building filters.</li>
* <li>{@link CategoryBuilder}: Category builders, these are building.
* categories, i.e. filters containers.</li>
* <li>{@link FilterLibraryMask}: Masks, for enable/disable categories according
* to the context.</li>
* <li>{@link Query}: Saved queries, look at <code>FilterController</code> for
* active queries.</li></ul>
* The lists of all <code>FilterBuilder</code> in the library can be obtained
* by doing the following command:
* <li>{@link FilterLibraryMask}: Masks, for enable/disable categories
* according to the context.</li>
* <li>{@link Query}: Saved queries, look at <code>FilterController</code>
* for active queries.</li></ul>
* The lists of all <code>FilterBuilder</code> in the library can be
* obtained by doing the following command:
* <pre>
* FilterLibrary.getLookup().lookupAll(FilterBuilder.class);
* </pre>
* @return the lookup container of this library
*
* @return the lookup container of this library
*/
@Override
public Lookup getLookup();
/**
* Registers <code>mask</code> as a new <code>FilterLibraryMask</code>. Such
* masks have categories enable/disable flag. Useful to disable for instance
* filters for undirected graphs when the current graph is directed.
* @param mask the mask that is to be registered
*
* @param mask the mask that is to be registered
*/
public void registerMask(FilterLibraryMask mask);
/**
* Unregisters <code>mask</code> in the library. The mask will no longer be
* used.
* @param mask the mask that is to be unregistered
*
* @param mask the mask that is to be unregistered
*/
public void unregisterMask(FilterLibraryMask mask);
/**
* Returns the builder that has created <code>filter</code>.
* @param filter the filter that the builder is to be returned
* @return the builder that has created <code>filter</code>
*
* @param filter the filter that the builder is to be returned
* @return the builder that has created <code>filter</code>
*/
public FilterBuilder getBuilder(Filter filter);
/**
* Save <code>query</code> in the library in order it can be reused. Saved
* queries are saved to the project.
* @param query the query that is to be saved
*
* @param query the query that is to be saved
*/
public void saveQuery(Query query);
/**
* Delete a saved <code>query</code> from the library. Deleted
* queries are deleted from the project.
* @param query the query that is to be deleted
* Delete a saved <code>query</code> from the library. Deleted queries are
* deleted from the project.
*
* @param query the query that is to be deleted
*/
public void deleteQuery(Query query);
}
......@@ -38,7 +38,7 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.filters.api;
import javax.swing.event.ChangeListener;
......@@ -46,9 +46,9 @@ import org.gephi.filters.spi.FilterBuilder;
/**
* The Filter Model hosts the queries defined in the system and the currently
* active query. It also stroe the selection or filtering flag. The filtering mode
* display the subgraph made from filters, whereas the selection mode highlight
* elements on the graph.
* active query. It also stroe the selection or filtering flag. The filtering
* mode display the subgraph made from filters, whereas the selection mode
* highlight elements on the graph.
*
* @author Mathieu Bastian
* @see FilterController
......@@ -58,24 +58,29 @@ public interface FilterModel {
/**
* Returns the <code>FilterLibrary</code>, where {@link FilterBuilder}
* belongs to.
* @return the filter library
*
* @return the filter library
*/
public FilterLibrary getLibrary();
/**
* Returns all queries in the model, represented by their root query.
* @return all root queries in the model
*
* @return all root queries in the model
*/
public Query[] getQueries();
/**
* Returns the query currently active or <code>null</code> if none is active.
* @return the current query
* Returns the query currently active or <code>null</code> if none is
* active.
*
* @return the current query
*/
public Query getCurrentQuery();
/**
* Returns <code>true</code> if the system is currently in filtering mode.
*
* @return <code>true</code> if the result graph is filtered,
* <code>false</code> if it's in selection mode
*/
......@@ -83,6 +88,7 @@ public interface FilterModel {
/**
* Returns <code>true</code> if the system is currently in selection mode.
*
* @return <code>true</code> if the result is selected on the graph,
* <code>false</code> if it's filtered
*/
......
......@@ -38,17 +38,17 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.filters.api;
import org.gephi.filters.spi.FilterProperty;
/**
* PropertyExecutor's role is to synchronize property edition with filter execution.
* When a filter is executed it usually uses properties users can edit. Editing
* properties values while a filter is executing in another thread could make
* uncertain behaviour. This executor is responsible to postpone value edition
* until filter's execution is finished.
* PropertyExecutor's role is to synchronize property edition with filter
* execution. When a filter is executed it usually uses properties users can
* edit. Editing properties values while a filter is executing in another thread
* could make uncertain behaviour. This executor is responsible to postpone
* value edition until filter's execution is finished.
*
* @author Mathieu Bastian
* @see FilterProperty
......@@ -58,9 +58,10 @@ public interface PropertyExecutor {
/**
* Set <code>value</code> on <code>property</code> in a safe way by using
* <code>callback</code>.
* @param property the filter property that value is to be set
* @param value the value that is to be set
* @param callback the callback function to be notified when setting has to
*
* @param property the filter property that value is to be set
* @param value the value that is to be set
* @param callback the callback function to be notified when setting has to
* be done
*/
public void setValue(FilterProperty property, Object value, Callback callback);
......
......@@ -38,7 +38,7 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.filters.api;
import org.gephi.filters.spi.Filter;
......@@ -46,14 +46,14 @@ import org.gephi.filters.spi.Filter;
/**
* Queries are wrapping filters and are assembled in a query tree. Each query is
* built from a single filter instance and it's role is to basically to execute
* the filter. The graph that is passed to the filter depends on the fact the query
* belongs to a complex query tree or if the tree is a single leaf.
* the filter. The graph that is passed to the filter depends on the fact the
* query belongs to a complex query tree or if the tree is a single leaf.
* <p>
* The system works like this. Leaves of the query tree receives the complete
* graph and the subgraphs they return are passed to the parent query. Thus the
* root query is the last query to get the subgraphs and returns the final result.
* This querying system make possible to create query chains and complex scenario
* with various operators (AND, OR, ...).
* root query is the last query to get the subgraphs and returns the final
* result. This querying system make possible to create query chains and complex
* scenario with various operators (AND, OR, ...).
* <p>
* Queries are built by the <code>FilterController</code> from filter instances.
*
......@@ -64,39 +64,45 @@ public interface Query {
/**
* Returns query's full name.
* @return query's name
*
* @return query's name
*/
public String getName();
/**
* Returns queries that are children of this query.
* @return query's children
*
* @return query's children
*/
public Query[] getChildren();
/**
* Returns the limit number of children this query can have. Return 1 for a
* standard query.
* @return the number of allowed children query
*
* @return the number of allowed children query
*/
public int getChildrenSlotsCount();
/**
* Returns the parent query or <code>null</code> if this query is root.
* @return the query's parent query, or <code>null</code>
*
* @return the query's parent query, or <code>null</code>
*/
public Query getParent();
/**
* Returns the number of properties this query has.
* @return the query's number of properties
*
* @return the query's number of properties
*/
public int getPropertiesCount();
/**
* Returns the name of the property at the specified <code>index</code>.
*
* @param index the index of the property
* @return the query's property name
* @return the query's property name
* @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
* bounds
*/
......@@ -104,8 +110,9 @@ public interface Query {
/**
* Returns the value of the property at the specified <code>index</code>.
*
* @param index the index of the property
* @return the query's property value
* @return the query's property value
* @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
* bounds
*/
......@@ -114,21 +121,24 @@ public interface Query {
/**
* Utility method that returns all queries in this query hierarchy that are
* <code>filterClass</code> instance.
*
* @param filterClass the filter class that is to be queried
* @return all queries, including self that are <code>filterClass</code>
* @return all queries, including self that are <code>filterClass</code>
* instance
*/
public Query[] getQueries(Class<? extends Filter> filterClass);
/**
* Utility method that returns all descendant queries plus this query.
* @return all descendant queries and self
*
* @return all descendant queries and self
*/
public Query[] getDescendantsAndSelf();
/**
* Returns the filter this query is wrapping.
* @return the filter
*
* @return the filter
*/
public Filter getFilter();
}
......@@ -38,7 +38,7 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.filters.spi;
import javax.swing.Icon;
......@@ -53,22 +53,22 @@ import org.gephi.filters.api.FilterLibrary;
* <li><code>FilterLibrary.ATTRIBUTES</code></li>
* <li><code>FilterLibrary.EDGE</code></li>
* <li><code>FilterLibrary.HIERARCHY</code></li></ul>
*
* @author Mathieu Bastian
* @see FilterLibrary
*/
public final class Category {
private String name;
private Icon icon;
private Category parent;
private final String name;
private final Icon icon;
private final Category parent;
public Category(String name) {
this.name = name;
this(name, null, null);
}
public Category(String name, Icon icon) {
this.name = name;
this.icon = icon;
this(name, icon, null);
}
public Category(String name, Icon icon, Category parent) {
......@@ -79,7 +79,8 @@ public final class Category {
/**
* Returns the category's name.
* @return the name of this category
*
* @return the name of this category
*/
public String getName() {
return name;
......@@ -87,7 +88,8 @@ public final class Category {
/**
* Returns the icon or <code>null</code> if the category has no icon.
* @return the icon or <code>null</code>
*
* @return the icon or <code>null</code>
*/
public Icon getIcon() {
return icon;
......@@ -96,7 +98,8 @@ public final class Category {
/**
* Returns this category parent category or <code>null</code> if this
* category has no parent.
* @return this category's parent or <code>null</code>
*
* @return this category's parent or <code>null</code>
*/
public Category getParent() {
return parent;
......@@ -109,7 +112,7 @@ public final class Category {
}
if (obj instanceof Category) {
Category cat = (Category) obj;
if (cat.icon == icon && (cat.name == name || cat.name.equals(name)) && (cat.parent == parent || cat.parent.equals(parent))) {
if (cat.icon == icon && cat.name.equals(name) && (cat.parent == parent || cat.parent.equals(parent))) {
return true;
}
}
......
......@@ -38,16 +38,16 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.filters.spi;
/**
* Category builder is a convenient way to define multiple builders from a single
* source and grouped in a single category.
* Category builder is a convenient way to define multiple builders from a
* single source and grouped in a single category.
* <p>
* Implement <code>CategoryBuilder</code>
* for instance for creating a set of filter builders working on attributes, with
* one <code>FilterBuilder</code> per attribute column.
* Implement <code>CategoryBuilder</code> for instance for creating a set of
* filter builders working on attributes, with one <code>FilterBuilder</code>
* per attribute column.
* <p>
* Note that filter builders returned by category builders don't have to be
* registered on they own, once here is enough.
......@@ -59,14 +59,16 @@ public interface CategoryBuilder {
/**
* Returns the filter builders this category builder is building.
* @return the builders this category builder is building
*
* @return the builders this category builder is building
*/
public FilterBuilder[] getBuilders();
/**
* Returns the category builders are to be grouped in. It can't be a
* default category.
* @return the category builders belong to
* Returns the category builders are to be grouped in. It can't be a default
* category.
*
* @return the category builders belong to
*/
public Category getCategory();
}
......@@ -38,15 +38,15 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.filters.spi;
import org.gephi.graph.api.Graph;
/**
* Filter working with full graphs and generally returning a subgraph. Node and
* Edge filters removes either nodes or edges but not both. This filter interface
* has to be used in these case.
* Edge filters removes either nodes or edges but not both. This filter
* interface has to be used in these case.
*
* @author Mathieu Bastian
*/
......
......@@ -38,24 +38,18 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.filters.spi;
import org.gephi.graph.api.Edge;
import org.gephi.graph.api.Graph;
/**
* Basic filters for edges, that works as predicates. For a given edge the filter's
* role is to return <code>true</code> if the edge is kept or <code>false</code>
* if it is removed.
* Basic filters for edges, that works as predicates. For a given edge the
* filter's role is to return <code>true</code> if the edge is kept or
* <code>false</code> if it is removed.
*
* @author Mathieu Bastian
*/
public interface EdgeFilter extends Filter {
public boolean init(Graph graph);
public boolean evaluate(Graph graph, Edge edge);
public interface EdgeFilter extends ElementFilter<Edge> {
public void finish();
}
......@@ -38,35 +38,29 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.filters.spi;
import org.gephi.graph.api.Attributable;
import org.gephi.graph.api.Element;
import org.gephi.graph.api.Graph;
/**
* Basic filters for attributable objects (nodes or edges). For a given object the filter's
* role is to return <code>true</code> if the attributable is kept or <code>false</code>
* if it is removed.
* Basic filters for elements (nodes or edges). For a given object the filter's
* role is to return <code>true</code> if the element is kept or
* <code>false</code> if it is removed.
* <p>
* This filter is useful for dealing with attributes, which can either be in nodes
* or edges. As a filter can't be for nodes and edges at the same time the filter has to
* return the appropriate type.
*
* This filter is useful for dealing with attributes, which can either be in
* nodes or edges. As a filter can't be for nodes and edges at the same time the
* filter has to specify K.
*
* @author Mathieu Bastian
* @param <K> element class
*/
public interface AttributableFilter extends Filter {
public enum Type {
NODE, EDGE
};
public interface ElementFilter<K extends Element> extends Filter {
public boolean init(Graph graph);
public boolean evaluate(Graph graph, Attributable attributable);
public boolean evaluate(Graph graph, K element);
public void finish();
public Type getType();
}
......@@ -38,21 +38,22 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.filters.spi;
import org.gephi.filters.api.Query;
/**
* Filters are pruning the graph by keeping only nodes and edges that satisify
* Filters are pruning the graph by keeping only nodes and edges that satisfy
* filters conditions. Filters are predicates or functions that reduce the graph
* and therefore create sub-graphs.
* <p>
* Filters are the basic building blocks that are wrapped in queries and assembled to
* make simple or complex conditions on nodes and edges.
* Filters are the basic building blocks that are wrapped in queries and
* assembled to make simple or complex conditions on nodes and edges.
* <p>
* Filters objects are built in {@link FilterBuilder}. Implementors should define
* their own <code>FilterBuilder</code> class to propose new filter to users.
* Filters objects are built in {@link FilterBuilder}. Implementors should
* define their own <code>FilterBuilder</code> class to propose new filter to
* users.
*
* @author Mathieu Bastian
* @see Query
......@@ -61,14 +62,16 @@ public interface Filter {
/**
* Returns the filter's display name.
* @return the filter's dispaly name
*
* @return the filter's display name
*/
public String getName();
/**
* Returns the filter properties. Property values can be get and set from
* <code>FilterProperty</code> objects.
* @return the filter's properties
*
* @return the filter's properties
*/
public FilterProperty[] getProperties();
}
......@@ -38,7 +38,7 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.filters.spi;
import javax.swing.Icon;
......@@ -46,8 +46,8 @@ import javax.swing.JPanel;
import org.gephi.filters.api.FilterLibrary;
/**
* Filter builder, creating <code>Filter</code> instances for a <b>single</b> type
* of filters. Provides also the settings panel for the type of filter.
* Filter builder, creating <code>Filter</code> instances for a <b>single</b>
* type of filters. Provides also the settings panel for the type of filter.
* <p>
* Implementors should add the <code>@ServiceProvider</code> annotation to be
* registered by the system or call <code>FilterLibrary.addBuilder()</code>.
......@@ -55,10 +55,11 @@ import org.gephi.filters.api.FilterLibrary;
* The <code>JPanel</code> returned by the <code>getPanel()</code> method is the
* settings panel that configures the filter parameters. These parameters can be
* get and set by using {@link Filter#getProperties()}. Settings panel should
* always set parameters values in that way. As a result the system will be aware
* values changed and update the filter.
* always set parameters values in that way. As a result the system will be
* aware values changed and update the filter.
* <p>
* See {@link CategoryBuilder} for builders that host multiple types of filters.
*
* @author Mathieu Bastian
* @see FilterLibrary
*/
......@@ -66,44 +67,51 @@ public interface FilterBuilder {
/**
* Returns the category this filter builder belongs to.
* @return the category this builder belongs to
*
* @return the category this builder belongs to
*/
public Category getCategory();
/**
* Returns the display name of this filter builder
* @return the display name
*
* @return the display name
*/
public String getName();
/**
* Returns the icon of this filter builder
* @return the icon
*
* @return the icon
*/
public Icon getIcon();
/**
* Returns ths description text of this filter builder
* @return the description
* Returns this description text of this filter builder
*
* @return the description
*/
public String getDescription();
/**
* Builds a new <code>Filter</code> instance.
* @return a new <code>Filter</code> object
*
* @return a new <code>Filter</code> object
*/
public Filter getFilter();
/**
* Returns the settings panel for the filter this builder is building, the
* <code>filter</code> object is passed as a parameter.
* @param filter the filter that the panel is to be configuring
* @return the filter's settings panel
*
* @param filter the filter that the panel is to be configuring
* @return the filter's settings panel
*/
public JPanel getPanel(Filter filter);
/**
* Notification when the filter is destroyed, to perform clean-up tasks.
* @param filter filter to be destroyed
*/
public void destroy(Filter filter);
}
......@@ -38,7 +38,7 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.filters.spi;
import org.gephi.filters.api.FilterLibrary;
......@@ -46,8 +46,8 @@ import org.gephi.filters.api.FilterLibrary;
/**
* Classes that implements this interface can be registered to the filter
* library to programmatically enable or disable categories, i.e. filters
* container. That is useful for instance to disable filters working on undirected
* graphs if the current graph is directed.
* container. That is useful for instance to disable filters working on
* undirected graphs if the current graph is directed.
* <p>
* When registered, masks are asked whether the category is valid.
*
......@@ -58,13 +58,15 @@ public interface FilterLibraryMask {
/**
* Returns the <code>Category</code> this masks is associated.
* @return the <code>Category</code> this filter is describing
*
* @return the <code>Category</code> this filter is describing
*/
public Category getCategory();
/**
* Returns <code>true</code> if this masks's category is valid.
* @return <code>true</code> if the category is valid, <code>false</code>
* Returns <code>true</code> if this masks' category is valid.
*
* @return <code>true</code> if the category is valid, <code>false</code>
* otherwise
*/
public boolean isValid();
......
......@@ -38,10 +38,12 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.filters.spi;
import java.beans.PropertyEditor;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.gephi.filters.api.PropertyExecutor;
import org.openide.nodes.PropertySupport;
import org.openide.util.Lookup;
......@@ -51,9 +53,9 @@ import org.openide.util.Lookup;
* through this class, especially setting value should be done by using
* {@link #setValue(java.lang.Object) }.
* <p>
* The role of this class is to define filter's properties in order value changes
* can be tracked by the system, UI can be generated and values correctly saved
* in projects file.
* The role of this class is to define filter's properties in order value
* changes can be tracked by the system, UI can be generated and values
* correctly saved in projects file.
*
* @author Mathieu Bastian
*/
......@@ -70,7 +72,8 @@ public final class FilterProperty {
/**
* Returns property's name
* @return property's name
*
* @return property's name
*/
public String getName() {
return property.getDisplayName();
......@@ -78,13 +81,14 @@ public final class FilterProperty {
/**
* Returns property's value, can be <code>null</code>
* @return property's value
*
* @return property's value
*/
public Object getValue() {
try {
return property.getValue();
} catch (Exception ex) {
ex.printStackTrace();
} catch (Exception e) {
Logger.getLogger("").log(Level.SEVERE, "Error while getting value for property '" + getName() + "'", e);
}
return null;
}
......@@ -92,17 +96,19 @@ public final class FilterProperty {
/**
* Set property's value. The type of <code>value</code> must match with this
* property value type.
*
* @param value the value that is to be set
*/
public void setValue(Object value) {
if (propertyExecutor != null) {
propertyExecutor.setValue(this, value, new PropertyExecutor.Callback() {
@Override
public void setValue(Object value) {
try {
property.setValue(value);
} catch (Exception e) {
e.printStackTrace();
Logger.getLogger("").log(Level.SEVERE, "Error while setting value for property '" + getName() + "'", e);
}
}
});
......@@ -110,14 +116,15 @@ public final class FilterProperty {
try {
property.setValue(value);
} catch (Exception e) {
e.printStackTrace();
Logger.getLogger("").log(Level.SEVERE, "Error while setting value for property '" + getName() + "'", e);
}
}
}
/**
* Returns the <code>PropertyEditor</code> associated to the property value.
* @return the property editor
*
* @return the property editor
*/
public PropertyEditor getPropertyEditor() {
return property.getPropertyEditor();
......@@ -126,6 +133,7 @@ public final class FilterProperty {
/**
* Sets the property editor class. The class must implement
* {@link PropertyEditor}.
*
* @param clazz the property editor class
*/
public void setPropertyEditorClass(Class<? extends PropertyEditor> clazz) {
......@@ -134,7 +142,8 @@ public final class FilterProperty {
/**
* Returns the property's value type.
* @return the value type
*
* @return the value type
*/
public Class getValueType() {
return property.getValueType();
......@@ -142,23 +151,27 @@ public final class FilterProperty {
/**
* Returns the filter instance this property is associated to.
* @return the filter this property belongs to
*
* @return the filter this property belongs to
*/
public Filter getFilter() {
return filter;
}
/**
* Create a property.
* Creates a property.
*
* @param filter The filter instance
* @param valueType The type of the property value, ex: <code>Double.class</code>
* @param valueType The type of the property value, ex:
* <code>Double.class</code>
* @param propertyName The display name of the property
* @param getMethod The name of the get method for this property, must exist
* to make Java reflexion working.
* @param setMethod The name of the set method for this property, must exist
* to make Java reflexion working.
* @return the created property
* @throws NoSuchMethodException if the getter or setter methods cannot be found
* @throws NoSuchMethodException if the getter or setter methods cannot be
* found
*/
public static FilterProperty createProperty(Filter filter, Class valueType, String propertyName, String getMethod, String setMethod) throws NoSuchMethodException {
final FilterProperty filterProperty = new FilterProperty(filter);
......@@ -170,11 +183,15 @@ public final class FilterProperty {
}
/**
* Create a property.
* @param filter The filter instance
* @param valueType The type of the property value, ex: <code>Double.class</code>
* @param fieldName The Java field name of the property
* @throws NoSuchMethodException if the getter or setter methods cannot be found
* Creates a property.
*
* @param filter filter instance
* @param valueType type of the property value, ex:
* <code>Double.class</code>
* @param fieldName java field name of the property
* @return the created property
* @throws NoSuchMethodException if the getter or setter methods cannot be
* found
*/
public static FilterProperty createProperty(Filter filter, Class valueType, String fieldName) throws NoSuchMethodException {
if (valueType == Boolean.class) {
......
......@@ -38,25 +38,18 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.filters.spi;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.Node;
/**
* Basic filters for nodes, that works as predicates. For a given node the filter's
* role is to return <code>true</code> if the node is kept or <code>false</code>
* if it is removed.
*
* Basic filters for nodes, that works as predicates. For a given node the
* filter's role is to return <code>true</code> if the node is kept or
* <code>false</code> if it is removed.
*
* @author Mathieu Bastian
*/
public interface NodeFilter extends Filter {
public boolean init(Graph graph);
public boolean evaluate(Graph graph, Node node);
public interface NodeFilter extends ElementFilter<Node> {
public void finish();
}
......@@ -38,10 +38,11 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.filters.spi;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.Subgraph;
/**
*
......@@ -49,7 +50,7 @@ import org.gephi.graph.api.Graph;
*/
public interface Operator extends Filter {
public Graph filter(Graph[] graphs);
public Graph filter(Subgraph[] graphs);
public Graph filter(Graph graph, Filter[] filters);
......
......@@ -38,7 +38,7 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.filters.spi;
import org.gephi.graph.api.Graph;
......@@ -48,9 +48,9 @@ import org.gephi.graph.api.Graph;
* @author mbastian
*/
public interface RangeFilter extends Filter {
public Number[] getValues(Graph graph);
public FilterProperty getRangeProperty();
}
......@@ -20,10 +20,6 @@
<groupId>org.netbeans.api</groupId>
<artifactId>org-netbeans-api-annotations-common</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>data-attributes-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>filters-api</artifactId>
......
......@@ -67,18 +67,24 @@ public abstract class AbstractQueryImpl implements Query {
this.children = new ArrayList<AbstractQueryImpl>();
}
@Override
public abstract int getChildrenSlotsCount();
@Override
public abstract int getPropertiesCount();
@Override
public abstract String getPropertyName(int index);
@Override
public abstract Object getPropertyValue(int index);
@Override
public abstract String getName();
public abstract void setName(String name);
@Override
public Query[] getChildren() {
return children.toArray(new Query[0]);
}
......@@ -100,6 +106,7 @@ public abstract class AbstractQueryImpl implements Query {
children.remove((AbstractQueryImpl) subQuery);
}
@Override
public Query getParent() {
return parent;
}
......@@ -158,6 +165,7 @@ public abstract class AbstractQueryImpl implements Query {
return copy;
}
@Override
public Query[] getQueries(Class<? extends Filter> filterClass) {
List<Query> r = new LinkedList<Query>();
LinkedList<Query> stack = new LinkedList<Query>();
......@@ -176,6 +184,7 @@ public abstract class AbstractQueryImpl implements Query {
return r.toArray(new Query[0]);
}
@Override
public Query[] getDescendantsAndSelf() {
List<Query> r = new LinkedList<Query>();
LinkedList<Query> stack = new LinkedList<Query>();
......
......@@ -38,14 +38,13 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.filters;
import java.beans.PropertyEditorSupport;
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.AttributeType;
import org.gephi.graph.api.Column;
import org.gephi.graph.api.GraphController;
import org.gephi.graph.api.GraphModel;
import org.openide.util.Lookup;
/**
......@@ -53,12 +52,12 @@ import org.openide.util.Lookup;
* @author Mathieu Bastian
*/
public class AttributeColumnPropertyEditor extends PropertyEditorSupport {
private AttributeColumn column;
private Column column;
@Override
public void setValue(Object value) {
this.column = (AttributeColumn) value;
this.column = (Column) value;
}
@Override
......@@ -69,11 +68,11 @@ public class AttributeColumnPropertyEditor extends PropertyEditorSupport {
@Override
public String getAsText() {
if (column != null) {
AttributeModel model = Lookup.getDefault().lookup(AttributeController.class).getModel();
GraphModel model = Lookup.getDefault().lookup(GraphController.class).getGraphModel();
if (model.getNodeTable().hasColumn(column.getTitle())) {
return "NODE*-*" + column.getId() + "*-*" + column.getType().getTypeString();
return "NODE*-*" + column.getId() + "*-*" + column.getTypeClass().getName();
} else if (model.getEdgeTable().hasColumn(column.getTitle())) {
return "EDGE*-*" + column.getId() + "*-*" + column.getType().getTypeString();
return "EDGE*-*" + column.getId() + "*-*" + column.getTypeClass().getName();
}
}
return "null";
......@@ -83,12 +82,12 @@ public class AttributeColumnPropertyEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
if (!text.equals("null")) {
AttributeModel model = Lookup.getDefault().lookup(AttributeController.class).getModel();
GraphModel model = Lookup.getDefault().lookup(GraphController.class).getGraphModel();
String[] arr = text.split("\\*-\\*");
if (arr[0].equals("NODE")) {
column = model.getNodeTable().getColumn(arr[1], AttributeType.valueOf(arr[2]));
column = model.getNodeTable().getColumn(arr[1]);
} else if (arr[0].equals("EDGE")) {
column = model.getEdgeTable().getColumn(arr[1], AttributeType.valueOf(arr[2]));
column = model.getEdgeTable().getColumn(arr[1]);
}
}
}
......
......@@ -41,23 +41,21 @@ Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.filters;
import java.util.concurrent.atomic.AtomicBoolean;
import org.gephi.graph.api.GraphEvent;
import org.gephi.graph.api.GraphListener;
import org.gephi.graph.api.GraphModel;
import org.gephi.graph.api.GraphObserver;
import org.openide.util.Exceptions;
/**
*
* @author Mathieu Bastian
*/
public class FilterAutoRefreshor extends Thread implements GraphListener {
public class FilterAutoRefreshor extends Thread {
private static final int TIMER = 1000;
private final GraphModel graphModel;
private final FilterModelImpl filterModel;
private GraphObserver observer;
private boolean running = true;
private AtomicBoolean refresh = new AtomicBoolean(false);
public FilterAutoRefreshor(FilterModelImpl filterModel, GraphModel graphModel) {
super("Filter Auto-Refresh");
......@@ -70,7 +68,7 @@ public class FilterAutoRefreshor extends Thread implements GraphListener {
public void run() {
while (running) {
try {
if (refresh.compareAndSet(true, false)) {
if (observer != null && observer.hasGraphChanged()) {
manualRefresh();
}
Thread.sleep(TIMER);
......@@ -82,30 +80,25 @@ public class FilterAutoRefreshor extends Thread implements GraphListener {
public void setEnable(boolean enable) {
if (enable) {
graphModel.addGraphListener(this);
} else {
graphModel.removeGraphListener(this);
refresh.set(false);
if (observer == null) {
observer = graphModel.createGraphObserver(graphModel.getGraph(), false);
}
} else if (observer != null && !observer.isDestroyed()) {
observer.destroy();
observer = null;
}
if (!isAlive()) {
start();
}
}
public void graphChanged(GraphEvent event) {
if (event.getSource().isMainView() && event.is(GraphEvent.EventType.ADD_NODES_AND_EDGES,
GraphEvent.EventType.REMOVE_NODES_AND_EDGES,
GraphEvent.EventType.MOVE_NODES)) {
refresh.set(true);
//System.out.println("set refresh true");
}
}
public void setRunning(boolean running) {
this.running = running;
if (!running) {
graphModel.removeGraphListener(this);
refresh.set(false);
if (observer != null && !observer.isDestroyed()) {
observer.destroy();
observer = null;
}
}
}
......
......@@ -42,11 +42,6 @@
package org.gephi.filters;
import java.beans.PropertyEditorManager;
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.AttributeOrigin;
import org.gephi.data.attributes.api.AttributeType;
import org.gephi.filters.api.FilterController;
import org.gephi.filters.api.FilterModel;
import org.gephi.filters.api.PropertyExecutor;
......@@ -54,13 +49,14 @@ import org.gephi.filters.api.Query;
import org.gephi.filters.api.Range;
import org.gephi.filters.FilterThread.PropertyModifier;
import org.gephi.filters.spi.*;
import org.gephi.graph.api.Column;
import org.gephi.graph.api.Edge;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.GraphController;
import org.gephi.graph.api.GraphModel;
import org.gephi.graph.api.GraphView;
import org.gephi.graph.api.HierarchicalGraph;
import org.gephi.graph.api.Node;
import org.gephi.graph.api.Origin;
import org.gephi.project.api.ProjectController;
import org.gephi.utils.progress.Progress;
import org.gephi.utils.progress.ProgressTicket;
......@@ -70,6 +66,7 @@ import org.gephi.project.api.WorkspaceInformation;
import org.gephi.project.api.WorkspaceListener;
import org.gephi.visualization.api.VisualizationController;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
import org.openide.util.lookup.ServiceProviders;
......@@ -87,16 +84,18 @@ public class FilterControllerImpl implements FilterController, PropertyExecutor
public FilterControllerImpl() {
//Register range editor
PropertyEditorManager.registerEditor(Range.class, RangePropertyEditor.class);
PropertyEditorManager.registerEditor(AttributeColumn.class, AttributeColumnPropertyEditor.class);
PropertyEditorManager.registerEditor(Column.class, AttributeColumnPropertyEditor.class);
//Model management
ProjectController pc = Lookup.getDefault().lookup(ProjectController.class);
pc.addWorkspaceListener(new WorkspaceListener() {
@Override
public void initialize(Workspace workspace) {
workspace.add(new FilterModelImpl(workspace));
}
@Override
public void select(Workspace workspace) {
model = (FilterModelImpl) workspace.getLookup().lookup(FilterModel.class);
if (model == null) {
......@@ -105,9 +104,11 @@ public class FilterControllerImpl implements FilterController, PropertyExecutor
}
}
@Override
public void unselect(Workspace workspace) {
}
@Override
public void close(Workspace workspace) {
FilterModelImpl m = (FilterModelImpl) workspace.getLookup().lookup(FilterModel.class);
if (m != null) {
......@@ -115,10 +116,14 @@ public class FilterControllerImpl implements FilterController, PropertyExecutor
}
}
@Override
public void disable() {
GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getModel();
if (model != null && model.getCurrentResult() != null && graphModel != null) {
graphModel.destroyView(model.getCurrentResult());
if (model != null && model.getCurrentResult() != null) {
GraphModel graphModel = model.getGraphModel();
if (graphModel != null) {
graphModel.destroyView(model.getCurrentResult());
}
model.setCurrentResult(null);
}
model = null;
......@@ -134,6 +139,7 @@ public class FilterControllerImpl implements FilterController, PropertyExecutor
}
}
@Override
public Query createQuery(Filter filter) {
if (filter instanceof Operator) {
return new OperatorQueryImpl((Operator) filter);
......@@ -141,6 +147,7 @@ public class FilterControllerImpl implements FilterController, PropertyExecutor
return new FilterQueryImpl(filter);
}
@Override
public void add(Query query) {
AbstractQueryImpl absQuery = ((AbstractQueryImpl) query);
absQuery = absQuery.getRoot();
......@@ -152,13 +159,13 @@ public class FilterControllerImpl implements FilterController, PropertyExecutor
if (model != null && model.getGraphModel() != null) {
graph = model.getGraphModel().getGraph();
} else {
GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getModel();
GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getGraphModel(model.getWorkspace());
graph = graphModel.getGraph();
}
for (Query q : query.getDescendantsAndSelf()) {
Filter filter = q.getFilter();
if (filter instanceof NodeFilter || filter instanceof EdgeFilter || filter instanceof AttributableFilter) {
if (filter instanceof NodeFilter || filter instanceof EdgeFilter || filter instanceof ElementFilter) {
FilterProcessor filterProcessor = new FilterProcessor();
filterProcessor.init(filter, graph);
}
......@@ -166,6 +173,7 @@ public class FilterControllerImpl implements FilterController, PropertyExecutor
}
}
@Override
public void remove(Query query) {
if (model.getCurrentQuery() == query) {
if (model.isSelecting()) {
......@@ -178,10 +186,12 @@ public class FilterControllerImpl implements FilterController, PropertyExecutor
model.remove(query);
}
@Override
public void rename(Query query, String name) {
model.rename(query, name);
}
@Override
public void setSubQuery(Query query, Query subQuery) {
//Init subquery when new filter
if (subQuery.getParent() == null && subQuery != model.getCurrentQuery()) {
......@@ -189,23 +199,25 @@ public class FilterControllerImpl implements FilterController, PropertyExecutor
if (model != null && model.getGraphModel() != null) {
graph = model.getGraphModel().getGraph();
} else {
GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getModel();
GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getGraphModel(model.getWorkspace());
graph = graphModel.getGraph();
}
Filter filter = subQuery.getFilter();
if (filter instanceof NodeFilter || filter instanceof EdgeFilter || filter instanceof AttributableFilter) {
if (filter instanceof NodeFilter || filter instanceof EdgeFilter || filter instanceof ElementFilter) {
FilterProcessor filterProcessor = new FilterProcessor();
filterProcessor.init(filter, graph);
}
}
model.setSubQuery(query, subQuery);
}
@Override
public void removeSubQuery(Query query, Query parent) {
model.removeSubQuery(query, parent);
}
@Override
public void filterVisible(Query query) {
if (query != null && model.getCurrentQuery() == query && model.isFiltering()) {
return;
......@@ -231,13 +243,15 @@ public class FilterControllerImpl implements FilterController, PropertyExecutor
}
}
@Override
public GraphView filter(Query query) {
FilterProcessor processor = new FilterProcessor();
GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getModel();
GraphModel graphModel = model.getGraphModel();
Graph result = processor.process((AbstractQueryImpl) query, graphModel);
return result.getView();
}
@Override
public void selectVisible(Query query) {
if (query != null && model.getCurrentQuery() == query && model.isSelecting()) {
return;
......@@ -269,68 +283,70 @@ public class FilterControllerImpl implements FilterController, PropertyExecutor
}
}
@Override
public void exportToColumn(String title, Query query) {
HierarchicalGraph result;
Graph result;
if (model.getCurrentQuery() == query) {
GraphView view = model.getCurrentResult();
if (view == null) {
return;
}
result = model.getGraphModel().getHierarchicalGraph(view);
result = model.getGraphModel().getGraph(view);
} else {
FilterProcessor processor = new FilterProcessor();
GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getModel();
result = (HierarchicalGraph) processor.process((AbstractQueryImpl) query, graphModel);
GraphModel graphModel = model.getGraphModel();
result = (Graph) processor.process((AbstractQueryImpl) query, graphModel);
}
AttributeModel am = Lookup.getDefault().lookup(AttributeController.class).getModel();
AttributeColumn nodeCol = am.getNodeTable().getColumn("filter_" + title);
Column nodeCol = result.getModel().getNodeTable().getColumn("filter_" + title);
if (nodeCol == null) {
nodeCol = am.getNodeTable().addColumn("filter_" + title, title, AttributeType.BOOLEAN, AttributeOrigin.COMPUTED, Boolean.FALSE);
nodeCol = result.getModel().getNodeTable().addColumn("filter_" + title, title, Boolean.class, Origin.DATA, Boolean.FALSE, false);
}
AttributeColumn edgeCol = am.getEdgeTable().getColumn("filter_" + title);
Column edgeCol = result.getModel().getEdgeTable().getColumn("filter_" + title);
if (edgeCol == null) {
edgeCol = am.getEdgeTable().addColumn("filter_" + title, title, AttributeType.BOOLEAN, AttributeOrigin.COMPUTED, Boolean.FALSE);
edgeCol = result.getModel().getEdgeTable().addColumn("filter_" + title, title, Boolean.class, Origin.DATA, Boolean.FALSE, false);
}
result.readLock();
for (Node n : result.getNodes()) {
n.getNodeData().getAttributes().setValue(nodeCol.getIndex(), Boolean.TRUE);
n.setAttribute(nodeCol, Boolean.TRUE);
}
for (Edge e : result.getEdgesAndMetaEdges()) {
e.getEdgeData().getAttributes().setValue(edgeCol.getIndex(), Boolean.TRUE);
for (Edge e : result.getEdges()) {
e.setAttribute(edgeCol, Boolean.TRUE);
}
result.readUnlock();
//StatusDisplayer.getDefault().setStatusText(NbBundle.getMessage(FilterControllerImpl.class, "FilterController.exportToColumn.status", title));
}
@Override
public void exportToNewWorkspace(Query query) {
HierarchicalGraph result;
Graph result;
if (model.getCurrentQuery() == query) {
GraphView view = model.getCurrentResult();
if (view == null) {
return;
}
result = model.getGraphModel().getHierarchicalGraph(view);
result = model.getGraphModel().getGraph(view);
} else {
FilterProcessor processor = new FilterProcessor();
GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getModel();
result = (HierarchicalGraph) processor.process((AbstractQueryImpl) query, graphModel);
GraphModel graphModel = model.getGraphModel();
result = (Graph) processor.process((AbstractQueryImpl) query, graphModel);
}
final HierarchicalGraph graphView = result;
final Graph graphView = result;
new Thread(new Runnable() {
@Override
public void run() {
ProgressTicketProvider progressProvider = Lookup.getDefault().lookup(ProgressTicketProvider.class);
ProgressTicket ticket = null;
if (progressProvider != null) {
ticket = progressProvider.createTicket("Export to workspace", null);
String msg = NbBundle.getMessage(FilterControllerImpl.class, "FilterController.exportToNewWorkspace.task");
ticket = progressProvider.createTicket(msg, null);
}
Progress.start(ticket);
ProjectController pc = Lookup.getDefault().lookup(ProjectController.class);
Workspace newWorkspace = pc.duplicateWorkspace(pc.getCurrentWorkspace());
GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getModel(newWorkspace);
graphModel.clear();
graphModel.pushFrom(graphView);
Workspace newWorkspace = pc.newWorkspace(pc.getCurrentProject());
GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getGraphModel(newWorkspace);
graphModel.bridge().copyNodes(graphView.getNodes().toArray());
Progress.finish(ticket);
String workspaceName = newWorkspace.getLookup().lookup(WorkspaceInformation.class).getName();
//StatusDisplayer.getDefault().setStatusText(NbBundle.getMessage(FilterControllerImpl.class, "FilterController.exportToNewWorkspace.status", workspaceName));
......@@ -338,47 +354,52 @@ public class FilterControllerImpl implements FilterController, PropertyExecutor
}, "Export filter to workspace").start();
}
@Override
public void exportToLabelVisible(Query query) {
HierarchicalGraph result;
Graph result;
if (model.getCurrentQuery() == query) {
GraphView view = model.getCurrentResult();
if (view == null) {
return;
}
result = model.getGraphModel().getHierarchicalGraph(view);
result = model.getGraphModel().getGraph(view);
} else {
FilterProcessor processor = new FilterProcessor();
result = (HierarchicalGraph) processor.process((AbstractQueryImpl) query, model.getGraphModel());
result = (Graph) processor.process((AbstractQueryImpl) query, model.getGraphModel());
}
HierarchicalGraph fullHGraph = model.getGraphModel().getHierarchicalGraph();
fullHGraph.readLock();
for (Node n : fullHGraph.getNodes()) {
boolean inView = n.getNodeData().getNode(result.getView().getViewId()) != null;
n.getNodeData().getTextData().setVisible(inView);
Graph fullGraph = model.getGraphModel().getGraph();
fullGraph.readLock();
for (Node n : fullGraph.getNodes()) {
boolean inView = result.contains(n);
n.getTextProperties().setVisible(inView);
}
for (Edge e : fullHGraph.getEdgesAndMetaEdges()) {
for (Edge e : fullGraph.getEdges()) {
boolean inView = result.contains(e);
e.getEdgeData().getTextData().setVisible(inView);
e.getTextProperties().setVisible(inView);
}
fullHGraph.readUnlock();
fullGraph.readUnlock();
}
@Override
public void setAutoRefresh(boolean autoRefresh) {
if (model != null) {
model.setAutoRefresh(autoRefresh);
}
}
@Override
public void setCurrentQuery(Query query) {
if (model != null) {
model.setCurrentQuery(query);
}
}
@Override
public FilterModel getModel() {
return model;
}
@Override
public synchronized FilterModel getModel(Workspace workspace) {
FilterModel filterModel = workspace.getLookup().lookup(FilterModel.class);
if (filterModel == null) {
......@@ -388,6 +409,7 @@ public class FilterControllerImpl implements FilterController, PropertyExecutor
return filterModel;
}
@Override
public void setValue(FilterProperty property, Object value, Callback callback) {
if (model != null) {
Query query = model.getQuery(property.getFilter());
......
......@@ -45,13 +45,10 @@ import java.util.HashMap;
import java.util.Map;
import org.gephi.filters.api.FilterLibrary;
import org.gephi.filters.api.Query;
import org.gephi.filters.spi.Category;
import org.gephi.filters.spi.CategoryBuilder;
import org.gephi.filters.spi.Filter;
import org.gephi.filters.spi.FilterBuilder;
import org.gephi.filters.spi.FilterLibraryMask;
import org.gephi.graph.api.GraphController;
import org.gephi.graph.api.GraphModel;
import org.openide.util.Lookup;
import org.openide.util.lookup.AbstractLookup;
import org.openide.util.lookup.InstanceContent;
......@@ -62,9 +59,9 @@ import org.openide.util.lookup.InstanceContent;
*/
public class FilterLibraryImpl implements FilterLibrary {
private AbstractLookup lookup;
private InstanceContent content;
private Map<Class<? extends Filter>, FilterBuilder> buildersMap;
private final AbstractLookup lookup;
private final InstanceContent content;
private final Map<Class<? extends Filter>, FilterBuilder> buildersMap;
public FilterLibraryImpl() {
content = new InstanceContent();
......@@ -82,11 +79,11 @@ public class FilterLibraryImpl implements FilterLibrary {
content.add(catBuilder);
}
content.add(new HierarchicalGraphMask());
buildersMap = new HashMap<Class<? extends Filter>, FilterBuilder>();
}
private void buildBuildersMap() {
buildersMap = new HashMap<Class<? extends Filter>, FilterBuilder>();
for (FilterBuilder builder : lookup.lookupAll(FilterBuilder.class)) {
try {
Filter f = builder.getFilter();
......@@ -107,33 +104,33 @@ public class FilterLibraryImpl implements FilterLibrary {
}
}
@Override
public Lookup getLookup() {
return lookup;
}
@Override
public void addBuilder(FilterBuilder builder) {
content.add(builder);
}
@Override
public void removeBuilder(FilterBuilder builder) {
content.remove(builder);
}
@Override
public void registerMask(FilterLibraryMask mask) {
content.add(mask);
}
@Override
public void unregisterMask(FilterLibraryMask mask) {
content.remove(mask);
}
@Override
public FilterBuilder getBuilder(Filter filter) {
if (buildersMap == null) {
buildBuildersMap();
}
if (buildersMap.get(filter.getClass()) != null) {
return buildersMap.get(filter.getClass());
}
buildBuildersMap();
if (buildersMap.get(filter.getClass()) != null) {
return buildersMap.get(filter.getClass());
......@@ -141,23 +138,13 @@ public class FilterLibraryImpl implements FilterLibrary {
return null;
}
@Override
public void saveQuery(Query query) {
content.add(query);
}
@Override
public void deleteQuery(Query query) {
content.remove(query);
}
private static class HierarchicalGraphMask implements FilterLibraryMask {
public Category getCategory() {
return FilterLibrary.HIERARCHY;
}
public boolean isValid() {
GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getModel();
return graphModel.isHierarchical();
}
}
}
......@@ -42,6 +42,7 @@ Portions Copyrighted 2011 Gephi Consortium.
package org.gephi.filters;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import javax.swing.event.ChangeEvent;
......@@ -63,33 +64,37 @@ import org.openide.util.Lookup;
*/
public class FilterModelImpl implements FilterModel {
private FilterLibraryImpl filterLibraryImpl;
private LinkedList<Query> queries;
private final FilterLibraryImpl filterLibraryImpl;
private final LinkedList<Query> queries;
private FilterThread filterThread;
private GraphModel graphModel;
private final GraphModel graphModel;
private final Workspace workspace;
private Query currentQuery;
private boolean filtering;
private boolean selecting;
private GraphView currentResult;
private boolean autoRefresh;
private FilterAutoRefreshor autoRefreshor;
private final FilterAutoRefreshor autoRefreshor;
//Listeners
private List<ChangeListener> listeners;
public FilterModelImpl(Workspace workspace) {
this.workspace = workspace;
filterLibraryImpl = new FilterLibraryImpl();
queries = new LinkedList<Query>();
listeners = new ArrayList<ChangeListener>();
autoRefresh = true;
graphModel = Lookup.getDefault().lookup(GraphController.class).getModel(workspace);
graphModel = Lookup.getDefault().lookup(GraphController.class).getGraphModel(workspace);
autoRefreshor = new FilterAutoRefreshor(this, graphModel);
}
@Override
public FilterLibrary getLibrary() {
return filterLibraryImpl;
}
@Override
public Query[] getQueries() {
return queries.toArray(new Query[0]);
}
......@@ -173,10 +178,12 @@ public class FilterModelImpl implements FilterModel {
return -1;
}
@Override
public boolean isFiltering() {
return currentQuery != null && filtering;
}
@Override
public boolean isSelecting() {
return currentQuery != null && selecting;
}
......@@ -195,6 +202,7 @@ public class FilterModelImpl implements FilterModel {
}
}
@Override
public boolean isAutoRefresh() {
return autoRefresh;
}
......@@ -209,6 +217,7 @@ public class FilterModelImpl implements FilterModel {
}
}
@Override
public Query getCurrentQuery() {
return currentQuery;
}
......@@ -246,9 +255,7 @@ public class FilterModelImpl implements FilterModel {
while (!stack.isEmpty()) {
Query q = stack.pop();
result.add(q);
for (Query child : q.getChildren()) {
stack.add(child);
}
stack.addAll(Arrays.asList(q.getChildren()));
}
return result.toArray(new Query[0]);
}
......@@ -282,6 +289,10 @@ public class FilterModelImpl implements FilterModel {
return graphModel;
}
public Workspace getWorkspace() {
return workspace;
}
public void destroy() {
if (filterThread != null) {
filterThread.setRunning(false);
......@@ -310,12 +321,14 @@ public class FilterModelImpl implements FilterModel {
}
//EVENTS
@Override
public void addChangeListener(ChangeListener listener) {
if (!listeners.contains(listener)) {
listeners.add(listener);
}
}
@Override
public void removeChangeListener(ChangeListener listener) {
if (listeners != null) {
listeners.remove(listener);
......
......@@ -70,15 +70,12 @@ public class FilterModelPersistenceProvider implements WorkspacePersistenceProvi
public void writeXML(XMLStreamWriter writer, Workspace workspace) {
FilterModelImpl filterModel = workspace.getLookup().lookup(FilterModelImpl.class);
if (filterModel != null) {
this.model = filterModel;
try {
writeXML(writer);
writeXML(writer, filterModel);
} catch (XMLStreamException ex) {
this.model = null;
throw new RuntimeException(ex);
}
}
this.model = null;
}
public void readXML(XMLStreamReader reader, Workspace workspace) {
......@@ -87,24 +84,21 @@ public class FilterModelPersistenceProvider implements WorkspacePersistenceProvi
filterModel = new FilterModelImpl(workspace);
workspace.add(filterModel);
}
this.model = filterModel;
try {
readXML(reader);
readXML(reader, filterModel);
} catch (XMLStreamException ex) {
this.model = null;
throw new RuntimeException(ex);
}
this.model = null;
}
@Override
public String getIdentifier() {
return "filtermodel";
}
//PERSISTENCE
private int queryId = 0;
private FilterModelImpl model;
public void writeXML(XMLStreamWriter writer) throws XMLStreamException {
public void writeXML(XMLStreamWriter writer, FilterModelImpl model) throws XMLStreamException {
writer.writeStartElement("filtermodel");
writer.writeAttribute("autorefresh", String.valueOf(model.isAutoRefresh()));
......@@ -112,14 +106,14 @@ public class FilterModelPersistenceProvider implements WorkspacePersistenceProvi
writer.writeStartElement("queries");
queryId = 0;
for (Query query : model.getQueries()) {
writeQuery(writer, query, -1);
writeQuery(writer, model, query, -1);
}
writer.writeEndElement();
writer.writeEndElement();
}
private void writeQuery(XMLStreamWriter writer, Query query, int parentId) throws XMLStreamException {
private void writeQuery(XMLStreamWriter writer, FilterModelImpl model, Query query, int parentId) throws XMLStreamException {
writer.writeStartElement("query");
int id = queryId++;
writer.writeAttribute("id", String.valueOf(id));
......@@ -140,7 +134,7 @@ public class FilterModelPersistenceProvider implements WorkspacePersistenceProvi
writer.writeEndElement();
for (Query child : query.getChildren()) {
writeQuery(writer, child, id);
writeQuery(writer, model, child, id);
}
}
......@@ -164,7 +158,7 @@ public class FilterModelPersistenceProvider implements WorkspacePersistenceProvi
}
}
public void readXML(XMLStreamReader reader) throws XMLStreamException {
public void readXML(XMLStreamReader reader, FilterModelImpl model) throws XMLStreamException {
String autofresh = reader.getAttributeValue(null, "autorefresh");
if (autofresh != null && !autofresh.isEmpty()) {
model.setAutoRefresh(Boolean.parseBoolean(autofresh));
......@@ -179,13 +173,13 @@ public class FilterModelPersistenceProvider implements WorkspacePersistenceProvi
if ("query".equalsIgnoreCase(name)) {
String id = reader.getAttributeValue(null, "id");
String parent = reader.getAttributeValue(null, "parent");
Query query = readQuery(reader);
Query query = readQuery(reader, model);
if (query != null) {
idMap.put(Integer.parseInt(id), query);
if (parent != null) {
int parentId = Integer.parseInt(parent);
Query parentQuery = idMap.get(parentId);
//A plugin filter may be missing, or the parent filter could not be deserialized.
//For example a partition filter, which depends on partitions, and partitions are not serialized
if (parentQuery != null) {
......@@ -205,18 +199,18 @@ public class FilterModelPersistenceProvider implements WorkspacePersistenceProvi
}
//Init filters
Graph graph = null;
if (model != null && model.getGraphModel() != null) {
Graph graph;
if (model != null) {
graph = model.getGraphModel().getGraph();
} else {
GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getModel();
GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getGraphModel(model.getWorkspace());
graph = graphModel.getGraph();
}
for (Query rootQuery : model.getQueries()) {
for (Query q : rootQuery.getDescendantsAndSelf()) {
Filter filter = q.getFilter();
if (filter instanceof NodeFilter || filter instanceof EdgeFilter || filter instanceof AttributableFilter) {
if (filter instanceof NodeFilter || filter instanceof EdgeFilter || filter instanceof ElementFilter) {
FilterProcessor filterProcessor = new FilterProcessor();
filterProcessor.init(filter, graph);
}
......@@ -224,7 +218,7 @@ public class FilterModelPersistenceProvider implements WorkspacePersistenceProvi
}
}
private Query readQuery(XMLStreamReader reader) throws XMLStreamException {
private Query readQuery(XMLStreamReader reader, FilterModelImpl model) throws XMLStreamException {
String builderClassName = reader.getAttributeValue(null, "builder");
String filterClassName = reader.getAttributeValue(null, "filter");
FilterBuilder builder = null;
......
......@@ -55,6 +55,7 @@ import org.gephi.graph.api.*;
public class FilterProcessor {
public Graph process(AbstractQueryImpl query, GraphModel graphModel) {
graphModel.getGraph().writeLock();
List<GraphView> views = new ArrayList<GraphView>();
query = simplifyQuery(query);
AbstractQueryImpl[] tree = getTree(query, true);
......@@ -68,7 +69,7 @@ public class FilterProcessor {
}
} else {
//Leaves
GraphView newView = graphModel.newView();
GraphView newView = graphModel.copyView(graphModel.getGraph().getView());
views.add(newView);
input = new Graph[]{graphModel.getGraph(newView)}; //duplicate root
}
......@@ -76,11 +77,15 @@ public class FilterProcessor {
if (q instanceof OperatorQueryImpl && !((OperatorQueryImpl) q).isSimple()) {
OperatorQueryImpl operatorQuery = (OperatorQueryImpl) q;
Operator op = (Operator) operatorQuery.getFilter();
q.setResult(op.filter(input));
Subgraph[] inputSG = new Subgraph[input.length];
for (int j = 0; j < inputSG.length; j++) {
inputSG[j] = (Subgraph) input[j];
}
q.setResult(op.filter(inputSG));
} else if (q instanceof OperatorQueryImpl && ((OperatorQueryImpl) q).isSimple()) {
OperatorQueryImpl operatorQuery = (OperatorQueryImpl) q;
Operator op = (Operator) operatorQuery.getFilter();
GraphView newView = graphModel.newView();
GraphView newView = graphModel.copyView(graphModel.getGraph().getView());
views.add(newView);
Graph newGraph = graphModel.getGraph(newView);
List<Filter> filters = new ArrayList<Filter>();
......@@ -104,9 +109,6 @@ public class FilterProcessor {
} else if (filter instanceof EdgeFilter) {
processEdgeFilter((EdgeFilter) filter, input[0]);
q.setResult(input[0]);
} else if (filter instanceof AttributableFilter) {
processAttributableFilter((AttributableFilter) filter, input[0]);
q.setResult(input[0]);
} else if (filter instanceof ComplexFilter) {
ComplexFilter cf = (ComplexFilter) filter;
q.setResult(cf.filter(input[0]));
......@@ -120,57 +122,14 @@ public class FilterProcessor {
//Destroy intermediate views
GraphView finalView = finalResult.getView();
for (GraphView v : views) {
if (v != finalView) {
if (v != finalView && !v.isMainView()) {
graphModel.destroyView(v);
}
}
graphModel.getGraph().writeUnlock();
return finalResult;
}
private void processAttributableFilter(AttributableFilter attributableFilter, Graph graph) {
if (((AttributableFilter) attributableFilter).getType().equals(AttributableFilter.Type.NODE)) {
if (init(attributableFilter, graph)) {
List<Node> nodesToRemove = new ArrayList<Node>();
for (Node n : graph.getNodes()) {
if (!attributableFilter.evaluate(graph, n)) {
nodesToRemove.add(n);
}
}
for (Node n : nodesToRemove) {
graph.removeNode(n);
}
attributableFilter.finish();
}
} else {
HierarchicalGraph hgraph = (HierarchicalGraph) graph;
if (init(attributableFilter, graph)) {
List<Edge> edgesToRemove = new ArrayList<Edge>();
for (Edge e : hgraph.getEdges()) {
if (!attributableFilter.evaluate(hgraph, e)) {
edgesToRemove.add(e);
}
}
for (Edge e : edgesToRemove) {
hgraph.removeEdge(e);
}
edgesToRemove.clear();
for (Edge e : hgraph.getMetaEdges()) {
if (!attributableFilter.evaluate(hgraph, e)) {
edgesToRemove.add(e);
}
}
for (Edge e : edgesToRemove) {
hgraph.removeMetaEdge(e);
}
attributableFilter.finish();
}
}
}
private void processNodeFilter(NodeFilter nodeFilter, Graph graph) {
if (init(nodeFilter, graph)) {
List<Node> nodesToRemove = new ArrayList<Node>();
......@@ -180,37 +139,25 @@ public class FilterProcessor {
}
}
for (Node n : nodesToRemove) {
graph.removeNode(n);
if (!nodesToRemove.isEmpty()) {
graph.removeAllNodes(nodesToRemove);
}
nodeFilter.finish();
}
}
private void processEdgeFilter(EdgeFilter edgeFilter, Graph graph) {
HierarchicalGraph hgraph = (HierarchicalGraph) graph;
if (init(edgeFilter, graph)) {
List<Edge> edgesToRemove = new ArrayList<Edge>();
for (Edge e : hgraph.getEdges()) {
if (!edgeFilter.evaluate(hgraph, e)) {
for (Edge e : graph.getEdges()) {
if (!edgeFilter.evaluate(graph, e)) {
edgesToRemove.add(e);
}
}
for (Edge e : edgesToRemove) {
hgraph.removeEdge(e);
if (!edgesToRemove.isEmpty()) {
graph.removeAllEdges(edgesToRemove);
}
edgesToRemove.clear();
for (Edge e : hgraph.getMetaEdges()) {
if (!edgeFilter.evaluate(hgraph, e)) {
edgesToRemove.add(e);
}
}
for (Edge e : edgesToRemove) {
hgraph.removeMetaEdge(e);
}
edgeFilter.finish();
}
}
......@@ -221,7 +168,7 @@ public class FilterProcessor {
if (q instanceof OperatorQueryImpl && q.getChildrenCount() > 0) {
boolean canSimplify = true;
for (AbstractQueryImpl child : q.children) {
if (child.getChildrenCount() > 0 || !(child.getFilter() instanceof NodeFilter || child.getFilter() instanceof EdgeFilter || child.getFilter() instanceof AttributableFilter)) {
if (child.getChildrenCount() > 0 || !(child.getFilter() instanceof NodeFilter || child.getFilter() instanceof EdgeFilter || child.getFilter() instanceof ElementFilter)) {
canSimplify = false;
}
}
......@@ -256,8 +203,6 @@ public class FilterProcessor {
res = ((NodeFilter) filter).init(graph);
} else if (filter instanceof EdgeFilter) {
res = ((EdgeFilter) filter).init(graph);
} else if (filter instanceof NodeFilter) {
res = ((AttributableFilter) filter).init(graph);
}
//Range
......@@ -279,45 +224,43 @@ public class FilterProcessor {
if (min == null || max == null) {
newRange = null;
rangeFilter.getRangeProperty().setValue(newRange);
} else if (previousRange == null) {
newRange = new Range(min, max, min, max, values);
rangeFilter.getRangeProperty().setValue(newRange);
} else if (previousRange != null && (previousRange.getMinimum() == null || previousRange.getMaximum() == null)) {
//Opening projects
newRange = new Range(previousRange.getLowerBound(), previousRange.getUpperBound(), min, max, previousRange.isLeftInclusive(), previousRange.isRightInclusive(), values);
rangeFilter.getRangeProperty().setValue(newRange);
} else {
if (previousRange == null) {
newRange = new Range(min, max, min, max, values);
rangeFilter.getRangeProperty().setValue(newRange);
} else if(previousRange != null && (previousRange.getMinimum() == null || previousRange.getMaximum() == null)) {
//Opening projects
newRange = new Range(previousRange.getLowerBound(), previousRange.getUpperBound(), min, max, previousRange.isLeftInclusive(), previousRange.isRightInclusive(), values);
rangeFilter.getRangeProperty().setValue(newRange);
} else {
//Collect some info
boolean stickyLeft = previousRange.getMinimum().equals(previousRange.getLowerBound());
boolean stickyRight = previousRange.getMaximum().equals(previousRange.getUpperBound());
Number lowerBound = previousRange.getLowerBound();
Number upperBound = previousRange.getUpperBound();
//The inteval grows on the right
if (stickyRight && comparator.superior(max, upperBound)) {
upperBound = max;
}
//Collect some info
boolean stickyLeft = previousRange.getMinimum().equals(previousRange.getLowerBound());
boolean stickyRight = previousRange.getMaximum().equals(previousRange.getUpperBound());
Number lowerBound = previousRange.getLowerBound();
Number upperBound = previousRange.getUpperBound();
//The inteval grows on the right
if (stickyRight && comparator.superior(max, upperBound)) {
upperBound = max;
}
//The interval grows on the left
if (stickyLeft && comparator.inferior(min, lowerBound)) {
lowerBound = min;
}
//The interval grows on the left
if (stickyLeft && comparator.inferior(min, lowerBound)) {
lowerBound = min;
}
//The interval shrinks on the right
if (comparator.superior(upperBound, max)) {
upperBound = max;
}
//The interval shrinks on the right
if (comparator.superior(upperBound, max)) {
upperBound = max;
}
//The interval shrinks on the left
if (comparator.inferior(lowerBound, min)) {
lowerBound = min;
}
//The interval shrinks on the left
if (comparator.inferior(lowerBound, min)) {
lowerBound = min;
}
newRange = new Range(lowerBound, upperBound, min, max, previousRange.isLeftInclusive(), previousRange.isRightInclusive(), values);
if (!newRange.equals(previousRange)) {
rangeFilter.getRangeProperty().setValue(newRange);
}
newRange = new Range(lowerBound, upperBound, min, max, previousRange.isLeftInclusive(), previousRange.isRightInclusive(), values);
if (!newRange.equals(previousRange)) {
rangeFilter.getRangeProperty().setValue(newRange);
}
}
}
......@@ -345,6 +288,7 @@ public class FilterProcessor {
return c > 0 ? a : b;
}
@Override
public int compare(Number number1, Number number2) {
if (((Object) number2).getClass().equals(((Object) number1).getClass())) {
if (number1 instanceof Comparable) {
......
......@@ -38,7 +38,7 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.filters;
import org.gephi.filters.spi.Filter;
......@@ -51,7 +51,7 @@ import org.gephi.filters.spi.FilterProperty;
public class FilterQueryImpl extends AbstractQueryImpl {
private Parameters[] parameters;
private Filter filter;
private final Filter filter;
private String name;
public FilterQueryImpl(Filter filter) {
......@@ -85,26 +85,30 @@ public class FilterQueryImpl extends AbstractQueryImpl {
this.name = name;
}
@Override
public int getPropertiesCount() {
return parameters.length;
}
@Override
public String getPropertyName(int index) {
return parameters[index].getKey();
}
@Override
public Object getPropertyValue(int index) {
return parameters[index].getValue();
}
@Override
public Filter getFilter() {
return filter;
}
private class Parameters {
private int index;
private Object value;
private final int index;
private final Object value;
public Parameters(int index, Object value) {
this.index = index;
......
......@@ -48,7 +48,6 @@ import org.gephi.filters.api.PropertyExecutor.Callback;
import org.gephi.filters.api.Query;
import org.gephi.filters.spi.FilterProperty;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.GraphController;
import org.gephi.graph.api.GraphModel;
import org.gephi.graph.api.GraphView;
import org.gephi.utils.progress.Progress;
......@@ -57,6 +56,7 @@ import org.gephi.utils.progress.ProgressTicketProvider;
import org.gephi.visualization.api.VisualizationController;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
/**
*
......@@ -64,15 +64,15 @@ import org.openide.util.Lookup;
*/
public class FilterThread extends Thread {
private FilterModelImpl model;
private AtomicReference<AbstractQueryImpl> rootQuery;
private final FilterModelImpl model;
private final AtomicReference<AbstractQueryImpl> rootQuery;
ConcurrentHashMap<String, PropertyModifier> modifiersMap;
private boolean running = true;
private final Object lock = new Object();
private final boolean filtering;
public FilterThread(FilterModelImpl model) {
super("Filter Thread");
super("Filter Thread - " + model.getWorkspace().toString());
setDaemon(true);
this.model = model;
this.filtering = model.isFiltering();
......@@ -112,7 +112,8 @@ public class FilterThread extends Thread {
ProgressTicket progressTicket = null;
ProgressTicketProvider progressTicketProvider = Lookup.getDefault().lookup(ProgressTicketProvider.class);
if (progressTicketProvider != null) {
progressTicket = progressTicketProvider.createTicket("Filtering", null);
String msg = NbBundle.getMessage(FilterThread.class, "FilterThread.progress.taskName", q.getName());
progressTicket = progressTicketProvider.createTicket(msg, null);
Progress.start(progressTicket);
}
......@@ -132,8 +133,7 @@ public class FilterThread extends Thread {
}
//clear map
Query q = null;
for (Iterator<PropertyModifier> itr = modifiersMap.values().iterator(); itr.hasNext();) {
PropertyModifier pm = itr.next();
for (PropertyModifier pm : modifiersMap.values()) {
pm.callback.setValue(pm.value);
q = pm.query;
}
......@@ -145,10 +145,8 @@ public class FilterThread extends Thread {
private void filter(AbstractQueryImpl query) {
FilterProcessor processor = new FilterProcessor();
GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getModel();
GraphModel graphModel = model.getGraphModel();
Graph result = processor.process((AbstractQueryImpl) query, graphModel);
// System.out.println("#Nodes: " + result.getNodeCount());
// System.out.println("#Edges: " + result.getEdgeCount());
if (running) {
GraphView view = result.getView();
graphModel.setVisibleView(view);
......@@ -164,10 +162,8 @@ public class FilterThread extends Thread {
private void select(AbstractQueryImpl query) {
FilterProcessor processor = new FilterProcessor();
GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getModel();
GraphModel graphModel = model.getGraphModel();
Graph result = processor.process((AbstractQueryImpl) query, graphModel);
// System.out.println("#Nodes: " + result.getNodeCount());
// System.out.println("#Edges: " + result.getEdgeCount());
if (running) {
VisualizationController visController = Lookup.getDefault().lookup(VisualizationController.class);
if (visController != null) {
......
......@@ -38,7 +38,7 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.filters;
import org.gephi.filters.spi.Filter;
......@@ -50,7 +50,7 @@ import org.gephi.filters.spi.Operator;
*/
public class OperatorQueryImpl extends AbstractQueryImpl {
private Operator operator;
private final Operator operator;
private boolean simple = false; //Simple when children are only NodeFilter/EdgeFilter leaves
public OperatorQueryImpl(Operator predicate) {
......@@ -62,6 +62,7 @@ public class OperatorQueryImpl extends AbstractQueryImpl {
return operator.getInputCount();
}
@Override
public String getName() {
return operator.getName();
}
......@@ -70,18 +71,22 @@ public class OperatorQueryImpl extends AbstractQueryImpl {
public void setName(String name) {
}
@Override
public int getPropertiesCount() {
return 0;
}
@Override
public String getPropertyName(int index) {
return null;
}
@Override
public Object getPropertyValue(int index) {
return null;
}
@Override
public Filter getFilter() {
return operator;
}
......
......@@ -2,7 +2,8 @@ OpenIDE-Module-Display-Category=Gephi Core
OpenIDE-Module-Name=Filters Impl
OpenIDE-Module-Short-Description=Implementation of Filters API
FilterController.exportToColumn.status = The column "{0}" has been filled with the filtering result
FilterController.exportToNewWorkspace.task = "Export to workspace"
FilterController.exportToNewWorkspace.status = The workspace "{0}" has been created and filled with the filtering result
FilterController.exportToColumn.status = The column ''{0}'' has been filled with the filtering result
FilterController.exportToNewWorkspace.task = Export to workspace
FilterController.exportToNewWorkspace.status = The workspace ''{0}'' has been created and filled with the filtering result
FilterThread.progress.taskName = Filtering {0}
\ No newline at end of file
......@@ -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>
......@@ -16,10 +16,6 @@
<name>FiltersPlugin</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>data-attributes-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>filters-api</artifactId>
......@@ -30,7 +26,7 @@
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>partition-api</artifactId>
<artifactId>appearance-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
......@@ -40,10 +36,10 @@
<groupId>${project.groupId}</groupId>
<artifactId>statistics-plugin</artifactId>
</dependency>
<dependency>
<!-- <dependency>
<groupId>${project.groupId}</groupId>
<artifactId>timeline</artifactId>
</dependency>
</dependency>-->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>utils-longtask</artifactId>
......
......@@ -41,38 +41,27 @@
*/
package org.gephi.filters.plugin;
import org.gephi.data.attributes.api.AttributeColumn;
import org.gephi.data.attributes.api.AttributeUtils;
import org.gephi.filters.spi.AttributableFilter;
import org.gephi.filters.spi.ElementFilter;
import org.gephi.graph.api.Column;
import org.gephi.graph.api.Element;
/**
*
* @author mbastian
*/
public abstract class AbstractAttributeFilter extends AbstractFilter implements AttributableFilter {
public abstract class AbstractAttributeFilter<K extends Element> extends AbstractFilter implements ElementFilter<K> {
protected AttributeColumn column;
protected AbstractAttributeFilter.Type type;
protected Column column;
public AbstractAttributeFilter(String name, AttributeColumn column) {
public AbstractAttributeFilter(String name, Column column) {
super(name + " (" + column.getTitle() + ")");
this.column = column;
this.type = AttributeUtils.getDefault().isNodeColumn(column) ? Type.NODE : Type.EDGE;
//Add column property
addProperty(AttributeColumn.class, "column");
}
public Type getType() {
return type;
addProperty(Column.class, "column");
}
public AttributeColumn getColumn() {
public Column getColumn() {
return column;
}
public void setColumn(AttributeColumn column) {
public void setColumn(Column column) {
this.column = column;
this.type = AttributeUtils.getDefault().isNodeColumn(column) ? Type.NODE : Type.EDGE;
}
}
......@@ -42,9 +42,9 @@
package org.gephi.filters.plugin;
import javax.swing.Icon;
import org.gephi.data.attributes.api.AttributeColumn;
import org.gephi.data.attributes.api.AttributeUtils;
import org.gephi.filters.spi.Category;
import org.gephi.graph.api.AttributeUtils;
import org.gephi.graph.api.Column;
import org.openide.util.NbBundle;
/**
......@@ -53,12 +53,12 @@ import org.openide.util.NbBundle;
*/
public abstract class AbstractAttributeFilterBuilder extends AbstractFilterBuilder {
protected final AttributeColumn column;
protected final Column column;
public AbstractAttributeFilterBuilder(AttributeColumn column, Category category, String description, Icon icon) {
public AbstractAttributeFilterBuilder(Column column, Category category, String description, Icon icon) {
super(category, "<font color='#000000'>" + column.getTitle() + "</font> "
+ "<font color='#999999'><i>" + column.getType().toString() + " "
+ (AttributeUtils.getDefault().isNodeColumn(column)
+ "<font color='#999999'><i>" + column.getTypeClass().getSimpleName() + " "
+ (AttributeUtils.isNodeColumn(column)
? "(" + NbBundle.getMessage(AbstractAttributeFilterBuilder.class, "AbstractAttributeFilterBuilder.Node") + ")"
: "(" + NbBundle.getMessage(AbstractAttributeFilterBuilder.class, "AbstractAttributeFilterBuilder.Edge") + ")")
+ "</i></font>",
......
......@@ -43,9 +43,10 @@ package org.gephi.filters.plugin;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.gephi.filters.spi.Filter;
import org.gephi.filters.spi.FilterProperty;
import org.openide.util.Exceptions;
/**
*
......@@ -61,10 +62,12 @@ public abstract class AbstractFilter implements Filter {
this.properties = new ArrayList<FilterProperty>();
}
@Override
public String getName() {
return name;
}
@Override
public FilterProperty[] getProperties() {
return properties.toArray(new FilterProperty[0]);
}
......@@ -73,7 +76,7 @@ public abstract class AbstractFilter implements Filter {
try {
properties.add(FilterProperty.createProperty(this, clazz, name));
} catch (NoSuchMethodException ex) {
Exceptions.printStackTrace(ex);
Logger.getLogger("").log(Level.SEVERE, "Error while creating '" + name + "' property", ex);
}
}
}
......@@ -64,22 +64,27 @@ public abstract class AbstractFilterBuilder implements FilterBuilder {
this.icon = icon;
}
@Override
public Category getCategory() {
return category;
}
@Override
public String getName() {
return name;
}
@Override
public Icon getIcon() {
return icon;
}
@Override
public String getDescription() {
return descrption;
}
@Override
public void destroy(Filter 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;
import org.gephi.data.attributes.api.Estimator;
import org.gephi.data.attributes.type.DynamicType;
import org.gephi.data.attributes.type.TimeInterval;
import org.gephi.dynamic.api.DynamicController;
import org.gephi.dynamic.api.DynamicModel;
import org.gephi.filters.api.FilterController;
import org.gephi.filters.api.FilterModel;
import org.gephi.filters.api.Query;
import org.gephi.filters.plugin.dynamic.DynamicRangeBuilder.DynamicRangeFilter;
import org.gephi.filters.spi.Filter;
import org.gephi.graph.api.Edge;
import org.gephi.graph.api.Graph;
import org.gephi.project.api.Workspace;
import org.openide.util.Lookup;
/**
*
* @author Mathieu Bastian
*/
public class DynamicAttributesHelper {
private final FilterModel filterModel;
private final DynamicModel dynamicModel;
private final boolean dynamic;
public DynamicAttributesHelper(Filter filter, Graph graph) {
if (graph != null) {
Workspace workspace = graph.getGraphModel().getWorkspace();
FilterController filterController = Lookup.getDefault().lookup(FilterController.class);
filterModel = filterController.getModel(workspace);
DynamicController dynamicController = Lookup.getDefault().lookup(DynamicController.class);
dynamicModel = dynamicController.getModel(workspace);
dynamic = isDynamic(filter);
} else {
filterModel = null;
dynamicModel = null;
dynamic = false;
}
}
private boolean isDynamic(Filter filter) {
if (filterModel.getCurrentQuery() == null) {
return false;
}
Query filterQuery = null;
for (Query q : filterModel.getCurrentQuery().getQueries(filter.getClass())) {
if (q.getFilter() == filter) {
filterQuery = q;
break;
}
}
if (filterQuery != null) {
for (Query query : filterQuery.getDescendantsAndSelf()) {
if (query.getFilter().getClass().equals(DynamicRangeFilter.class)) {
return true;
}
}
}
return false;
}
public Object getDynamicValue(Object attributeValue) {
if (attributeValue != null && attributeValue instanceof DynamicType) {
DynamicType dynamicValue = (DynamicType) attributeValue;
Estimator estimator = dynamicModel == null ? Estimator.FIRST : dynamicModel.getEstimator();
if (Number.class.isAssignableFrom(dynamicValue.getUnderlyingType())) {
estimator = dynamicModel == null ? Estimator.AVERAGE : dynamicModel.getNumberEstimator();
}
TimeInterval timeInterval = new TimeInterval(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
if (dynamic) {
timeInterval = dynamicModel.getVisibleInterval();
}
return dynamicValue.getValue(timeInterval.getLow(), timeInterval.getHigh(), estimator);
}
return attributeValue;
}
public float getEdgeWeight(Edge edge) {
if (dynamic) {
TimeInterval timeInterval = dynamicModel.getVisibleInterval();
return edge.getWeight(timeInterval.getLow(), timeInterval.getHigh());
}
return edge.getWeight();
}
}
......@@ -42,18 +42,24 @@
package org.gephi.filters.plugin.attribute;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import javax.swing.JPanel;
import org.gephi.data.attributes.api.*;
import org.gephi.filters.api.FilterLibrary;
import org.gephi.filters.api.Range;
import org.gephi.filters.plugin.AbstractAttributeFilter;
import org.gephi.filters.plugin.AbstractAttributeFilterBuilder;
import org.gephi.filters.plugin.DynamicAttributesHelper;
import org.gephi.filters.spi.*;
import org.gephi.graph.api.*;
import org.gephi.graph.api.AttributeUtils;
import org.gephi.graph.api.Column;
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.types.IntervalBooleanMap;
import org.gephi.graph.api.types.IntervalStringMap;
import org.gephi.graph.api.types.TimestampBooleanMap;
import org.gephi.graph.api.types.TimestampStringMap;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
......@@ -70,26 +76,30 @@ public class AttributeEqualBuilder implements CategoryBuilder {
null,
FilterLibrary.ATTRIBUTES);
@Override
public Category getCategory() {
return EQUAL;
}
@Override
public FilterBuilder[] getBuilders() {
List<FilterBuilder> builders = new ArrayList<FilterBuilder>();
AttributeModel am = Lookup.getDefault().lookup(AttributeController.class).getModel();
List<AttributeColumn> columns = new ArrayList<AttributeColumn>();
columns.addAll(Arrays.asList(am.getNodeTable().getColumns()));
columns.addAll(Arrays.asList(am.getEdgeTable().getColumns()));
for (AttributeColumn c : columns) {
if (AttributeUtils.getDefault().isStringColumn(c) || c.getType().equals(AttributeType.DYNAMIC_STRING)) {
EqualStringFilterBuilder b = new EqualStringFilterBuilder(c);
builders.add(b);
} else if (AttributeUtils.getDefault().isNumberColumn(c) || AttributeUtils.getDefault().isDynamicNumberColumn(c)) {
EqualNumberFilterBuilder b = new EqualNumberFilterBuilder(c);
builders.add(b);
} else if (c.getType().equals(AttributeType.BOOLEAN) || c.getType().equals(AttributeType.DYNAMIC_BOOLEAN)) {
EqualBooleanFilterBuilder b = new EqualBooleanFilterBuilder(c);
builders.add(b);
GraphModel am = Lookup.getDefault().lookup(GraphController.class).getGraphModel();
List<Column> columns = new ArrayList<Column>();
columns.addAll(am.getNodeTable().toList());
columns.addAll(am.getEdgeTable().toList());
for (Column c : columns) {
if (!c.isProperty() && !c.isArray()) {
if (c.getTypeClass().equals(String.class) || c.getTypeClass().equals(TimestampStringMap.class) || c.getTypeClass().equals(IntervalStringMap.class)) {
EqualStringFilterBuilder b = new EqualStringFilterBuilder(c);
builders.add(b);
} else if (AttributeUtils.isNumberType(c.getTypeClass())) {
EqualNumberFilterBuilder b = new EqualNumberFilterBuilder(c);
builders.add(b);
} else if (c.getTypeClass().equals(Boolean.class) || c.getTypeClass().equals(TimestampBooleanMap.class) || c.getTypeClass().equals(IntervalBooleanMap.class)) {
EqualBooleanFilterBuilder b = new EqualBooleanFilterBuilder(c);
builders.add(b);
}
}
}
return builders.toArray(new FilterBuilder[0]);
......@@ -97,17 +107,19 @@ public class AttributeEqualBuilder implements CategoryBuilder {
private static class EqualStringFilterBuilder extends AbstractAttributeFilterBuilder {
public EqualStringFilterBuilder(AttributeColumn column) {
public EqualStringFilterBuilder(Column column) {
super(column,
EQUAL,
NbBundle.getMessage(AttributeEqualBuilder.class, "AttributeEqualBuilder.description"),
null);
}
@Override
public EqualStringFilter getFilter() {
return new EqualStringFilter(column);
return AttributeUtils.isNodeColumn(column) ? new EqualStringFilter.Node(column) : new EqualStringFilter.Edge(column);
}
@Override
public JPanel getPanel(Filter filter) {
EqualStringUI ui = Lookup.getDefault().lookup(EqualStringUI.class);
if (ui != null) {
......@@ -117,14 +129,13 @@ public class AttributeEqualBuilder implements CategoryBuilder {
}
}
public static class EqualStringFilter extends AbstractAttributeFilter {
public static abstract class EqualStringFilter<K extends Element> extends AbstractAttributeFilter<K> {
private String pattern;
private boolean useRegex;
private Pattern regex;
private DynamicAttributesHelper dynamicHelper = new DynamicAttributesHelper(this, null);
public EqualStringFilter(AttributeColumn column) {
public EqualStringFilter(Column column) {
super(NbBundle.getMessage(AttributeEqualBuilder.class, "AttributeEqualBuilder.name"),
column);
......@@ -133,26 +144,26 @@ public class AttributeEqualBuilder implements CategoryBuilder {
addProperty(Boolean.class, "useRegex");
}
@Override
public boolean init(Graph graph) {
HierarchicalGraph hg = (HierarchicalGraph) graph;
dynamicHelper = new DynamicAttributesHelper(this, hg);
return true;
}
public boolean evaluate(Graph graph, Attributable attributable) {
@Override
public boolean evaluate(Graph graph, Element element) {
if (pattern == null) {
return true;
}
Object val = attributable.getAttributes().getValue(column.getIndex());
val = dynamicHelper.getDynamicValue(val);
String val = (String) element.getAttribute(column, graph.getView());
if (val != null && useRegex) {
return regex.matcher(val.toString()).matches();
return regex.matcher(val).matches();
} else if (val != null) {
return pattern.equals(val.toString());
return pattern.equals(val);
}
return false;
}
@Override
public void finish() {
}
......@@ -172,22 +183,37 @@ public class AttributeEqualBuilder implements CategoryBuilder {
public void setUseRegex(boolean useRegex) {
this.useRegex = useRegex;
}
public static class Node extends EqualStringFilter<org.gephi.graph.api.Node> implements NodeFilter {
public Node(Column column) {
super(column);
}
}
public static class Edge extends EqualStringFilter<org.gephi.graph.api.Edge> implements EdgeFilter {
public Edge(Column column) {
super(column);
}
}
}
private static class EqualNumberFilterBuilder extends AbstractAttributeFilterBuilder {
public EqualNumberFilterBuilder(AttributeColumn column) {
public EqualNumberFilterBuilder(Column column) {
super(column,
EQUAL,
NbBundle.getMessage(AttributeEqualBuilder.class, "AttributeEqualBuilder.description"),
null);
}
@Override
public EqualNumberFilter getFilter() {
return new EqualNumberFilter(column);
return AttributeUtils.isNodeColumn(column) ? new EqualNumberFilter.Node(column) : new EqualNumberFilter.Edge(column);
}
@Override
public JPanel getPanel(Filter filter) {
EqualNumberUI ui = Lookup.getDefault().lookup(EqualNumberUI.class);
if (ui != null) {
......@@ -197,13 +223,12 @@ public class AttributeEqualBuilder implements CategoryBuilder {
}
}
public static class EqualNumberFilter extends AbstractAttributeFilter implements RangeFilter {
public static abstract class EqualNumberFilter<K extends Element> extends AbstractAttributeFilter<K> implements RangeFilter {
private Number match;
private Range range;
private DynamicAttributesHelper dynamicHelper = new DynamicAttributesHelper(this, null);
public EqualNumberFilter(AttributeColumn column) {
public EqualNumberFilter(Column column) {
super(NbBundle.getMessage(AttributeEqualBuilder.class, "AttributeEqualBuilder.name"), column);
//App property
......@@ -211,47 +236,46 @@ public class AttributeEqualBuilder implements CategoryBuilder {
addProperty(Range.class, "range");
}
@Override
public boolean init(Graph graph) {
HierarchicalGraph hg = (HierarchicalGraph) graph;
if (AttributeUtils.getDefault().isNodeColumn(column)) {
if (AttributeUtils.isNodeColumn(column)) {
if (graph.getNodeCount() == 0) {
return false;
}
} else if (AttributeUtils.getDefault().isEdgeColumn(column)) {
if (hg.getTotalEdgeCount() == 0) {
} else if (AttributeUtils.isEdgeColumn(column)) {
if (graph.getEdgeCount() == 0) {
return false;
}
}
dynamicHelper = new DynamicAttributesHelper(this, hg);
return true;
}
public boolean evaluate(Graph graph, Attributable attributable) {
Object val = attributable.getAttributes().getValue(column.getIndex());
val = dynamicHelper.getDynamicValue(val);
@Override
public boolean evaluate(Graph graph, Element element) {
Object val = element.getAttribute(column, graph.getView());
if (val != null) {
return val.equals(match);
}
return false;
}
@Override
public void finish() {
}
@Override
public Number[] getValues(Graph graph) {
List<Number> vals = new ArrayList<Number>();
if (AttributeUtils.getDefault().isNodeColumn(column)) {
for (Node n : graph.getNodes()) {
Object val = n.getNodeData().getAttributes().getValue(column.getIndex());
val = dynamicHelper.getDynamicValue(val);
if (AttributeUtils.isNodeColumn(column)) {
for (Element n : graph.getNodes()) {
Object val = n.getAttribute(column, graph.getView());
if (val != null) {
vals.add((Number) val);
}
}
} else {
for (Edge e : ((HierarchicalGraph) graph).getEdgesAndMetaEdges()) {
Object val = e.getEdgeData().getAttributes().getValue(column.getIndex());
val = dynamicHelper.getDynamicValue(val);
for (Element e : graph.getEdges()) {
Object val = e.getAttribute(column, graph.getView());
if (val != null) {
vals.add((Number) val);
}
......@@ -260,6 +284,7 @@ public class AttributeEqualBuilder implements CategoryBuilder {
return vals.toArray(new Number[0]);
}
@Override
public FilterProperty getRangeProperty() {
return getProperties()[2];
}
......@@ -270,7 +295,7 @@ public class AttributeEqualBuilder implements CategoryBuilder {
public void setRange(Range range) {
this.range = range;
if(match == null) {
if (match == null) {
match = range.getMinimum();
} else {
match = Range.trimToBounds(range.getMinimum(), range.getMaximum(), match);
......@@ -284,20 +309,36 @@ public class AttributeEqualBuilder implements CategoryBuilder {
public void setMatch(Number match) {
this.match = match;
}
public static class Node extends EqualNumberFilter<org.gephi.graph.api.Node> implements NodeFilter {
public Node(Column column) {
super(column);
}
}
public static class Edge extends EqualNumberFilter<org.gephi.graph.api.Edge> implements EdgeFilter {
public Edge(Column column) {
super(column);
}
}
}
private static class EqualBooleanFilterBuilder extends AbstractAttributeFilterBuilder {
public EqualBooleanFilterBuilder(AttributeColumn column) {
public EqualBooleanFilterBuilder(Column column) {
super(column,
EQUAL,
NbBundle.getMessage(AttributeEqualBuilder.class, "AttributeEqualBuilder.description"), null);
}
@Override
public EqualBooleanFilter getFilter() {
return new EqualBooleanFilter(column);
return AttributeUtils.isNodeColumn(column) ? new EqualBooleanFilter.Node(column) : new EqualBooleanFilter.Edge(column);
}
@Override
public JPanel getPanel(Filter filter) {
EqualBooleanUI ui = Lookup.getDefault().lookup(EqualBooleanUI.class);
if (ui != null) {
......@@ -307,12 +348,11 @@ public class AttributeEqualBuilder implements CategoryBuilder {
}
}
public static class EqualBooleanFilter extends AbstractAttributeFilter {
public static abstract class EqualBooleanFilter<K extends Element> extends AbstractAttributeFilter<K> {
private boolean match = false;
private DynamicAttributesHelper dynamicHelper = new DynamicAttributesHelper(this, null);
public EqualBooleanFilter(AttributeColumn column) {
public EqualBooleanFilter(Column column) {
super(NbBundle.getMessage(AttributeEqualBuilder.class, "AttributeEqualBuilder.name"),
column);
......@@ -320,21 +360,21 @@ public class AttributeEqualBuilder implements CategoryBuilder {
addProperty(Boolean.class, "match");
}
@Override
public boolean init(Graph graph) {
HierarchicalGraph hg = (HierarchicalGraph) graph;
dynamicHelper = new DynamicAttributesHelper(this, hg);
return true;
}
public boolean evaluate(Graph graph, Attributable attributable) {
Object val = attributable.getAttributes().getValue(column.getIndex());
val = dynamicHelper.getDynamicValue(val);
@Override
public boolean evaluate(Graph graph, Element element) {
Object val = element.getAttribute(column, graph.getView());
if (val != null) {
return val.equals(match);
}
return false;
}
@Override
public void finish() {
}
......@@ -345,5 +385,19 @@ public class AttributeEqualBuilder implements CategoryBuilder {
public void setMatch(boolean match) {
this.match = match;
}
public static class Node extends EqualBooleanFilter<org.gephi.graph.api.Node> implements NodeFilter {
public Node(Column column) {
super(column);
}
}
public static class Edge extends EqualBooleanFilter<org.gephi.graph.api.Edge> implements EdgeFilter {
public Edge(Column column) {
super(column);
}
}
}
}
......@@ -42,23 +42,23 @@
package org.gephi.filters.plugin.attribute;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.JPanel;
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.filters.api.FilterLibrary;
import org.gephi.filters.plugin.AbstractAttributeFilter;
import org.gephi.filters.plugin.AbstractAttributeFilterBuilder;
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.graph.api.Attributable;
import org.gephi.filters.spi.NodeFilter;
import org.gephi.graph.api.AttributeUtils;
import org.gephi.graph.api.Column;
import org.gephi.graph.api.Element;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.HierarchicalGraph;
import org.gephi.graph.api.GraphController;
import org.gephi.graph.api.GraphModel;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
......@@ -75,68 +75,92 @@ public class AttributeNonNullBuilder implements CategoryBuilder {
null,
FilterLibrary.ATTRIBUTES);
@Override
public Category getCategory() {
return NONNULL;
}
@Override
public FilterBuilder[] getBuilders() {
List<FilterBuilder> builders = new ArrayList<FilterBuilder>();
AttributeModel am = Lookup.getDefault().lookup(AttributeController.class).getModel();
List<AttributeColumn> columns = new ArrayList<AttributeColumn>();
columns.addAll(Arrays.asList(am.getNodeTable().getColumns()));
columns.addAll(Arrays.asList(am.getEdgeTable().getColumns()));
for (AttributeColumn c : columns) {
AttributeNonNullFilterBuilder b = new AttributeNonNullFilterBuilder(c);
builders.add(b);
GraphModel am = Lookup.getDefault().lookup(GraphController.class).getGraphModel();
for (Column col : am.getNodeTable()) {
if (!col.isProperty()) {
AttributeNonNullFilterBuilder b = new AttributeNonNullFilterBuilder(col);
builders.add(b);
}
}
for (Column col : am.getEdgeTable()) {
if (!col.isProperty()) {
AttributeNonNullFilterBuilder b = new AttributeNonNullFilterBuilder(col);
builders.add(b);
}
}
return builders.toArray(new FilterBuilder[0]);
}
private static class AttributeNonNullFilterBuilder extends AbstractAttributeFilterBuilder {
public AttributeNonNullFilterBuilder(AttributeColumn column) {
public AttributeNonNullFilterBuilder(Column column) {
super(column,
NONNULL,
NbBundle.getMessage(AttributeEqualBuilder.class, "AttributeNonNullBuilder.description"),
null);
}
@Override
public AttributeNonNullFilter getFilter() {
AttributeNonNullFilter f = new AttributeNonNullFilter(column);
return f;
return AttributeUtils.isNodeColumn(column) ? new AttributeNonNullFilter.Node(column) : new AttributeNonNullFilter.Edge(column);
}
@Override
public JPanel getPanel(Filter filter) {
return null;
}
}
public static class AttributeNonNullFilter extends AbstractAttributeFilter {
public static abstract class AttributeNonNullFilter<K extends Element> extends AbstractAttributeFilter<K> {
public AttributeNonNullFilter(AttributeColumn column) {
public AttributeNonNullFilter(Column column) {
super(NbBundle.getMessage(AttributeEqualBuilder.class, "AttributeNonNullBuilder.name"),
column);
}
@Override
public boolean init(Graph graph) {
HierarchicalGraph hg = (HierarchicalGraph) graph;
if (AttributeUtils.getDefault().isNodeColumn(column)) {
if (AttributeUtils.isNodeColumn(column)) {
if (graph.getNodeCount() == 0) {
return false;
}
} else if (AttributeUtils.getDefault().isEdgeColumn(column)) {
if (hg.getTotalEdgeCount() == 0) {
} else if (AttributeUtils.isEdgeColumn(column)) {
if (graph.getEdgeCount() == 0) {
return false;
}
}
return true;
}
public boolean evaluate(Graph graph, Attributable attributable) {
return attributable.getAttributes().getValue(column.getIndex()) != null;
@Override
public boolean evaluate(Graph graph, Element element) {
return element.getAttribute(column) != null;
}
@Override
public void finish() {
}
public static class Node extends AttributeNonNullFilter<org.gephi.graph.api.Node> implements NodeFilter {
public Node(Column column) {
super(column);
}
}
public static class Edge extends AttributeNonNullFilter<org.gephi.graph.api.Edge> implements EdgeFilter {
public Edge(Column column) {
super(column);
}
}
}
}
......@@ -42,18 +42,12 @@
package org.gephi.filters.plugin.attribute;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.JPanel;
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.filters.api.FilterLibrary;
import org.gephi.filters.api.Range;
import org.gephi.filters.plugin.AbstractAttributeFilter;
import org.gephi.filters.plugin.AbstractAttributeFilterBuilder;
import org.gephi.filters.plugin.DynamicAttributesHelper;
import org.gephi.filters.plugin.graph.RangeUI;
import org.gephi.filters.spi.*;
import org.gephi.graph.api.*;
......@@ -73,20 +67,24 @@ public class AttributeRangeBuilder implements CategoryBuilder {
null,
FilterLibrary.ATTRIBUTES);
@Override
public Category getCategory() {
return RANGE;
}
@Override
public FilterBuilder[] getBuilders() {
List<FilterBuilder> builders = new ArrayList<FilterBuilder>();
AttributeModel am = Lookup.getDefault().lookup(AttributeController.class).getModel();
List<AttributeColumn> columns = new ArrayList<AttributeColumn>();
columns.addAll(Arrays.asList(am.getNodeTable().getColumns()));
columns.addAll(Arrays.asList(am.getEdgeTable().getColumns()));
for (AttributeColumn c : columns) {
if (AttributeUtils.getDefault().isNumberColumn(c) || AttributeUtils.getDefault().isDynamicNumberColumn(c)) {
AttributeRangeFilterBuilder b = new AttributeRangeFilterBuilder(c);
builders.add(b);
GraphModel am = Lookup.getDefault().lookup(GraphController.class).getGraphModel();
List<Column> columns = new ArrayList<Column>();
columns.addAll(am.getNodeTable().toList());
columns.addAll(am.getEdgeTable().toList());
for (Column c : columns) {
if (!c.isProperty() && !c.isArray()) {
if (AttributeUtils.isNumberType(c.getTypeClass())) {
AttributeRangeFilterBuilder b = new AttributeRangeFilterBuilder(c);
builders.add(b);
}
}
}
return builders.toArray(new FilterBuilder[0]);
......@@ -94,17 +92,19 @@ public class AttributeRangeBuilder implements CategoryBuilder {
private static class AttributeRangeFilterBuilder extends AbstractAttributeFilterBuilder {
public AttributeRangeFilterBuilder(AttributeColumn column) {
public AttributeRangeFilterBuilder(Column column) {
super(column,
RANGE,
NbBundle.getMessage(AttributeEqualBuilder.class, "AttributeRangeBuilder.description"),
null);
}
@Override
public AttributeRangeFilter getFilter() {
return new AttributeRangeFilter(column);
return AttributeUtils.isNodeColumn(column) ? new AttributeRangeFilter.Node(column) : new AttributeRangeFilter.Edge(column);
}
@Override
public JPanel getPanel(Filter filter) {
RangeUI ui = Lookup.getDefault().lookup(RangeUI.class);
if (ui != null) {
......@@ -114,12 +114,11 @@ public class AttributeRangeBuilder implements CategoryBuilder {
}
}
public static class AttributeRangeFilter extends AbstractAttributeFilter implements RangeFilter {
public static abstract class AttributeRangeFilter<K extends Element> extends AbstractAttributeFilter<K> implements RangeFilter {
private Range range;
private DynamicAttributesHelper dynamicHelper = new DynamicAttributesHelper(this, null);
public AttributeRangeFilter(AttributeColumn column) {
public AttributeRangeFilter(Column column) {
super(NbBundle.getMessage(AttributeRangeBuilder.class, "AttributeRangeBuilder.name"),
column);
......@@ -127,24 +126,23 @@ public class AttributeRangeBuilder implements CategoryBuilder {
addProperty(Range.class, "range");
}
@Override
public boolean init(Graph graph) {
HierarchicalGraph hg = (HierarchicalGraph) graph;
if (AttributeUtils.getDefault().isNodeColumn(column)) {
if (AttributeUtils.isNodeColumn(column)) {
if (graph.getNodeCount() == 0) {
return false;
}
} else if (AttributeUtils.getDefault().isEdgeColumn(column)) {
if (hg.getTotalEdgeCount() == 0) {
} else if (AttributeUtils.isEdgeColumn(column)) {
if (graph.getEdgeCount() == 0) {
return false;
}
}
dynamicHelper = new DynamicAttributesHelper(this, hg);
return true;
}
public boolean evaluate(Graph graph, Attributable attributable) {
Object val = attributable.getAttributes().getValue(column.getIndex());
val = dynamicHelper.getDynamicValue(val);
@Override
public boolean evaluate(Graph graph, Element element) {
Object val = element.getAttribute(column, graph.getView());
if (val != null) {
return range.isInRange((Number) val);
}
......@@ -152,23 +150,23 @@ public class AttributeRangeBuilder implements CategoryBuilder {
}
@Override
public void finish() {
}
@Override
public Number[] getValues(Graph graph) {
List<Number> vals = new ArrayList<Number>();
if (AttributeUtils.getDefault().isNodeColumn(column)) {
for (Node n : graph.getNodes()) {
Object val = n.getNodeData().getAttributes().getValue(column.getIndex());
val = dynamicHelper.getDynamicValue(val);
if (AttributeUtils.isNodeColumn(column)) {
for (Element n : graph.getNodes()) {
Object val = n.getAttribute(column, graph.getView());
if (val != null) {
vals.add((Number) val);
}
}
} else {
for (Edge e : ((HierarchicalGraph) graph).getEdgesAndMetaEdges()) {
Object val = e.getEdgeData().getAttributes().getValue(column.getIndex());
val = dynamicHelper.getDynamicValue(val);
for (Element e : graph.getEdges()) {
Object val = e.getAttribute(column, graph.getView());
if (val != null) {
vals.add((Number) val);
}
......@@ -177,6 +175,7 @@ public class AttributeRangeBuilder implements CategoryBuilder {
return vals.toArray(new Number[0]);
}
@Override
public FilterProperty getRangeProperty() {
return getProperties()[1];
}
......@@ -188,5 +187,19 @@ public class AttributeRangeBuilder implements CategoryBuilder {
public void setRange(Range range) {
this.range = range;
}
public static class Node extends AttributeRangeFilter<org.gephi.graph.api.Node> implements NodeFilter {
public Node(Column column) {
super(column);
}
}
public static class Edge extends AttributeRangeFilter<org.gephi.graph.api.Edge> implements EdgeFilter {
public Edge(Column column) {
super(column);
}
}
}
}
/*
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.data.attributes.api.AttributeColumn;
import org.gephi.data.attributes.api.AttributeController;
import org.gephi.data.attributes.api.AttributeModel;
import org.gephi.data.attributes.type.TimeInterval;
import org.gephi.dynamic.api.DynamicController;
import org.gephi.dynamic.api.DynamicModel;
import org.gephi.dynamic.api.DynamicModelEvent;
import org.gephi.dynamic.api.DynamicModelListener;
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.gephi.timeline.api.TimelineController;
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);
public Category getCategory() {
return DYNAMIC;
}
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;
}
public Category getCategory() {
return DYNAMIC;
}
public String getName() {
return "Time Interval";
}
public Icon getIcon() {
return null;
}
public String getDescription() {
return null;
}
public DynamicRangeFilter getFilter() {
TimelineController timelineController = Lookup.getDefault().lookup(TimelineController.class);
DynamicController dynamicController = Lookup.getDefault().lookup(DynamicController.class);
return new DynamicRangeFilter(timelineController, dynamicController, nodeColumn, edgeColumn);
}
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;
}
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;
}
public boolean init(Graph graph) {
dynamicController.addModelListener(this);
visibleInterval = dynamicModel.getVisibleInterval();
return true;
}
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;
}
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;
}
public void finish() {
}
public String getName() {
return NbBundle.getMessage(DynamicRangeBuilder.class, "DynamicRangeBuilder.name");
}
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.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 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);
//}
......@@ -48,12 +48,10 @@ import javax.swing.JPanel;
import org.gephi.filters.api.FilterLibrary;
import org.gephi.filters.api.Range;
import org.gephi.filters.plugin.AbstractFilter;
import org.gephi.filters.plugin.DynamicAttributesHelper;
import org.gephi.filters.plugin.graph.RangeUI;
import org.gephi.filters.spi.*;
import org.gephi.graph.api.Edge;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.HierarchicalGraph;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
......@@ -65,26 +63,32 @@ import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = FilterBuilder.class)
public class EdgeWeightBuilder implements FilterBuilder {
@Override
public Category getCategory() {
return FilterLibrary.EDGE;
}
@Override
public String getName() {
return NbBundle.getMessage(EdgeWeightBuilder.class, "EdgeWeightBuilder.name");
}
@Override
public Icon getIcon() {
return null;
}
@Override
public String getDescription() {
return NbBundle.getMessage(EdgeWeightBuilder.class, "EdgeWeightBuilder.description");
}
@Override
public Filter getFilter() {
return new EdgeWeightFilter();
}
@Override
public JPanel getPanel(Filter filter) {
RangeUI ui = Lookup.getDefault().lookup(RangeUI.class);
if (ui != null) {
......@@ -93,13 +97,13 @@ public class EdgeWeightBuilder implements FilterBuilder {
return null;
}
@Override
public void destroy(Filter filter) {
}
public static class EdgeWeightFilter extends AbstractFilter implements RangeFilter, EdgeFilter {
private Range range;
private DynamicAttributesHelper dynamicHelper = new DynamicAttributesHelper(this, null);
public EdgeWeightFilter() {
super(NbBundle.getMessage(EdgeWeightBuilder.class, "EdgeWeightBuilder.name"));
......@@ -107,33 +111,32 @@ public class EdgeWeightBuilder implements FilterBuilder {
addProperty(Range.class, "range");
}
@Override
public boolean init(Graph graph) {
HierarchicalGraph hgraph = (HierarchicalGraph) graph;
if (hgraph.getTotalEdgeCount() == 0) {
return false;
}
dynamicHelper = new DynamicAttributesHelper(this, hgraph);
return true;
return graph.getEdgeCount() != 0;
}
@Override
public boolean evaluate(Graph graph, Edge edge) {
float weight = dynamicHelper.getEdgeWeight(edge);
double weight = edge.getWeight(graph.getView());
return range.isInRange(weight);
}
@Override
public void finish() {
}
@Override
public Number[] getValues(Graph graph) {
HierarchicalGraph hgraph = (HierarchicalGraph) graph;
List<Number> values = new ArrayList<Number>();
for (Edge e : hgraph.getEdgesAndMetaEdges()) {
float weight = dynamicHelper.getEdgeWeight(e);
for (Edge e : graph.getEdges()) {
double weight = e.getWeight(graph.getView());
values.add(weight);
}
return values.toArray(new Number[0]);
}
@Override
public FilterProperty getRangeProperty() {
return getProperties()[0];
}
......
......@@ -57,50 +57,62 @@ import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = FilterBuilder.class)
public class SelfLoopFilterBuilder implements FilterBuilder {
@Override
public Category getCategory() {
return FilterLibrary.EDGE;
}
@Override
public String getName() {
return NbBundle.getMessage(SelfLoopFilterBuilder.class, "SelfLoopFilterBuilder.name");
}
@Override
public Icon getIcon() {
return null;
}
@Override
public String getDescription() {
return NbBundle.getMessage(SelfLoopFilterBuilder.class, "SelfLoopFilterBuilder.description");
}
@Override
public Filter getFilter() {
return new SelfLoopFilter();
}
@Override
public JPanel getPanel(Filter filter) {
return null;
}
@Override
public void destroy(Filter filter) {
}
public static class SelfLoopFilter implements EdgeFilter {
@Override
public boolean init(Graph graph) {
return true;
}
@Override
public String getName() {
return NbBundle.getMessage(SelfLoopFilterBuilder.class, "SelfLoopFilterBuilder.name");
}
@Override
public boolean evaluate(Graph graph, Edge edge) {
return !edge.isSelfLoop();
}
@Override
public void finish() {
}
@Override
public FilterProperty[] getProperties() {
return null;
}
......
......@@ -50,7 +50,6 @@ import org.gephi.filters.api.Range;
import org.gephi.filters.plugin.AbstractFilter;
import org.gephi.filters.spi.*;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.HierarchicalGraph;
import org.gephi.graph.api.Node;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
......@@ -63,26 +62,32 @@ import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = FilterBuilder.class)
public class DegreeRangeBuilder implements FilterBuilder {
@Override
public Category getCategory() {
return FilterLibrary.TOPOLOGY;
}
@Override
public String getName() {
return NbBundle.getMessage(DegreeRangeBuilder.class, "DegreeRangeBuilder.name");
}
@Override
public Icon getIcon() {
return null;
}
@Override
public String getDescription() {
return NbBundle.getMessage(DegreeRangeBuilder.class, "DegreeRangeBuilder.description");
}
@Override
public DegreeRangeFilter getFilter() {
return new DegreeRangeFilter();
}
@Override
public JPanel getPanel(Filter filter) {
RangeUI ui = Lookup.getDefault().lookup(RangeUI.class);
if (ui != null) {
......@@ -91,6 +96,7 @@ public class DegreeRangeBuilder implements FilterBuilder {
return null;
}
@Override
public void destroy(Filter filter) {
}
......@@ -104,31 +110,32 @@ public class DegreeRangeBuilder implements FilterBuilder {
addProperty(Range.class, "range");
}
@Override
public boolean init(Graph graph) {
if (graph.getNodeCount() == 0) {
return false;
}
return true;
return graph.getNodeCount() != 0;
}
@Override
public boolean evaluate(Graph graph, Node node) {
int degree = ((HierarchicalGraph) graph).getTotalDegree(node);
int degree = graph.getDegree(node);
return range.isInRange(degree);
}
@Override
public void finish() {
}
@Override
public Number[] getValues(Graph graph) {
HierarchicalGraph hgraph = (HierarchicalGraph) graph;
List<Integer> values = new ArrayList<Integer>(((HierarchicalGraph) graph).getNodeCount());
for (Node n : hgraph.getNodes()) {
int degree = hgraph.getTotalDegree(n);
List<Integer> values = new ArrayList<Integer>(graph.getNodeCount());
for (Node n : graph.getNodes()) {
int degree = graph.getDegree(n);
values.add(degree);
}
return values.toArray(new Number[0]);
}
@Override
public FilterProperty getRangeProperty() {
return getProperties()[0];
}
......
......@@ -54,7 +54,6 @@ import org.gephi.filters.spi.Filter;
import org.gephi.filters.spi.FilterBuilder;
import org.gephi.filters.spi.FilterProperty;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.HierarchicalGraph;
import org.gephi.graph.api.Node;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
......@@ -67,26 +66,32 @@ import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = FilterBuilder.class)
public class EgoBuilder implements FilterBuilder {
@Override
public Category getCategory() {
return FilterLibrary.TOPOLOGY;
}
@Override
public String getName() {
return NbBundle.getMessage(EgoBuilder.class, "EgoBuilder.name");
}
@Override
public Icon getIcon() {
return null;
}
@Override
public String getDescription() {
return NbBundle.getMessage(EgoBuilder.class, "EgoBuilder.description");
}
@Override
public Filter getFilter() {
return new EgoFilter();
}
@Override
public JPanel getPanel(Filter filter) {
EgoUI ui = Lookup.getDefault().lookup(EgoUI.class);
if (ui != null) {
......@@ -95,6 +100,7 @@ public class EgoBuilder implements FilterBuilder {
return null;
}
@Override
public void destroy(Filter filter) {
}
......@@ -104,16 +110,15 @@ public class EgoBuilder implements FilterBuilder {
private boolean self = true;
private int depth = 1;
@Override
public Graph filter(Graph graph) {
HierarchicalGraph hgraph = (HierarchicalGraph) graph;
String str = pattern.toLowerCase();
List<Node> nodes = new ArrayList<Node>();
for (Node n : hgraph.getNodes()) {
if (n.getNodeData().getId().toLowerCase().equals(str)) {
for (Node n : graph.getNodes()) {
if (n.getId().toString().toLowerCase().equals(str)) {
nodes.add(n);
} else if ((n.getNodeData().getLabel() != null) && n.getNodeData().getLabel().toLowerCase().equals(str)) {
} else if ((n.getLabel() != null) && n.getLabel().toLowerCase().equals(str)) {
nodes.add(n);
}
}
......@@ -127,7 +132,7 @@ public class EgoBuilder implements FilterBuilder {
Node[] nei = neighbours.toArray(new Node[0]);
neighbours.clear();
for (Node n : nei) {
for (Node neighbor : hgraph.getNeighbors(n)) {
for (Node neighbor : graph.getNeighbors(n)) {
if (!result.contains(neighbor)) {
neighbours.add(neighbor);
result.add(neighbor);
......@@ -145,25 +150,27 @@ public class EgoBuilder implements FilterBuilder {
result.removeAll(nodes);
}
for (Node node : hgraph.getNodes().toArray()) {
for (Node node : graph.getNodes().toArray()) {
if (!result.contains(node)) {
hgraph.removeNode(node);
graph.removeNode(node);
}
}
return hgraph;
return graph;
}
@Override
public String getName() {
return NbBundle.getMessage(EgoBuilder.class, "EgoBuilder.name");
}
@Override
public FilterProperty[] getProperties() {
try {
return new FilterProperty[]{
FilterProperty.createProperty(this, String.class, "pattern"),
FilterProperty.createProperty(this, Integer.class, "depth"),
FilterProperty.createProperty(this, Boolean.class, "self")};
FilterProperty.createProperty(this, String.class, "pattern"),
FilterProperty.createProperty(this, Integer.class, "depth"),
FilterProperty.createProperty(this, Boolean.class, "self")};
} catch (NoSuchMethodException ex) {
ex.printStackTrace();
}
......
......@@ -43,21 +43,17 @@ package org.gephi.filters.plugin.graph;
import javax.swing.Icon;
import javax.swing.JPanel;
import org.gephi.data.attributes.api.AttributeColumn;
import org.gephi.data.attributes.api.AttributeController;
import org.gephi.data.attributes.api.AttributeModel;
import org.gephi.filters.api.FilterLibrary;
import org.gephi.filters.spi.Category;
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.Column;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.HierarchicalUndirectedGraph;
import org.gephi.graph.api.Node;
import org.gephi.graph.api.UndirectedGraph;
import org.gephi.statistics.plugin.ConnectedComponents;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
......@@ -68,74 +64,79 @@ import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = FilterBuilder.class)
public class GiantComponentBuilder implements FilterBuilder {
@Override
public Category getCategory() {
return FilterLibrary.TOPOLOGY;
}
@Override
public String getName() {
return NbBundle.getMessage(GiantComponentBuilder.class, "GiantComponentBuilder.name");
}
@Override
public Icon getIcon() {
return null;
}
@Override
public String getDescription() {
return NbBundle.getMessage(GiantComponentBuilder.class, "GiantComponentBuilder.description");
}
@Override
public Filter getFilter() {
return new GiantComponentFilter();
}
@Override
public JPanel getPanel(Filter filter) {
return null;
}
@Override
public void destroy(Filter filter) {
}
public static class GiantComponentFilter implements NodeFilter {
private AttributeModel attributeModel;
private int componentId;
private AttributeColumn column;
private Column column;
public GiantComponentFilter() {
}
@Override
public boolean init(Graph graph) {
ConnectedComponents cc = new ConnectedComponents();
HierarchicalUndirectedGraph undirectedGraph = null;
if (cc instanceof UndirectedGraph) {
undirectedGraph = (HierarchicalUndirectedGraph) graph;
} else {
undirectedGraph = graph.getView().getGraphModel().getHierarchicalUndirectedGraph(graph.getView());
}
UndirectedGraph undirectedGraph = graph.getModel().getUndirectedGraph(graph.getView());
attributeModel = Lookup.getDefault().lookup(AttributeController.class).getModel(graph.getGraphModel().getWorkspace());
cc.weaklyConnected(undirectedGraph, attributeModel);
cc.weaklyConnected(undirectedGraph);
componentId = cc.getGiantComponent();
column = attributeModel.getNodeTable().getColumn(ConnectedComponents.WEAKLY);
column = graph.getModel().getNodeTable().getColumn(ConnectedComponents.WEAKLY);
return column != null && componentId != -1;
}
@Override
public boolean evaluate(Graph graph, Node node) {
Integer component = (Integer) node.getNodeData().getAttributes().getValue(column.getIndex());
Integer component = (Integer) node.getAttribute(column);
if (component != null) {
return component.equals(componentId);
}
return false;
}
@Override
public void finish() {
}
@Override
public String getName() {
return NbBundle.getMessage(GiantComponentBuilder.class, "GiantComponentBuilder.name");
}
@Override
public FilterProperty[] getProperties() {
return new FilterProperty[0];
}
......
......@@ -61,26 +61,32 @@ import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = FilterBuilder.class)
public class InDegreeRangeBuilder implements FilterBuilder {
@Override
public Category getCategory() {
return FilterLibrary.TOPOLOGY;
}
@Override
public String getName() {
return NbBundle.getMessage(InDegreeRangeBuilder.class, "InDegreeRangeBuilder.name");
}
@Override
public Icon getIcon() {
return null;
}
@Override
public String getDescription() {
return NbBundle.getMessage(InDegreeRangeBuilder.class, "InDegreeRangeBuilder.description");
}
@Override
public InDegreeRangeFilter getFilter() {
return new InDegreeRangeFilter();
}
@Override
public JPanel getPanel(Filter filter) {
RangeUI ui = Lookup.getDefault().lookup(RangeUI.class);
if (ui != null) {
......@@ -89,6 +95,7 @@ public class InDegreeRangeBuilder implements FilterBuilder {
return null;
}
@Override
public void destroy(Filter filter) {
}
......@@ -103,31 +110,33 @@ public class InDegreeRangeBuilder implements FilterBuilder {
addProperty(Range.class, "range");
}
@Override
public boolean init(Graph graph) {
if (graph.getNodeCount() == 0 || !(graph instanceof DirectedGraph)) {
return false;
}
return true;
return !(graph.getNodeCount() == 0 || !(graph.isDirected()));
}
@Override
public boolean evaluate(Graph graph, Node node) {
int degree = ((HierarchicalDirectedGraph) graph).getTotalInDegree(node);
int degree = ((DirectedGraph) graph).getInDegree(node);
return range.isInRange(degree);
}
@Override
public void finish() {
}
@Override
public Number[] getValues(Graph graph) {
HierarchicalDirectedGraph hgraph = (HierarchicalDirectedGraph) graph;
List<Integer> values = new ArrayList<Integer>(((HierarchicalGraph) graph).getNodeCount());
for (Node n : hgraph.getNodes()) {
int degree = hgraph.getTotalInDegree(n);
DirectedGraph dgraph = (DirectedGraph) graph;
List<Integer> values = new ArrayList<Integer>(dgraph.getNodeCount());
for (Node n : dgraph.getNodes()) {
int degree = dgraph.getInDegree(n);
values.add(degree);
}
return values.toArray(new Number[0]);
}
@Override
public FilterProperty getRangeProperty() {
return getProperties()[0];
}
......
......@@ -63,26 +63,32 @@ import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = FilterBuilder.class)
public class KCoreBuilder implements FilterBuilder {
@Override
public Category getCategory() {
return FilterLibrary.TOPOLOGY;
}
@Override
public String getName() {
return NbBundle.getMessage(KCoreBuilder.class, "KCoreBuilder.name");
}
@Override
public Icon getIcon() {
return null;
}
@Override
public String getDescription() {
return NbBundle.getMessage(KCoreBuilder.class, "KCoreBuilder.description");
}
@Override
public Filter getFilter() {
return new KCoreFilter();
}
@Override
public JPanel getPanel(Filter filter) {
KCoreUI ui = Lookup.getDefault().lookup(KCoreUI.class);
if (ui != null) {
......@@ -91,6 +97,7 @@ public class KCoreBuilder implements FilterBuilder {
return null;
}
@Override
public void destroy(Filter filter) {
}
......@@ -99,6 +106,7 @@ public class KCoreBuilder implements FilterBuilder {
private FilterProperty[] filterProperties;
private Integer k = 1;
@Override
public Graph filter(Graph graph) {
int removed = 0;
do {
......@@ -113,10 +121,12 @@ public class KCoreBuilder implements FilterBuilder {
return graph;
}
@Override
public String getName() {
return NbBundle.getMessage(KCoreBuilder.class, "KCoreBuilder.name");
}
@Override
public FilterProperty[] getProperties() {
if (filterProperties == null) {
filterProperties = new FilterProperty[0];
......
......@@ -61,26 +61,32 @@ import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = FilterBuilder.class)
public class MutualDegreeRangeBuilder implements FilterBuilder {
@Override
public Category getCategory() {
return FilterLibrary.TOPOLOGY;
}
@Override
public String getName() {
return NbBundle.getMessage(MutualDegreeRangeBuilder.class, "MutualDegreeRangeBuilder.name");
}
@Override
public Icon getIcon() {
return null;
}
@Override
public String getDescription() {
return NbBundle.getMessage(MutualDegreeRangeBuilder.class, "MutualDegreeRangeBuilder.description");
}
@Override
public MutualDegreeRangeFilter getFilter() {
return new MutualDegreeRangeFilter();
}
@Override
public JPanel getPanel(Filter filter) {
RangeUI ui = Lookup.getDefault().lookup(RangeUI.class);
if (ui != null) {
......@@ -89,6 +95,7 @@ public class MutualDegreeRangeBuilder implements FilterBuilder {
return null;
}
@Override
public void destroy(Filter filter) {
}
......@@ -103,31 +110,44 @@ public class MutualDegreeRangeBuilder implements FilterBuilder {
addProperty(Range.class, "range");
}
@Override
public boolean init(Graph graph) {
if (graph.getNodeCount() == 0 || !(graph instanceof DirectedGraph)) {
return false;
}
return true;
return !(graph.getNodeCount() == 0 || !(graph.isDirected()));
}
@Override
public boolean evaluate(Graph graph, Node node) {
int degree = ((HierarchicalDirectedGraph) graph).getMutualDegree(node);
DirectedGraph dgraph = (DirectedGraph) graph;
int degree = 0;
for (Edge e : dgraph.getOutEdges(node)) {
if (dgraph.getMutualEdge(e) != null) {
degree++;
}
}
return range.isInRange(degree);
}
@Override
public void finish() {
}
@Override
public Number[] getValues(Graph graph) {
HierarchicalDirectedGraph hgraph = (HierarchicalDirectedGraph) graph;
List<Integer> values = new ArrayList<Integer>(((HierarchicalGraph) graph).getNodeCount());
for (Node n : hgraph.getNodes()) {
int degree = hgraph.getMutualDegree(n);
DirectedGraph dgraph = (DirectedGraph) graph;
List<Integer> values = new ArrayList<Integer>(dgraph.getNodeCount());
for (Node n : dgraph.getNodes()) {
int degree = 0;
for (Edge e : dgraph.getOutEdges(n)) {
if (dgraph.getMutualEdge(e) != null) {
degree++;
}
}
values.add(degree);
}
return values.toArray(new Number[0]);
}
@Override
public FilterProperty getRangeProperty() {
return getProperties()[0];
}
......
......@@ -8,4 +8,7 @@ IntraEdgesBuilder.name = Intra Edges
IntraEdgesBuilder.description = Keep only edges between elements from different parts
InterEdgesBuilder.name = Inter Edges
InterEdgesBuilder.description = Keep only edges between elements from the same part
\ No newline at end of file
InterEdgesBuilder.description = Keep only edges between elements from the same part
PartitionFilterBuilder.name.node = Node
PartitionFilterBuilder.name.edge = Edge
\ No newline at end of file
此差异已折叠。
<?xml version="1.1" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<NonVisualComponents>
......
......@@ -38,7 +38,7 @@ made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
*/
package org.gephi.ui.filters.plugin.attribute;
import javax.swing.JPanel;
......@@ -53,6 +53,7 @@ import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = EqualBooleanUI.class)
public class EqualBooleanUIImpl implements EqualBooleanUI {
@Override
public JPanel getPanel(EqualBooleanFilter filter) {
EqualBooleanPanel panel = new EqualBooleanPanel();
panel.setup(filter);
......
<?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>
......
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册