Place the test inside the text control

Hi, ALL,
Lets say I have a GtkEntry which is stretched horizontally and vertically.
By default the text in this control will be visually vertically centered inside the control.

Is there a way to make it visually appear at the top? Something like “text-alignment” thing?

TIA!!

p.s.:
One scenario where this could be useful is when you want to have a text control that is multiline (at least visually) with the maximum number of characters restrictions.
It would be weird to see the text position center vertically instead of top vertically.

1 Like

For multiline editable text, you really want a GtkTextView. GtkEntry doesn’t do multline, and ‘stretching’ an entry vertically would probably be considered a bug

Mathias,
There is no way to set max length for GtkTextView, is there?
At east that is not easy.

So one is pushed to use GtkEntry which will be stretched vertically to give a visual queue about a possibility of having a multiline control.

Do you have any suggestions on how to easily implement something like this?

TIA!

Hi.
You can make a simple callback that notifies you when the content of textview is changed and freeze its editability based on the length.
You may think it could be a overkill, but using entry for multiline text is completely wrong way.
^^

j_arun_mani,
I probably can.
But what about pasting the text? The code will become very ugly.

It would of course be nice if the GtkTextView can support it internally and not in the user code, but I guess its too much to ask.
Or at the very least give user access to the text is about to be pasted so that the user program can grab the size of the resulting text and if it is bigger - modify the buffer, rejecting the paste in the “paste-clipboard” handler.

Thank you.

1 Like

Yea that’s also needs to be taken care. You can however watch for the paste signal and act on it.

Have you tried entering multiline text in a GtkEntry ? I doesn’t do it

GtkTextBuffer indeed does not have a max length. You can probably make something work by
connecting to ::changed and enforcing length limits

J_arun_mani,
Can you help with some code?
Like I said - that signal doesn’t provide access to the buffer to be pasted…

TIA!

1 Like

Mathias,
This is what I’m doing.
However it does not take care of the text paste…

Thank you.

Don’t use the “paste” signal: it’s an action signal, and it’s only meant for key bindings.

Every time the contents of a GtkEntry widgets are changed, the notify::text signal will be emitted.

Emmanuelle,
Well, we are talking about GtkTextView.
Is there something similar?

Thank you.

For GtkTextView you will need to connect to the notify::text signal on the GtkTextBuffer.

Emmanuelle,
And how do I do that?
Lets say I have a text “abc” my cursor is set at position 2, maximum length is set at 10, and I want to paste the text " My very long text to paste".
What I’m looking for is - the paste will not happen (meaning the text will still be “abc”) and the cursor will still be at position 2.

Thank you.

Not sure I understand - why do you need to implement pasting yourself ? That is something GtkTextView does on its own.

Or maybe you are asking how to intercept a paste that would exceed your max text length ?

Mathias,
Yes, that is what I’m asking.
Unless there is a solution that will take care of typing text and pasting at the same time.

Hmm, not sure I have a good suggestion for that.

The best I can come up with is: let the paste happen, clip the result, and inform the user

Mathias,
Could you give me a code example?

TIA!

Here you go. The example is in Python and the character limit is 80.

import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk


def text_changed(buf):
    count = buf.get_char_count()
    if count <= 80:
        print("Text is all in limit")
        return
    start = buf.get_iter_at_offset(80)
    end = buf.get_end_iter()
    buf.delete(start, end)
    print("Deleted extra text")



buf = Gtk.TextBuffer()
view = Gtk.TextView(buffer=buf, hexpand=True, vexpand=True, editable=True)

buf.connect("changed", text_changed)

box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
label = Gtk.Label(label="Tell us about you in 80 characters", halign=Gtk.Align.START)
box.pack_start(label, False, False, 0)
box.pack_start(view, True, True, 0)

win = Gtk.Window(title="Example")
win.add(box)
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

^^

j_arun_mani,
Thank you for the reply and the code.
I am looking at it and I don’t understand how it will work in the case I described earlier.
Let me repeat it.

If I have a text “abc” my cursor is at position 2 to insert text between ‘b’ and ‘c’, the maximum is set to 10 and I want to paste the text “My very long string goes here”.

I expect the paste to not happen, the text should still read “abc” and the cursor should still be at the position 2.

However it looks like upon reading the code it looks like the text will be simply cut off at 10 characters and the cursor will be positioned at the end.

Am I right?

Please clarify.

TIA!

P.S.: Also in the past I was connecting to the “text-change” signal with following code:

extern "C"
{
    static void maxlen_handler(GtkTextBuffer*buffer, GtkTextIter *location, gchar *text, gint len, void *data)
    {
        gint count = gtk_text_buffer_get_char_count( buffer );
        unsigned long maxlen = 80;
        if ( count > maxlen )
        {
            GtkTextIter offset, end;
            gint startPos = gtk_text_iter_get_offset( location );
            gtk_text_buffer_get_iter_at_offset( buffer, &offset, startPos - 1 );
            gtk_text_buffer_get_iter_at_offset( buffer, &end, (startPos - 1) + len );
            gtk_text_buffer_delete( buffer, &offset, &end );
            // Without following line GTK3 produces following warning
            // Gtk-WARNING **: Invalid text buffer iterator: either the iterator is uninitialized,
            // or the characters/pixbufs/widgets in the buffer have been modified since the iterator was created.
            // GTK+2 is more forgiving in this case
#if GTK_CHECK_VERSION( 3, 0, 0 )
            gtk_text_iter_assign( location, &offset );
#endif
        }
    }
    }

This worked fine for typing text, as text-changed, but did nothing on paste.

So maybe I should modify my handler to use the appropriate positions to modify the buffer accordingly?
Because unfortunately the signature is not correct for the “changed” signal…

1 Like

I think that will cause confusion to users. Because when I press Ctrl V I want the text to be pasted. If we had somehow stopped the paste from happening, then the users will be confused if the text view allows any paste or not.

Let me look at the docs and see if we can do it. Also this will be the expected behavior in Gtk.Entry too : the new text will be trimmed to the character limit. ^^