

// import des classes Java :
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.text.*; 
import javax.swing.text.Highlighter; 
import javax.swing.event.*;
import java.util.*;

import javax.swing.text.*; 
import javax.swing.text.BadLocationException;

public class MonJTextPane extends JFrame implements CaretListener, ActionListener
{	/****
		*	Attributs :
		*****/
	private JTextPane monTextPane;
	private JLabel monLabel;
	private JButton monBouton;
	private StyleAide style; // class qui defini les effets de style de l'editeur
	
	/****
		*	Constructeur :
		*****/
	public MonJTextPane ()
	{	super ("Aide");

		// construction du composant Texte 
		this.style = new StyleAide (new StyleContext ());
		this.monTextPane = new JTextPane ();
		this.monTextPane.setDocument (style);
		this.monTextPane.addCaretListener (this);

		// construction de la fenetre :
		this.getContentPane ().setLayout (new BorderLayout ());
		this.setBounds (150,150,600,550);
		this.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

		this.monLabel = new JLabel ("Auncune ligne saisie...");
		this.monBouton = new JButton ("change de style");
		this.monBouton.addActionListener (this);
		JPanel panel = new JPanel ();
		panel.setLayout (new GridLayout (1,2));
		panel.add (monLabel);
		panel.add (monBouton);
		this.getContentPane ().add (panel, BorderLayout.SOUTH);
		this.getContentPane ().add (this.monTextPane, BorderLayout.CENTER);
		this.setVisible (true);
	}
	

	/****
		*	Methodes :
		*****/	
	private int getCurrentLigne ()
	{	return ( this.style.getNumLigne (monTextPane.getCaretPosition ())+1 );
	}
	
	public int getCurrentColonne ()
	{	return ( this.style.getNumColonne (monTextPane.getCaretPosition ())+1 );
	}
	
	/****
		*	Methodes CaretListener:
		*****/	
	// ecoute les deplacements du curseur d'insertion
	public void caretUpdate(CaretEvent e)
	{	int debut = java.lang.Math.min (e.getDot (), e.getMark ());
		int fin   = java.lang.Math.max (e.getDot (), e.getMark ());
		this.monLabel.setText ("Ligne numero : "+ this.getCurrentLigne ()+" Colonne : "+this.getCurrentColonne ()+" (debut : "+debut+", fin : "+fin+")");
	}
	
	/****
		*	Methodes ActionListener:
		*****/	
	public void actionPerformed (ActionEvent e)
	{	int start	= monTextPane.getSelectionStart(); 
		int end		= monTextPane.getSelectionEnd();
		
		int debut	= java.lang.Math.min (start, end);
		int fin		= java.lang.Math.max (start, end);
		int longueur= fin - debut;
		
		this.style.changeStyleSurligne (debut, longueur);
	}
	
	
	// lance le tout ....
	public static void main (String argv [])
	{	new MonJTextPane ();
	}
	
}


// la Classe DefaultStyledDocument correspond a la classe utilise comme Model pour les 
// composant Texte evolue comme : JTextPane ou JEditorPane
// en derivant de cette derniere nous pouvons donc redefinir les methodes d'insertion afin de personnalise
// le style d'ecriture en fonction du texte et creer une methode permettant de modifier le style utilise pour 
// une partie de texte deja ecrite.

class StyleAide extends DefaultStyledDocument
{	/****
		*	Constructeur :
		*****/
	public StyleAide (StyleContext styles)
	{	super (styles);
		initStyle (styles);
	}
	

	/****
		*	Methodes :
		*****/
	// redefini pour choisir l'effet de style a utiliser
	public void insertString(int offs, String str, AttributeSet a) throws BadLocationException
	{	try
		{	// si le texte insere est egale a HELP le texte s'ecrit avec le style "styleOp"
			if ( str.equals ("HELP") )
			{	super.insertString (offs, str, getStyle ("styleOp"));
			}
			else // sinon le texte est ecrit avec le style "styleNormal"
			{	super.insertString (offs, str, getStyle ("styleNormal"));
			}
		}
		catch (BadLocationException e)
		{	System.out.println ("Tuuuttt erreur Insere");
		}
	}
	
	// modifie le style d'ecriture d'un texte deja ecrit compris
	public void changeStyleSurligne (int positionDepart, int longueur)
	{	setCharacterAttributes (positionDepart, longueur, getStyle ("styleKeyWord"), true);
	}	
	
	// le Model d'un composant texte est enregistre sous form d'un arbre
	// cette methode permet de recuperer le noeud root de l'arbre
	private Element getRootElement ()
	{	return this.getDefaultRootElement ();
	}

	// methode permettant d'obtenir la ligne correspondant a un offset donnee
	public int getNumLigne (int offset)
	{	Element eltR = getRootElement ();
		int numLigne = eltR.getElementIndex (offset);
		Element elt  = eltR.getElement (numLigne);
		
		if ( offset != elt.getEndOffset () )
		{	return numLigne;
		}
		else
		{	if ( numLigne != 0 )
			{	return numLigne+1;
			}
		}
		return 0;
	}
	
	public int getNumColonne (int offset)
	{	Element eltR = getRootElement ();
		Element elt = eltR.getElement (eltR.getElementIndex (offset));
		int numColonne = offset-elt.getStartOffset ();
		return numColonne;
	}
	
	
	// Defini les differents styles
	private static void initStyle (StyleContext styles)
	{	// definition du style pour le texte normal (brute)

		javax.swing.text.Style defaut = styles.getStyle (StyleContext.DEFAULT_STYLE);
		
		javax.swing.text.Style styleNormal = styles.addStyle("styleNormal", defaut);
		StyleConstants.setFontFamily (styleNormal, "Courier");
		StyleConstants.setFontSize (styleNormal, 11);
		StyleConstants.setForeground(styleNormal, Color.black);
		
		
		javax.swing.text.Style tmp = styles.addStyle("styleKeyWord", styleNormal);
		// Ajout de la couleur blue et du style gras pour les mots cle
		StyleConstants.setForeground(tmp, Color.blue);
		StyleConstants.setBold(tmp, true);

		tmp = styles.addStyle("styleOp", styleNormal);
		// Ajout de la couleur rouge pour le style des operateurs
		StyleConstants.setForeground(tmp, Color.red);
	}
}