mirror of
https://github.com/ToshioCP/Gtk4-tutorial.git
synced 2025-01-12 20:03:28 +01:00
Bug fixed (section 30, list editor).
This commit is contained in:
parent
d2f89cd1e7
commit
9650830860
5 changed files with 284 additions and 162 deletions
173
docs/sec30.html
173
docs/sec30.html
|
@ -186,53 +186,59 @@ class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span i
|
||||||
<span id="cb2-2"><a href="#cb2-2"></a>setup2_cb <span class="op">(</span>GtkListItemFactory <span class="op">*</span>factory<span class="op">,</span> GtkListItem <span class="op">*</span>listitem<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb2-2"><a href="#cb2-2"></a>setup2_cb <span class="op">(</span>GtkListItemFactory <span class="op">*</span>factory<span class="op">,</span> GtkListItem <span class="op">*</span>listitem<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb2-3"><a href="#cb2-3"></a> GtkWidget <span class="op">*</span>text <span class="op">=</span> gtk_text_new <span class="op">();</span></span>
|
<span id="cb2-3"><a href="#cb2-3"></a> GtkWidget <span class="op">*</span>text <span class="op">=</span> gtk_text_new <span class="op">();</span></span>
|
||||||
<span id="cb2-4"><a href="#cb2-4"></a> gtk_list_item_set_child <span class="op">(</span>listitem<span class="op">,</span> GTK_WIDGET <span class="op">(</span>text<span class="op">));</span></span>
|
<span id="cb2-4"><a href="#cb2-4"></a> gtk_list_item_set_child <span class="op">(</span>listitem<span class="op">,</span> GTK_WIDGET <span class="op">(</span>text<span class="op">));</span></span>
|
||||||
<span id="cb2-5"><a href="#cb2-5"></a><span class="op">}</span></span>
|
<span id="cb2-5"><a href="#cb2-5"></a> gtk_editable_set_alignment <span class="op">(</span>GTK_EDITABLE <span class="op">(</span>text<span class="op">),</span> <span class="fl">0.0</span><span class="op">);</span></span>
|
||||||
<span id="cb2-6"><a href="#cb2-6"></a></span>
|
<span id="cb2-6"><a href="#cb2-6"></a><span class="op">}</span></span>
|
||||||
<span id="cb2-7"><a href="#cb2-7"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
<span id="cb2-7"><a href="#cb2-7"></a></span>
|
||||||
<span id="cb2-8"><a href="#cb2-8"></a>bind2_cb <span class="op">(</span>GtkListItemFactory <span class="op">*</span>factory<span class="op">,</span> GtkListItem <span class="op">*</span>listitem<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb2-8"><a href="#cb2-8"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||||
<span id="cb2-9"><a href="#cb2-9"></a> GtkWidget <span class="op">*</span>text <span class="op">=</span> gtk_list_item_get_child <span class="op">(</span>listitem<span class="op">);</span></span>
|
<span id="cb2-9"><a href="#cb2-9"></a>bind2_cb <span class="op">(</span>GtkListItemFactory <span class="op">*</span>factory<span class="op">,</span> GtkListItem <span class="op">*</span>listitem<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb2-10"><a href="#cb2-10"></a> LeData <span class="op">*</span>data <span class="op">=</span> LE_DATA <span class="op">(</span>gtk_list_item_get_item <span class="op">(</span>listitem<span class="op">));</span></span>
|
<span id="cb2-10"><a href="#cb2-10"></a> GtkWidget <span class="op">*</span>text <span class="op">=</span> gtk_list_item_get_child <span class="op">(</span>listitem<span class="op">);</span></span>
|
||||||
<span id="cb2-11"><a href="#cb2-11"></a> GtkEntryBuffer <span class="op">*</span>buffer<span class="op">;</span></span>
|
<span id="cb2-11"><a href="#cb2-11"></a> GtkEntryBuffer <span class="op">*</span>buffer <span class="op">=</span> gtk_text_get_buffer <span class="op">(</span>GTK_TEXT <span class="op">(</span>text<span class="op">));</span></span>
|
||||||
<span id="cb2-12"><a href="#cb2-12"></a> GBinding <span class="op">*</span>bind<span class="op">;</span></span>
|
<span id="cb2-12"><a href="#cb2-12"></a> LeData <span class="op">*</span>data <span class="op">=</span> LE_DATA <span class="op">(</span>gtk_list_item_get_item <span class="op">(</span>listitem<span class="op">));</span></span>
|
||||||
<span id="cb2-13"><a href="#cb2-13"></a></span>
|
<span id="cb2-13"><a href="#cb2-13"></a> GBinding <span class="op">*</span>bind<span class="op">;</span></span>
|
||||||
<span id="cb2-14"><a href="#cb2-14"></a> buffer <span class="op">=</span> gtk_text_get_buffer <span class="op">(</span>GTK_TEXT <span class="op">(</span>text<span class="op">));</span></span>
|
<span id="cb2-14"><a href="#cb2-14"></a></span>
|
||||||
<span id="cb2-15"><a href="#cb2-15"></a> gtk_entry_buffer_set_text <span class="op">(</span>buffer<span class="op">,</span> le_data_look_string <span class="op">(</span>data<span class="op">),</span> <span class="op">-</span><span class="dv">1</span><span class="op">);</span></span>
|
<span id="cb2-15"><a href="#cb2-15"></a> gtk_editable_set_text <span class="op">(</span>GTK_EDITABLE <span class="op">(</span>text<span class="op">),</span> le_data_look_string <span class="op">(</span>data<span class="op">));</span></span>
|
||||||
<span id="cb2-16"><a href="#cb2-16"></a> bind <span class="op">=</span> g_object_bind_property <span class="op">(</span>buffer<span class="op">,</span> <span class="st">"text"</span><span class="op">,</span> data<span class="op">,</span> <span class="st">"string"</span><span class="op">,</span> G_BINDING_DEFAULT<span class="op">);</span></span>
|
<span id="cb2-16"><a href="#cb2-16"></a> gtk_editable_set_position <span class="op">(</span>GTK_EDITABLE <span class="op">(</span>text<span class="op">),</span> <span class="dv">0</span><span class="op">);</span></span>
|
||||||
<span id="cb2-17"><a href="#cb2-17"></a> g_object_set_data <span class="op">(</span>G_OBJECT <span class="op">(</span>listitem<span class="op">),</span> <span class="st">"bind"</span><span class="op">,</span> bind<span class="op">);</span></span>
|
<span id="cb2-17"><a href="#cb2-17"></a></span>
|
||||||
<span id="cb2-18"><a href="#cb2-18"></a><span class="op">}</span></span>
|
<span id="cb2-18"><a href="#cb2-18"></a> bind <span class="op">=</span> g_object_bind_property <span class="op">(</span>buffer<span class="op">,</span> <span class="st">"text"</span><span class="op">,</span> data<span class="op">,</span> <span class="st">"string"</span><span class="op">,</span> G_BINDING_DEFAULT<span class="op">);</span></span>
|
||||||
<span id="cb2-19"><a href="#cb2-19"></a></span>
|
<span id="cb2-19"><a href="#cb2-19"></a> g_object_set_data <span class="op">(</span>G_OBJECT <span class="op">(</span>listitem<span class="op">),</span> <span class="st">"bind"</span><span class="op">,</span> bind<span class="op">);</span></span>
|
||||||
<span id="cb2-20"><a href="#cb2-20"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
<span id="cb2-20"><a href="#cb2-20"></a><span class="op">}</span></span>
|
||||||
<span id="cb2-21"><a href="#cb2-21"></a>unbind2_cb <span class="op">(</span>GtkListItemFactory <span class="op">*</span>factory<span class="op">,</span> GtkListItem <span class="op">*</span>listitem<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb2-21"><a href="#cb2-21"></a></span>
|
||||||
<span id="cb2-22"><a href="#cb2-22"></a> GBinding <span class="op">*</span>bind <span class="op">=</span> G_BINDING <span class="op">(</span>g_object_get_data <span class="op">(</span>G_OBJECT <span class="op">(</span>listitem<span class="op">),</span> <span class="st">"bind"</span><span class="op">));</span></span>
|
<span id="cb2-22"><a href="#cb2-22"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||||
<span id="cb2-23"><a href="#cb2-23"></a></span>
|
<span id="cb2-23"><a href="#cb2-23"></a>unbind2_cb <span class="op">(</span>GtkListItemFactory <span class="op">*</span>factory<span class="op">,</span> GtkListItem <span class="op">*</span>listitem<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb2-24"><a href="#cb2-24"></a> g_binding_unbind<span class="op">(</span>bind<span class="op">);</span></span>
|
<span id="cb2-24"><a href="#cb2-24"></a> GBinding <span class="op">*</span>bind <span class="op">=</span> G_BINDING <span class="op">(</span>g_object_get_data <span class="op">(</span>G_OBJECT <span class="op">(</span>listitem<span class="op">),</span> <span class="st">"bind"</span><span class="op">));</span></span>
|
||||||
<span id="cb2-25"><a href="#cb2-25"></a> g_object_set_data <span class="op">(</span>G_OBJECT <span class="op">(</span>listitem<span class="op">),</span> <span class="st">"bind"</span><span class="op">,</span> NULL<span class="op">);</span></span>
|
<span id="cb2-25"><a href="#cb2-25"></a></span>
|
||||||
<span id="cb2-26"><a href="#cb2-26"></a><span class="op">}</span></span></code></pre></div>
|
<span id="cb2-26"><a href="#cb2-26"></a> g_binding_unbind<span class="op">(</span>bind<span class="op">);</span></span>
|
||||||
|
<span id="cb2-27"><a href="#cb2-27"></a> g_object_set_data <span class="op">(</span>G_OBJECT <span class="op">(</span>listitem<span class="op">),</span> <span class="st">"bind"</span><span class="op">,</span> NULL<span class="op">);</span></span>
|
||||||
|
<span id="cb2-28"><a href="#cb2-28"></a><span class="op">}</span></span></code></pre></div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>1-5: <code>setup2_cb</code> is a setup signal handler on the
|
<li>1-6: <code>setup2_cb</code> is a setup signal handler on the
|
||||||
GtkSignalListItemFactory. This factory is inserted to the factory
|
GtkSignalListItemFactory. This factory is inserted to the factory
|
||||||
property of the second GtkColumnViewColumn. Te handler just creates a
|
property of the second GtkColumnViewColumn. The handler just creates a
|
||||||
GtkText instance and sets the child of <code>listitem</code> to it. The
|
GtkText instance and sets the child of <code>listitem</code> to it. The
|
||||||
instance will be destroyed automatically when the <code>listitem</code>
|
instance will be destroyed automatically when the <code>listitem</code>
|
||||||
is destroyed. So, teardown signal handler isn’t necessary.</li>
|
is destroyed. So, teardown signal handler isn’t necessary.</li>
|
||||||
<li>7-18: <code>bind2_cb</code> is a bind signal handler. It is called
|
<li>8-20: <code>bind2_cb</code> is a bind signal handler. It is called
|
||||||
when the <code>listitem</code> is bound to an item in the list. The list
|
when the <code>listitem</code> is bound to an item in the list. The list
|
||||||
items are LeData instances. LeData is defined in the file
|
items are LeData instances. LeData is defined in the file
|
||||||
<code>listeditor.c</code> (the C source file of the list editor). It is
|
<code>listeditor.c</code> (the C source file of the list editor). It is
|
||||||
a child class of GObject and has two data. The one is
|
a child class of GObject and has two data. The one is
|
||||||
<code>listitem</code> which points a GtkListItem instance when they are
|
<code>listitem</code> which points a first column GtkListItem instance
|
||||||
connected. If no GtkListItem is connected, it is NULL. The other is
|
when they are connected. Be careful that the GtkListItem instance is
|
||||||
<code>string</code> which is a content of the line.
|
<em>not</em> the <code>listitem</code> in this handler. If no
|
||||||
|
GtkListItem is connected, it is NULL. The other is <code>string</code>
|
||||||
|
which is a content of the line.
|
||||||
<ul>
|
<ul>
|
||||||
<li>9-10: <code>text</code> is a child of the <code>listitem</code> and
|
<li>10-11: <code>text</code> is a child of the <code>listitem</code> and
|
||||||
it is a GtkText instance. <code>data</code> is an item pointed by the
|
it is a GtkText instance. And <code>buffer</code> is a GtkTextBuffer
|
||||||
<code>listitem</code>. It is a LeData instance.</li>
|
instance of the <code>text</code>.</li>
|
||||||
<li>14: Gets the buffer of the <code>text</code>.</li>
|
<li>12: The LeData instance <code>data</code> is an item pointed by the
|
||||||
<li>15: Sets the text of the buffer to
|
<code>listitem</code>.</li>
|
||||||
|
<li>15-16: Sets the text of <code>text</code> to
|
||||||
<code>le_data_look_string (data)</code>. le_data_look_string returns the
|
<code>le_data_look_string (data)</code>. le_data_look_string returns the
|
||||||
string of the data and the ownership of the string is taken by the
|
string of the <code>data</code> and the ownership of the string is still
|
||||||
<code>data</code>. So, the caller don’t need to free the string.</li>
|
taken by the <code>data</code>. So, the caller don’t need to free the
|
||||||
<li>16: <code>g_object_bind_property</code> binds a property and another
|
string.</li>
|
||||||
|
<li>18: <code>g_object_bind_property</code> binds a property and another
|
||||||
object property. This line binds the “text” property of the
|
object property. This line binds the “text” property of the
|
||||||
<code>buffer</code> (source) and the “string” property of the
|
<code>buffer</code> (source) and the “string” property of the
|
||||||
<code>data</code> (destination). It is a uni-directional binding
|
<code>data</code> (destination). It is a uni-directional binding
|
||||||
|
@ -241,19 +247,19 @@ the same string is immediately put into the <code>data</code>. The
|
||||||
function returns a GBinding instance. This binding is different from
|
function returns a GBinding instance. This binding is different from
|
||||||
bindings of GtkExpression. This binding needs the existence of the two
|
bindings of GtkExpression. This binding needs the existence of the two
|
||||||
properties.</li>
|
properties.</li>
|
||||||
<li>17: GObjec has a table. The key is a string (or GQuark) and the
|
<li>19: GObjec has a table. The key is a string (or GQuark) and the
|
||||||
value is a gpointer (pointer to any type). The function
|
value is a gpointer (pointer to any type). The function
|
||||||
<code>g_object_set_data</code> sets the association from the key to the
|
<code>g_object_set_data</code> sets the association from the key to the
|
||||||
value. This line sets the association from “bind” to <code>bind</code>
|
value. This line sets the association from “bind” to <code>bind</code>
|
||||||
instance on the <code>listitem</code> instance. It makes possible for
|
instance. It makes possible for the “unbind” handler to get the
|
||||||
the “unbind” handler to get the <code>bind</code> instance.</li>
|
<code>bind</code> instance.</li>
|
||||||
</ul></li>
|
</ul></li>
|
||||||
<li>20-26: <code>unbind2_cb</code> is a unbind signal handler.
|
<li>22-28: <code>unbind2_cb</code> is a unbind signal handler.
|
||||||
<ul>
|
<ul>
|
||||||
<li>22: Retrieves the <code>bind</code> instance from the table in the
|
<li>24: Retrieves the <code>bind</code> instance from the table in the
|
||||||
<code>listitem</code> instance.</li>
|
<code>listitem</code> instance.</li>
|
||||||
<li>24: Unbind the binding.</li>
|
<li>26: Unbind the binding.</li>
|
||||||
<li>25: Removes the value corresponds to the “bind” key.</li>
|
<li>27: Removes the value corresponds to the “bind” key.</li>
|
||||||
</ul></li>
|
</ul></li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>This technique is not so complicated. You can use it when you make a
|
<p>This technique is not so complicated. You can use it when you make a
|
||||||
|
@ -271,6 +277,10 @@ moves.</p>
|
||||||
<li>When the current line is deleted, no line will be current.</li>
|
<li>When the current line is deleted, no line will be current.</li>
|
||||||
<li>When a button in the first column of GtkColumnView is clicked, the
|
<li>When a button in the first column of GtkColumnView is clicked, the
|
||||||
line will be current.</li>
|
line will be current.</li>
|
||||||
|
<li>It is necessary to set the line status (whether current or not) when
|
||||||
|
a GtkListItem is bound to an item in the list. It is because GtkListItem
|
||||||
|
is recycled. A GtkListItem was possibly current line before but not
|
||||||
|
current after recycled. The opposite can also be happen.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>The button of the current line is colored with red and otherwise
|
<p>The button of the current line is colored with red and otherwise
|
||||||
white.</p>
|
white.</p>
|
||||||
|
@ -284,7 +294,7 @@ the item in the list. It is the opposite direction from
|
||||||
<code>gtk_list_item_get_item</code> function. To accomplish this, we set
|
<code>gtk_list_item_get_item</code> function. To accomplish this, we set
|
||||||
a <code>listitem</code> element of LeData to point the corresponding
|
a <code>listitem</code> element of LeData to point the corresponding
|
||||||
GtkListItem instance. Therefore, items (LeData) in the list always know
|
GtkListItem instance. Therefore, items (LeData) in the list always know
|
||||||
the GtkListItem. If there’s no GtkListItem binded to the item, NULL is
|
the GtkListItem. If there’s no GtkListItem bound to the item, NULL is
|
||||||
assigned.</p>
|
assigned.</p>
|
||||||
<div class="sourceCode" id="cb3"><pre
|
<div class="sourceCode" id="cb3"><pre
|
||||||
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1"></a><span class="dt">void</span></span>
|
class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1"></a><span class="dt">void</span></span>
|
||||||
|
@ -298,42 +308,56 @@ class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span i
|
||||||
<span id="cb3-9"><a href="#cb3-9"></a>setup1_cb <span class="op">(</span>GtkListItemFactory <span class="op">*</span>factory<span class="op">,</span> GtkListItem <span class="op">*</span>listitem<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb3-9"><a href="#cb3-9"></a>setup1_cb <span class="op">(</span>GtkListItemFactory <span class="op">*</span>factory<span class="op">,</span> GtkListItem <span class="op">*</span>listitem<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb3-10"><a href="#cb3-10"></a> GtkWidget <span class="op">*</span>button <span class="op">=</span> gtk_button_new <span class="op">();</span></span>
|
<span id="cb3-10"><a href="#cb3-10"></a> GtkWidget <span class="op">*</span>button <span class="op">=</span> gtk_button_new <span class="op">();</span></span>
|
||||||
<span id="cb3-11"><a href="#cb3-11"></a> gtk_list_item_set_child <span class="op">(</span>listitem<span class="op">,</span> button<span class="op">);</span></span>
|
<span id="cb3-11"><a href="#cb3-11"></a> gtk_list_item_set_child <span class="op">(</span>listitem<span class="op">,</span> button<span class="op">);</span></span>
|
||||||
<span id="cb3-12"><a href="#cb3-12"></a> g_signal_connect <span class="op">(</span>button<span class="op">,</span> <span class="st">"clicked"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>select_cb<span class="op">),</span> listitem<span class="op">);</span></span>
|
<span id="cb3-12"><a href="#cb3-12"></a> gtk_widget_set_focusable <span class="op">(</span>GTK_WIDGET <span class="op">(</span>button<span class="op">),</span> FALSE<span class="op">);</span></span>
|
||||||
<span id="cb3-13"><a href="#cb3-13"></a><span class="op">}</span></span>
|
<span id="cb3-13"><a href="#cb3-13"></a> g_signal_connect <span class="op">(</span>button<span class="op">,</span> <span class="st">"clicked"</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>select_cb<span class="op">),</span> listitem<span class="op">);</span></span>
|
||||||
<span id="cb3-14"><a href="#cb3-14"></a></span>
|
<span id="cb3-14"><a href="#cb3-14"></a><span class="op">}</span></span>
|
||||||
<span id="cb3-15"><a href="#cb3-15"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
<span id="cb3-15"><a href="#cb3-15"></a></span>
|
||||||
<span id="cb3-16"><a href="#cb3-16"></a>bind1_cb <span class="op">(</span>GtkListItemFactory <span class="op">*</span>factory<span class="op">,</span> GtkListItem <span class="op">*</span>listitem<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb3-16"><a href="#cb3-16"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||||
<span id="cb3-17"><a href="#cb3-17"></a> LeData <span class="op">*</span>data <span class="op">=</span> LE_DATA <span class="op">(</span>gtk_list_item_get_item <span class="op">(</span>listitem<span class="op">));</span></span>
|
<span id="cb3-17"><a href="#cb3-17"></a>bind1_cb <span class="op">(</span>GtkListItemFactory <span class="op">*</span>factory<span class="op">,</span> GtkListItem <span class="op">*</span>listitem<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb3-18"><a href="#cb3-18"></a> <span class="cf">if</span> <span class="op">(</span>data<span class="op">)</span></span>
|
<span id="cb3-18"><a href="#cb3-18"></a> LeWindow <span class="op">*</span>win <span class="op">=</span> LE_WINDOW <span class="op">(</span>user_data<span class="op">);</span></span>
|
||||||
<span id="cb3-19"><a href="#cb3-19"></a> le_data_set_listitem <span class="op">(</span>data<span class="op">,</span> listitem<span class="op">);</span></span>
|
<span id="cb3-19"><a href="#cb3-19"></a> GtkWidget <span class="op">*</span>button <span class="op">=</span> gtk_list_item_get_child <span class="op">(</span>listitem<span class="op">);</span></span>
|
||||||
<span id="cb3-20"><a href="#cb3-20"></a><span class="op">}</span></span>
|
<span id="cb3-20"><a href="#cb3-20"></a> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>non_current<span class="op">[</span><span class="dv">1</span><span class="op">]</span> <span class="op">=</span> <span class="op">{</span>NULL<span class="op">};</span></span>
|
||||||
<span id="cb3-21"><a href="#cb3-21"></a></span>
|
<span id="cb3-21"><a href="#cb3-21"></a> <span class="dt">const</span> <span class="dt">char</span> <span class="op">*</span>current<span class="op">[</span><span class="dv">2</span><span class="op">]</span> <span class="op">=</span> <span class="op">{</span><span class="st">"current"</span><span class="op">,</span> NULL<span class="op">};</span></span>
|
||||||
<span id="cb3-22"><a href="#cb3-22"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
<span id="cb3-22"><a href="#cb3-22"></a> LeData <span class="op">*</span>data <span class="op">=</span> LE_DATA <span class="op">(</span>gtk_list_item_get_item <span class="op">(</span>listitem<span class="op">));</span></span>
|
||||||
<span id="cb3-23"><a href="#cb3-23"></a>unbind1_cb <span class="op">(</span>GtkListItemFactory <span class="op">*</span>factory<span class="op">,</span> GtkListItem <span class="op">*</span>listitem<span class="op">)</span> <span class="op">{</span></span>
|
<span id="cb3-23"><a href="#cb3-23"></a></span>
|
||||||
<span id="cb3-24"><a href="#cb3-24"></a> LeData <span class="op">*</span>data <span class="op">=</span> LE_DATA <span class="op">(</span>gtk_list_item_get_item <span class="op">(</span>listitem<span class="op">));</span></span>
|
<span id="cb3-24"><a href="#cb3-24"></a> <span class="cf">if</span> <span class="op">(</span>data<span class="op">)</span> <span class="op">{</span></span>
|
||||||
<span id="cb3-25"><a href="#cb3-25"></a> <span class="cf">if</span> <span class="op">(</span>data<span class="op">)</span></span>
|
<span id="cb3-25"><a href="#cb3-25"></a> le_data_set_listitem <span class="op">(</span>data<span class="op">,</span> listitem<span class="op">);</span></span>
|
||||||
<span id="cb3-26"><a href="#cb3-26"></a> le_data_set_listitem <span class="op">(</span>data<span class="op">,</span> NULL<span class="op">);</span></span>
|
<span id="cb3-26"><a href="#cb3-26"></a> <span class="cf">if</span> <span class="op">(</span>win<span class="op">-></span>position <span class="op">==</span> gtk_list_item_get_position <span class="op">(</span>listitem<span class="op">))</span></span>
|
||||||
<span id="cb3-27"><a href="#cb3-27"></a><span class="op">}</span></span></code></pre></div>
|
<span id="cb3-27"><a href="#cb3-27"></a> gtk_widget_set_css_classes <span class="op">(</span>GTK_WIDGET <span class="op">(</span>button<span class="op">),</span> current<span class="op">);</span></span>
|
||||||
|
<span id="cb3-28"><a href="#cb3-28"></a> <span class="cf">else</span></span>
|
||||||
|
<span id="cb3-29"><a href="#cb3-29"></a> gtk_widget_set_css_classes <span class="op">(</span>GTK_WIDGET <span class="op">(</span>button<span class="op">),</span> non_current<span class="op">);</span></span>
|
||||||
|
<span id="cb3-30"><a href="#cb3-30"></a> <span class="op">}</span></span>
|
||||||
|
<span id="cb3-31"><a href="#cb3-31"></a><span class="op">}</span></span>
|
||||||
|
<span id="cb3-32"><a href="#cb3-32"></a></span>
|
||||||
|
<span id="cb3-33"><a href="#cb3-33"></a><span class="dt">static</span> <span class="dt">void</span></span>
|
||||||
|
<span id="cb3-34"><a href="#cb3-34"></a>unbind1_cb <span class="op">(</span>GtkListItemFactory <span class="op">*</span>factory<span class="op">,</span> GtkListItem <span class="op">*</span>listitem<span class="op">)</span> <span class="op">{</span></span>
|
||||||
|
<span id="cb3-35"><a href="#cb3-35"></a> LeData <span class="op">*</span>data <span class="op">=</span> LE_DATA <span class="op">(</span>gtk_list_item_get_item <span class="op">(</span>listitem<span class="op">));</span></span>
|
||||||
|
<span id="cb3-36"><a href="#cb3-36"></a> <span class="cf">if</span> <span class="op">(</span>data<span class="op">)</span></span>
|
||||||
|
<span id="cb3-37"><a href="#cb3-37"></a> le_data_set_listitem <span class="op">(</span>data<span class="op">,</span> NULL<span class="op">);</span></span>
|
||||||
|
<span id="cb3-38"><a href="#cb3-38"></a><span class="op">}</span></span></code></pre></div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>8-13: <code>setup1_cb</code> is a setup signal handler on the
|
<li>8-14: <code>setup1_cb</code> is a setup signal handler on the
|
||||||
GtkSignalListItemFactory. This factory is inserted to the factory
|
GtkSignalListItemFactory. This factory is inserted to the factory
|
||||||
property of the first GtkColumnViewColumn. It sets the child of
|
property of the first GtkColumnViewColumn. It sets the child of
|
||||||
<code>listitem</code> to a newly created GtkButton instance. The
|
<code>listitem</code> to a GtkButton instance. The “clicked” signal on
|
||||||
“clicked” signal on the button is connected to the handler
|
the button is connected to the handler <code>select_cb</code>. When the
|
||||||
<code>select_cb</code>. When the listitem is destroyed, the child
|
listitem is destroyed, the child (GtkButton) is also destroyed. At the
|
||||||
(GtkButton) is also destroyed. At the same time, the connection of the
|
same time, the connection of the signal and the handler is also
|
||||||
signal and handler is also destroyed. So, you don’t need teardown signal
|
destroyed. So, you don’t need teardown signal handler.</li>
|
||||||
handler.</li>
|
|
||||||
<li>1-6: <code>select_cb</code> is a “clicked” signal handler. LeWindow
|
<li>1-6: <code>select_cb</code> is a “clicked” signal handler. LeWindow
|
||||||
is defined in <code>listeditor.c</code>. It’s a child class of
|
is defined in <code>listeditor.c</code>. It’s a child class of
|
||||||
GtkApplicationWindow. The handler just calls the
|
GtkApplicationWindow. The handler just calls the
|
||||||
<code>update_current</code> function. The function will be explained
|
<code>update_current</code> function. The function will be explained
|
||||||
later.</li>
|
later.</li>
|
||||||
<li>15-20: <code>bind1_cb</code> is a bind signal handler. It sets the
|
<li>16-31: <code>bind1_cb</code> is a bind signal handler. It sets the
|
||||||
“listitem” element of the item (LeData) to point the
|
“listitem” element of the item (LeData) to point the
|
||||||
<code>listitem</code> (GtkListItem instance). It makes the item possible
|
<code>listitem</code> (GtkListItem instance). It makes the item possible
|
||||||
to find the corresponding GtkListItem instance.</li>
|
to find the corresponding GtkListItem instance. If the item is the
|
||||||
<li>22-27: <code>unbind1_cb</code> is an unbind signal handler. It
|
current line, the CSS class of the button includes “current” class.
|
||||||
|
Otherwise it has no CSS class. This is necessary because the button may
|
||||||
|
be recycled and it has had former CSS class. The class need to be
|
||||||
|
updated.</li>
|
||||||
|
<li>33-38: <code>unbind1_cb</code> is an unbind signal handler. It
|
||||||
removes the <code>listitem</code> instance from the “listitem” element
|
removes the <code>listitem</code> instance from the “listitem” element
|
||||||
of the item. The element becomes NULL, which tells no GtkListItem is
|
of the item. The element becomes NULL, which tells no GtkListItem is
|
||||||
bound. When referring GtkListItem, it needs to check the “listitem”
|
bound. When referring GtkListItem, it needs to check the “listitem”
|
||||||
|
@ -423,6 +447,15 @@ template children for the given widget. This is the opposite of
|
||||||
<code>gtk_widget_init_template()</code>. It is a new function of GTK 4.8
|
<code>gtk_widget_init_template()</code>. It is a new function of GTK 4.8
|
||||||
version. If your GTK version is lower than 4.8, you need to modify the
|
version. If your GTK version is lower than 4.8, you need to modify the
|
||||||
program.</p>
|
program.</p>
|
||||||
|
<h2 id="a-waring-from-gtktext">A waring from GtkText</h2>
|
||||||
|
<p>If the list has many items and it needs to be scrolled, a warning
|
||||||
|
message can be issued.</p>
|
||||||
|
<pre><code>GtkText - unexpected blinking selection. Removing</code></pre>
|
||||||
|
<p>I don’t have an idea why this happens. But if GtkText “focusable”
|
||||||
|
property is FALSE, the warning doesn’t happen. So it probably come from
|
||||||
|
focus and scroll. If you know the reason, please let me know.</p>
|
||||||
|
<p>It is a warning message, not a fatal error. I think we can ignore
|
||||||
|
it.</p>
|
||||||
</div>
|
</div>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
159
gfm/sec30.md
159
gfm/sec30.md
|
@ -78,65 +78,68 @@ The following is their sgnal handlers.
|
||||||
2 setup2_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
2 setup2_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
||||||
3 GtkWidget *text = gtk_text_new ();
|
3 GtkWidget *text = gtk_text_new ();
|
||||||
4 gtk_list_item_set_child (listitem, GTK_WIDGET (text));
|
4 gtk_list_item_set_child (listitem, GTK_WIDGET (text));
|
||||||
5 }
|
5 gtk_editable_set_alignment (GTK_EDITABLE (text), 0.0);
|
||||||
6
|
6 }
|
||||||
7 static void
|
7
|
||||||
8 bind2_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
8 static void
|
||||||
9 GtkWidget *text = gtk_list_item_get_child (listitem);
|
9 bind2_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
||||||
10 LeData *data = LE_DATA (gtk_list_item_get_item (listitem));
|
10 GtkWidget *text = gtk_list_item_get_child (listitem);
|
||||||
11 GtkEntryBuffer *buffer;
|
11 GtkEntryBuffer *buffer = gtk_text_get_buffer (GTK_TEXT (text));
|
||||||
12 GBinding *bind;
|
12 LeData *data = LE_DATA (gtk_list_item_get_item (listitem));
|
||||||
13
|
13 GBinding *bind;
|
||||||
14 buffer = gtk_text_get_buffer (GTK_TEXT (text));
|
14
|
||||||
15 gtk_entry_buffer_set_text (buffer, le_data_look_string (data), -1);
|
15 gtk_editable_set_text (GTK_EDITABLE (text), le_data_look_string (data));
|
||||||
16 bind = g_object_bind_property (buffer, "text", data, "string", G_BINDING_DEFAULT);
|
16 gtk_editable_set_position (GTK_EDITABLE (text), 0);
|
||||||
17 g_object_set_data (G_OBJECT (listitem), "bind", bind);
|
17
|
||||||
18 }
|
18 bind = g_object_bind_property (buffer, "text", data, "string", G_BINDING_DEFAULT);
|
||||||
19
|
19 g_object_set_data (G_OBJECT (listitem), "bind", bind);
|
||||||
20 static void
|
20 }
|
||||||
21 unbind2_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
21
|
||||||
22 GBinding *bind = G_BINDING (g_object_get_data (G_OBJECT (listitem), "bind"));
|
22 static void
|
||||||
23
|
23 unbind2_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
||||||
24 g_binding_unbind(bind);
|
24 GBinding *bind = G_BINDING (g_object_get_data (G_OBJECT (listitem), "bind"));
|
||||||
25 g_object_set_data (G_OBJECT (listitem), "bind", NULL);
|
25
|
||||||
26 }
|
26 g_binding_unbind(bind);
|
||||||
|
27 g_object_set_data (G_OBJECT (listitem), "bind", NULL);
|
||||||
|
28 }
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
- 1-5: `setup2_cb` is a setup signal handler on the GtkSignalListItemFactory.
|
- 1-6: `setup2_cb` is a setup signal handler on the GtkSignalListItemFactory.
|
||||||
This factory is inserted to the factory property of the second GtkColumnViewColumn.
|
This factory is inserted to the factory property of the second GtkColumnViewColumn.
|
||||||
Te handler just creates a GtkText instance and sets the child of `listitem` to it.
|
The handler just creates a GtkText instance and sets the child of `listitem` to it.
|
||||||
The instance will be destroyed automatically when the `listitem` is destroyed.
|
The instance will be destroyed automatically when the `listitem` is destroyed.
|
||||||
So, teardown signal handler isn't necessary.
|
So, teardown signal handler isn't necessary.
|
||||||
- 7-18: `bind2_cb` is a bind signal handler.
|
- 8-20: `bind2_cb` is a bind signal handler.
|
||||||
It is called when the `listitem` is bound to an item in the list.
|
It is called when the `listitem` is bound to an item in the list.
|
||||||
The list items are LeData instances.
|
The list items are LeData instances.
|
||||||
LeData is defined in the file `listeditor.c` (the C source file of the list editor).
|
LeData is defined in the file `listeditor.c` (the C source file of the list editor).
|
||||||
It is a child class of GObject and has two data.
|
It is a child class of GObject and has two data.
|
||||||
The one is `listitem` which points a GtkListItem instance when they are connected.
|
The one is `listitem` which points a first column GtkListItem instance when they are connected.
|
||||||
|
Be careful that the GtkListItem instance is *not* the `listitem` in this handler.
|
||||||
If no GtkListItem is connected, it is NULL.
|
If no GtkListItem is connected, it is NULL.
|
||||||
The other is `string` which is a content of the line.
|
The other is `string` which is a content of the line.
|
||||||
- 9-10: `text` is a child of the `listitem` and it is a GtkText instance.
|
- 10-11: `text` is a child of the `listitem` and it is a GtkText instance.
|
||||||
`data` is an item pointed by the `listitem`. It is a LeData instance.
|
And `buffer` is a GtkTextBuffer instance of the `text`.
|
||||||
- 14: Gets the buffer of the `text`.
|
- 12: The LeData instance `data` is an item pointed by the `listitem`.
|
||||||
- 15: Sets the text of the buffer to `le_data_look_string (data)`.
|
- 15-16: Sets the text of `text` to `le_data_look_string (data)`.
|
||||||
le\_data\_look\_string returns the string of the data and the ownership of the string is taken by the `data`.
|
le\_data\_look\_string returns the string of the `data` and the ownership of the string is still taken by the `data`.
|
||||||
So, the caller don't need to free the string.
|
So, the caller don't need to free the string.
|
||||||
- 16: `g_object_bind_property` binds a property and another object property.
|
- 18: `g_object_bind_property` binds a property and another object property.
|
||||||
This line binds the "text" property of the `buffer` (source) and the "string" property of the `data` (destination).
|
This line binds the "text" property of the `buffer` (source) and the "string" property of the `data` (destination).
|
||||||
It is a uni-directional binding (`G_BINDING_DEFAULT`).
|
It is a uni-directional binding (`G_BINDING_DEFAULT`).
|
||||||
When a user changes the GtkText text, the same string is immediately put into the `data`.
|
When a user changes the GtkText text, the same string is immediately put into the `data`.
|
||||||
The function returns a GBinding instance.
|
The function returns a GBinding instance.
|
||||||
This binding is different from bindings of GtkExpression.
|
This binding is different from bindings of GtkExpression.
|
||||||
This binding needs the existence of the two properties.
|
This binding needs the existence of the two properties.
|
||||||
- 17: GObjec has a table.
|
- 19: GObjec has a table.
|
||||||
The key is a string (or GQuark) and the value is a gpointer (pointer to any type).
|
The key is a string (or GQuark) and the value is a gpointer (pointer to any type).
|
||||||
The function `g_object_set_data` sets the association from the key to the value.
|
The function `g_object_set_data` sets the association from the key to the value.
|
||||||
This line sets the association from "bind" to `bind` instance on the `listitem` instance.
|
This line sets the association from "bind" to `bind` instance.
|
||||||
It makes possible for the "unbind" handler to get the `bind` instance.
|
It makes possible for the "unbind" handler to get the `bind` instance.
|
||||||
- 20-26: `unbind2_cb` is a unbind signal handler.
|
- 22-28: `unbind2_cb` is a unbind signal handler.
|
||||||
- 22: Retrieves the `bind` instance from the table in the `listitem` instance.
|
- 24: Retrieves the `bind` instance from the table in the `listitem` instance.
|
||||||
- 24: Unbind the binding.
|
- 26: Unbind the binding.
|
||||||
- 25: Removes the value corresponds to the "bind" key.
|
- 27: Removes the value corresponds to the "bind" key.
|
||||||
|
|
||||||
This technique is not so complicated.
|
This technique is not so complicated.
|
||||||
You can use it when you make a cell editable application.
|
You can use it when you make a cell editable application.
|
||||||
|
@ -152,6 +155,10 @@ The line editor has the current position of the list.
|
||||||
- When a line is appended or inserted, the line is current.
|
- When a line is appended or inserted, the line is current.
|
||||||
- When the current line is deleted, no line will be current.
|
- When the current line is deleted, no line will be current.
|
||||||
- When a button in the first column of GtkColumnView is clicked, the line will be current.
|
- When a button in the first column of GtkColumnView is clicked, the line will be current.
|
||||||
|
- It is necessary to set the line status (whether current or not) when a GtkListItem is bound to an item in the list.
|
||||||
|
It is because GtkListItem is recycled.
|
||||||
|
A GtkListItem was possibly current line before but not current after recycled.
|
||||||
|
The opposite can also be happen.
|
||||||
|
|
||||||
The button of the current line is colored with red and otherwise white.
|
The button of the current line is colored with red and otherwise white.
|
||||||
|
|
||||||
|
@ -165,7 +172,7 @@ It is necessary to know the corresponding GtkListItem instance from the item in
|
||||||
It is the opposite direction from `gtk_list_item_get_item` function.
|
It is the opposite direction from `gtk_list_item_get_item` function.
|
||||||
To accomplish this, we set a `listitem` element of LeData to point the corresponding GtkListItem instance.
|
To accomplish this, we set a `listitem` element of LeData to point the corresponding GtkListItem instance.
|
||||||
Therefore, items (LeData) in the list always know the GtkListItem.
|
Therefore, items (LeData) in the list always know the GtkListItem.
|
||||||
If there's no GtkListItem binded to the item, NULL is assigned.
|
If there's no GtkListItem bound to the item, NULL is assigned.
|
||||||
|
|
||||||
~~~C
|
~~~C
|
||||||
1 void
|
1 void
|
||||||
|
@ -179,40 +186,55 @@ If there's no GtkListItem binded to the item, NULL is assigned.
|
||||||
9 setup1_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
9 setup1_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
||||||
10 GtkWidget *button = gtk_button_new ();
|
10 GtkWidget *button = gtk_button_new ();
|
||||||
11 gtk_list_item_set_child (listitem, button);
|
11 gtk_list_item_set_child (listitem, button);
|
||||||
12 g_signal_connect (button, "clicked", G_CALLBACK (select_cb), listitem);
|
12 gtk_widget_set_focusable (GTK_WIDGET (button), FALSE);
|
||||||
13 }
|
13 g_signal_connect (button, "clicked", G_CALLBACK (select_cb), listitem);
|
||||||
14
|
14 }
|
||||||
15 static void
|
15
|
||||||
16 bind1_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
16 static void
|
||||||
17 LeData *data = LE_DATA (gtk_list_item_get_item (listitem));
|
17 bind1_cb (GtkListItemFactory *factory, GtkListItem *listitem, gpointer user_data) {
|
||||||
18 if (data)
|
18 LeWindow *win = LE_WINDOW (user_data);
|
||||||
19 le_data_set_listitem (data, listitem);
|
19 GtkWidget *button = gtk_list_item_get_child (listitem);
|
||||||
20 }
|
20 const char *non_current[1] = {NULL};
|
||||||
21
|
21 const char *current[2] = {"current", NULL};
|
||||||
22 static void
|
22 LeData *data = LE_DATA (gtk_list_item_get_item (listitem));
|
||||||
23 unbind1_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
23
|
||||||
24 LeData *data = LE_DATA (gtk_list_item_get_item (listitem));
|
24 if (data) {
|
||||||
25 if (data)
|
25 le_data_set_listitem (data, listitem);
|
||||||
26 le_data_set_listitem (data, NULL);
|
26 if (win->position == gtk_list_item_get_position (listitem))
|
||||||
27 }
|
27 gtk_widget_set_css_classes (GTK_WIDGET (button), current);
|
||||||
|
28 else
|
||||||
|
29 gtk_widget_set_css_classes (GTK_WIDGET (button), non_current);
|
||||||
|
30 }
|
||||||
|
31 }
|
||||||
|
32
|
||||||
|
33 static void
|
||||||
|
34 unbind1_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
||||||
|
35 LeData *data = LE_DATA (gtk_list_item_get_item (listitem));
|
||||||
|
36 if (data)
|
||||||
|
37 le_data_set_listitem (data, NULL);
|
||||||
|
38 }
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
- 8-13: `setup1_cb` is a setup signal handler on the GtkSignalListItemFactory.
|
- 8-14: `setup1_cb` is a setup signal handler on the GtkSignalListItemFactory.
|
||||||
This factory is inserted to the factory property of the first GtkColumnViewColumn.
|
This factory is inserted to the factory property of the first GtkColumnViewColumn.
|
||||||
It sets the child of `listitem` to a newly created GtkButton instance.
|
It sets the child of `listitem` to a GtkButton instance.
|
||||||
The "clicked" signal on the button is connected to the handler `select_cb`.
|
The "clicked" signal on the button is connected to the handler `select_cb`.
|
||||||
When the listitem is destroyed, the child (GtkButton) is also destroyed.
|
When the listitem is destroyed, the child (GtkButton) is also destroyed.
|
||||||
At the same time, the connection of the signal and handler is also destroyed.
|
At the same time, the connection of the signal and the handler is also destroyed.
|
||||||
So, you don't need teardown signal handler.
|
So, you don't need teardown signal handler.
|
||||||
- 1-6: `select_cb` is a "clicked" signal handler.
|
- 1-6: `select_cb` is a "clicked" signal handler.
|
||||||
LeWindow is defined in `listeditor.c`.
|
LeWindow is defined in `listeditor.c`.
|
||||||
It's a child class of GtkApplicationWindow.
|
It's a child class of GtkApplicationWindow.
|
||||||
The handler just calls the `update_current` function.
|
The handler just calls the `update_current` function.
|
||||||
The function will be explained later.
|
The function will be explained later.
|
||||||
- 15-20: `bind1_cb` is a bind signal handler.
|
- 16-31: `bind1_cb` is a bind signal handler.
|
||||||
It sets the "listitem" element of the item (LeData) to point the `listitem` (GtkListItem instance).
|
It sets the "listitem" element of the item (LeData) to point the `listitem` (GtkListItem instance).
|
||||||
It makes the item possible to find the corresponding GtkListItem instance.
|
It makes the item possible to find the corresponding GtkListItem instance.
|
||||||
- 22-27: `unbind1_cb` is an unbind signal handler.
|
If the item is the current line, the CSS class of the button includes "current" class.
|
||||||
|
Otherwise it has no CSS class.
|
||||||
|
This is necessary because the button may be recycled and it has had former CSS class.
|
||||||
|
The class need to be updated.
|
||||||
|
- 33-38: `unbind1_cb` is an unbind signal handler.
|
||||||
It removes the `listitem` instance from the "listitem" element of the item.
|
It removes the `listitem` instance from the "listitem" element of the item.
|
||||||
The element becomes NULL, which tells no GtkListItem is bound.
|
The element becomes NULL, which tells no GtkListItem is bound.
|
||||||
When referring GtkListItem, it needs to check the "listitem" element whether it points a GtkListItem or not (NULL).
|
When referring GtkListItem, it needs to check the "listitem" element whether it points a GtkListItem or not (NULL).
|
||||||
|
@ -258,7 +280,6 @@ Otherwise bad things will happen.
|
||||||
37 }
|
37 }
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
|
||||||
The function `update_current` does several things.
|
The function `update_current` does several things.
|
||||||
|
|
||||||
- It has two parameters.
|
- It has two parameters.
|
||||||
|
@ -300,4 +321,20 @@ This is the opposite of `gtk_widget_init_template()`.
|
||||||
It is a new function of GTK 4.8 version.
|
It is a new function of GTK 4.8 version.
|
||||||
If your GTK version is lower than 4.8, you need to modify the program.
|
If your GTK version is lower than 4.8, you need to modify the program.
|
||||||
|
|
||||||
|
## A waring from GtkText
|
||||||
|
|
||||||
|
If the list has many items and it needs to be scrolled, a warning message can be issued.
|
||||||
|
|
||||||
|
~~~
|
||||||
|
GtkText - unexpected blinking selection. Removing
|
||||||
|
~~~
|
||||||
|
|
||||||
|
I don't have an idea why this happens.
|
||||||
|
But if GtkText "focusable" property is FALSE, the warning doesn't happen.
|
||||||
|
So it probably come from focus and scroll.
|
||||||
|
If you know the reason, please let me know.
|
||||||
|
|
||||||
|
It is a warning message, not a fatal error.
|
||||||
|
I think we can ignore it.
|
||||||
|
|
||||||
Up: [README.md](../README.md), Prev: [Section 29](sec29.md)
|
Up: [README.md](../README.md), Prev: [Section 29](sec29.md)
|
||||||
|
|
|
@ -101,12 +101,12 @@ le_data_take_string (LeData *self, char *string) {
|
||||||
|
|
||||||
GtkListItem *
|
GtkListItem *
|
||||||
le_data_get_listitem (LeData *self) {
|
le_data_get_listitem (LeData *self) {
|
||||||
return g_object_ref (self->listitem);
|
return self->listitem ? g_object_ref (self->listitem) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkListItem *
|
GtkListItem *
|
||||||
le_data_look_listitem (LeData *self) {
|
le_data_look_listitem (LeData *self) {
|
||||||
return self->listitem;
|
return self->listitem ? self->listitem : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
|
@ -396,14 +396,25 @@ static void
|
||||||
setup1_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
setup1_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
||||||
GtkWidget *button = gtk_button_new ();
|
GtkWidget *button = gtk_button_new ();
|
||||||
gtk_list_item_set_child (listitem, button);
|
gtk_list_item_set_child (listitem, button);
|
||||||
|
gtk_widget_set_focusable (GTK_WIDGET (button), FALSE);
|
||||||
g_signal_connect (button, "clicked", G_CALLBACK (select_cb), listitem);
|
g_signal_connect (button, "clicked", G_CALLBACK (select_cb), listitem);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bind1_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
bind1_cb (GtkListItemFactory *factory, GtkListItem *listitem, gpointer user_data) {
|
||||||
|
LeWindow *win = LE_WINDOW (user_data);
|
||||||
|
GtkWidget *button = gtk_list_item_get_child (listitem);
|
||||||
|
const char *non_current[1] = {NULL};
|
||||||
|
const char *current[2] = {"current", NULL};
|
||||||
LeData *data = LE_DATA (gtk_list_item_get_item (listitem));
|
LeData *data = LE_DATA (gtk_list_item_get_item (listitem));
|
||||||
if (data)
|
|
||||||
|
if (data) {
|
||||||
le_data_set_listitem (data, listitem);
|
le_data_set_listitem (data, listitem);
|
||||||
|
if (win->position == gtk_list_item_get_position (listitem))
|
||||||
|
gtk_widget_set_css_classes (GTK_WIDGET (button), current);
|
||||||
|
else
|
||||||
|
gtk_widget_set_css_classes (GTK_WIDGET (button), non_current);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -417,17 +428,19 @@ static void
|
||||||
setup2_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
setup2_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
||||||
GtkWidget *text = gtk_text_new ();
|
GtkWidget *text = gtk_text_new ();
|
||||||
gtk_list_item_set_child (listitem, GTK_WIDGET (text));
|
gtk_list_item_set_child (listitem, GTK_WIDGET (text));
|
||||||
|
gtk_editable_set_alignment (GTK_EDITABLE (text), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bind2_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
bind2_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
||||||
GtkWidget *text = gtk_list_item_get_child (listitem);
|
GtkWidget *text = gtk_list_item_get_child (listitem);
|
||||||
|
GtkEntryBuffer *buffer = gtk_text_get_buffer (GTK_TEXT (text));
|
||||||
LeData *data = LE_DATA (gtk_list_item_get_item (listitem));
|
LeData *data = LE_DATA (gtk_list_item_get_item (listitem));
|
||||||
GtkEntryBuffer *buffer;
|
|
||||||
GBinding *bind;
|
GBinding *bind;
|
||||||
|
|
||||||
buffer = gtk_text_get_buffer (GTK_TEXT (text));
|
gtk_editable_set_text (GTK_EDITABLE (text), le_data_look_string (data));
|
||||||
gtk_entry_buffer_set_text (buffer, le_data_look_string (data), -1);
|
gtk_editable_set_position (GTK_EDITABLE (text), 0);
|
||||||
|
|
||||||
bind = g_object_bind_property (buffer, "text", data, "string", G_BINDING_DEFAULT);
|
bind = g_object_bind_property (buffer, "text", data, "string", G_BINDING_DEFAULT);
|
||||||
g_object_set_data (G_OBJECT (listitem), "bind", bind);
|
g_object_set_data (G_OBJECT (listitem), "bind", bind);
|
||||||
}
|
}
|
||||||
|
@ -440,6 +453,13 @@ unbind2_cb (GtkListItemFactory *factory, GtkListItem *listitem) {
|
||||||
g_object_set_data (G_OBJECT (listitem), "bind", NULL);
|
g_object_set_data (G_OBJECT (listitem), "bind", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static void
|
||||||
|
// adjustment_value_changed_cb (GtkAdjustment *adjustment, gpointer user_data) {
|
||||||
|
// GtkWidget *win = GTK_WIDGET (user_data);
|
||||||
|
|
||||||
|
// gtk_widget_set_can_focus (win, FALSE);
|
||||||
|
// }
|
||||||
|
|
||||||
static void
|
static void
|
||||||
le_window_init (LeWindow *win) {
|
le_window_init (LeWindow *win) {
|
||||||
gtk_widget_init_template (GTK_WIDGET (win));
|
gtk_widget_init_template (GTK_WIDGET (win));
|
||||||
|
@ -483,6 +503,7 @@ le_window_class_init (LeWindowClass *class) {
|
||||||
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), setup2_cb);
|
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), setup2_cb);
|
||||||
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), bind2_cb);
|
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), bind2_cb);
|
||||||
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), unbind2_cb);
|
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), unbind2_cb);
|
||||||
|
// gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), adjustment_value_changed_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget *
|
GtkWidget *
|
||||||
|
|
|
@ -84,6 +84,13 @@
|
||||||
<object class="GtkScrolledWindow">
|
<object class="GtkScrolledWindow">
|
||||||
<property name="hexpand">TRUE</property>
|
<property name="hexpand">TRUE</property>
|
||||||
<property name="vexpand">TRUE</property>
|
<property name="vexpand">TRUE</property>
|
||||||
|
<!--
|
||||||
|
<property name="vadjustment">
|
||||||
|
<object class="GtkAdjustment">
|
||||||
|
<signal name="value-changed" handler="adjustment_value_changed_cb" swapped="no" object="LeWindow"/>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
-->
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkColumnView" id="columnview">
|
<object class="GtkColumnView" id="columnview">
|
||||||
<property name="hexpand">TRUE</property>
|
<property name="hexpand">TRUE</property>
|
||||||
|
@ -104,7 +111,7 @@
|
||||||
<property name="factory">
|
<property name="factory">
|
||||||
<object class="GtkSignalListItemFactory">
|
<object class="GtkSignalListItemFactory">
|
||||||
<signal name="setup" handler="setup1_cb"></signal>
|
<signal name="setup" handler="setup1_cb"></signal>
|
||||||
<signal name="bind" handler="bind1_cb"></signal>
|
<signal name="bind" handler="bind1_cb" swapped="no" object="LeWindow"></signal>
|
||||||
<signal name="unbind" handler="unbind1_cb"></signal>
|
<signal name="unbind" handler="unbind1_cb"></signal>
|
||||||
</object>
|
</object>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
@ -75,41 +75,42 @@ The following is their sgnal handlers.
|
||||||
listeditor/listeditor.c setup2_cb bind2_cb unbind2_cb
|
listeditor/listeditor.c setup2_cb bind2_cb unbind2_cb
|
||||||
@@@
|
@@@
|
||||||
|
|
||||||
- 1-5: `setup2_cb` is a setup signal handler on the GtkSignalListItemFactory.
|
- 1-6: `setup2_cb` is a setup signal handler on the GtkSignalListItemFactory.
|
||||||
This factory is inserted to the factory property of the second GtkColumnViewColumn.
|
This factory is inserted to the factory property of the second GtkColumnViewColumn.
|
||||||
Te handler just creates a GtkText instance and sets the child of `listitem` to it.
|
The handler just creates a GtkText instance and sets the child of `listitem` to it.
|
||||||
The instance will be destroyed automatically when the `listitem` is destroyed.
|
The instance will be destroyed automatically when the `listitem` is destroyed.
|
||||||
So, teardown signal handler isn't necessary.
|
So, teardown signal handler isn't necessary.
|
||||||
- 7-18: `bind2_cb` is a bind signal handler.
|
- 8-20: `bind2_cb` is a bind signal handler.
|
||||||
It is called when the `listitem` is bound to an item in the list.
|
It is called when the `listitem` is bound to an item in the list.
|
||||||
The list items are LeData instances.
|
The list items are LeData instances.
|
||||||
LeData is defined in the file `listeditor.c` (the C source file of the list editor).
|
LeData is defined in the file `listeditor.c` (the C source file of the list editor).
|
||||||
It is a child class of GObject and has two data.
|
It is a child class of GObject and has two data.
|
||||||
The one is `listitem` which points a GtkListItem instance when they are connected.
|
The one is `listitem` which points a first column GtkListItem instance when they are connected.
|
||||||
|
Be careful that the GtkListItem instance is *not* the `listitem` in this handler.
|
||||||
If no GtkListItem is connected, it is NULL.
|
If no GtkListItem is connected, it is NULL.
|
||||||
The other is `string` which is a content of the line.
|
The other is `string` which is a content of the line.
|
||||||
- 9-10: `text` is a child of the `listitem` and it is a GtkText instance.
|
- 10-11: `text` is a child of the `listitem` and it is a GtkText instance.
|
||||||
`data` is an item pointed by the `listitem`. It is a LeData instance.
|
And `buffer` is a GtkTextBuffer instance of the `text`.
|
||||||
- 14: Gets the buffer of the `text`.
|
- 12: The LeData instance `data` is an item pointed by the `listitem`.
|
||||||
- 15: Sets the text of the buffer to `le_data_look_string (data)`.
|
- 15-16: Sets the text of `text` to `le_data_look_string (data)`.
|
||||||
le\_data\_look\_string returns the string of the data and the ownership of the string is taken by the `data`.
|
le\_data\_look\_string returns the string of the `data` and the ownership of the string is still taken by the `data`.
|
||||||
So, the caller don't need to free the string.
|
So, the caller don't need to free the string.
|
||||||
- 16: `g_object_bind_property` binds a property and another object property.
|
- 18: `g_object_bind_property` binds a property and another object property.
|
||||||
This line binds the "text" property of the `buffer` (source) and the "string" property of the `data` (destination).
|
This line binds the "text" property of the `buffer` (source) and the "string" property of the `data` (destination).
|
||||||
It is a uni-directional binding (`G_BINDING_DEFAULT`).
|
It is a uni-directional binding (`G_BINDING_DEFAULT`).
|
||||||
When a user changes the GtkText text, the same string is immediately put into the `data`.
|
When a user changes the GtkText text, the same string is immediately put into the `data`.
|
||||||
The function returns a GBinding instance.
|
The function returns a GBinding instance.
|
||||||
This binding is different from bindings of GtkExpression.
|
This binding is different from bindings of GtkExpression.
|
||||||
This binding needs the existence of the two properties.
|
This binding needs the existence of the two properties.
|
||||||
- 17: GObjec has a table.
|
- 19: GObjec has a table.
|
||||||
The key is a string (or GQuark) and the value is a gpointer (pointer to any type).
|
The key is a string (or GQuark) and the value is a gpointer (pointer to any type).
|
||||||
The function `g_object_set_data` sets the association from the key to the value.
|
The function `g_object_set_data` sets the association from the key to the value.
|
||||||
This line sets the association from "bind" to `bind` instance on the `listitem` instance.
|
This line sets the association from "bind" to `bind` instance.
|
||||||
It makes possible for the "unbind" handler to get the `bind` instance.
|
It makes possible for the "unbind" handler to get the `bind` instance.
|
||||||
- 20-26: `unbind2_cb` is a unbind signal handler.
|
- 22-28: `unbind2_cb` is a unbind signal handler.
|
||||||
- 22: Retrieves the `bind` instance from the table in the `listitem` instance.
|
- 24: Retrieves the `bind` instance from the table in the `listitem` instance.
|
||||||
- 24: Unbind the binding.
|
- 26: Unbind the binding.
|
||||||
- 25: Removes the value corresponds to the "bind" key.
|
- 27: Removes the value corresponds to the "bind" key.
|
||||||
|
|
||||||
This technique is not so complicated.
|
This technique is not so complicated.
|
||||||
You can use it when you make a cell editable application.
|
You can use it when you make a cell editable application.
|
||||||
|
@ -125,6 +126,10 @@ The line editor has the current position of the list.
|
||||||
- When a line is appended or inserted, the line is current.
|
- When a line is appended or inserted, the line is current.
|
||||||
- When the current line is deleted, no line will be current.
|
- When the current line is deleted, no line will be current.
|
||||||
- When a button in the first column of GtkColumnView is clicked, the line will be current.
|
- When a button in the first column of GtkColumnView is clicked, the line will be current.
|
||||||
|
- It is necessary to set the line status (whether current or not) when a GtkListItem is bound to an item in the list.
|
||||||
|
It is because GtkListItem is recycled.
|
||||||
|
A GtkListItem was possibly current line before but not current after recycled.
|
||||||
|
The opposite can also be happen.
|
||||||
|
|
||||||
The button of the current line is colored with red and otherwise white.
|
The button of the current line is colored with red and otherwise white.
|
||||||
|
|
||||||
|
@ -138,28 +143,32 @@ It is necessary to know the corresponding GtkListItem instance from the item in
|
||||||
It is the opposite direction from `gtk_list_item_get_item` function.
|
It is the opposite direction from `gtk_list_item_get_item` function.
|
||||||
To accomplish this, we set a `listitem` element of LeData to point the corresponding GtkListItem instance.
|
To accomplish this, we set a `listitem` element of LeData to point the corresponding GtkListItem instance.
|
||||||
Therefore, items (LeData) in the list always know the GtkListItem.
|
Therefore, items (LeData) in the list always know the GtkListItem.
|
||||||
If there's no GtkListItem binded to the item, NULL is assigned.
|
If there's no GtkListItem bound to the item, NULL is assigned.
|
||||||
|
|
||||||
@@@include
|
@@@include
|
||||||
listeditor/listeditor.c select_cb setup1_cb bind1_cb unbind1_cb
|
listeditor/listeditor.c select_cb setup1_cb bind1_cb unbind1_cb
|
||||||
@@@
|
@@@
|
||||||
|
|
||||||
- 8-13: `setup1_cb` is a setup signal handler on the GtkSignalListItemFactory.
|
- 8-14: `setup1_cb` is a setup signal handler on the GtkSignalListItemFactory.
|
||||||
This factory is inserted to the factory property of the first GtkColumnViewColumn.
|
This factory is inserted to the factory property of the first GtkColumnViewColumn.
|
||||||
It sets the child of `listitem` to a newly created GtkButton instance.
|
It sets the child of `listitem` to a GtkButton instance.
|
||||||
The "clicked" signal on the button is connected to the handler `select_cb`.
|
The "clicked" signal on the button is connected to the handler `select_cb`.
|
||||||
When the listitem is destroyed, the child (GtkButton) is also destroyed.
|
When the listitem is destroyed, the child (GtkButton) is also destroyed.
|
||||||
At the same time, the connection of the signal and handler is also destroyed.
|
At the same time, the connection of the signal and the handler is also destroyed.
|
||||||
So, you don't need teardown signal handler.
|
So, you don't need teardown signal handler.
|
||||||
- 1-6: `select_cb` is a "clicked" signal handler.
|
- 1-6: `select_cb` is a "clicked" signal handler.
|
||||||
LeWindow is defined in `listeditor.c`.
|
LeWindow is defined in `listeditor.c`.
|
||||||
It's a child class of GtkApplicationWindow.
|
It's a child class of GtkApplicationWindow.
|
||||||
The handler just calls the `update_current` function.
|
The handler just calls the `update_current` function.
|
||||||
The function will be explained later.
|
The function will be explained later.
|
||||||
- 15-20: `bind1_cb` is a bind signal handler.
|
- 16-31: `bind1_cb` is a bind signal handler.
|
||||||
It sets the "listitem" element of the item (LeData) to point the `listitem` (GtkListItem instance).
|
It sets the "listitem" element of the item (LeData) to point the `listitem` (GtkListItem instance).
|
||||||
It makes the item possible to find the corresponding GtkListItem instance.
|
It makes the item possible to find the corresponding GtkListItem instance.
|
||||||
- 22-27: `unbind1_cb` is an unbind signal handler.
|
If the item is the current line, the CSS class of the button includes "current" class.
|
||||||
|
Otherwise it has no CSS class.
|
||||||
|
This is necessary because the button may be recycled and it has had former CSS class.
|
||||||
|
The class need to be updated.
|
||||||
|
- 33-38: `unbind1_cb` is an unbind signal handler.
|
||||||
It removes the `listitem` instance from the "listitem" element of the item.
|
It removes the `listitem` instance from the "listitem" element of the item.
|
||||||
The element becomes NULL, which tells no GtkListItem is bound.
|
The element becomes NULL, which tells no GtkListItem is bound.
|
||||||
When referring GtkListItem, it needs to check the "listitem" element whether it points a GtkListItem or not (NULL).
|
When referring GtkListItem, it needs to check the "listitem" element whether it points a GtkListItem or not (NULL).
|
||||||
|
@ -169,7 +178,6 @@ Otherwise bad things will happen.
|
||||||
listeditor/listeditor.c update_current
|
listeditor/listeditor.c update_current
|
||||||
@@@
|
@@@
|
||||||
|
|
||||||
|
|
||||||
The function `update_current` does several things.
|
The function `update_current` does several things.
|
||||||
|
|
||||||
- It has two parameters.
|
- It has two parameters.
|
||||||
|
@ -210,3 +218,19 @@ The function `gtk_widget_dispose_template` clears the template children for the
|
||||||
This is the opposite of `gtk_widget_init_template()`.
|
This is the opposite of `gtk_widget_init_template()`.
|
||||||
It is a new function of GTK 4.8 version.
|
It is a new function of GTK 4.8 version.
|
||||||
If your GTK version is lower than 4.8, you need to modify the program.
|
If your GTK version is lower than 4.8, you need to modify the program.
|
||||||
|
|
||||||
|
## A waring from GtkText
|
||||||
|
|
||||||
|
If the list has many items and it needs to be scrolled, a warning message can be issued.
|
||||||
|
|
||||||
|
~~~
|
||||||
|
GtkText - unexpected blinking selection. Removing
|
||||||
|
~~~
|
||||||
|
|
||||||
|
I don't have an idea why this happens.
|
||||||
|
But if GtkText "focusable" property is FALSE, the warning doesn't happen.
|
||||||
|
So it probably come from focus and scroll.
|
||||||
|
If you know the reason, please let me know.
|
||||||
|
|
||||||
|
It is a warning message, not a fatal error.
|
||||||
|
I think we can ignore it.
|
||||||
|
|
Loading…
Reference in a new issue