GtkTextBuffer : Applying tags to newly input text

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

GtkTextBuffer : Applying tags to newly input text

Gary Kramlich
Hi all,

I'm working on a GtkTextBuffer subclass that needs to apply tags to to
newly inserted text.  I've tried all sort of tricks to make this happen
automatically, but I am coming up short.

Basically the GtkTextView is editable and I'm trying to allow the user to
set a format and then start typing. I've tried to apply a tag from the iter
of the insertion mark to the end of the buffer and have any newly inserted
text have that tag applied.  However, my attempts at doing this have been
nothing but failures.

I believe this is possible because if I start typing in the middle of an
already applied tag the newly inserted text has that tag applied and all of
the existing text retains the tag.

I've played around a bit with additional marks and their gravity but
haven't had any success there either.

Any pointers would be greatly appreciated!

Thanks,

--
Gary Kramlich <[hidden email]>
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|

Re: GtkTextBuffer : Applying tags to newly input text

Karan Ahuja
What are tags applied to ?
In the apply tag function - what are the tags applied to.

On 13 Jun 2018 12:34, "Gary Kramlich" <[hidden email]> wrote:
>
> Hi all,
>
> I'm working on a GtkTextBuffer subclass that needs to apply tags to to
> newly inserted text.  I've tried all sort of tricks to make this happen
> automatically, but I am coming up short.
>
> Basically the GtkTextView is editable and I'm trying to allow the user to
> set a format and then start typing. I've tried to apply a tag from the
iter
> of the insertion mark to the end of the buffer and have any newly inserted
> text have that tag applied.  However, my attempts at doing this have been
> nothing but failures.
>
> I believe this is possible because if I start typing in the middle of an
> already applied tag the newly inserted text has that tag applied and all
of

> the existing text retains the tag.
>
> I've played around a bit with additional marks and their gravity but
> haven't had any success there either.
>
> Any pointers would be greatly appreciated!
>
> Thanks,
>
> --
> Gary Kramlich <[hidden email]>
> _______________________________________________
> gtk-app-devel-list mailing list
> [hidden email]
> https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|

Re: GtkTextBuffer : Applying tags to newly input text

Gary Kramlich
I'm not sure I'm following your question unless you're trying to point out
that they're applied to GtkTextIter's that are invalidated once the text is
changed.  That said, something is happening internally in the
`_gtk_text_btree` functions that implements the behavior I'm trying to
reproduce.  If i have text like `<b>foo bar</b>` and i put the cursor at
the space and type `baz ` the text will end up being `<b>foo baz bar</b>`.
So the behavior is clearly there to read a current set of tags and apply
them.  I haven't dug too much into the `_gtk_text_btree` code as it's all
internal to Gtk and clearly I can't call any of it directly.

I'm simply asking is it possible and if so, how do I do that at the end of
the buffer.  Using the example above starting with `<b>foo bar</b>` and
entering ` baz` at the end of bar should result in `<b>foo bar baz</b>`,
but everything I've tried ends up in `<b>foo bar</b> baz`.  Unfortunately I
haven't kept an exhaustive list of everything I've tried, but it's been a
lot, including the obvious of insert mark + the iter from
`gtk_text_buffer_get_end_iter`.

I haven't yet played with adding a mark at the end with right gravity as
that would result in me having to track the currently applied tags and
constantly reapply them which seems like a lot of overhead for something
that is already being handled internally in some way shape or form.

On Wed, Jun 13, 2018 at 2:51 AM, Karan Ahuja <[hidden email]>
wrote:

> What are tags applied to ?
> In the apply tag function - what are the tags applied to.
>
> On 13 Jun 2018 12:34, "Gary Kramlich" <[hidden email]> wrote:
> >
> > Hi all,
> >
> > I'm working on a GtkTextBuffer subclass that needs to apply tags to to
> > newly inserted text.  I've tried all sort of tricks to make this happen
> > automatically, but I am coming up short.
> >
> > Basically the GtkTextView is editable and I'm trying to allow the user to
> > set a format and then start typing. I've tried to apply a tag from the
> iter
> > of the insertion mark to the end of the buffer and have any newly
> inserted
> > text have that tag applied.  However, my attempts at doing this have been
> > nothing but failures.
> >
> > I believe this is possible because if I start typing in the middle of an
> > already applied tag the newly inserted text has that tag applied and all
> of
> > the existing text retains the tag.
> >
> > I've played around a bit with additional marks and their gravity but
> > haven't had any success there either.
> >
> > Any pointers would be greatly appreciated!
> >
> > Thanks,
> >
> > --
> > Gary Kramlich <[hidden email]>
> > _______________________________________________
> > gtk-app-devel-list mailing list
> > [hidden email]
> > https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
>
>


--
Thanks,

--
Gary Kramlich <[hidden email]>
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|

Re: GtkTextBuffer : Applying tags to newly input text

Gtk+ - Apps Dev mailing list
In reply to this post by Gary Kramlich

 
Hi Gary,

Test setting up your callback with g_signal_connect_after. Then the location iter should be at the end of the insert. Then the tag can be applied to the inserted text.

Eric

   
//gcc -Wall highlight1.c -o highlight1 `pkg-config --cflags --libs gtk+-3.0`

#include <gtk/gtk.h>

static gboolean set_tag=FALSE;

static void button_toggled(GtkToggleButton *button, gpointer data)
  {
    g_print("Button Toggled\n");
    set_tag=gtk_toggle_button_get_active(button);
  }
static void insert_text(GtkTextBuffer *textbuffer, GtkTextIter *location, gchar *text, gint len, GtkTextTag * cyan_tag)
  {
    g_print("Insert %s Offset %i\n", text, gtk_text_iter_get_offset(location));

    if(set_tag)
      {
        GtkTextIter *start=gtk_text_iter_copy(location);
        gtk_text_iter_backward_chars(start, len);
        gtk_text_buffer_apply_tag(textbuffer, cyan_tag, start, location);
        gtk_text_iter_free(start);
      }
  }
int main(int argc, char *argv[])
  {
    gtk_init(&argc, &argv);

    GtkWidget *window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "Highlight");
    gtk_window_set_default_size(GTK_WINDOW(window), 300, 300);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_container_set_border_width(GTK_CONTAINER(window), 20);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

    GtkWidget *textview=gtk_text_view_new();
    gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textview), GTK_WRAP_CHAR);
    gtk_widget_set_hexpand(textview, TRUE);
    gtk_widget_set_vexpand(textview, TRUE);

    GtkTextBuffer *buffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
    GtkTextTag *cyan_tag=gtk_text_buffer_create_tag(buffer, "cyan-tag", "background", "cyan", NULL);
    g_signal_connect_after(buffer, "insert-text", G_CALLBACK(insert_text), cyan_tag);

    GtkWidget *button=gtk_toggle_button_new_with_label("Cyan Highlight");
    g_signal_connect(button, "toggled", G_CALLBACK(button_toggled), NULL);

    GtkWidget *grid=gtk_grid_new();
    gtk_grid_attach(GTK_GRID(grid), textview, 0, 0, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), button, 0, 1, 1, 1);

    gtk_container_add(GTK_CONTAINER(window), grid);

    gtk_widget_show_all(window);
   
    gtk_main();

    return 0;
  }



 


_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|

Re: GtkTextBuffer : Applying tags to newly input text

Gary Kramlich
Hi Eric,

I meant to respond sooner but I've been busy.  This worked like a charm!!
Thank you very much.  Not sure how I overloaded
`gtk_text_iter_backward_chars` but yeah that made things way easier.

A followup I've been struggling with though is how to avoid applying this
formatting when rich text is being pasted (I process it and tag it before
calling my parent's `insert_text` method).  I'm using a horrible heuristic
right now of only applying formatting if the `text_len` passed into my
`insert_text` is equal to `1`.  The heuristic here is that the user can
only enter 1 character at a time and you wouldn't have rich text on the
clipboard of only a single character.  This has the side affect that plain
text won't be formatted via the UI buttons.

I've been looking for a way to hook into the clipboard stuff, but that
doesn't seem like it'll fix the original problem of just knowing to not
apply the set formatting when rich text is pasted.

Any suggestions?

Thanks,

--
Gary Kramlich <[hidden email]>
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|

Re: GtkTextBuffer : Applying tags to newly input text

Gtk+ - Apps Dev mailing list

 
The textview understands Pango markup. Maybe something to give a try. There are a lot of text formats and you might have to do some text parsing depending on the format. If it is possible to use gtk_text_buffer_insert_markup(), this can save a lot of time dealing with text tags especially if you intend to print the text. It is far easier to send a pango markup string to print than to go through all the tags and draw them with cairo.

https://developer.gnome.org/pango/stable/PangoMarkupFormat.html

Eric

 


_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|

Re: GtkTextBuffer : Applying tags to newly input text

Gary Kramlich
The formats I need to handle are HTML and Markdown, while I could convert
them to Pango markup, it seems redundant to do so.  That said, I was
looking to be able to copy HTML back out from a buffer that's handling HTML
(by parsing it on insert).

I should note, as I haven't already, that my use case here is the input
widget for Pidgin an instant messaging client.  So some networks don't
support any formatting, some do HTML, and others do markdown.  So the way I
have this structured right now is that there's a text table with all the
tags, there's a text view that handles the wysiwyg stuff discussed
previously, and then there's an html buffer that parses the html in the
insert_text handler and applies the tags to that.  That said, I need both
the specific markup and the plain text for a number of scenarios.  So if
there's a way I can have the text view how to do additional parsing that is
mostly likely the direction I'll need to go.

Thanks,

--
Gary Kramlich <[hidden email]>
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|

Re: GtkTextBuffer : Applying tags to newly input text

Gtk+ - Apps Dev mailing list

 

 
With the text buffer and tag table you can get the text with pango attributes or even rebuild pango markup for print output. This allows the pango markup to be parsed into and then to be extracted from the text buffer without loss(Easier said than done). You only need one text buffer to manage. I suspect that you can't do that with html. I don't think that you can rebuild html after parsing it into a text buffer. Maybe a small subset of html? Having more than one buffer and trying to synchronize them upon edits,,, doesn't sound very easy either but might be the better choice. A bit of a tough problem.

Eric


_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|

Re: GtkTextBuffer : Applying tags to newly input text

Gary Kramlich
I already have html parsing working into a Pango subset.  The issue I have
right now is 100% related to the clipboard usage only.  Right now I'm
parsing HTML on the text_insert, but i really only need to do it on paste.
Likewise for copy I need to parse the buffer and put html back onto the
clipboard.  I have another idea that'll kind of make that possible by
inserting the literal html tags into the buffer with a tag that's invisible.

I'm not trying to do multiple buffers at the same time.  Some protocols
support plain text, some support html, and some markdown.  Depending on
which one is being displayed I either use a GtkTextBuffer, or my HTML
buffer, or my Markdown buffer respectively.

Thanks,

--
Gary Kramlich <[hidden email]>
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list