I. Présentation▲
Nous développons une application Eclipse RCP dans laquelle nous utilisons le pattern Master/Details page, avec les UI FormsUI Forms. Cela nous permet d'afficher nos données sous forme d'arbres et de pages détaillées, contenant les propriétés de l'élément édité. Dans les Details Page, nous utilisons donc des StyledText, pour renseigner les valeurs des différentes propriétés. Le choix du StyledText pour les champs d'édition s'explique par le fait qu'il s'agit d'un widget customisable qui permet de modifier la fonte ainsi que la couleur du texte affiché.
II. La problématique▲
La problématique est donc de mettre en place les actions Copy/Paste et Undo/Redo dans nos différents StyleText, et que, de plus, celles-ci soient incorporées à notre RCP, via le menu Edit, comme n'importe quelle autre action disponible, par exemple dans les arbres.
Cependant, le StyledText ne dispose pas de ces actions, que l'on peut avoir habituellement dans les champs texte, que ce soit par le biais d'un menu contextuel ou de raccourcis clavier, ce qui est donc problématique pour renseigner les différents champs que l'on retrouve dans notre application. Ceci s'explique par le fait que le StyledText est non natif, il ne bénéficie donc pas des actions par défaut, que l'on peut retrouver sur les widgets de gestion de texte. Il s'agit d'un « widget émulé, pour être utilisé dans les éditeurs Eclipse ».
Nous souhaitons donc pouvoir disposer de ces actions dans nos widgets, que ce soit directement avec les raccourcis clavier, ou avec un menu contextuel sur le StyledText.
III. La solution mise en place▲
Pour résoudre ce problème, la solution mise en place est la suivante.
Tout d'abord, nous créons la classe MyStyledText, dans laquelle nous avons un StyledText. Cette classe nous permet de gérer les listeners, ainsi que les actions que nous voulons ajouter au StyledText.
Nous avons trois types de listeners :
- ModifyListener : qui prend en compte la modification au niveau de l'élément, et informe l'éditeur qu'il a été modifié ;
- FocusListener : qui gère les actions Copy/Paste et Undo/Redo en fonction du widget qui prend le focus.
Lorsqu'un StyledText prend le focus, nous modifions les actions de l'ActionBars pour que celles-ci lui soient applicables. Ensuite, lors de la perte du focus du StyledText, nous restaurons les actions de l'ActionBarContributor. En réaffectant les actions de l'ActionBars avec les actions du StyledText, nos actions sont donc intégrées à l'application RCP, et sont de ce fait, accessibles dans la barre de menu, via la section Edit.
myStyledText.addFocusListener
(
new
FocusListener
(
) {
IAction undoActionOld;
IAction redoActionOld;
...
public
void
focusLost
(
FocusEvent e) {
// Restore previous commands
IActionBars actionBars =
getEditor
(
).getEditorSite
(
).getActionBars
(
);
actionBars.setGlobalActionHandler
(
ActionFactory.UNDO.getId
(
), undoActionOld);
actionBars.setGlobalActionHandler
(
ActionFactory.REDO.getId
(
), redoActionOld);
...
actionBars.updateActionBars
(
);
}
public
void
focusGained
(
FocusEvent e) {
// Stock previous commands
undoActionOld =
getActionBars
(
).getGlobalActionHandler
(
ActionFactory.UNDO.getId
(
));
redoActionOld =
getActionBars
(
).getGlobalActionHandler
(
ActionFactory.REDO.getId
(
));
...
// Create the undo action
undoAction=
new
UndoActionHandler
(
getEditor
(
).getSite
(
), undoManager.getUndoContext
(
));
actionBars.setGlobalActionHandler
(
ActionFactory.UNDO.getId
(
), undoAction);
// Create the redo action.
redoAction=
new
RedoActionHandler
(
getEditor
(
).getSite
(
), undoManager.getUndoContext
(
));
actionBars.setGlobalActionHandler
(
ActionFactory.REDO.getId
(
), redoAction);
actionBars.updateActionBars
(
);
}
}
);
Pour les actions d'Undo/Redo du StyledText, nous avons créé la classe UndoStyledTextManager, qui permet de gérer les actions effectuées dans le widget. Pour cela, elle contient un IUndoContext (qui filtre les opérations sur lesquelles le undo/redo est possible) et un IOperationHistory (les actions sont ajoutées à l'historique une fois qu'elles ont été exécutées) des opérations disponibles sur le widget.
- MouseListener : qui gère le menu contextuel pour les actions sur le contenu du StyledText
La classe PopUpMenu est couplée avec les actions construites précédemment.
//Create the menu
menu =
new
Menu
(
parent.getShell
(
),SWT.POP_UP);
menuItemCancel =
new
MenuItem
(
menu, SWT.CASCADE);
menuItemSeparator =
new
MenuItem
(
menu, SWT.SEPARATOR);
menuItemSeparator.setEnabled
(
true
);
menuItemCut =
new
MenuItem
(
menu, SWT.CASCADE);
menuItemCopy =
new
MenuItem
(
menu, SWT.CASCADE);
menuItemPaste =
new
MenuItem
(
menu, SWT.CASCADE);
menuItemDelete =
new
MenuItem
(
menu, SWT.CASCADE);
...
menuItemCancel.addListener
(
SWT.Selection, new
Listener
(
) {
public
void
handleEvent
(
Event event) {
setActionCancel
(
true
);
//Get the StyledText undo action
myStyledText.getUndoAction.run
(
);
setMenuState
(
0
);
}
}
);
...
Ensuite, nous avons la classe UndoStyledTextManager, qui va gérer le contexte et l'historique des opérations lors des modifications du contenu du StyledText. Le widget sera connecté à ce manager durant son existence.
UndoStyledTextManager undoManager =
new
UndoStyledTextManager
(
undoSize);
undoManager.connect
(
myStyledText);
Grâce à cette connexion, nous lui associons le contexte. Il s'agit de connaitre le contexte de l'action courante, pour déterminer les opérations à réaliser pour effectuer le Undo. De plus, nous avons également l'historique qui va gérer l'historique des opérations possibles suivant l'action courante. Celui-ci est géré par le biais d'un écouteur sur le StyledText. En effet, à chaque modification de son contenu, nous créons une nouvelle opération, et nous l'ajoutons à l'historique. Il s'agit de nos propres opérations de type UndoableOperation. Celles-ci permettent d'enregistrer les modifications apportées au contenu du StyledText pour pouvoir ensuite bénéficier des actions de Undo et de Redo.
IV. Évolution▲
L'axe d'évolution concerne la gestion des actions Undo/Redo, afin que celles-ci soient similaires à un éditeur de texte. En effet, actuellement ces actions agissent caractère par caractère, et non par suite de caractères tapés ou supprimés. Il pourrait donc être envisageable d'améliorer les actions de l'UndoableOperation.
V. Remerciements▲
Je voudrais remercier Furr pour sa relecture, ainsi que tous ceux qui ont pu m'aider à la rédaction de cet article.