Vous êtes à peu près ici : Accueil  »   tutoriel PyGTK  »   PyGTK : sommaire

13.3. TextBuffer : le buffer de texte

Le TextBuffer est le composant principal du système d'édition de texte de PyGTK. Il contient le texte, les TextTag (dans une TextTagTable), et les TextMark, qui, ensemble, décrivent comment le texte doit être affiché et permettent à l'utilisateur de modifier interactivement le texte ou la manière dont il s'affiche. Comme nous l'avons fait remarquer dans la section précédente, un TextBuffer est associé à un ou plusieurs TextView, qui se chargent d'afficher son contenu.

La création d'un TextBuffer se fait soit automatiquement lorsque l'on crée un TextView, soit avec la fonction :

  bufferdetexte = TextBuffer(table=None)

table est une TextTagTable. Si table n'est pas spécifié (ou s'il vaut None), une nouvelle TextTagTable sera créée pour le TextBuffer.

Un grand nombre de méthodes est disponible pour :

13.3.1. Récupérer des informations sur le buffer

Vous pouvez récupérer le nombre de lignes d'un TextBuffer avec la méthode :

  nombre_lignes = bufferdetexte.get_line_count()

De la même manière, vous pouvez obtenir le nombre de caractères présents dans le TextBuffer :

  nombre_caract = bufferdetexte.get_char_count()

Lorsque le contenu du TextBuffer est modifié, le drapeau de modification est levé. L'état de ce drapeau peut être obtenu à l'aide de la méthode :

  modif = bufferdetexte.get_modified()

Si le programme sauvegarde le contenu du buffer, la méthode suivante peut réinitialiser le drapeau de modification :

  bufferdetexte.set_modified(choix)

13.3.2. Créer des TextIter

On utilise les TextIter pour spécifier une position entre deux caractères d'un TextBuffer. Les méthodes du TextBuffer qui manipulent du texte s'en servent pour indiquer à quelle position elles doivent s'appliquer. Les TextIter possèdent de nombreuses méthodes qui seront décrites dans la section TextIter.

Les méthodes de TextBuffer basiques pour créer des TextIter sont :

  iter = bufferdetexte.get_iter_at_offset(n)

  iter = bufferdetexte.get_iter_at_line(x)

  iter = bufferdetexte.get_iter_at_line_offset(x, n)

  iter = bufferdetexte.get_iter_at_mark(marque)

get_iter_at_offset() crée un itérateur juste après le nème caractère à partir du début du TextBuffer.

get_iter_at_line() crée un itérateur juste avant le premier caractère de la xème ligne.

get_iter_at_line_offset() crée un itérateur juste après le nème caractère de la xème ligne.

get_iter_at_mark() crée un itérateur à la même position que la TextMark marque.

Le méthode qui suit crée un ou plusieurs TextIter à des emplacements spécifiques du buffer :

  iterdebut = bufferdetexte.get_start_iter()

  iterfin = bufferdetexte.get_end_iter()

  iterdebut, iterfin = bufferdetexte.get_bounds()

  debut, fin = bufferdetexte.get_selection_bounds()

get_start_iter() crée un itérateur juste avant le premier caractère du buffer.

get_end_iter() crée un itérateur juste après le dernier caractère du buffer.

get_bounds() crée un tuple de deux itérateurs respectivement situés juste avant le premier caractère et juste après le dernier caractère du buffer.

get_selection_bounds() crée un tuple de deux itérateurs aux mêmes positions que les marques insert et selection_bound du buffer.

13.3.3. Insérer, récupérer et supprimer du texte

Le texte contenu par un TextBuffer peut être défini avec la méthode suivante :

  bufferdetexte.set_text(texte)

Cette méthode remplace le contenu actuel de bufferdetexte par texte.

La méthode la plus générale pour insérer des caractères dans un TextBuffer est :

  bufferdetexte.insert(iter, texte)

où l'on insère le texte texte à l'emplacement de bufferdetexte spécifié par iter.

Si vous souhaitez simuler une insertion de texte par un utilisateur interactif, faites appel à la méthode suivante :

  resultat = bufferdetexte.insert_interactive(iter, texte, defaut_editable)

qui insèrera texte dans le buffer, à la position spécifiée par iter, mais seulement si cette position est éditable (c'est-à-dire si elle ne porte pas de balise mentionnant que le texte est non éditable) et que la valeur de defaut_editable est TRUE. Le résultat indique si le texte a été inséré.

L'argument defaut_editable précise si un texte peut être édité dans le cas où il ne porte pas de balise le spécifiant ; defaut_editable est généralement déterminé par un appel à la méthode get_editable() du TextView.

D'autres méthodes existent pour insérer du texte :

  bufferdetexte.insert_at_cursor(texte)

  resultat = bufferdetexte.insert_at_cursor_interactive(texte, defaut_editable)

  bufferdetexte.insert_range(iter, debut, fin)

  resultat = bufferdetexte.insert_range_interactive(iter, debut, fin, defaut_editable)

insert_at_cursor() est une méthode pratique pour insérer du texte à l'emplacement courant du curseur (insert).

insert_range() copie le texte, les pixbufs et les balises compris entre les itérateurs debut et fin d'un TextBuffer (si ce TextBuffer n'est pas bufferdetexte, la table des balises doit être la même), puis colle le tout dans bufferdetexte à l'emplacement indiqué par iter.

Les versions interactives de ces méthodes opèrent de la même manière à la différence qu'elles n'insèrent la copie que si l'emplacement est éditable.

Enfin, en peut insérer du texte et lui appliquer des balises en même temps par l'intermédiaire des méthodes :

  bufferdetexte.insert_with_tags(iter, texte, balise1, balise2, ...)
  
  bufferdetexte.insert_with_tags_by_name(iter, texte, nom_balise1, nom_balise2, ...)

insert_with_tags() insère le texte dans le bufferdetexte, à l'emplacement spécifié par l'iter, et lui applique les balises données.

insert_with_tags_by_name() fait la même chose mais permet de spécifier les balises en les nommant.

On peut effacer du texte d'un buffer avec les méthodes :

  bufferdetexte.delete(debut, fin)
  
  resultat = bufferdetexte.delete_interactive(debut, fin, defaut_editable)

delete() supprime le texte compris entre les TextIter debut et fin de bufferdetexte.

delete_interactive() supprime tout texte éditable (déterminé comme tel par les balises de texte applicables et par l'argument defaut_editable) compris entre debut et fin.

Vous pouvez récupérer une copie du texte d'un TextBuffer grâce aux méthodes :

  texte = bufferdetexte.get_text(debut, fin, include_hidden_chars=TRUE)

  texte = bufferdetexte.get_slice(debut, fin, include_hidden_chars=TRUE)

get_text() retourne une copie du texte du buffer compris entre debut et fin ; le texte non affiché est exclu si include_hidden_chars vaut FALSE. Les caractères représentant des images incrustées ou des widgets sont exclus.

get_slice() est identique à get_text() à la différence que le texte qu'elle retourne inclut un caractère 0xFFFC pour chaque image incrustée ou widget.

13.3.4. Créer et manipuler des TextMark

Les TextMark sont similaires aux TextIter en ceci qu'elles spécifient une position entre deux caractères d'un TextBuffer. Cependant, les TextMark maintiennent leur information de position même après modification du buffer. Les méthodes des TextMark seront décrites plus loin dans la section TextMark.

Un buffer de texte contient deux marques inhérentes : la marque insert (insertion) et la marque selection_bound (fin de sélection). La marque insert est la position par défaut pour l'insertion de texte (le curseur). La marque selection_bound se combine avec la marque insert pour définir une sélection.

On peut retrouver ces deux marques en faisant appel aux méthodes suivantes :

  marque_insert = bufferdetexte.get_insert()

  marque_selectionbound = bufferdetexte.get_selection_bound()

Les marques insert et selection_bound peuvent être placées simultanément à une position grâce à la méthode :

  bufferdetexte.place_cursor(emplacement)

emplacement est un TextIter qui indique la position. La méthode place_cursor() est nécessaire pour éviter de créer temporairement une sélection si les marques ont été déplacées individuellement.

On crée des TextMark avec la méthode :

  marque = bufferdetexte.create_mark(nom_marque, emplacement, left_gravity=FALSE)

nom_marque est le nom assigné à la marque créée (None pour une marque anonyme), emplacement est l'itérateur de texte indiquant la position de la marque dans le buffer, et left_gravity indique la situation de la marque après que du texte y aura été inséré (gauche si TRUE, droite si FALSE).

Une marque peut être déplacée dans le buffer avec les méthodes :

  bufferdetexte.move_mark(marque, emplacement)

  bufferdetexte.move_mark_by_name(nom_marque, emplacement)

marque désigne la marque à déplacer. nom_marque spécifie le nom de la marque à déplacer. emplacement est un itérateur de texte indiquant la nouvelle position.

On peut supprimer une marque d'un buffer avec les méthodes :

  bufferdetexte.delete_mark(marque)

  bufferdetexte.delete_mark_by_name(nom_marque)

On peut récupérer une marque par son nom avec la méthode :

  marque = bufferdetexte.get_mark(nom_marque)

13.3.5. Créer et appliquer des TextTag

Les TextTag contiennent un ou plusieurs attributs (comme les couleurs d'arrière-plan et de premier plan, la police, la possibilité d'édition) que l'on peut appliquer à une ou plusieurs portions du texte d'un buffer. Les attributs pouvant être spécifiés par une TextTag seront décrits dans la section TextTag.

La méthode suivante crée une TextTag avec des attributs et l'installe dans la TextTagTable d'un TextBuffer :

  balise = bufferdetexte.create_tag(name=None, attribut1=valeur1, attribut2=valeur2, ...)

name est soit une chaîne de caractères spécifiant le nom de la balise, soit None si la balise est anonyme. Les couples attribut-valeur déterminent les attributs de la balise. Reportez-vous à la section TextTag pour des informations concernant les attributs qui peuvent être définis par les propriétés d'une TextTag.

Une balise peut être appliquée à une portion du texte d'un buffer par la méthode suivante :

  bufferdetexte.apply_tag(balise, debut, fin)

  bufferdetexte.apply_tag_by_name(nom_balise, debut, fin)

balise est la balise à appliquer au texte, nom_balise le nom de la balise, et debut et fin des itérateurs de texte qui indiquent la portion de texte à laquelle la balise doit être appliquée.

On peut retirer une balise d'une portion de texte en utilisant les méthodes suivantes :

  bufferdetexte.remove_tag(balise, debut, fin)

  bufferdetexte.remove_tag_by_name(nom_balise, debut, fin)

Pour retirer toutes les balises d'une portion de texte, on utilisera :

  bufferdetexte.remove_all_tags(debut, fin)

13.3.6. Insérer des images et des widgets

En plus du texte, un TextBuffer peut contenir des images pixbuf et un point d'ancrage pour widgets. Ce point d'ancrage sert à ajouter un widget à une TextView. Un widget différent peut être ajouté dans chaque TextView qui affiche un buffer contenant un point d'ancrage.

On peut insérer une image pixbuf avec la méthode suivante :

  bufferdetexte.insert_pixbuf(iter, pixbuf)

dans laquelle iter précise l'emplacement du buffer où insérer l'image pixbuf. Cette image comptera pour un caractère et sera représentée par le caractère Unicode "0xFFFC" dans le texte retourné par la méthode get_slice() (il ne figurera pas dans celui retourné par get_text() ).

On peut insérer un widget GTK+ dans une TextView, ` un emplacement du buffer spécifiée par un TextChildAnchor (point d'ancrage pour enfant). Tout comme une image pixbuf, le TextChildAnchor comptera pour un caractère représenté par "0xFFFC".

Le moyen le plus commode de créer et d'insérer un TextChildAnchor est la méthode suivante :

  ancrage = bufferdetexte.create_child_anchor(iter)

iter est l'emplacement destiné à recevoir le point d'ancrage.

Mais on peut aussi créer et insérer le TextChildAnchor en deux temps ainsi:

  ancrage = gtk.TextChildAnchor()

  bufferdetexte.insert_child_anchor(iter, ancrage)

Puis l'on peut ajouter le widget à la TextView, au point d'ancrage, grâce à la méthode suivante :

  zonedetexte.add_child_at_anchor(widget_enfant, ancrage)

La méthode qui suit permet de récupérer la liste des widgets attachés à un point d'ancrage :

  liste_widgets = ancrage.get_widgets()

On peut également ajouter un widget à une TextView en utilisant cette méthode :

  zonedetexte.add_child_in_window(widget_enfant, fenetre, position_x, position_y)

où le widget_enfant sera placé dans la fenêtre fenetre à la positon spécifiée par position_x et position_y. fenetre indique laquelle des fenêtres qui composent la TextView doit recevoir le widget enfant :

  gtk.TEXT_WINDOW_TOP       # fenêtre supérieure
  gtk.TEXT_WINDOW_BOTTOM    # fenêtre inférieure
  gtk.TEXT_WINDOW_LEFT      # fenêtre de gauche
  gtk.TEXT_WINDOW_RIGHT     # fenêtre de droite
  gtk.TEXT_WINDOW_TEXT      # fenêtre du texte
  gtk.TEXT_WINDOW_WIDGET    # fenêtre du widget