Syndication : Atom 1.0  RSS 2.0
Blogs des développeurs   »   Akrogen Blog

Article complet: Conception d'un Editeur Eclipse de workflow XML [step 14]

21/08/2009

Permalink 10:22:39, Catégories: Plugin Eclipse, Récapitulatif Eclipse, Frameworks, 2075 mots   French (FR) , azerr

[Eclipse][Java] Conception d'un Editeur Eclipse de workflow XML [step 14]

A l'étape du billet précédant [step13] nous avons mis en place le layout automatique. Dans ce billet nous allons améliorer l'aspect visuel des figures draw2d des states et des actions :

  • les states seront représentés par l'icône gear.gif .
  • les actions seront représentées par un rectangle de couleur jaune pâle (couleur personnalisée) avec une bordure noire.

Vous pouvez télécharger le projet org.example.workflow_step14.zip présenté dans ce billet.

[Suite:]

SWT Color#dispose() / Font#dispose()

A ce stade nous n'avons pas encore utilisé d'images ni personnalisé de couleurs (nous utilisons les couleurs systèmes provenant de la constante GEF org.eclipse.draw2d.ColorConstants). Draw2d utilise les classes ressources SWT org.eclipse.swt.graphics.Image et org.eclipse.swt.graphics.Color pour personnaliser les figures drawd2. Ces 2 ressources SWT possédent une méthode dispose() qui doit être apppelée lorsque la ressource n'est plus utilisée par le programme. En effet SWT sollicite le système d'exploitation lorsqu'il créé une ressource SWT Color ou Image. Une fois que la ressource SWT n'est plus utilisée, l'appel de la méthode dispose() permet d'avertir le système d'exploitation que la ressource n'est plus utilisée (pour qu'il puisse libérer sa mémoire).

Une ressource SWT Color, Image est associée à une Thread SWT org.eclipse.swt.widgets.Display qui gère la connection entre SWT et le système d'exploitation.

StateTypeFigure

Dans cette section nous allons représenter un state par l'icône gear.gif :

Copiez l'image gear.gif dans le répertoire icons/graphical du projet org.example.workflow.editor :

e

Il est important d'avoir à l'esprit que qand une Image est créée, elle doit être libérée lorsque qu'elle n'est plus utilisée, ce qui signifie la méthode Image#dispose() doit être appelée :

  • à la fermeture de l'editeur de workflow.
  • OU à la fermeture de l'IDE Eclipse (lorsque le Display SWT se libère).

Personnellement je préfère la deuxième solution car ceci permet de faire partager la même image pour tous les editeur de workflow ouverts. De plus la création de l'image s'effectuera qu'une seule fois et pas à chaque ouverture
d'un éditeur de workflow.

Notre projet contient un wizard de création d'un fichier workflow.xml. Ce wizard utilise l'image icons/full/wizban/NewWorkflow.gif :

Il est générée par EMF. Voici le code de l'initialisation du wizard qui indique l'image à utiliser :

public void init(IWorkbench workbench, IStructuredSelection selection) { 
  this.workbench = workbench; 
  this.selection = selection; 
  setWindowTitle(WorkflowEditorPlugin.INSTANCE.getString("_UI_Wizard_label")); 
  setDefaultPageImageDescriptor(ExtendedImageRegistry.INSTANCE.getImageDescriptor(WorkflowEditorPlugin.INSTANCE.getImage("full/wizban/NewWorkflow"))); 
}

Le code qui nous intérèsse est :

setDefaultPageImageDescriptor(ExtendedImageRegistry.INSTANCE.getImageDescriptor(WorkflowEditorPlugin.INSTANCE.getImage("full/wizban/NewWorkflow")));

La classe EMF générique org.eclipse.emf.edit.ui.provider.ExtendedImageRegistry permet de gérer un repository d'images :

  • qui évite de créer la même image plusieurs fois
  • qui libère l'image lorsque le Display SWT associé à l'image est libéré :

    protected void handleDisplayDispose()  

      for (Image image : table.values()) 
      { 
      image.dispose(); 
      } 
      table = null; 

     
    protected void hookDisplayDispose(Display display)  

      display.disposeExec 
      (new Runnable()  
      { 
      public void run()  
      { 
      handleDisplayDispose(); 
      }  
      }); 
    }

Nous allons utiliser cette classe pour récupérer l'image icons/graphical/gear.gif. Modifiez la classe StateTypeFigure comme suit :

package org.example.workflow.presentation.graphical.figures; 
 
import org.eclipse.draw2d.Label; 
import org.eclipse.emf.edit.ui.provider.ExtendedImageRegistry; 
import org.example.workflow.presentation.WorkflowEditorPlugin; 
 
public class StateTypeFigure extends Label { 
 
  public StateTypeFigure() { 
    super.setIcon(ExtendedImageRegistry.INSTANCE 
        .getImage(WorkflowEditorPlugin.INSTANCE 
            .getImage("graphical/gear.gif"))); 
  } 
 
  public void setName(String name) { 
    super.setText(name); 
  } 
}

Nous n'avons plus besoin de la méthode StateTypeFigure#paintFigure(Graphics graphics) qui s'occupait de dessiner une ellipse. Relancez le plugin et vous pourrez voir les states représentés par l'icône gear.gif :

Le libélle des state est un peu trop près de l'icône gear. Il est possible de décaler ce libéllé vers la droite à l'aide du code suivant :

super.setIconTextGap(5);

Voici le code en entier de StateTypeFigure :

package org.example.workflow.presentation.graphical.figures; 
 
import org.eclipse.draw2d.Label; 
import org.eclipse.draw2d.PositionConstants; 
import org.eclipse.emf.edit.ui.provider.ExtendedImageRegistry; 
import org.example.workflow.presentation.WorkflowEditorPlugin; 
 
public class StateTypeFigure extends Label { 
 
  public StateTypeFigure() { 
    super.setIcon(ExtendedImageRegistry.INSTANCE 
        .getImage(WorkflowEditorPlugin.INSTANCE 
            .getImage("graphical/gear.gif"))); 
    super.setIconTextGap(5); 
  } 
 
  public void setName(String name) { 
    super.setText(name); 
  } 
}

ActionTypeFigure

Nous souhaions représenter nos actions par des rectangles jaunes pâles avec une bordure noire.

Figure#setOpaque

Actuellement voici le code de ActionTypeFigure :

package org.example.workflow.presentation.graphical.figures; 
 
import org.eclipse.draw2d.ColorConstants; 
import org.eclipse.draw2d.Graphics; 
import org.eclipse.draw2d.Label; 
 
public class ActionTypeFigure extends Label { 
 
  public ActionTypeFigure() { 
    super.setForegroundColor(ColorConstants.black); 
  } 
 
  @Override 
  protected void paintFigure(Graphics graphics) { 
    graphics.setBackgroundColor(ColorConstants.orange); 
    graphics.fillRectangle(getBounds()); 
    super.paintFigure(graphics); 
  } 
  
  public void setName(String name) { 
    super.setText(name);  
  } 
}

Ici nous avons re-défini la méthode paintFigure(Graphics graphics) pour dessiner un rectangle avec un fond orange. Mais nous pouvons avoir le même code sans être obligé de redefinir cette méthode comme ceci :

package org.example.workflow.presentation.graphical.figures; 
 
import org.eclipse.draw2d.ColorConstants; 
import org.eclipse.draw2d.Label; 
 
public class ActionTypeFigure extends Label { 
 
  public ActionTypeFigure() { 
    super.setForegroundColor(ColorConstants.black); 
    super.setBackgroundColor(ColorConstants.orange); 
    super.setOpaque(true); 
  } 
 
  public void setName(String name) { 
    super.setText(name); 
  } 
}

La couleur de fond est mise dans le constructuer avec

super.setBackgroundColor(ColorConstants.orange);

mais pour que cette couleur soit pris en compte, il faut ajouter le code

super.setOpaque(true);

sinon la figure action apparaît blanche.

WorkflowColorConstants

Jusqu'a maintenant nous avons utilisé des couleurs systèmes provenant de l'interface GEF org.eclipse.draw2d.ColorConstants. Ici nous souhaitons représenter les actions avec une couleur de fond jaune pâle, couleur que nous allons créer. Une couleur utilisé dans draw2d est représentée par une instance Color SWT. Pour créer cette couleur nous allons créer une interface WorkflowColorConstants avec nos couleurs personnalisées comme ceci :

package org.example.workflow.presentation.graphical.color; 
 
import org.eclipse.swt.graphics.Color; 
 
public class WorkflowColorConstants { 
 
  public static final Color lightYellow = new Color(null, 255, 255, 206); 
}

C'est d'ailleurs ce que fait le projet d'exemple GEF org.eclipse.gef.examples.logic en définissant l'interface org.eclipse.gef.examples.logicdesigner.figures.LogicColorConstants :

package org.eclipse.gef.examples.logicdesigner.figures; 
 
import org.eclipse.swt.graphics.Color; 
 
public interface LogicColorConstants 

 
public final static Color andGate = new Color(null, 220,70,80); 
public final static Color orGate = new Color (null, 0, 134, 255); 
public final static Color xorGate = new Color (null, 240,240,40); 
public final static Color logicGreen = new Color(null, 123,174,148); 
public final static Color logicHighlight = new Color(null,66,166,115); 
public final static Color connectorGreen = new Color(null,0,69,40); 
public final static Color logicBackgroundBlue = new Color(null, 200, 200, 240); 
public final static Color ghostFillColor = new Color(null, 31, 31, 31); 
 
}

Ceci marche bien, mais comme nous avons vu, une instance Color SWT doit être libérée (méthode Color#dispose())
quand elle n'est plus utilisée
. Il n'y aurra certes pas beaucoup d'instance Color qui ne seront pas libérés, mais étant pointilleux, cette solution ne me satisfait pas totalement.

ColorRegistry

Pour régler ce problème nous allons créer un registry de Color SWT, qui libèrera les Color SWT lorsque le Display SWT se libèrera.
Créez la classe org.example.workflow.presentation.graphical.color.ColorRegistry comme suit :

package org.example.workflow.presentation.graphical.color; 
 
import java.util.HashMap; 
import java.util.Map; 
 
import org.eclipse.swt.graphics.Color; 
import org.eclipse.swt.graphics.RGB; 
import org.eclipse.swt.widgets.Display; 
 
public class ColorRegistry { 
 
  public final static ColorRegistry INSTANCE = new ColorRegistry(); 
 
  private Display display; 
 
  private Map<RGB, Color> colors = new HashMap<RGB, Color>(); 
 
  public ColorRegistry() { 
    this(Display.getCurrent()); 
  } 
 
  public ColorRegistry(Display display) { 
    this.display = display; 
    hookDisplayDispose(display); 
  } 
 
  public Color getColor(int red, int green, int blue) { 
    return getColor(new RGB(red, green, blue)); 
  } 
 
  public Color getColor(RGB rgb) { 
    Color color = colors.get(rgb); 
    if (color != null) 
      return color; 
    color = new Color(display, rgb); 
    colors.put(rgb, color); 
    return color; 
  } 
 
  protected void handleDisplayDispose() { 
    for (Color color : colors.values()) { 
      color.dispose(); 
    } 
    colors = null; 
  } 
 
  protected void hookDisplayDispose(Display display) { 
    display.disposeExec(new Runnable() { 
      public void run() { 
        handleDisplayDispose(); 
      } 
    }); 
  } 
}

WorkflowColorConstants

Modifiez la classe WorkflowColorConstants pour utiliser notre ColorRegisrty comme suit :

package org.example.workflow.presentation.graphical.color; 
 
import org.eclipse.swt.graphics.Color; 
 
public class WorkflowColorConstants { 
 
  public static final Color lightYellow = ColorRegistry.INSTANCE.getColor(255, 255, 206); 
}

ActionTypeFigure

Nous pouvons maintanenat utiliser notre couleur jaune pâle. Modifiez la classe ActionTypeFigure comme suit :

package org.example.workflow.presentation.graphical.figures; 
 
import org.eclipse.draw2d.ColorConstants; 
import org.eclipse.draw2d.Label; 
import org.eclipse.draw2d.LineBorder; 
import org.example.workflow.presentation.graphical.color.WorkflowColorConstants; 
 
public class ActionTypeFigure extends Label { 
 
  public ActionTypeFigure() { 
    super.setForegroundColor(ColorConstants.black); 
    super.setBackgroundColor(WorkflowColorConstants.lightYellow); 
    super.setOpaque(true); 
    super.setBorder(new LineBorder(1)); 
  } 
 
  public void setName(String name) { 
    super.setText(name); 
  } 
}

Relancez le plugin et vous pourrez constater que les actions sont représentées par des rectangles jaunes pâles avec une bordure noire :

Conclusion

La représentation graphique de notre workflow est maintenant terminée. Dans les prochains billets nous allons mettre en place la Palette d'outils GEF qui permettra à partir d'outil de la palette, d'ajouter des figures states, actions et connections dans la page Graphics GEF.

Social Bookmarking:

                                     

Commentaires, Pingbacks:

Connectez-vous pour vous abonner à cet article:

Flux de commentaires pour cet article : Atom 1.0  RSS 2.0

Cet article n'a pas de Commentaires/Pingbacks pour le moment...

Vous devez être identifié pour poster un commentaire.

Liste des blogs

Akrogen Blog

Catégories


Rechercher

<  Mai 2012  >
Lun Mar Mer Jeu Ven Sam Dim
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      

Syndiquez ce blog XML

Articles :

Commentaires :

 
 
 
 
Partenaires

Hébergement Web