11from travertino .size import at_least
22
3+ from toga .handlers import WeakrefCallable
34from toga .keys import Key
45from toga_gtk .keys import toga_key
56
6- from ..libs import Gtk , gtk_text_align
7+ from ..libs import GTK_VERSION , Gtk , gtk_text_align
78from .base import Widget
89
910
1011class TextInput (Widget ):
1112 def create (self ):
1213 self .native = Gtk .Entry ()
1314
14- self .native .connect ("changed" , self .gtk_on_change )
15- self .native .connect ("focus-in-event" , self .gtk_focus_in_event )
16- self .native .connect ("focus-out-event" , self .gtk_focus_out_event )
17- self .native .connect ("key-press-event" , self .gtk_key_press_event )
15+ if GTK_VERSION < (4 , 0 , 0 ): # pragma: no-cover-if-gtk4
16+ self .native .connect ("changed" , self .gtk_on_change )
17+ self .native .connect ("focus-in-event" , self .gtk_focus_in_event )
18+ self .native .connect ("focus-out-event" , self .gtk_focus_out_event )
19+ self .native .connect ("key-press-event" , self .gtk_key_press_event )
20+ else : # pragma: no-cover-if-gtk3
21+ # Ideally we would connect to the `changed` signal, but it is
22+ # emitting two events each time text is changed
23+ # https://gitlab.gnome.org/GNOME/gtk/-/issues/7077
24+ self .native .connect ("notify::text" , self .gtk_on_change )
25+
26+ self .focus_controller = Gtk .EventControllerFocus .new ()
27+ self .native .add_controller (self .focus_controller )
28+
29+ self .focus_controller .connect (
30+ "enter" , WeakrefCallable (self .gtk_focus_in_event )
31+ )
32+ self .focus_controller .connect (
33+ "leave" , WeakrefCallable (self .gtk_focus_out_event )
34+ )
35+
36+ self .key_controller = Gtk .EventControllerKey .new ()
37+ self .native .add_controller (self .key_controller )
38+ self .key_controller .connect (
39+ "key-pressed" , WeakrefCallable (self .gtk_key_pressed )
40+ )
1841
1942 def gtk_on_change (self , * _args ):
2043 self .interface ._value_changed ()
@@ -25,10 +48,19 @@ def gtk_focus_in_event(self, *_args):
2548 def gtk_focus_out_event (self , * _args ):
2649 self .interface .on_lose_focus ()
2750
28- def gtk_key_press_event (self , _entry , event ):
29- key_pressed = toga_key (event .keyval , event .state )
30- if key_pressed and key_pressed ["key" ] in {Key .ENTER , Key .NUMPAD_ENTER }:
31- self .interface .on_confirm ()
51+ if GTK_VERSION < (4 , 0 , 0 ): # pragma: no-cover-if-gtk4
52+
53+ def gtk_key_press_event (self , _entry , event ):
54+ key_pressed = toga_key (event .keyval , event .state )
55+ if key_pressed and key_pressed ["key" ] in {Key .ENTER , Key .NUMPAD_ENTER }:
56+ self .interface .on_confirm ()
57+
58+ else : # pragma: no-cover-if-gtk3
59+
60+ def gtk_key_pressed (self , _controller , keyval , _keycode , state ):
61+ key_pressed = toga_key (keyval , state )
62+ if key_pressed and key_pressed ["key" ] in {Key .ENTER , Key .NUMPAD_ENTER }:
63+ self .interface .on_confirm ()
3264
3365 def get_readonly (self ):
3466 return not self .native .get_property ("editable" )
@@ -55,21 +87,35 @@ def set_value(self, value):
5587 self .native .set_text (value )
5688
5789 def rehint (self ):
58- # print(
59- # "REHINT",
60- # self,
61- # self._impl.get_preferred_width(),
62- # self._impl.get_preferred_height(),
63- # getattr(self, "_fixed_height", False),
64- # getattr(self, "_fixed_width", False),
65- # )
66- width = self .native .get_preferred_width ()
67- height = self .native .get_preferred_height ()
68-
69- self .interface .intrinsic .width = at_least (
70- max (self .interface ._MIN_WIDTH , width [1 ])
71- )
72- self .interface .intrinsic .height = height [1 ]
90+ if GTK_VERSION < (4 , 0 , 0 ): # pragma: no-cover-if-gtk4
91+ # print(
92+ # "REHINT",
93+ # self,
94+ # self._impl.get_preferred_width(),
95+ # self._impl.get_preferred_height(),
96+ # getattr(self, "_fixed_height", False),
97+ # getattr(self, "_fixed_width", False),
98+ # )
99+ width = self .native .get_preferred_width ()
100+ height = self .native .get_preferred_height ()
101+
102+ self .interface .intrinsic .width = at_least (
103+ max (self .interface ._MIN_WIDTH , width [1 ])
104+ )
105+ self .interface .intrinsic .height = height [1 ]
106+ else : # pragma: no-cover-if-gtk3
107+ print (
108+ "[DEBUG TextInput] REHINT" ,
109+ self ,
110+ self .native .get_preferred_size ()[1 ].width ,
111+ self .native .get_preferred_size ()[1 ].height ,
112+ )
113+ min_size , size = self .native .get_preferred_size ()
114+
115+ self .interface .intrinsic .width = at_least (
116+ max (min_size .width , self .interface ._MIN_WIDTH )
117+ )
118+ self .interface .intrinsic .height = min_size .height
73119
74120 def set_error (self , error_message ):
75121 self .native .set_icon_from_icon_name (Gtk .EntryIconPosition .SECONDARY , "error" )
0 commit comments