Plugin dans l’interface graphique 2D.

... ou comment ajouter de nouvelles fonctionnalités dans l’interface graphique de GeOxygene.

Les contributions des développeurs ne sont pas incluses dans le module de l’interface graphique 2D, elles sont implémentées à l’aide de plugins.

Actuellement les plugins sont regroupés suivant les thèmes de recherche du laboratoire : sémiologie, généralisation ou appariement de données.

Plugins GeOxygene

Il existe deux types de plugins :

  • les GeOxygeneApplicationPlugin, qui permettent par exemple d’ajouter des menus à l’interface principale (c’est ceux qui existaient avant).
  • les ProjectFramePlugin, qui permettent d’ajouter des éléments graphiques (toolbar, slider, ...) à un projectFrame afin de le modifier.

L’initialisation des plugins se fait à différents moments suivant le type choisi. Les plugins classiques (GeOxygeneApplicationPlugin) sont initialisés au chargement de l’interface graphique, et les plugins de type ProjectFrame sont initialisés à chaque nouvelle création d’un projectFrame.

Ci-dessous le diagramme de classes des plugins implémentés dans le module geoxygene-appli :

../../_images/class-diagram01.png

Figure 1 : Diagramme de classe des plugins dans GeOxygene

En général les plugins sont implémentés dans un module Maven dédié à un thème.

Les plugins sont configurés dans le fichier geoxygene-configuration.xml stocké à la racine de votre module.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<GeOxygeneApplicationProperties>
    <plugin>fr.ign.cogit.geoxygene.appli.plugin.datamatching.NetworkDataMatchingPlugin</plugin>
    <plugin>fr.ign.cogit.geoxygene.appli.plugin.datamatching.DataMatchingPlugin</plugin>
    <plugin>fr.ign.cogit.geoxygene.appli.plugin.cartetopo.BuildingBlocksCreationPlugin</plugin>
    <plugin>fr.ign.cogit.geoxygene.appli.plugin.cartetopo.ImportAsEdgesPlugin</plugin>
    <plugin>fr.ign.cogit.geoxygene.appli.plugin.BezierCurvePlugin</plugin>
    <plugin>fr.ign.cogit.geoxygene.appli.plugin.TINPlugin</plugin>
    <plugin>fr.ign.cogit.geoxygene.appli.plugin.CubicSplinePlugin</plugin>
    <plugin>fr.ign.cogit.geoxygene.appli.plugin.TriangulationJTSPlugin</plugin>
    <plugin>fr.ign.cogit.geoxygene.appli.plugin.CharacteristicShapeJTSPlugin</plugin>
    <plugin>fr.ign.cogit.geoxygene.appli.plugin.VoronoiDiagramJTSPlugin</plugin>
    <plugin>fr.ign.cogit.geoxygene.appli.plugin.SwingingArmPlugin</plugin>
    <plugin>fr.ign.cogit.geoxygene.appli.plugin.script.GroovyConsolePlugin</plugin>
    <plugin>fr.ign.cogit.geoxygene.appli.plugin.semio.SemioPlugin</plugin>
    <plugin>fr.ign.cogit.geoxygene.appli.plugin.cartagen.CartAGenPlugin</plugin>
    <plugin>fr.ign.cogit.geoxygene.appli.plugin.osm.OSMPlugin</plugin>
</GeOxygeneApplicationProperties>

Quickstart

Ce tutoriel explique comment créer un plugin GeOxygene depuis un nouveau module Maven à partir d’un exemple. Nous voulons ici ajouter un nouveau bouton dans la barre de menu (notre plugin sera donc de type GeOxygeneApplicationPlugin) qui permet de lancer un filtre gaussien (lissage) sur un réseau linéaire.

  1. Tout d’abord il faut ajouter la librairie “geoxygene-appli” à notre projet. Cette librairie contient les classes de l’interface graphique GeOxygene 2D.

Ouvrir le fichier pom.xml de votre module Maven et ajouter une dépendance au module “geoxygene-appli” :

<?xml version="1.0" encoding="UTF-8"?>
<project>

    <!-- Version number of GeOxygene -->
    <properties>
        <geoxygene.noyau.version>1.6-SNAPSHOT</geoxygene.noyau.version>
    </properties>

    <!-- ... -->

    <!-- GeOxygene modules which your application will need -->
    <dependencies>
	    <dependency>
	        <groupId>fr.ign.cogit</groupId>
	        <artifactId>geoxygene-appli</artifactId>
	        <version>${geoxygene.noyau.version}</version>
	    </dependency>
    </dependencies>
    
    <!-- ... -->
    
    <!-- Repositories to download geoxygene jars -->
    <repositories>
        <repository>
            <id>snapshots</id>
            <name>Nexus Snapshots Repository</name>
            <url>https://forge-cogit.ign.fr/nexus/content/repositories/snapshots</url>
        </repository>
        <repository>
            <id>releases</id>
            <name>Internal Releases</name>
            <url>https://forge-cogit.ign.fr/nexus/content/repositories/releases/</url>
        </repository>
    </repositories>
    
</project>
  1. Créer une nouvelle classe qui implémente GeOxygeneApplicationPlugin, par exemple GaussianFilterPlugin.java :
package fr.ign.cogit.plugin;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Set;

import javax.swing.JMenuItem;
import javax.swing.JOptionPane;

import org.apache.log4j.Logger;

import fr.ign.cogit.geoxygene.api.feature.IFeature;
import fr.ign.cogit.geoxygene.api.spatial.coordgeom.ILineString;
import fr.ign.cogit.geoxygene.api.spatial.geomaggr.IMultiCurve;
import fr.ign.cogit.geoxygene.appli.GeOxygeneApplication;
import fr.ign.cogit.geoxygene.appli.api.ProjectFrame;
import fr.ign.cogit.geoxygene.appli.plugin.GeOxygeneApplicationPlugin;
import fr.ign.cogit.geoxygene.feature.DefaultFeature;
import fr.ign.cogit.geoxygene.feature.Population;
import fr.ign.cogit.geoxygene.schema.schemaConceptuelISOJeu.FeatureType;
import fr.ign.cogit.geoxygene.generalisation.GaussianFilter;
import fr.ign.cogit.geoxygene.style.Layer;

/**
 * 
 * 
 *
 */
public class GaussianFilterPlugin implements GeOxygeneApplicationPlugin, ActionListener {

  /** Logger. */
  private final static Logger LOGGER = Logger.getLogger(GaussianFilterPlugin.class.getName());
  
  /** GeOxygeneApplication */
  private GeOxygeneApplication application = null;

  // ...

}

3. Puis il faut surcharger la méthode “initialize” qui initialise le plugin. Dans notre exemple, on ajoute un nouveau bouton et un évènement sur celui-ci.

  /**
   * Initialize the plugin.
   * @param application the application
   */
  @Override
  public final void initialize(final GeOxygeneApplication application) {
    this.application = application;
    
    JMenu menuExample = null;
    String menuName = "Curve";
    for (Component c : application.getMainFrame().getMenuBar().getComponents()) {
      if (c instanceof JMenu) {
        JMenu aMenu = (JMenu) c;
        if (aMenu.getText() != null
            && aMenu.getText().equalsIgnoreCase(menuName)) {
          menuExample = aMenu;
        }
      }
    }
    if (menuExample == null) {
      menuExample = new JMenu(menuName);
    }

    JMenuItem menuItem = new JMenuItem("Gaussian Filter");
    menuItem.addActionListener(this);
    menuExample.add(menuItem);

  }
  1. Enfin on définit notre processus dans la fonction qui traite l’évènement :
  @SuppressWarnings("unchecked")
  @Override
  public void actionPerformed(final ActionEvent e) {

    // On récupère la couche sélectionnée
    ProjectFrame project = this.application.getMainFrame().getSelectedProjectFrame();
    Set<Layer> selectedLayers = project.getLayerLegendPanel().getSelectedLayers();
    if (selectedLayers.size() != 1) {
      javax.swing.JOptionPane.showMessageDialog(null, "You need to select one (and only one) layer.");
      GaussianFilterPlugin.LOGGER.error("You need to select one (and only one) layer.");
      return;
    }
    Layer layer = selectedLayers.iterator().next();
    
    // On propose le champ de saisie du paramètre sigma pour le filtrage gaussien.
    double sigma = Double.parseDouble(JOptionPane.showInputDialog(GaussianFilterPlugin.this.application.getMainFrame(), "Sigma"));
    
    // On construit une population de DefaultFeature
    Population<DefaultFeature> pop = new Population<DefaultFeature>("GaussianFilter " + layer.getName() + " " + sigma);
    pop.setClasse(DefaultFeature.class);
    pop.setPersistant(false);
    for (IFeature f : layer.getFeatureCollection()) {
      ILineString line = null;
      if (ILineString.class.isAssignableFrom(f.getGeom().getClass())) {
        line = (ILineString) f.getGeom();
      } else {
        if (IMultiCurve.class.isAssignableFrom(f.getGeom().getClass())) {
          line = ((IMultiCurve<ILineString>) f.getGeom()).get(0);
        }
      }
      // On ajoute à la population l'arc lissé
      pop.nouvelElement(GaussianFilter.gaussianFilter(line, sigma, 1));
    }
    
    // Créer les métadonnées du jeu correspondant et on l'ajoute à la population
    FeatureType newFeatureType = new FeatureType();
    newFeatureType.setGeometryType(ILineString.class);
    pop.setFeatureType(newFeatureType);
    
    // On ajoute au ProjectFrame la nouvelle couche créée à partir de la nouvelle population
    project.getDataSet().addPopulation(pop);
    project.addFeatureCollection(pop, pop.getNom(), layer.getCRS());
  }
  1. Fichier de configuration

Dans votre module, ajouter à la racine du projet un fichier geoxygene-configuration.xml qui contient ces lignes :

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<GeOxygeneApplicationProperties>
    
    <plugin>fr.ign.cogit.geoxygene.appli.plugin.SymubruitExtractionPlugin</plugin>
    
</GeOxygeneApplicationProperties>
  1. Lancement de l’interface

Enfin, exécuter une nouvelle java application en spécifiant :

Name : GaussianFilterPlugin

Project : monProjet

Main class : fr.ign.cogit.geoxygene.appli.GeOxygeneApplication

../../_images/LancementInterfaceGeoxAutreModule.png

Figure 1 : Lancement de l’interface GeOxygene avec votre nouveau plugin

Ce qui donne :

../../_images/GaussianFilterPluginGUI.png

Figure 2 : Gaussian Filter Plugin