|
||
![]() |
|
![]() |
|
Table of Contents
JFace Field AssistanceA partir d’Eclipse 3.2M4, JFace inclut un package consacré à l’aide à la saisie (org.eclipse.jface.fieldassist). Il apporte des fonctionnalités qui améliorent l’ergonomie des formulaires en offrant la possibilité d’ajouter pour chaque champ :
Rien que la possibilité d’ajouter une icône nous permet enfin de mettre en oeuvre convenablement une particularité bien connue des formulaires : la fameuse étoile pour indiquer qu’un champ est obligatoire. Mais l’API est suffisamment ouverte pour imaginer d’autres usages. DecoratedFieldLes possibilitésDecoratedField, comme son nom l’indique, correspond à un champ décoré. En l’occurrence, la décoration peut se concrétiser par la présence d’icônes, placées autour du champ. L’exemple ci-dessous comporte 2 icônes : Le choix des icônes est libre, il faut simplement fournir à l’API des instances d’Image SWT. Chacune des icônes peut porter une bulle d’aide qui apparaîtra naturellement en passant la souris dessus. Ceci peut s’avérer utile pour préciser à l’utilisateur la signification de l’icône. Création d'un champ texte décoréVoyons maintenant comment utiliser DecoratedField pour mettre en oeuvre cette fonctionnalité. Pour un simple champ texte (Text), le code est relativement simple : DecoratedField dField = new DecoratedField(parent, SWT.BORDER, new TextControlCreator()); Image img = PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT); FieldDecoration decoration = new FieldDecoration(img, "description"); dField.addFieldDecoration(decoration, SWT.LEFT | SWT.TOP, false);
Le résultat est le suivant : Décoration d'autres composantsDécorer d’autres composants est possible et repose sur la même API. Il suffit de passer une implémentation particulière d’IControlDecorator à la création du DecoratedField. En effet, le rôle d’IControlCreator est de créer le composant à décorer (Control SWT). Par exemple, nous pouvons remplacer le champ text (Text) précédent par un bouton (Button) de la façon suivante : DecoratedField dField = new DecoratedField(parent, SWT.BORDER, new IControlCreator() { public Control createControl(Composite parent, int style) { Button b = new Button(parent, SWT.PUSH); b.setText("Button"); return b; } }); Utilisation avec le plugin FormsLe plugin Forms apporte des facilités pour créer des formulaires de saisie. Il apparaît donc naturel de vouloir utiliser DecoratedField avec ce dernier. FormToolkit apporte des facilités pour ajouter des champs à un formulaire (createText()) mais n’est pas prévu pour ajouter des instances de DecoratedField. Heureusement, le plugin est suffisamment ouvert pour y parvenir : FormToolkit toolkit = new FormToolkit(parent.getDisplay()); DecoratedField df = new DecoratedField(form.getBody(), SWT.BORDER, new TextControlCreator()); toolkit.adapt(df.getLayoutControl(), false, false); Les particularités qui apparaissent sont les suivantes :
Malheureusement un problème subsiste malgré l’adaptation du champ décoré au formulaire : si les icônes ont des zones transparentes, celles-ci apparaîtront en gris et non en blanc. Ce n’est qu’un détail mais il peut être embarrassant du point de vue visuel. En attendant une amélioration sur ce point, il vaut mieux éviter la transparence dans les images utilisées. J’ai moi-même posté une demande pour améliorer la compatibilité entre Forms et JFace Field Assistance. ProposalsLa fonctionnalité appelée “Proposals” est l’autre aspect de l’API Field Assistance. Elle permet de faire apparaître une liste de propositions (liste déroulante) pour la valeur à saisir. Elle correspond à la fonction disponible dans l’éditeur de code Java d’Eclipse IDE avec la combinaison de touches Ctrl+Espace. Voici ses possibilités :
ContentProposalAdapterPour mettre en oeuvre les “Proposals”, il suffit de créer une instance de ContentProposalAdapter. Mais le constructeur attend de nombreux arguments :
IContentProposalProviderComme nous l’avons vu, il est nécessaire de passer une implémentation d’IContentProposalProvider. Celle-ci a pour rôle de fournir les propositions en fonction du texte saisi (méthode getProposals()). Chacune de ses propositions doit elle-même implémenter IContentProposal dont les méthodes sont les suivantes :
ExempleCompte tenu des possibilités, on imagine que l’implémentation des propositions peut être assez complexe. Voici un exemple qui reste relativement trivial puisqu’il présente comme propositions des valeurs qui sont simplement prises dans un tableau de Strings sous l’action du raccourci clavier Ctrl+Espace : IContentProposalProvider proposalProvider = new IContentProposalProvider() { private String[] values= {"abc", "toto", "titi", "tata", "tutu"}; public IContentProposal[] getProposals(String contents, int position) { IContentProposal[] proposals = new IContentProposal[values.length]; for (int i = 0; i < values.length; i++) { final String val = values[i]; proposals[i] = new IContentProposal() { public String getContent() { return val; } public String getLabel() { return null; } public String getDescription() { return MessageFormat.format("{0} est un excellent choix.", new String[] { val }); } public int getCursorPosition() { return val.length(); } }; } return proposals; } }; try { KeyStroke keyStroke = KeyStroke.getInstance("Ctrl+Space"); new ContentProposalAdapter(text, new TextContentAdapter(), proposalProvider, null, keyStroke, null, true, true, ContentProposalAdapter.PROPOSAL_REPLACE); } catch (ParseException e) { e.printStackTrace(); } Conclusion
Cette API offre des possibilités qui ne demandent qu’à être exploitées. Elle permet d’apporter des informations avant, pendant et/ou après la saisie. On peut par exemple envisager de s’en servir pour signaler des erreurs. Il va de soi que la mise en oeuvre de ces fonctionnalités alourdit le code source et qu’il serait judicieux de disposer de composants pré-décorés, prêts à l’emploi, notamment pour signaler les champs obligatoires. — Frédéric ESNAULT 2006/02/27 09:45 LiensDiscussion
Le système a évolué en Eclipse 3.2M5. Le code de l’article ne fonctionne plus. Voici un exemple de code qui fonctionne : public class Main {
/**
* @param args
*/
public static void main(String[] args) {
DeviceData data = new DeviceData();
data.tracking = true; Display display = new Display(data); final Shell shell = new Shell(display); shell.setBackgroundMode(SWT.INHERIT_DEFAULT); GridLayout layoutShell = new GridLayout(); shell.setLayout(layoutShell);
DecoratedField dField = new DecoratedField(shell, SWT.BORDER, new TextControlCreator());
FieldDecoration decoration = getWarningDecoration();
dField.addFieldDecoration(decoration, SWT.LEFT | SWT.TOP, false);
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
private static FieldDecoration getWarningDecoration() {
return FieldDecorationRegistry.getDefault().getFieldDecoration(
FieldDecorationRegistry.DEC_WARNING);
}
} |
||