IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

AWT/Swing Java Discussion :

[SWING] Undo/Redo. Comment filtrer les actions à enregistrer


Sujet :

AWT/Swing Java

  1. #1
    Futur Membre du Club
    Inscrit en
    Août 2003
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Août 2003
    Messages : 9
    Points : 6
    Points
    6
    Par défaut [SWING] Undo/Redo. Comment filtrer les actions à enregistrer
    Bonjour à tous,

    Je suis en train de développer un éditeur de texte dédié à un langage particulier (essentiellement des mots-clés).
    Cet éditeur doit pouvoir supporter les opérations les plus usuelles : couper/copier/coller, coloration syntaxique et undo/redo.

    J'ai donc choisi un JTextPane pour l'implémentation.
    Pour la coloration syntaxique j'utilise un DefautStyledDocument sur lequel je surcharge les méthodes insertString, remove et replace.
    Sur l'appel de ces méthodes, je parse mon texte et je colorise les différents tokens trouvés.

    Le problème survient lors de la gestion du undo/redo.
    Il existe dans Swing une implémentation toute faite du undo/redo via UndoableEditListener et UndoManager.
    Mais lorsque je dépile les évènements enregistrés lors de la saisie de mon texte, je m'aperçois qu'il prend en compte également les évènements de parsing et de coloration.

    Exemple concret :
    Si on considère que le mot 'IF' est un mot-clé que l'éditeur doit coloriser en rouge.
    J'éxécute la séquence suivante :
    - je tape la lettre 'I'
    - je tape la lettre 'F' => l'éditeur parse le texte, détecte le mot-clé 'IF' et le colorise en rouge.
    - je fais UNDO (via un raccourci-clavier) => l'éditeur décolorise le texte 'IF'.
    - je re-fais UNDO => l'éditeur bouge le curseur (caret) vers la gauche (il dépile l'action parsing)
    - je re-re-fais UNDO => l'éditeur supprime enfin la lettre 'F'.

    Ma question est donc la suivante :
    Y'a t-il un moyen de filtrer les évènements que le undoableListener doit enregistrer ?
    Quand je fais UNDO après avoir entré une lettre, je veux qu'il supprime la lettre tout simplement.

    J'espère avoir été assez clair dans mes explications

    Merci de vos réponses.
    When the seagulls follow the troiler, it's because they think that sardins will be thrown into the sea.
    [ EC ]

  2. #2
    Membre émérite
    Avatar de xavlours
    Inscrit en
    Février 2004
    Messages
    1 832
    Détails du profil
    Informations forums :
    Inscription : Février 2004
    Messages : 1 832
    Points : 2 410
    Points
    2 410
    Par défaut
    Bonjour,

    je ne connais pas trop les composants de texte, alors je n'ai que des solutions javadoc :
    - getPresentationName ne suffit pas à différencier les évènements ?

    Sinon, je propose une autre solution :
    - à chaque coloration syntaxique, tu envoies un UndoableEvent customisé du style "le UndoableEvent précédent celui-ci est une coloration syntaxique"
    - tu surcharges les méthodes undo et redo du UndoManager pour que lorsqu'il tombe sur un UndoableEvent customisé, il undo du même coup les 2 précédents (i.e. la coloration syntaxique et l'undo "visible par l'utilisateur")

    Ca veut dire quelque chose, ce que j'ai écrit ?
    "Le bon ni le mauvais ne me feraient de peine si si si je savais que j'en aurais l'étrenne." B.V.
    Non au langage SMS ! Je ne répondrai pas aux questions techniques par MP.
    Eclipse : News, FAQ, Cours, Livres, Blogs.Et moi.

  3. #3
    Futur Membre du Club
    Inscrit en
    Août 2003
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Août 2003
    Messages : 9
    Points : 6
    Points
    6
    Par défaut
    Salut xavlours,

    merci de me répondre sur un sujet qui n'a pas l'air de passionner grand monde

    Tes réponses sont pertinentes en effet.
    Le seul inconvénient c'est que je ne peux pas savoir à-priori le nombre d'undo que je dois lancer manuellement à un instant donné.
    Si les séquences d'action enregistrées se résumaient à une suite de :
    (coloration - insertion) - (coloration - insertion) - ..., il serait assez facile de lancer 2 UNDO chaque fois qu'un undo utilisateur est levé.

    Car vient s'enregistrer également comme action, le parsing du texte.
    C'est-à-dire, en gros, le déplacement du curseur lettre après lettre voire mot après mot. Avec ça, je ne peux pas calculer combien d'actions je dois manuellement dépiler avant d'effectuer l'undo adéquat.
    En plus je serais vite limité par le nombre total d'actions enregistrables.

    L'idéal serait de savoir exactement comment marche l'enregistrement des actions afin de les filtrer à ce niveau.

    Merci pour vos réponses
    When the seagulls follow the troiler, it's because they think that sardins will be thrown into the sea.
    [ EC ]

  4. #4
    Membre émérite
    Avatar de xavlours
    Inscrit en
    Février 2004
    Messages
    1 832
    Détails du profil
    Informations forums :
    Inscription : Février 2004
    Messages : 1 832
    Points : 2 410
    Points
    2 410
    Par défaut
    Oui, en fait, ma tactique repose sur une hypothèse : c'est que si tu appelles fireUndoableEditUpdate(new MonUndoableEvent()) juste après la coloration, il sera reçu par le UndoManager exactement après l'évènement de coloration.

    Si ça ne marche pas, tu peux synchroniser les appels à fireUndoableEditEvent, mais c'est un peu barbare.

    Mais concernant les séquences, je ne vois pas en quoi ça pose problème :
    - tu crées une classe CustomUndoableEdit implémentant UndoableEdit et qui ne fait strictement rien (retourne null, etc)
    - juste après la coloration d'un mot clé, tu appelles à partir de ton document :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fireUndoableEditEvent(new UndoableEditEvent(this, new CustomUndoableEdit()))
    - tu utilises ton propre UndoManager qui fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    public class CustomUndoManager extends UndoManager {
     
      @Override
      public void undo() {
        if(editToBeUndone() instanceof CustomUndoableEdit) {
          super.undo(); // undo sur l'évènement maison, ne fait rien
          super.undo(); // undo la coloration syntaxique
          super.undo(); // undo la saisie de texte qui a provoqué la coloration
        } else // évènement normal
          super.undo();
      }
     
      @Override
      public void redo() {
        int redoIndex = edits.indexOf(editToBeRedone());
        if(redoIndex + 2 < edits.size() && edits.get(redoIndex + 2) instanceof CustomUndoableEdit) {
           super.redo(); // redo la saisie de texte
           super.redo(); // redo la coloration
           super.redo(); // redo le CUE, ne fait rien
        } else // évènement normal
          super.redo();
      }
     
      @Override
      public void addEdit(UndoableEdit e) {
        if(e instanceof CustomUndoableEdit)
          setLimit(getLimit() + 1);
     
        super.addEdit(e);
      }
    }
    Ton CustomUndoableEdit doit même pouvoir être un singleton, je crois.

    Et comme d'hab, si je suis totalement à côté de la plaque, merci de m'en informer

    [EDIT] ajout des else dans undo() et redo().
    "Le bon ni le mauvais ne me feraient de peine si si si je savais que j'en aurais l'étrenne." B.V.
    Non au langage SMS ! Je ne répondrai pas aux questions techniques par MP.
    Eclipse : News, FAQ, Cours, Livres, Blogs.Et moi.

  5. #5
    Futur Membre du Club
    Inscrit en
    Août 2003
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Août 2003
    Messages : 9
    Points : 6
    Points
    6
    Par défaut
    Je crois saisir l'idée que tu as derrière la tête.
    C'est une tactique à laquelle je n'avais pas pensé, mais astucieuse (comme j'aime ).

    De mon côté, je pensais plutôt filtrer les enregistrements en surchargeant la méthode addEdit de UndoManager.
    Je filtre les UndoableEdit à l'aide de la valeur retournée par getPresentationName() ("addition", "deletion" ou "style change").
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    @Override
    @see javax.swing.undo.UndoManager#undoableEditHappened(javax.swing.event.UndoableEditEvent)
    public synchronized boolean addEdit( UndoableEdit inAnEdit ) {
        String pName = inAnEdit.getPresentationName();
        if ( pName.equals( "addition" ) || pName.equals( "deletion" ) ) {
            return super.addEdit(inAnEdit);
        }
        return false;
    }
    Cela marche à peu près mais ça génère des effets de bord curieux sur mon éditeur et ça a tendance à le faire planter (perte du caret de la zone de texte, nullPointerException, arrayIndexOutOfBoundsException, BadLocationException...).

    Pour l'heure il est grandement temps pour moi de partir en week-end.
    La tête au calme j'y verrais plus clair.

    Dès lundi matin je me penche sur l'implémentation de ta tactique.

    Je te remercie encore pour ton aide

    PS : pour quelqu'un qui annonçait ne pas connaitre les composants texte, je trouve que tu apprends vite
    When the seagulls follow the troiler, it's because they think that sardins will be thrown into the sea.
    [ EC ]

  6. #6
    Membre émérite
    Avatar de xavlours
    Inscrit en
    Février 2004
    Messages
    1 832
    Détails du profil
    Informations forums :
    Inscription : Février 2004
    Messages : 1 832
    Points : 2 410
    Points
    2 410
    Par défaut
    Bon week end !
    Citation Envoyé par Peewee
    PS : pour quelqu'un qui annonçait ne pas connaitre les composants texte, je trouve que tu apprends vite
    Les évènements/listeners, c'est bon, je maîtrise relativement bien. Et la structure des UndoableEvent est assez compréhensible.

    Mais alors tout ce qui est Document, Element, Attribute, Style, là, j'aurais pas pu t'aider. Il faudra que je m'y mette, un jour.
    "Le bon ni le mauvais ne me feraient de peine si si si je savais que j'en aurais l'étrenne." B.V.
    Non au langage SMS ! Je ne répondrai pas aux questions techniques par MP.
    Eclipse : News, FAQ, Cours, Livres, Blogs.Et moi.

Discussions similaires

  1. Réponses: 10
    Dernier message: 18/07/2007, 17h36
  2. Réponses: 2
    Dernier message: 14/04/2007, 12h33
  3. Réponses: 8
    Dernier message: 04/04/2007, 11h16
  4. comment rechercher les derniers enregistrement d'une table ?
    Par hornetboy dans le forum Langage SQL
    Réponses: 4
    Dernier message: 28/09/2005, 09h13
  5. Comment désactiver les actions automatiques de Windows ?
    Par j-phi dans le forum API, COM et SDKs
    Réponses: 7
    Dernier message: 06/01/2005, 12h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo