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

 Java Discussion :

Comment faire la correspondance entre le code source et le WYSIWYG ?


Sujet :

Java

  1. #1
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 891
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 891
    Points : 3 729
    Points
    3 729
    Par défaut Comment faire la correspondance entre le code source et le WYSIWYG ?
    Salut,

    Comment faire la correspondance entre le code source et le wysiwyg ?

    Je ne sais pas si je suis clair :

    Prenons par exemple un JTextPane on a la page html qui s'affiche et on a aussi le code source correspondant, j'aimerais les afficher tous les deux en même temps dans un panel différent et pouvoir faire la correspondance entre les deux, c'est-à-dire par exemple si je place le curseur à un endroit (dans la page html) je dois le voir aussi apparaitre à l'endroit correspondant dans le source et vice versa.

    J’espère que ma question est compréhensible...

    Merci.

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    Cela n'est pas évident à faire, car cela présente deux difficultés :

    1. Le modèle de classes des éditeurs/document/editorkit de Java est relativement fermé, et ne permet pas à la base de le faire. Il faudrait réécrire pas mal de code, en se basant sur HtmlDocument, HtmlEditorKit, HtmlWriter, et ceci, en plus de n'être pas simple, est un travail très important. Mais on peut s'en sortir en faisant un bricolage.
    2. La seconde difficulté n'est pas technique : elle réside dans le comportement du curseur.
      Prenons par exemple le html suivant :
      Code html : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      <html>
         <body>
                <p>Ceci est un <i>exemple</i> de html</p>
         </body>
      </html>
      Qui va donc s'afficher : Ceci est un exemple de html
      Si on sélectionne exemple :
      Ceci est un exemple de html
      Veut-on
      Code html : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      <html>
         <body>
                <p>Ceci est un <i>exemple</i> de html</p>
         </body>
      </html>
      ou
      Code html : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      <html>
         <body>
                <p>Ceci est un <i>exemple</i> de html</p>
         </body>
      </html>
      On voit qu'il y a des façons différentes de traiter la correspondance. Ce qui peut se faire pas des heuristiques (des tests multiples, du type si je suis au début du balise, ou à la fin, je prends ou pas la balise dans la sélection), ce qui peut demander un certain temps de mise au point.


    Evidemment, pour que cela fonctionne, il faut au moins mettre à jour le source à chaque modification du texte dans l'éditeur html, par un DocumentListener.
    Le principe est d'écouter le curseur (Caret) : d'en déduire l'élément du document qui correspond à la sélection, ce qui permet d'obtenir les offsets dans le texte édité en html. Malheureusement, on a pas d'accès direct aux positions correspondantes dans le source : la bidouille que j'utilise dans l'exemple suivant et de faire une fausse serialisation html, en comptant les caractères. Ceci impose que le html source affiché n'est pas le source en entrée, mais toujours le résultat de la serialisation. Bien sûr, on peut écrire son propre sérialiseur : dans l'exemple ci-après, je me contente d'utiliser le serialiseur de l'HtmlEditorKit standard. Il s'agit d'un exemple de principe et je n'ai pas fait la sélection inverse (lorsqu'on modifie la position du curseur dans le source, le curseur se place sur la partie correspondante dans l'éditeur html).

    A noter, qu'il y a une petite difficulté supplémentaire : par défaut, la sélection dans un éditeur n'est visible que si l'éditeur a le focus. Pour contourner ce problème, j'ai fait mon curseur (SelectionCaret).

    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
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    import java.awt.Component;
    import java.io.IOException;
    import java.io.Writer;
     
    import javax.swing.JEditorPane;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JSplitPane;
    import javax.swing.event.CaretEvent;
    import javax.swing.event.CaretListener;
    import javax.swing.event.DocumentEvent;
    import javax.swing.event.DocumentListener;
    import javax.swing.text.AbstractDocument.LeafElement;
    import javax.swing.text.BadLocationException;
    import javax.swing.text.Caret;
    import javax.swing.text.DefaultCaret;
    import javax.swing.text.Element;
    import javax.swing.text.JTextComponent;
    import javax.swing.text.html.HTMLDocument;
    import javax.swing.text.html.HTMLWriter;
     
     
    public class HtmlEditorWithSource {
     
    	public static void main(String[] args) {
     
    		final String html = "<html><body><p>Ceci est un <i>exemple</i> de html</p></body></html>";
     
     
    		JFrame frame = new JFrame("Démo");
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		frame.getContentPane().add(createEditor(html));
     
    		frame.setSize(600, 400);
    		frame.setLocationRelativeTo(null);
    		frame.setVisible(true);
     
    	}
     
    	private static Component createEditor(String html) {
    		JSplitPane panel = new JSplitPane();
     
    		final JEditorPane htmlEditor = new JEditorPane();
    		htmlEditor.setContentType("text/html");
    		htmlEditor.setText(html);
    		htmlEditor.setCaret(new SelectionCaret(htmlEditor.getCaret()));
    		JScrollPane htmlEditorPane=new JScrollPane(htmlEditor, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    		panel.setLeftComponent(htmlEditorPane);
     
    		final JEditorPane sourceEditor = new JEditorPane();
    		sourceEditor.setContentType("text/plain");
    		sourceEditor.setText(htmlEditor.getText());
    		sourceEditor.setCaret(new SelectionCaret(sourceEditor.getCaret()));
    		JScrollPane sourceEditorPane=new JScrollPane(sourceEditor, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    		panel.setRightComponent(sourceEditorPane);
     
    		panel.setResizeWeight(0.5);
     
    		htmlEditor.getDocument().addDocumentListener(new DocumentListener() {
     
    			@Override
    			public void removeUpdate(DocumentEvent e) {
    				update();
    			}
     
    			@Override
    			public void insertUpdate(DocumentEvent e) {
    				update();
    			}
     
    			@Override
    			public void changedUpdate(DocumentEvent e) {
    				update();
    			}
     
    			private void update() {
    				sourceEditor.setText(htmlEditor.getText());
    			}
     
    		});
     
    		htmlEditor.addCaretListener(new CaretListener() {
     
    			@Override
    			public void caretUpdate(CaretEvent e) {
    				int start = e.getDot();
    				int end = e.getMark();
    				if ( end<start ) {
    					int swap=end;
    					end=start;
    					start=swap;
    				}
    				Element rootElement = htmlEditor.getDocument().getDefaultRootElement();
    				LeafElement startElement = getLeaf(rootElement,start, start==htmlEditor.getDocument().getLength());
    				LeafElement endElement = getLeaf(rootElement,end, end==htmlEditor.getDocument().getLength());
     
    				CounterHtmlWriter startwriter = new CounterHtmlWriter((HTMLDocument)htmlEditor.getDocument(), startElement, true);
    				int startPosition=0;
    				try {
    					startwriter.write();
    					startPosition=startwriter.getOffset();
    				} catch (IOException | BadLocationException e1) {
    					e1.printStackTrace();
    				}
    				CounterHtmlWriter endwriter = new CounterHtmlWriter((HTMLDocument)htmlEditor.getDocument(), endElement, false);
    				int endPosition=0;
    				try {
    					endwriter.write();
    					endPosition=endwriter.getOffset();
    				} catch (IOException | BadLocationException e1) {
    					e1.printStackTrace();
    				}
    				sourceEditor.select(startPosition+start-startElement.getStartOffset(),endPosition-(endElement.getEndOffset()-end));
     
    			}
     
    			private LeafElement getLeaf(Element element, int offset, boolean enddoc) {
     
    				if (enddoc ) {
    					if ( element.getStartOffset()<=offset && offset<=element.getEndOffset() ) {
    						if ( element.isLeaf() ) {
    							return (LeafElement) element;
    						}
    						for( int i=0; i<element.getElementCount(); i++) {
    							LeafElement child = getLeaf(element.getElement(i), offset, enddoc);
    							if ( child!=null ) {
    								return child;
    							}
    						}
    					}
    				}
    				else {
    					if ( element.getStartOffset()<=offset && offset<element.getEndOffset() ) {
    						if ( element.isLeaf() ) {
    							return (LeafElement) element;
    						}
    						for( int i=0; i<element.getElementCount(); i++) {
    							LeafElement child = getLeaf(element.getElement(i), offset, enddoc);
    							if ( child!=null ) {
    								return child;
    							}
    						}
    					}
    				}
    				return null;
    			}
     
    		});
     
    		sourceEditor.setEditable(false);
     
     
    		return panel;
    	}
     
    	private static class CounterHtmlWriter extends HTMLWriter {
     
    		private LeafElement leaf;
    		private int offset;
    		private int tagoffset;
    		private final CounterWriter counterWriter;
    		private final boolean start;
     
    		public CounterHtmlWriter(HTMLDocument doc, LeafElement element, boolean start) {
    			super(new CounterWriter(), doc);
    			counterWriter=(CounterWriter) getWriter();
    			this.leaf=element;
    			this.start=start;
    		}
     
    		@Override
    		protected void startTag(Element elem) throws IOException,
    				BadLocationException {
    			if (start && leaf==elem) tagoffset=counterWriter.count;
    			super.startTag(elem);
    		}
     
    		@Override
    		protected void endTag(Element elem) throws IOException {
    			super.endTag(elem);
    			if (!start && leaf==elem) tagoffset=counterWriter.count;
    			if (!start && leaf==elem) tagoffset=counterWriter.count;
    		}
     
    		@Override
    		protected void emptyTag(Element elem) throws BadLocationException,
    				IOException {
    			if (start && leaf==elem) tagoffset=counterWriter.count;
    			super.emptyTag(elem);
    			if (!start && leaf==elem) tagoffset=counterWriter.count;
    		}
     
    		@Override
    		protected void text(Element elem) throws BadLocationException,
    				IOException {
    			if (start && leaf==elem) offset=counterWriter.count;
    			super.text(elem);
    			if (!start && leaf==elem) offset=counterWriter.count;
    		}
     
    		public int getOffset() {
    			return offset;
    		}
    		public int getTagOffset() {
    			return tagoffset;
    		}
     
    		private static class CounterWriter extends Writer {
     
    			public int count;
     
    			@Override
    			public void write(char[] cbuf, int off, int len) throws IOException {
    				count+=len;
    			}
     
    			@Override
    			public void flush() throws IOException {
    			}
     
    			@Override
    			public void close() throws IOException {
    			}
     
    		}
     
    	}
     
    	private static class SelectionCaret extends DefaultCaret {
     
    		public SelectionCaret(Caret caret) {
    			setBlinkRate(caret.getBlinkRate());
    		}
     
    		@Override
    		public void setVisible(boolean visible) {
    			super.setVisible(true);
    		}
     
    		@Override
    		public void setSelectionVisible(boolean visible) {
    			super.setSelectionVisible(true);
    		}
     
    		@Override
    		public void install(JTextComponent c) {
    			super.install(c);
    			super.setVisible(true);
    			super.setSelectionVisible(true);
    		}
     
    	}
     
    }
    EDIT : j'ai fait quelques ajustements pour que ça fonctionne mieux

  3. #3
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 891
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 891
    Points : 3 729
    Points
    3 729
    Par défaut
    Ah merci c'est super, ça marche bien !

    Merci pour l'explication et le code, je vais regarder et chercher à comprendre...

    Citation Envoyé par joel.drigo Voir le message
    Il s'agit d'un exemple de principe et je n'ai pas fait la sélection inverse (lorsqu'on modifie la position du curseur dans le source, le curseur se place sur la partie correspondante dans l'éditeur html).
    L'inverse est peut-être plus difficile, j'en sait rien en fait je me dis ça car j'ai remarqué que Visual Studio Express pour le web ne le fait que dans le sens que tu as fait et pour l'inverse (en cas de changement de la page html) eh bien il signale juste que le source et le wysiwyg ne sont pas synchronisés et propose de cliquer pour faire la synchronisation... Cela ne se fait donc pas de manière automatique et encore moins en temps réel...

    Par contre amaya semble le faire dans les deux sens...

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Ce serait plus simple si le modèle le prévoyait (ou en faisant un modèle qui le prévoit, ce qui est énormément de travail). La difficulté étant que la position dans le source dépend de la façon de serialiser le html (de l'indentation, des retour chariot, etc...). Et de tout un tas de cas particulier, ce qui rend pénible la mise au point.

    D'ailleurs, voici un correctif du code; qui ne fonctionnait pas correctement (avec la fin de la balise <i>), et pas du tout avec plusieurs paragraphes. Il est probable que d'autres cas particuliers dysfonctionnent.

    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
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    import java.awt.Component;
    import java.io.IOException;
    import java.io.Writer;
    import java.util.ArrayList;
    import java.util.Enumeration;
    import java.util.List;
     
    import javax.swing.JEditorPane;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JSplitPane;
    import javax.swing.event.CaretEvent;
    import javax.swing.event.CaretListener;
    import javax.swing.event.DocumentEvent;
    import javax.swing.event.DocumentListener;
    import javax.swing.text.AbstractDocument.LeafElement;
    import javax.swing.text.BadLocationException;
    import javax.swing.text.Caret;
    import javax.swing.text.DefaultCaret;
    import javax.swing.text.Element;
    import javax.swing.text.JTextComponent;
    import javax.swing.text.html.HTML;
    import javax.swing.text.html.HTMLDocument;
    import javax.swing.text.html.HTMLWriter;
     
     
    public class HtmlEditorWithSource {
     
    	public static void main(String[] args) {
     
    		final String html = "<html><body><p>Ceci est un <i>exemple</i> de html</p><p>Ceci est un <b><i>exemple</i> de html</b></p></body></html>";
     
     
    		JFrame frame = new JFrame("Démo");
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		frame.getContentPane().add(createEditor(html));
     
    		frame.setSize(600, 400);
    		frame.setLocationRelativeTo(null);
    		frame.setVisible(true);
     
    	}
     
    	private static Component createEditor(String html) {
    		JSplitPane panel = new JSplitPane();
     
    		final JEditorPane htmlEditor = new JEditorPane();
    		htmlEditor.setContentType("text/html");
    		htmlEditor.setText(html);
    		htmlEditor.setCaret(new SelectionCaret(htmlEditor.getCaret()));
    		JScrollPane htmlEditorPane=new JScrollPane(htmlEditor, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    		panel.setLeftComponent(htmlEditorPane);
     
    		final JEditorPane sourceEditor = new JEditorPane();
    		sourceEditor.setContentType("text/plain");
    		sourceEditor.setText(htmlEditor.getText());
    		sourceEditor.setCaret(new SelectionCaret(sourceEditor.getCaret()));
    		JScrollPane sourceEditorPane=new JScrollPane(sourceEditor, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    		panel.setRightComponent(sourceEditorPane);
     
    		panel.setResizeWeight(0.5);
     
    		htmlEditor.getDocument().addDocumentListener(new DocumentListener() {
     
    			@Override
    			public void removeUpdate(DocumentEvent e) {
    				update();
    			}
     
    			@Override
    			public void insertUpdate(DocumentEvent e) {
    				update();
    			}
     
    			@Override
    			public void changedUpdate(DocumentEvent e) {
    				update();
    			}
     
    			private void update() {
    				sourceEditor.setText(htmlEditor.getText());
    			}
     
    		});
     
    		htmlEditor.addCaretListener(new CaretListener() {
     
    			@Override
    			public void caretUpdate(CaretEvent e) {
    				int start = e.getDot();
    				int end = e.getMark();
    				if ( end<start ) {
    					int swap=end;
    					end=start;
    					start=swap;
    				}
    				Element rootElement = htmlEditor.getDocument().getDefaultRootElement();
     
    				List<LeafElement> startElements = getLeaves(rootElement,start);
    				List<LeafElement> endElements = getLeaves(rootElement,end);
     
    				LeafElement startElement = getStartElement(start, end, startElements);
    				LeafElement endElement = getEndElement(start, end, endElements);
     
    				CounterHtmlWriter startwriter = new CounterHtmlWriter((HTMLDocument)htmlEditor.getDocument(), startElement, true);
    				int startPosition=0;
    				try {
    					startwriter.write();
    					startPosition=startwriter.getOffset();
    				} catch (IOException | BadLocationException e1) {
    					e1.printStackTrace();
    				}
    				CounterHtmlWriter endwriter = new CounterHtmlWriter((HTMLDocument)htmlEditor.getDocument(), endElement, false);
    				int endPosition=0;
    				try {
    					endwriter.write();
    					endPosition=endwriter.getOffset();
    				} catch (IOException | BadLocationException e1) {
    					e1.printStackTrace();
    				}
    				sourceEditor.select(startPosition+start-startElement.getStartOffset(),endPosition-(endElement.getEndOffset()-end));
     
    			}
     
    			private LeafElement getStartElement(int start, int end,
    					List<LeafElement> elements) {
    					return getElement(start, end, elements, false);
    		    }
    			private LeafElement getElement(int start, int end,
    					List<LeafElement> elements, boolean getEnd) {
    				if ( elements.size()>1 ) {
    					if ( start!=end ) {
    						LeafElement last = elements.get(elements.size()-1);
    						Element parent = last.getParentElement();
    						if ( !getEnd || last.getEndOffset()==parent.getEndOffset() && last.getStartOffset()==parent.getStartOffset() ) {
    							return last;
    						}
    						return elements.get(0);
    					}
    					Element parent = elements.get(0).getParentElement();
    					if ( parent.getStartOffset()==start || parent.getEndOffset()==end) {
    						return elements.get(elements.size()-1);
    					}
    					else {
    						for(LeafElement leafElement : elements) {
    							if ( isTag(leafElement) ) {
    								return leafElement;
    							}
    						}
    					}
    				}
    				return elements.get(0);
    			}
     
    			private boolean isTag(LeafElement leafElement) {
    				Enumeration<?> attributeNames = leafElement.getAttributeNames();
    				for(;attributeNames.hasMoreElements();) {
    					if ( attributeNames.nextElement() instanceof HTML.Tag ) {
    						return true;
    					}
    				}
    				return false;
    			}
     
    			private LeafElement getEndElement(int start, int end,
    					List<LeafElement> elements) {
    				return getElement(start, end, elements, true);
    			}
     
    			private List<LeafElement> getLeaves(Element element, int offset) {
    				List<LeafElement> leaves = new ArrayList<>();
    				getLeaves(element, offset, leaves);
    				return leaves;
    			}
     
    			private void getLeaves(Element element, int offset, List<LeafElement> leaves) {
    				if ( element.getStartOffset()<=offset && offset<=element.getEndOffset() ) {
    					if ( element.isLeaf() ) {
    						leaves.add((LeafElement) element);
    					}
    					for( int i=0; i<element.getElementCount(); i++) {
    						getLeaves(element.getElement(i), offset, leaves);
    					}
    				}
    			}
     
    		});
     
    		sourceEditor.setEditable(false);
     
     
    		return panel;
    	}
     
    	private static class CounterHtmlWriter extends HTMLWriter {
     
    		private LeafElement leaf;
    		private int offset;
    		private int tagoffset;
    		private final CounterWriter counterWriter;
    		private final boolean start;
     
    		public CounterHtmlWriter(HTMLDocument doc, LeafElement element, boolean start) {
    			super(new CounterWriter(), doc);
    			counterWriter=(CounterWriter) getWriter();
    			this.leaf=element;
    			this.start=start;
    		}
     
    		@Override
    		protected void startTag(Element elem) throws IOException,
    				BadLocationException {
    			if (start && leaf==elem) tagoffset=counterWriter.count;
    			super.startTag(elem);
    		}
     
    		@Override
    		protected void endTag(Element elem) throws IOException {
    			super.endTag(elem);
    			if (!start && leaf==elem) tagoffset=counterWriter.count;
    		}
     
    		@Override
    		protected void emptyTag(Element elem) throws BadLocationException,
    				IOException {
    			if (start && leaf==elem) tagoffset=counterWriter.count;
    			super.emptyTag(elem);
    			if (!start && leaf==elem) tagoffset=counterWriter.count;
    		}
     
    		@Override
    		protected void text(Element elem) throws BadLocationException,
    				IOException {
    			if (start && leaf==elem) offset=counterWriter.count;
    			super.text(elem);
    			if (!start && leaf==elem) offset=counterWriter.count;
    		}
     
    		public int getOffset() {
    			return offset;
    		}
    		public int getTagOffset() {
    			return tagoffset;
    		}
     
    		private static class CounterWriter extends Writer {
     
    			public int count;
     
    			@Override
    			public void write(char[] cbuf, int off, int len) throws IOException {
    				count+=len;
    			}
     
    			@Override
    			public void flush() throws IOException {
    			}
     
    			@Override
    			public void close() throws IOException {
    			}
     
    		}
     
    	}
     
    	private static class SelectionCaret extends DefaultCaret {
     
    		public SelectionCaret(Caret caret) {
    			setBlinkRate(caret.getBlinkRate());
    		}
     
    		@Override
    		public void setVisible(boolean visible) {
    			super.setVisible(true);
    		}
     
    		@Override
    		public void setSelectionVisible(boolean visible) {
    			super.setSelectionVisible(true);
    		}
     
    		@Override
    		public void install(JTextComponent c) {
    			super.install(c);
    			super.setVisible(true);
    			super.setSelectionVisible(true);
    		}
     
    	}
     
    }
    Pour le faire dans l'autre sens, il faut que j'y réflechisse mais à priori, je pense qu'il faut simuler le parsing (on parse jusqu'à la position et on regarde quels sont les offsets de l'élément(des éléments) qui contient le curseur (ou la sélection).

    A noter, une difficulté supplémentaire, si on veut pouvoir éditer le source : il peut ne pas être forcément conforme aux règles html, et donc n'être pas directement affichable.

  5. #5
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 891
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 891
    Points : 3 729
    Points
    3 729
    Par défaut
    Citation Envoyé par joel.drigo Voir le message

    Pour le faire dans l'autre sens, il faut que j'y réflechisse mais à priori, je pense qu'il faut simuler le parsing (on parse jusqu'à la position et on regarde quels sont les offsets de l'élément(des éléments) qui contient le curseur (ou la sélection).

    A noter, une difficulté supplémentaire, si on veut pouvoir éditer le source : il peut ne pas être forcément conforme aux règles html, et donc n'être pas directement affichable.
    Merci pour le correctif...

    Sinon oui je crois que tu as raison pour le problème que tu soulèves : je viens de revoir ce que fait amaya et effectivement il ne fait pas la correspondance avec le source à proprement parler mais il le fait avec une "source structurée" (qu'il appelle "structure").

    Voici une image de cette "structure" :

    Nom : Amaya.PNG
Affichages : 253
Taille : 68,7 Ko

    D'ailleurs ce qu'il fait n'est pas tout-à-fait en temps réel comme tu l'as fait : car la synchronisation ne se fait pas à chaque frappe d'une touche du clavier mais pour que la synchronisation se fasse il faut par exemple déplacer le curseur avec les flèches ou la souris. Bon c'est quand même bien car le but c'est surtout de faire la correspondance...

    Ce qui est bien justement c'est que quand on clique sur une balise dans la source structurée il fait la correspondance avec la page html en mettant en surbrillance, exemple en cliquant sur la balise "ul" :

    Nom : amaya2.PNG
Affichages : 560
Taille : 79,2 Ko

  6. #6
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 891
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 891
    Points : 3 729
    Points
    3 729
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    Ce qui est bien justement c'est que quand on clique sur une balise dans la source structurée il fait la correspondance avec la page html en mettant en surbrillance, exemple en cliquant sur la balise "ul" :
    Je crois que cela a été fait ici : http://java-sl.com/editor_kit_tutorial_views.html ou presque (il faudrait mettre dans l'arbre le nom des balises). Je n'ai pas regardé en détail, je ne sais pas comment il fait... Je crois que cela correspond à ce programme qu'on peut télécharger : JEditorPane/JTextPane's Document and Views structure viewer demo app. structure.jar ~19kb.

    ----------

    Je me demandais : Est-ce que la correspondance est faisable avec un WebView (JavaFX) - SwingSimpleBrowser ? Si oui est-ce que ce serait plus simple ou plus difficile ?

  7. #7
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    Je crois que cela a été fait ici : http://java-sl.com/editor_kit_tutorial_views.html ou presque (il faudrait mettre dans l'arbre le nom des balises). Je n'ai pas regardé en détail, je ne sais pas comment il fait... Je crois que cela correspond à ce programme qu'on peut télécharger : JEditorPane/JTextPane's Document and Views structure viewer demo app. structure.jar ~19kb.
    L'article que tu cites ne fait que parler du fonctionnement interne du rendu, du modèle et de l'interactivité de l'EditorKit. C'est une voie possible (l'autre dont je te parlais), qui demande un travail considérable pour mettre au point un modèle (une implémentation concrète de Document) capable d'être rendue en html wysiwyg et en html source à partir du même modèle (surtout la seconde partie, qui n'existe pas, en standard en tout cas). Personnellement, j'utilise un logiciel dont l'API fournit un tel modèle. C'est l'idéal.
    ----------
    Citation Envoyé par Beginner. Voir le message
    Je me demandais : Est-ce que la correspondance est faisable avec un WebView (JavaFX) - SwingSimpleBrowser ? Si oui est-ce que ce serait plus simple ou plus difficile ?
    A ma connaissance, on n'a pas accès au modèle en Java. On y a accès en JavaScript assurément (et on peut invoquer des JavaScript en Java), et il est possible qu'on puisse avoir cette correspondance : je ne connais pas assez JavaScript / DOM pour te le dire. A la limite, intégrer CKEditor dans une webview te permettra peut-être de faire tout ça avec un minimum de code (je ne sais pas exactement ce que propose CKEditor au niveau correspondance html wysiwyg).

  8. #8
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 891
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 891
    Points : 3 729
    Points
    3 729
    Par défaut
    Citation Envoyé par joel.drigo Voir le message
    L'article que tu cites ne fait que parler du fonctionnement interne du rendu, du modèle et de l'interactivité de l'EditorKit. C'est une voie possible (l'autre dont je te parlais), qui demande un travail considérable pour mettre au point un modèle (une implémentation concrète de Document) capable d'être rendue en html wysiwyg et en html source à partir du même modèle (surtout la seconde partie, qui n'existe pas, en standard en tout cas).
    Ok je n'ai pas encore regardé en détail, j'ai juste essayé et on a bien une correspondance : quand on clique sur une branche de l’arbre il met bien en surbrillance l’élément correspondant dans la page html. Sinon pour ce que tu dis on pourrait utiliser un parser ?

    Citation Envoyé par joel.drigo Voir le message
    Personnellement, j'utilise un logiciel dont l'API fournit un tel modèle. C'est l'idéal.
    C'est quel logiciel si ce n'est pas indiscret ?

    Citation Envoyé par joel.drigo Voir le message

    A ma connaissance, on n'a pas accès au modèle en Java. On y a accès en JavaScript assurément (et on peut invoquer des JavaScript en Java), et il est possible qu'on puisse avoir cette correspondance : je ne connais pas assez JavaScript / DOM pour te le dire. A la limite, intégrer CKEditor dans une webview te permettra peut-être de faire tout ça avec un minimum de code (je ne sais pas exactement ce que propose CKEditor au niveau correspondance html wysiwyg).
    Ah oui je m'en doutais un peu... J'ai d’ailleurs posé la question sur la manière de faire en JavaScript... Sinon oui il se trouve que j'ai essayé CKEditor et ça marche bien dans une webview mais par contre il n'y a (à ma connaissance actuelle) aucune correspondance entre la page html et le source. Mais c'est vrai que ça reste une piste car on peut ajouter des modules...

  9. #9
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    Ok je n'ai pas encore regardé en détail, j'ai juste essayé et on a bien une correspondance : quand on clique sur une branche de l’arbre il met bien en surbrillance l’élément correspondant dans la page html. Sinon pour ce que tu dis on pourrait utiliser un parser ?
    Non, mais ça c'est relativement facile (à part la problématique du curseur entre 2 éléments : un curseur n'est jamais sur un caractère donné, mais entre 2 caractères, donc possiblement entre la fin d'un élément et le début d'un autre), pour sélectionner une élément dans un arbre : c'est autre chose de le sélectionner dans un éditeur qui affiche le source, car il faut savoir où se trouve cet élément dans le texte. Ensuite, la sélection ne correspond pas forcément à un élément unique entier, mais possiblement à plusieurs, et certains en partie.

    Citation Envoyé par Beginner. Voir le message
    C'est quel logiciel si ce n'est pas indiscret ?
    Ephox EditLive.

  10. #10
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 891
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 891
    Points : 3 729
    Points
    3 729
    Par défaut
    Merci encore pour ces infos...

    Citation Envoyé par Beginner. Voir le message
    Ah oui je m'en doutais un peu... J'ai d’ailleurs posé la question sur la manière de faire en JavaScript... Sinon oui il se trouve que j'ai essayé CKEditor et ça marche bien dans une webview mais par contre il n'y a (à ma connaissance actuelle) aucune correspondance entre la page html et le source. Mais c'est vrai que ça reste une piste car on peut ajouter des modules...
    Justement je viens de voir ce plugin : http://ckeditor.com/addon/textselection

    Mais JavaScript c'est dur ! Dur Dur de comprendre le code JS fait par un autre... Alors quand c'est une usine à gaz comme CKEditor ou autre il faut être bon et avoir du courage je trouve...

Discussions similaires

  1. Réponses: 1
    Dernier message: 19/03/2014, 10h46
  2. Réponses: 1
    Dernier message: 13/06/2012, 09h28
  3. Réponses: 2
    Dernier message: 26/04/2011, 18h44
  4. Réponses: 1
    Dernier message: 17/06/2007, 14h19

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