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

Android Discussion :

Ajouter les fonctions undo et redo


Sujet :

Android

  1. #1
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    118
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 118
    Points : 84
    Points
    84
    Par défaut Ajouter les fonctions undo et redo
    Bonjour,

    Je suis en train de réaliser une application android, ou j'ajoute des lignes et des cercles sur un plan quadrillé. J'ai une fonction doBitmap qui permet d'insérer mes éléments sur le plan, je suis en train d'essayer de faire les fonctions undo et redo mais j'éprouve quelques difficultés. Les boutons sont créés. Mon code concernant la ligne est le suivant :

    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    public class Ligne extends EltPlan {
    	private static final int epaisseur = 8;
    	private int a, b;
     
    	private Ligne(int x, int y, int width, int height) {
    		super(x, y, width, height);
    	}
     
    	public static Ligne LigneHorizontal(int x, int y, int lgr) {
    		return new Ligne(x, y, lgr, epaisseur);
    	}
     
    	public static Ligne LigneVertical(int x, int y, int lgr) {
    		return new Ligne(x, y, epaisseur, lgr);
    	}
     
    	public void doBitmap() {
    		// Si la ligne est selectionné on l'encadre en rouge
    		if (isSelected()) {
    			setBitmap(Bitmap.createBitmap(getPixelsWidth() + 10,
    					getPixelsHeight() + 10, Config.ARGB_8888));
    			for (b = 5; b < getBitmap().getHeight() - 5; b++) {
    				for (a = 5; a < getBitmap().getWidth() - 5; a++)
    					getBitmap().setPixel(a, b, Color.GRAY);
    			}
    			for (a = 0; a < getBitmap().getWidth(); a++)
    				getBitmap().setPixel(a, 0, Color.RED);
    			for (a = 0; a < getBitmap().getWidth(); a++)
    				getBitmap().setPixel(a, getBitmap().getHeight() - 1, Color.RED);
    			for (b = 0; b < getBitmap().getHeight(); b++)
    				getBitmap().setPixel(0, b, Color.RED);
    			for (b = 0; b < getBitmap().getHeight(); b++)
    				getBitmap().setPixel(getBitmap().getWidth() - 1, b, Color.RED);
    		} else {
    			setBitmap(Bitmap.createBitmap(getPixelsWidth(), getPixelsHeight(),
    					Config.ARGB_8888));
    			for (b = 0; b < getBitmap().getHeight(); b++) {
    				for (a = 0; a < getBitmap().getWidth(); a++)
    					getBitmap().setPixel(a, b, Color.GRAY);
    			}
    		}
    	}
    }
    Je ne sais pas si j'ai bien compris le fonctionnement mais j'ai l'impression que ma fonction doBitmap pourrait etre une fonction redo ?
    Ensuite ma classe EltPlan :

    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
     
    public abstract class EltPlan {
     
     
    	private Point position = null;
    	private float x;
    	private float y;
    	private int pixelsHeight;
    	private int pixelsWidth;
     
     
    	public EltPlan(int x, int y, int pixelsWidth,
    			int pixelsHeight) {
    		position = new Point(x, y);
    		setX(x);
    		setY(y);
    		setPixelsWidth(pixelsWidth);
    		setPixelsHeight(pixelsHeight);
    	}
     
    	public abstract void doBitmap();
    }
    Et j'ai ma classe principale ensuite ou je gère les actions pour mes boutons.

    Merci de votre aide

  2. #2
    Modérateur
    Avatar de kolodz
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2008
    Messages
    2 211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 211
    Points : 8 316
    Points
    8 316
    Billets dans le blog
    52
    Par défaut
    La fonctionnalité do/undo nécessite l'utilisation du pattern "Processeur de commande".
    Wikipédia :
    http://fr.wikipedia.org/wiki/Command..._conception%29

    L'idée est :
    Chaque commande est réalisé par le processeur ET mémoriser dans l'historique par celui-ci !
    Quand tu veux faire un undo, tu demande au processeur de défaire la dernière action.

    En général tu as :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public interface Command {
       void do();
       void undo();
       // permet de savoir si on peut appeler le undo
       boolean canBeUnDone();
       // permet de savoir si on a à historiser la commande
       // Exemple de commande qui retourne faux : Sauvegarder
       boolean isHistorisable();
    }
    Cordialement,
    Patrick Kolodziejczyk.
    Si une réponse vous a été utile pensez à
    Si vous avez eu la réponse à votre question, marquez votre discussion
    Pensez aux FAQs et aux tutoriels et cours.

  3. #3
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    118
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 118
    Points : 84
    Points
    84
    Par défaut
    Je vous remercie de votre réponse, j'ai lu l'article, et je comprends bien la manière de procéder seulement dans mon cas lorsque je suis arrivée le code été fait comme cela et il y a plein d'autre classe qui on été faite et dont la fonction dobitmap dépend, du coup j'ai l'impression que dans mon cas je ne peux pas procéder de cette manière.

  4. #4
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 710
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur java, access, sql server
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 710
    Points : 4 791
    Points
    4 791
    Par défaut
    Reprenons à la base :
    Est-ce que pour ajouter une ligne tu crées un nouvel objet Ligne
    que tu ajoutes dans sur un plan et qui est ensuite dessiné ?
    Labor improbus omnia vincit un travail acharné vient à bout de tout - Ambroise Paré (1510-1590)

    Consulter sans modération la FAQ ainsi que les bons ouvrages : http://jmdoudoux.developpez.com/cours/developpons/java/

  5. #5
    Modérateur
    Avatar de kolodz
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2008
    Messages
    2 211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 211
    Points : 8 316
    Points
    8 316
    Billets dans le blog
    52
    Par défaut
    Logiquement,Ligne n'est qu'un élément de ton plan.
    A un endroit, tu dois avoir un ajouterElement(elt), qui ajoute à la liste tout des éléments le nouvelle éléments crée.
    C'est là que doit intervenir ta commande.
    Tu dois avoir quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Plan p;
    Ligne l;
    p.ajouterElement(l);
    A la place tu dois avoir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Plan p;
    Ligne l;
    Commande commande = AjoutCommande(p,l);
    // On suppose que le processeur est un singleton dans l'exemple !
    Processeur.getInstance().execute(commande);
    Avec :
    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
    public class AjoutCommande extends Commande {
    	private Plan p;
    	private Element e;
    	AjoutCommande(Plan p, Element e){
    		this.p=p;
    		this.e=e;
    	}
    	public void execute(){
    		this.p.ajouterElement(this.e);
    	}
    	public void undo(){
    		this.p.supprimerElement(this.e);
    	}
    	public boolean canBeUnDone(){
    		return true;
    	}
    	public boolean isHistorisable(){
    		return true;
    	}
    }
    Cordialement,
    Patrick Kolodziejczyk.
    Si une réponse vous a été utile pensez à
    Si vous avez eu la réponse à votre question, marquez votre discussion
    Pensez aux FAQs et aux tutoriels et cours.

  6. #6
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    118
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 118
    Points : 84
    Points
    84
    Par défaut
    Alors comme je l'expliquais dans le premier poste afin de dessiner ma ligne sur ma tablette j'utilise seulement doBitmap et ce qui me permet de la dessiner c'est cette partie du code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    setBitmap(Bitmap.createBitmap(getPixelsWidth(), getPixelsHeight(),Config.ARGB_8888));
    	for (b = 0; b < getBitmap().getHeight(); b++) {
    		for (a = 0; a < getBitmap().getWidth(); a++)
    				getBitmap().setPixel(a, b, Color.GRAY);
    	}
    Du coup lorsque je clique sur l'icone ligne avec mon doigt j'appuie une premiere fois sur l'ecran pour l'origine de ma ligne et une seconde fois pour la fin, je ne sais pas si c'est cela que vous vouliez savoir

    Merci

  7. #7
    Modérateur
    Avatar de kolodz
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2008
    Messages
    2 211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 211
    Points : 8 316
    Points
    8 316
    Billets dans le blog
    52
    Par défaut
    Je ne sais pas si j'ai bien compris le fonctionnement mais j'ai l'impression que ma fonction doBitmap pourrait etre une fonction redo ?
    Ta fonction doBitmap() ne peux pas être une fonction redo.

    La fonction doBitmap() permet just pour chaque ligne de l'afficher correctement dans ta Bitmap. Il est fort probable que tu ai une liste à un endroit qui réalise un foreach pour l'ensemble des éléments de ton Plan/Dessin. Pour annuler, ta ligne il faut simplement enlever cette ligne de ta liste et demande un rafraichissement de ta Bitmap (qui fait le foreach).
    Le "redo" qui correspond à relancer la méthode exécuter de la commande :
    1.Ajouter la ligne à la liste
    2.Refaire la Bitmap avec le foreach

    Il faut que tu intervienne au niveau du modèle de donnée et non dans les fonctions (qui dessinent).

    Cordialement,
    Patrick Kolodziejczyk.
    Si une réponse vous a été utile pensez à
    Si vous avez eu la réponse à votre question, marquez votre discussion
    Pensez aux FAQs et aux tutoriels et cours.

  8. #8
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    118
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 118
    Points : 84
    Points
    84
    Par défaut
    Du coup, en suivant tes conseils, j'ai donc fait une classe Command :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public interface Command {
    	void redo();
    	void undo();
    	// permet de savoir si on peut appeler le undo
    	boolean canBeUndone();
    	// permet de savoir si on a à historiser la commande
    	boolean isHistorisable();
    }
    Ensuite j'ai fait un singletion CommandManager :
    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
     
    public class CommandManager {
     
    	private ArrayList<Command> redoList = new ArrayList<Command>();
    	private ArrayList<Command> undoList = new ArrayList<Command>();
    	private boolean reallyDirty = false;
    	static CommandManager _instance = null;
     
    	public static CommandManager getInstance() {
     
    		if (_instance == null)
    			_instance = new CommandManager();
    		return _instance;
    	}
     
    	public static void execute(Command command) {
    		getInstance().performAction(command);
    	}
     
    	public static void undo() {
    		getInstance().performUndo();
    	}
     
    	public static void redo() {
    		getInstance().performRedo();
    	}
     
    	public boolean isDirty() {
    		return this.reallyDirty || !hasUndo();
    	}
     
    	public boolean hasUndo() {
    		return !this.undoList.isEmpty();
    	}
     
    	public boolean hasRedo() {
    		return !this.redoList.isEmpty();
    	}
     
    	public void performAction(Command command) {
    		command.redo();
    		this.redoList.clear();
    		if (command instanceof Command) {
    			this.undoList.add((Command) command);
    		} else {
    			this.undoList.clear();
    			this.reallyDirty = true;
    		}
    	}
     
    	public void performRedo() {
    		if (!this.redoList.isEmpty()) {
    			Command command = this.redoList.get(this.redoList.size() - 1);
    			this.redoList.remove(this.redoList.size() - 1);
    			command.redo();
    			this.undoList.add(command);
    		}
    	}
     
    	public void performUndo() {
    		if (!this.undoList.isEmpty()) {
    			Command command = this.undoList.get(this.undoList.size() - 1);
    			this.undoList.remove(this.undoList.size() - 1);
    			command.undo();
    			this.redoList.add(command);
    		}
    	}
     
    	public void reset() {
    		this.undoList.clear();
    		this.redoList.clear();
    		this.reallyDirty = false;
    	}
     
    	private CommandManager() {
    	}
    }
    Dans ma classe pour insérer un ligne, j'avais bien comme tu me l'as dit, plan.add(ligne);
    J'ai donc mis ceci :
    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
     
    public class InsertionLigneListener implements OnTouchListener  {
     
    	private Plan plan;
    	Ligne nvlElt;
    	Command command; 
    	private int lastEltX, lastEltY;
    	private int selection;
    	private boolean onRight = false;
     
    	public static final int NO_SELECTION = 0;
    	public static final int SELECT_LIGNE = 1;
     
    	public InsertionLigneListener(Plan plan) {
    		this.plan = plan;
    	}
     
    	@Override
    	public boolean onTouch(View v, MotionEvent event) {
    		v.performClick();
    		switch (event.getAction()) {
    		case MotionEvent.ACTION_DOWN:
    			onTouchDown(event);
    			return true;
    		case MotionEvent.ACTION_MOVE:
    			onTouchMove(event);
    			return true;
    		case MotionEvent.ACTION_UP:
    			onTouchUp(event);
    			break;
    		}
    		return false;
    	}
     
    	private void onTouchDown(MotionEvent event) {
     
    	}
     
    	private void onTouchMove(MotionEvent evnet) {
     
    	}
     
     
    	private void onTouchUp(MotionEvent event) {
    		switch (selection) {
    		case SELECT_LIGNE:
    			if (lastEltX == -1) {
    				lastEltX = (int) event.getX();
    				lastEltY = (int) event.getY();
    			} else {
    				int departX, departY;
    				if (Math.abs((int) event.getY() - lastEltY) > Math
    						.abs((int) event.getX() - lastEltX)) {
     
    					// Ligne vertical
    					if ((int) event.getY() > lastEltY){
    						departY = lastEltY;
    					}else{
    						departY = (int) event.getY();
    					}
    					departX = lastEltX;
    					if (onRight) {
    						nvlElt = Ligne.LigneVertical(departX, departY,
    								Math.abs((int) event.getY() - lastEltY));
    						 nvlElt.setPixelsHeight(nvlElt.getPixelsHeight()
    								+ nvlElt.getPixelsWidth());
    					} else {
    						nvlElt = Ligne.LigneVertical(departX, departY,
    								Math.abs((int) event.getY() - lastEltY));
    					}
     
    					lastEltY = (int) event.getY();
    					onRight = false;
     
    				} else {
    					// Ligne horizontal
    					if ((int) event.getX() > lastEltX) {
    						onRight = true;
    						departX = lastEltX;
    					} else {
    						onRight = false;
    						departX = (int) event.getX();
    					}
    					departY = lastEltY;
    					nvlElt = Ligne.LigneHorizontal(departX, departY,
    							Math.abs((int) event.getX() - lastEltX));
    					lastEltX = (int) event.getX();
    				}
     
    				command = AddCommand(plan,nvlElt);
    				CommandManager.getInstance();
    				CommandManager.execute(command);
    				//plan.add(nvlElt);
     
    				plan.invalidate();
    			}
    			break;
    		}
    	}
    Et du coup j'ai crée une classe AddCommand :

    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
    32
    33
    34
    35
    36
     
    public class AddCommand implements Command {
     
    	private Plan plan;
    	private Ligne ligne;
     
    	AddCommand(Plan p, Ligne l) {
    		this.plan = p;
    		this.ligne = l;
    	}
     
    	public void execute() {
    		this.plan.add(this.ligne);
    	}
     
    	@Override
    	public void redo() {
    		// TODO Auto-generated method stub
     
    	}
     
    	@Override
    	public void undo() {
    		this.plan.deleteLigne(this.ligne);
    	}
     
    	@Override
    	public boolean canBeUndone() {
    		return true;
    	}
     
    	@Override
    	public boolean isHistorisable() {
    		return true;
    	}
    }
    Voila je voulais savoir si c'est comme cela qu'il faut faire ou pas ? qu'est ce que je dois améliorer pour que çà fonctionne

    Merci

  9. #9
    Modérateur
    Avatar de kolodz
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2008
    Messages
    2 211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 211
    Points : 8 316
    Points
    8 316
    Billets dans le blog
    52
    Par défaut
    Ne pouvant pas tester votre code.
    Je me suis permis d'écrire un article sur comment réalisé le undo/redo avec un processeur de commande :
    http://www.developpez.net/forums/blo...principe-base/

    D'après ce que je vois votre implémentation me semble correcte. Il me semble que tu ne vérifie pas le cas de la commande qui n'est pas annulable. Ce qui peut-être problématique !

    Cordialement,
    Patrick Kolodziejczyk.
    Si une réponse vous a été utile pensez à
    Si vous avez eu la réponse à votre question, marquez votre discussion
    Pensez aux FAQs et aux tutoriels et cours.

  10. #10
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    118
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 118
    Points : 84
    Points
    84
    Par défaut
    Je n'arrive pas a voir la différence entre mon singleton commandManager et la classe addCommand ?

    Si je rajoute çà :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    command = AddCommand(plan,nvlElt);
    CommandManager.getInstance();
    CommandManager.execute(command);

    Comme vous me l'avez conseillé, il faut donc que je rajoute dans la même classe la methode addCommand

  11. #11
    Modérateur
    Avatar de kolodz
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2008
    Messages
    2 211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 211
    Points : 8 316
    Points
    8 316
    Billets dans le blog
    52
    Par défaut
    Dans ta class AddCommand, tu as deux méthodes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public void execute() {
    		this.plan.add(this.ligne);
    	}
     
    	@Override
    	public void redo() {
    		// TODO Auto-generated method stub
     
    	}
    Cela n'est pas normal, tu dois avoir seulement execute(), une commande n'a pas à savoir si c'est la première fois qu'on l'exécute ou non. Et cela ne doit pas changer son comportement.

    Donc, tu replace tout test redo() par execute(). Seul le processeur à besoin de savoir qu'il faut refaire la dernière commande annuler. (Pour savoir qu'elle commande il doit lancer) D'ailleurs normalement, redo() à le comportent suivant :
    [CODE]public void redo(){
    Command command = this.getLastCommandUndo();
    this.execute(command);
    this.removeLastCommandUndo();
    }[/CODE
    Car basiquement redo() et un execute() sans paramètre !

    Cordialement,
    Patrick Kolodziejczyk.
    Si une réponse vous a été utile pensez à
    Si vous avez eu la réponse à votre question, marquez votre discussion
    Pensez aux FAQs et aux tutoriels et cours.

  12. #12
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    118
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 118
    Points : 84
    Points
    84
    Par défaut
    Du coup ma classe addCommand est une classe abstract, sinon on me demande d'ajouter les méthodes de mon interface Command vu que ma classe addCommand implements Command.

    Ma classe addCommand est donc comme cela :

    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
     
    public abstract class AddCommand implements Command {
     
    	private Plan plan;
    	private Ligne ligne;
     
    	AddCommand(Plan p, Ligne l {
    		this.plan = p;
    		this.ligne = l;
    	}
     
    	public void execute() {
    		this.plan.add(this.ligne);
    	}
     
    }
    ma classe commandManager est comme ceci :

    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
     
    public class CommandManager {
     
    	private ArrayList<Command> redoList; 
    	private ArrayList<Command> undoList;
    	private boolean reallyDirty = false;
    	static CommandManager _instance = null;
     
    	public static CommandManager getInstance() {
     
    		if (_instance == null)
    			_instance = new CommandManager();
    		return _instance;
    	}
     
    	public static void execute(Command command) {
    		getInstance().performAction(command);
    	}
     
    	public static void undo() {
    		getInstance().performUndo();
    	}
     
    	public static void redo() {
    		getInstance().performRedo();
    	}
     
    	public boolean isDirty() {
    		return this.reallyDirty || !hasUndo();
    	}
     
    	public boolean hasUndo() {
    		return !this.undoList.isEmpty();
    	}
     
    	public boolean hasRedo() {
    		return !this.redoList.isEmpty();
    	}
     
    	public void performAction(Command command) {
    		command.redo();
    		this.redoList.clear();
    		if (command instanceof Command) {
    			this.undoList.add((Command) command);
    		} else {
    			this.undoList.clear();
    			this.reallyDirty = true;
    		}
    	}
     
    	public void performRedo() {
    		if (!this.redoList.isEmpty()) {
    			Command command = this.redoList.get(this.redoList.size() - 1);
    			this.redoList.remove(this.redoList.size() - 1);
    			command.redo();
    			this.undoList.add(command);
    		}else{
    			System.out.println("Debug processor : No command to redo");
    		}
    	}
     
    	public void performUndo() {
    		if (!this.undoList.isEmpty()) {
    			Command command = this.undoList.get(this.undoList.size() - 1);
    			this.undoList.remove(this.undoList.size() - 1);
    			command.undo();
    			this.redoList.add(command);
    		}else{
    			System.out.println("Debug processor : No command to undo");
    		}
    	}
     
    	public void reset() {
    		this.undoList.clear();
    		this.redoList.clear();
    		this.reallyDirty = false;
    	}
     
    	private CommandManager() {
    		redoList = new ArrayList<Command>();
    		undoList = new ArrayList<Command>();
    	}
    et mon interface Command est comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    public interface Command {
    	void redo();
     
    	void undo();
     
    	/** permet de savoir si on peut appeler le undo **/
    	boolean canBeUndone();
     
    	/** permet de savoir si on a à historiser la commande **/
    	boolean isHistorisable();
     
    }
    Du coup maintenant il me reste à faire quoi ? dans ma classe insertionLigneListener à la place de plan.add(nvlElt);

    Je remplace par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    command = AddCommand(plan,nvlElt);
    CommandManager.getInstance();
    CommandManager.execute(command);
    Mais du coup AddCommand je dois l'impémenter dans ma classe insertionLigneListener ?

    et j'ai ajouter dan ma classe MainActivity cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public void onClick(View v) {	
     
      if (v == btnUndo) { 
        CommandManager.undo();
      }
     
    }
    Merci

  13. #13
    Modérateur
    Avatar de kolodz
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2008
    Messages
    2 211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 211
    Points : 8 316
    Points
    8 316
    Billets dans le blog
    52
    Par défaut
    Ton interface doit avoir seulement execute(). C'est sa principale fonction !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public interface Command {
    	void execute();
     
    	void undo();
     
    	/** permet de savoir si on peut appeler le undo **/
    	boolean canBeUndone();
     
    	/** permet de savoir si on a à historiser la commande **/
    	boolean isHistorisable();
     
    }
    undo() est un plus pour faire l'inverse.
    Il est totalement possible d'imaginé une implémentation ou ce n'est pas à la commande de s'annuler. Le processeur de commande pourrai par exemple avoir un private Command getOpositeCommand(Command command) Et de faire un execute() sur celle-ci !

    canBeUndone() se dans le cas de l'exemple précédent l’existence d'une commande inverse ie (si private Command getOpositeCommand(Command command) retourne autre chose que null)

    isHistorisable() est un plus pour faire des commandes qui n'impacte pas l'historique.

    Donc l'interface Command, c'est à 95%execute() !!!

    Cordialement,
    Patrick Kolodziejczyk.
    Si une réponse vous a été utile pensez à
    Si vous avez eu la réponse à votre question, marquez votre discussion
    Pensez aux FAQs et aux tutoriels et cours.

  14. #14
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    118
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 118
    Points : 84
    Points
    84
    Par défaut
    D'accord donc pour l'interface je ne mets que execute et du coup pour ma fonction undo c'est dans mon singleton que je l'a mets.
    Car dans ma classe commandManager je ne peux donc pas faire cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    public void performAction(Command command) {
    		command.redo();
    		this.redoList.clear();
    		if (command instanceof Command) {
    			this.undoList.add((Command) command);
    		} else {
    			this.undoList.clear();
    			this.reallyDirty = true;
    		}
    	}

  15. #15
    Modérateur
    Avatar de kolodz
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2008
    Messages
    2 211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 211
    Points : 8 316
    Points
    8 316
    Billets dans le blog
    52
    Par défaut
    Non !!!
    Ce que j'explique dans mon exemple, c'est que undo(). C'est qu'un "bonus" dans l'interface. Mais que ce n'est pas son bût principale.

    Par contre au regarde ce ce que tu as tu le laisse là !

    Il te sera bien plus facile pour toi de faire faire la fonction undo() dans la commande, que de crée une commande inverse...

    Cordialement,
    Patrick Kolodziejczyk.
    Si une réponse vous a été utile pensez à
    Si vous avez eu la réponse à votre question, marquez votre discussion
    Pensez aux FAQs et aux tutoriels et cours.

  16. #16
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    118
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 118
    Points : 84
    Points
    84
    Par défaut
    a oui voila, c'est pour çà je ne comprennais plus rien. Du coup mon interface est comme cela:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public interface Command {
    	void execute();
     
    	void undo();
     
    	void redo();
    }
    et ma classe addCommand est comme cela :
    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
     
    public abstract class AddCommand implements Command {
     
    	private Plan plan;
    	private Ligne ligne;
     
    	AddCommand(Plan p, Ligne l) {
    		this.plan = p;
    		this.ligne = l;
    	}
     
    	public void execute() {
    		this.plan.add(this.ligne);
    	}
     
    }
    Maintenant qu'est ce que je dois ajouter ou modifier pour que çà marche, dans ma classe insertionLigneListener je dois faire une méthode addcommand ?

  17. #17
    Modérateur
    Avatar de kolodz
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2008
    Messages
    2 211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 211
    Points : 8 316
    Points
    8 316
    Billets dans le blog
    52
    Par défaut
    Dégage moi ce redo() de cette interface !
    ...Tu va pas me faire une fonction reredo() en plus non ?

    Et ta commande n'est pas abstract ! Tu veux en crée une instance pour la donner à ton Processeur de commande !

    K
    Si une réponse vous a été utile pensez à
    Si vous avez eu la réponse à votre question, marquez votre discussion
    Pensez aux FAQs et aux tutoriels et cours.

  18. #18
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    118
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 118
    Points : 84
    Points
    84
    Par défaut
    Ok, du coup redo c'est la même chose que execute, j'avais pas saisie cela, du coup mon interface Command est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    public interface Command {
    	void execute();
     
    	void undo();
     
    }
    et ma classe addCommand est :
    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
     
    public class AddCommand implements Command {
     
    	private Plan plan;
    	private Ligne ligne;
     
    	AddCommand(Plan p, Ligne l) {
    		this.plan = p;
    		this.ligne = l;
    	}
     
    	public void execute() {
    		this.plan.add(this.ligne);
    	}
     
    	@Override
    	public void undo() {
     
    	}
     
    }
    Du coup dans ma classe commandManager je dois changer des choses, car le redo n'est plus reconnu donc je le remplace par execute:
    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
     
     
    public class CommandManager {
     
    	private ArrayList<Command> redoList; 
    	private ArrayList<Command> undoList;
    	private boolean reallyDirty = false;
    	static CommandManager _instance = null;
     
    	public static CommandManager getInstance() {
     
    		if (_instance == null)
    			_instance = new CommandManager();
    		return _instance;
    	}
     
    	public static void execute(Command command) {
    		getInstance().performAction(command);
    	}
     
    	public static void undo() {
    		getInstance().performUndo();
    	}
     
    	public static void execute() {
    		getInstance().performExecute();
    	}
     
    	public boolean isDirty() {
    		return this.reallyDirty || !hasUndo();
    	}
     
    	public boolean hasUndo() {
    		return !this.undoList.isEmpty();
    	}
     
    	public boolean hasExecute() {
    		return !this.redoList.isEmpty();
    	}
     
    	public void performAction(Command command) {
    		command.execute();
    		this.redoList.clear();
    		if (command instanceof Command) {
    			this.undoList.add((Command) command);
    		} else {
    			this.undoList.clear();
    			this.reallyDirty = true;
    		}
    	}
     
    	public void performExecute() {
    		if (!this.redoList.isEmpty()) {
    			Command command = this.redoList.get(this.redoList.size() - 1);
    			this.redoList.remove(this.redoList.size() - 1);
    			command.execute();
    			this.undoList.add(command);
    		}else{
    			System.out.println("Debug processor : No command to redo");
    		}
    	}
     
    	public void performUndo() {
    		if (!this.undoList.isEmpty()) {
    			Command command = this.undoList.get(this.undoList.size() - 1);
    			this.undoList.remove(this.undoList.size() - 1);
    			command.undo();
    			this.redoList.add(command);
    		}else{
    			System.out.println("Debug processor : No command to undo");
    		}
    	}
     
    	public void reset() {
    		this.undoList.clear();
    		this.redoList.clear();
    		this.reallyDirty = false;
    	}
     
    	private CommandManager() {
    		redoList = new ArrayList<Command>();
    		undoList = new ArrayList<Command>();
    	}
    }
    Merci

  19. #19
    Modérateur
    Avatar de kolodz
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2008
    Messages
    2 211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 211
    Points : 8 316
    Points
    8 316
    Billets dans le blog
    52
    Par défaut
    Vue que tu ne veux pas juste un historique des commandes, tu va vouloir implémenté le code dans AddCommand:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    	@Override
    	public void undo() {
    		this.plan.remove(this.ligne);
    	}
    Sinon, tu va annuler la commande qui ne fera rien à son annulation et tu va chercher pourquoi ça fonctionne pas...

    Cordialement,
    Patrick Kolodziejczyk.
    Si une réponse vous a été utile pensez à
    Si vous avez eu la réponse à votre question, marquez votre discussion
    Pensez aux FAQs et aux tutoriels et cours.

  20. #20
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    118
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 118
    Points : 84
    Points
    84
    Par défaut
    Oui voila c'est juste, je te remercie, et maintenant du coup dans ma classe insertionListeListener :
    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
     
     
     
    public class InsertionLigneListener implements OnTouchListener  {
     
    	private Plan plan;
    	Ligne nvlLigne; 
    	private int lastEltX, lastEltY;
    	private int selection;
    	private boolean onRight = false;
     
    	public static final int NO_SELECTION = 0;
    	public static final int SELECT_LIGNE = 1;
     
    	public InsertionLigneListener(Plan plan) {
    		this.plan = plan;
    	}
     
    	@Override
    	public boolean onTouch(View v, MotionEvent event) {
    		v.performClick();
    		switch (event.getAction()) {
    		case MotionEvent.ACTION_DOWN:
    			onTouchDown(event);
    			return true;
    		case MotionEvent.ACTION_MOVE:
    			onTouchMove(event);
    			return true;
    		case MotionEvent.ACTION_UP:
    			onTouchUp(event);
    			break;
    		}
    		return false;
    	}
     
    	private void onTouchDown(MotionEvent event) {
     
    	}
     
    	private void onTouchMove(MotionEvent evnet) {
     
    	}
     
     
    	private void onTouchUp(MotionEvent event) {
    		switch (selection) {
    		case SELECT_LIGNE:
    			if (lastEltX == -1) {
    				lastEltX = (int) event.getX();
    				lastEltY = (int) event.getY();
    			} else {
    				int departX, departY;
    				if (Math.abs((int) event.getY() - lastEltY) > Math
    						.abs((int) event.getX() - lastEltX)) {
     
    					// Ligne vertical
    					if ((int) event.getY() > lastEltY){
    						departY = lastEltY;
    					}else{
    						departY = (int) event.getY();
    					}
    					departX = lastEltX;
    					if (onRight) {
    						nvlLigne = Ligne.LigneVertical(departX, departY,
    								Math.abs((int) event.getY() - lastEltY));
    						 nvlLigne.setPixelsHeight(nvlLigne.getPixelsHeight()
    								+ nvlLigne.getPixelsWidth());
    					} else {
    						nvlLigne = Ligne.LigneVertical(departX, departY,
    								Math.abs((int) event.getY() - lastEltY));
    					}
     
    					lastEltY = (int) event.getY();
    					onRight = false;
     
    				} else {
    					// Ligne horizontal
    					if ((int) event.getX() > lastEltX) {
    						onRight = true;
    						departX = lastEltX;
    					} else {
    						onRight = false;
    						departX = (int) event.getX();
    					}
    					departY = lastEltY;
    					nvlLigne = Ligne.LigneHorizontal(departX, departY,
    							Math.abs((int) event.getX() - lastEltX));
    					lastEltX = (int) event.getX();
    				}
     
    				plan.add(nvlLigne);
     
    				plan.invalidate();
    			}
    			break;
    	}
     
     
     
    	public void reinitialize() {
    		lastEltX = -1;
    		lastEltY = -1;
    		onRight = false;
    	}
     
    	public void setSelection(int selection) {
    		this.selection = selection;
    	}
     
    	public int getLastEltX() {
    		return lastEltX;
    	}
     
    	public void setLastEltX(int lastEltX) {
    		this.lastEltX = lastEltX;
    	}
     
    	public int getLastEltY() {
    		return lastEltY;
    	}
     
    	public void setLastEltY(int lastEltY) {
    		this.lastEltY = lastEltY;
    	}
     
     
    }
    je remplace :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    plan.add(nvlLigne);
    par quoi ?

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 4
    Dernier message: 05/02/2013, 08h26
  2. Réponses: 4
    Dernier message: 14/02/2012, 16h18
  3. retrouver un élément ajouté avec les fonction javascript-DOM
    Par adilsoft dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 27/02/2010, 16h16
  4. Ajouter des étapes undo / redo
    Par atalon1 dans le forum PyQt
    Réponses: 8
    Dernier message: 14/07/2009, 12h30
  5. Réponses: 5
    Dernier message: 09/07/2006, 18h14

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